Skip to content

Commit

Permalink
Add get_trade_history_by_sequence API, for bitshares#448
Browse files Browse the repository at this point in the history
  • Loading branch information
abitmore committed Nov 10, 2017
1 parent ad23d58 commit 243b9cf
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 4 deletions.
113 changes: 113 additions & 0 deletions libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
market_volume get_24_volume( const string& base, const string& quote )const;
order_book get_order_book( const string& base, const string& quote, unsigned limit = 50 )const;
vector<market_trade> get_trade_history( const string& base, const string& quote, fc::time_point_sec start, fc::time_point_sec stop, unsigned limit = 100 )const;
vector<market_trade> get_trade_history_by_sequence( const string& base, const string& quote, int64_t start, fc::time_point_sec stop, unsigned limit = 100 )const;

// Witnesses
vector<optional<witness_object>> get_witnesses(const vector<witness_id_type>& witness_ids)const;
Expand Down Expand Up @@ -1429,6 +1430,118 @@ vector<market_trade> database_api_impl::get_trade_history( const string& base,
return result;
}

vector<market_trade> database_api::get_trade_history_by_sequence(
const string& base,
const string& quote,
int64_t start,
fc::time_point_sec stop,
unsigned limit )const
{
return my->get_trade_history_by_sequence( base, quote, start, stop, limit );
}

vector<market_trade> database_api_impl::get_trade_history_by_sequence(
const string& base,
const string& quote,
int64_t start,
fc::time_point_sec stop,
unsigned limit )const
{
FC_ASSERT( limit <= 100 );
FC_ASSERT( start >= 0 );
int64_t start_seq = -start;

auto assets = lookup_asset_symbols( {base, quote} );
FC_ASSERT( assets[0], "Invalid base asset symbol: ${s}", ("s",base) );
FC_ASSERT( assets[1], "Invalid quote asset symbol: ${s}", ("s",quote) );

auto base_id = assets[0]->id;
auto quote_id = assets[1]->id;

if( base_id > quote_id ) std::swap( base_id, quote_id );
const auto& history_idx = _db.get_index_type<graphene::market_history::history_index>().indices().get<by_key>();
history_key hkey;
hkey.base = base_id;
hkey.quote = quote_id;
hkey.sequence = start_seq;

auto asset_to_real = [&]( const asset& a, int p ) { return double( a.amount.value ) / pow( 10, p ); };
auto price_to_real = [&]( const price& p )
{
if( p.base.asset_id == assets[0]->id )
return asset_to_real( p.base, assets[0]->precision ) / asset_to_real( p.quote, assets[1]->precision );
else
return asset_to_real( p.quote, assets[0]->precision ) / asset_to_real( p.base, assets[1]->precision );
};

uint32_t count = 0;
auto itr = history_idx.lower_bound( hkey );
vector<market_trade> result;

while( itr != history_idx.end() && count < limit && !( itr->key.base != base_id || itr->key.quote != quote_id || itr->time < stop ) )
{
if( itr->key.sequence == start_seq ) // found the key, should skip this and the other direction if found
{
auto next_itr = std::next(itr);
if( next_itr != history_idx.end() && next_itr->key.base == base_id && next_itr->key.quote == quote_id
&& next_itr->time == itr->time && next_itr->op.is_maker != itr->op.is_maker )
{ // next_itr now could be the other direction // FIXME not 100% sure
// skip the other direction
itr = next_itr;
}
}
else
{
market_trade trade;

if( assets[0]->id == itr->op.receives.asset_id )
{
trade.amount = asset_to_real( itr->op.pays, assets[1]->precision );
trade.value = asset_to_real( itr->op.receives, assets[0]->precision );
}
else
{
trade.amount = asset_to_real( itr->op.receives, assets[1]->precision );
trade.value = asset_to_real( itr->op.pays, assets[0]->precision );
}

trade.date = itr->time;
trade.price = price_to_real( itr->op.fill_price );

if( itr->op.is_maker )
{
trade.sequence = -itr->key.sequence;
trade.side1_account_id = itr->op.account_id;
}
else
trade.side2_account_id = itr->op.account_id;

auto next_itr = std::next(itr);
// Trades are usually tracked in each direction, exception: for global settlement only one side is recorded
if( next_itr != history_idx.end() && next_itr->key.base == base_id && next_itr->key.quote == quote_id
&& next_itr->time == itr->time && next_itr->op.is_maker != itr->op.is_maker )
{ // next_itr now could be the other direction // FIXME not 100% sure
if( next_itr->op.is_maker )
{
trade.sequence = -next_itr->key.sequence;
trade.side1_account_id = next_itr->op.account_id;
}
else
trade.side2_account_id = next_itr->op.account_id;
// skip the other direction
itr = next_itr;
}

result.push_back( trade );
++count;
}

++itr;
}

return result;
}

//////////////////////////////////////////////////////////////////////
// //
// Witnesses //
Expand Down
21 changes: 17 additions & 4 deletions libraries/app/include/graphene/app/database_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,17 +428,29 @@ class database_api
order_book get_order_book( const string& base, const string& quote, unsigned limit = 50 )const;

/**
* @brief Returns recent trades for the market assetA:assetB
* Note: Currentlt, timezone offsets are not supported. The time must be UTC.
* @brief Returns recent trades for the market assetA:assetB, ordered by time, most recent first. The range is [stop, start)
* Note: Currently, timezone offsets are not supported. The time must be UTC.
* @param a String name of the first asset
* @param b String name of the second asset
* @param stop Stop time as a UNIX timestamp
* @param stop Stop time as a UNIX timestamp, the earliest trade to retrieve
* @param limit Number of trasactions to retrieve, capped at 100
* @param start Start time as a UNIX timestamp
* @param start Start time as a UNIX timestamp, the latest trade to retrieve
* @return Recent transactions in the market
*/
vector<market_trade> get_trade_history( const string& base, const string& quote, fc::time_point_sec start, fc::time_point_sec stop, unsigned limit = 100 )const;

/**
* @brief Returns trades for the market assetA:assetB, ordered by time, most recent first. The range is [stop, start)
* Note: Currently, timezone offsets are not supported. The time must be UTC.
* @param a String name of the first asset
* @param b String name of the second asset
* @param stop Stop time as a UNIX timestamp, the earliest trade to retrieve
* @param limit Number of trasactions to retrieve, capped at 100
* @param start Start sequence as an Integer, the latest trade to retrieve
* @return Transactions in the market
*/
vector<market_trade> get_trade_history_by_sequence( const string& base, const string& quote, int64_t start, fc::time_point_sec stop, unsigned limit = 100 )const;



///////////////
Expand Down Expand Up @@ -681,6 +693,7 @@ FC_API(graphene::app::database_api,
(get_ticker)
(get_24_volume)
(get_trade_history)
(get_trade_history_by_sequence)

// Witnesses
(get_witnesses)
Expand Down

0 comments on commit 243b9cf

Please sign in to comment.