38 namespace graphene {
namespace market_history {
91 const auto& history_idx = order_his_idx.get<by_key>();
92 const auto& his_time_idx = order_his_idx.get<by_market_time>();
98 if( hkey.base > hkey.quote )
99 std::swap( hkey.base, hkey.quote );
100 hkey.sequence = std::numeric_limits<int64_t>::min();
102 auto itr = history_idx.lower_bound( hkey );
104 if( itr != history_idx.end() && itr->key.base == hkey.base && itr->key.quote == hkey.quote )
105 hkey.sequence = itr->key.sequence - 1;
116 if(
_meta ==
nullptr )
119 if( meta_idx.size() == 0 )
125 _meta = &( *meta_idx.begin() );
130 hkey.sequence += max_records;
131 itr = history_idx.lower_bound( hkey );
132 if( itr != history_idx.end() && itr->key.base == hkey.base && itr->key.quote == hkey.quote )
136 if( min_time + max_seconds <
_now )
137 min_time =
_now - max_seconds;
138 auto time_itr = his_time_idx.lower_bound( std::make_tuple( hkey.base, hkey.quote, min_time ) );
139 if( time_itr != his_time_idx.end() && time_itr->key.base == hkey.base && time_itr->key.quote == hkey.quote )
141 if( itr->key.sequence >= time_itr->key.sequence )
143 while( itr != history_idx.end() && itr->key.base == hkey.base && itr->key.quote == hkey.quote )
147 db.remove( *old_itr );
152 while( time_itr != his_time_idx.end() && time_itr->key.base == hkey.base && time_itr->key.quote == hkey.quote )
154 auto old_itr = time_itr;
156 db.remove( *old_itr );
175 trade_price = ~trade_price;
180 fill_price = ~fill_price;
184 auto ticker_itr = ticker_idx.find( std::make_tuple( key.
base, key.
quote ) );
185 if( ticker_itr == ticker_idx.end() )
189 mt.quote = key.
quote;
190 mt.last_day_base = 0;
191 mt.last_day_quote = 0;
210 if( max_history == 0 )
return;
213 if( buckets.size() == 0 )
return;
215 const auto& bucket_idx = db.get_index_type<
bucket_index>();
216 for(
auto bucket : buckets )
220 if( bucket_num > max_history )
221 cutoff = cutoff + ( bucket * ( bucket_num - max_history ) );
226 const auto& by_key_idx = bucket_idx.indices().get<by_key>();
227 auto bucket_itr = by_key_idx.find( key );
228 if( bucket_itr == by_key_idx.end() )
239 b.high_base = b.close_base;
240 b.high_quote = b.close_quote;
241 b.low_base = b.close_base;
242 b.low_quote = b.close_quote;
252 }
catch( fc::overflow_exception& ) {
253 b.
base_volume = std::numeric_limits<int64_t>::max();
257 }
catch( fc::overflow_exception& ) {
262 if( b.
high() < fill_price )
267 if( b.
low() > fill_price )
278 bucket_itr = by_key_idx.lower_bound( key );
280 while( bucket_itr != by_key_idx.end() &&
281 bucket_itr->key.base == key.
base &&
282 bucket_itr->key.quote == key.
quote &&
283 bucket_itr->key.seconds == bucket &&
284 bucket_itr->key.open < cutoff )
287 auto old_bucket_itr = bucket_itr;
289 db.remove( *old_bucket_itr );
302 if( meta_idx.size() > 0 )
303 _meta = &( *meta_idx.begin() );
307 if( lp_meta_idx.size() > 0 )
308 _lp_meta = &( *lp_meta_idx.begin() );
325 if( _meta !=
nullptr )
327 time_point_sec last_day = b.timestamp - 86400;
334 while( history_itr != history_idx.end() && history_itr->time < last_day )
350 trade_price = ~trade_price;
355 fill_price = ~fill_price;
357 auto ticker_itr = ticker_idx.find( std::make_tuple( key.
base, key.
quote ) );
358 if( ticker_itr != ticker_idx.end() )
368 last_min_his_id = history_itr->id;
372 if( history_itr != history_idx.end() )
395 if( _lp_meta !=
nullptr )
397 time_point_sec last_day = b.timestamp - 86400;
403 while( history_itr != history_idx.end() && history_itr->time < last_day )
411 if( ticker !=
nullptr )
446 auto amount_in = op.amount_to_sell.amount - result.fees.front().amount;
447 auto amount_out = result.received.front().amount + result.fees.at(1).amount;
448 if( op.amount_to_sell.asset_id < op.min_to_receive.asset_id )
470 last_min_his_id = history_itr->id;
474 if( history_itr != history_idx.end() )
542 uint64_t sequence = 0;
557 const auto& his_seq_idx = his_index.get<by_pool_seq>();
558 const auto& his_time_idx = his_index.get<by_pool_time>();
562 auto itr = his_seq_idx.lower_bound( *pool );
563 if( itr != his_seq_idx.end() && itr->pool == *pool )
564 sequence = itr->sequence + 1;
580 if( lp_meta ==
nullptr )
583 if( lp_meta_idx.size() == 0 )
589 lp_meta = &( *lp_meta_idx.begin() );
596 auto itr = his_seq_idx.lower_bound( std::make_tuple( *pool, min_seq ) );
597 if( itr != his_seq_idx.end() && itr->pool == *pool )
602 auto time_itr = his_time_idx.lower_bound( std::make_tuple( *pool, min_time ) );
603 if( time_itr != his_time_idx.end() && time_itr->pool == *pool )
605 if( itr->sequence <= time_itr->sequence )
607 while( itr != his_seq_idx.end() && itr->pool == *pool )
611 db.remove( *old_itr );
616 while( time_itr != his_time_idx.end() && time_itr->pool == *pool )
618 auto old_itr = time_itr;
620 db.remove( *old_itr );
634 }
while( ticker->
id.
instance() < pool->instance );
640 if( ticker !=
nullptr )
689 auto amount_in = op.amount_to_sell.amount - result.fees.front().amount;
690 auto amount_out = result.received.front().amount + result.fees.at(1).amount;
691 if( op.amount_to_sell.asset_id < op.min_to_receive.asset_id )
734 my(
std::make_unique<detail::market_history_plugin_impl>(*this) )
743 return "market_history";
747 boost::program_options::options_description& cli,
748 boost::program_options::options_description& cfg
754 boost::program_options::value<string>()->default_value(
"[60,300,900,3600,14400,86400,604800]"),
755 "Track market history by grouping orders into buckets of equal size measured "
756 "in seconds specified as a JSON array of numbers")
757 (
"history-per-size", boost::program_options::value<uint32_t>()->default_value(1500),
758 "How far back in time to track history for each bucket size, "
759 "measured in the number of buckets (default: 1500)")
760 (
"max-order-his-records-per-market", boost::program_options::value<uint32_t>()->default_value(1000),
761 "Will only store this amount of matched orders for each market in order history for querying, "
762 "or those meet the other option, which has more data (default: 1000). "
763 "This parameter is reused for liquidity pools as maximum operations per pool in history.")
764 (
"max-order-his-seconds-per-market", boost::program_options::value<uint32_t>()->default_value(259200),
765 "Will only store matched orders in last X seconds for each market in order history for querying, "
766 "or those meet the other option, which has more data (default: 259200 (3 days)). "
767 "This parameter is reused for liquidity pools as operations in last X seconds per pool in history. "
768 "Note: this parameter need to be greater than 24 hours to be able to serve market ticker data correctly.")
787 if( options.count(
"bucket-size" ) > 0 )
789 const std::string& buckets = options[
"bucket-size"].as<
string>();
791 my->_tracked_buckets.erase( 0 );
793 if( options.count(
"history-per-size" ) > 0 )
794 my->_maximum_history_per_bucket_size = options[
"history-per-size"].as<uint32_t>();
795 if( options.count(
"max-order-his-records-per-market" ) > 0 )
796 my->_max_order_his_records_per_market = options[
"max-order-his-records-per-market"].as<uint32_t>();
797 if( options.count(
"max-order-his-seconds-per-market" ) > 0 )
798 my->_max_order_his_seconds_per_market = options[
"max-order-his-seconds-per-market"].as<uint32_t>();
807 return my->_tracked_buckets;
812 return my->_maximum_history_per_bucket_size;
817 return my->_max_order_his_records_per_market;
822 return my->_max_order_his_seconds_per_market;