Skip to content

Commit

Permalink
Iterate calls by collateral in check_call_orders()
Browse files Browse the repository at this point in the history
  • Loading branch information
abitmore committed Sep 1, 2018
1 parent c62831f commit a0225fb
Showing 1 changed file with 44 additions and 28 deletions.
72 changes: 44 additions & 28 deletions libraries/chain/db_market.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -959,9 +959,6 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa
if( bitasset.is_prediction_market ) return false;
if( bitasset.current_feed.settlement_price.is_null() ) return false;

const call_order_index& call_index = get_index_type<call_order_index>();
const auto& call_price_index = call_index.indices().get<by_price>();

const limit_order_index& limit_index = get_index_type<limit_order_index>();
const auto& limit_price_index = limit_index.indices().get<by_price>();

Expand All @@ -980,10 +977,28 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa
if( limit_itr == limit_end )
return false;

const call_order_index& call_index = get_index_type<call_order_index>();
const auto& call_price_index = call_index.indices().get<by_price>();
const auto& call_collateral_index = call_index.indices().get<by_collateral>();

auto call_min = price::min( bitasset.options.short_backing_asset, mia.id );
auto call_max = price::max( bitasset.options.short_backing_asset, mia.id );
auto call_itr = call_price_index.lower_bound( call_min );
auto call_end = call_price_index.upper_bound( call_max );

auto call_price_itr = call_price_index.begin();
auto call_price_end = call_price_itr;
auto call_collateral_itr = call_collateral_index.begin();
auto call_collateral_end = call_collateral_itr;

if( before_core_hardfork_1270 )
{
call_price_itr = call_price_index.lower_bound( call_min );
call_price_end = call_price_index.upper_bound( call_max );
}
else
{
call_collateral_itr = call_collateral_index.lower_bound( call_min );
call_collateral_end = call_collateral_index.upper_bound( call_max );
}

bool filled_limit = false;
bool margin_called = false;
Expand All @@ -1001,34 +1016,33 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa
bool before_core_hardfork_606 = ( maint_time <= HARDFORK_CORE_606_TIME ); // feed always trigger call
bool before_core_hardfork_834 = ( maint_time <= HARDFORK_CORE_834_TIME ); // target collateral ratio option

while( !check_for_blackswan( mia, enable_black_swan, &bitasset ) && call_itr != call_end )
while( !check_for_blackswan( mia, enable_black_swan, &bitasset ) // TODO perhaps improve performance by passing in iterators
&& limit_itr != limit_end
&& ( ( !before_core_hardfork_1270 && call_collateral_itr != call_collateral_end )
|| ( before_core_hardfork_1270 && call_price_itr != call_price_end ) ) )
{
bool filled_call = false;
price match_price;
asset usd_for_sale;
if( limit_itr != limit_end )
{
assert( limit_itr != limit_price_index.end() );
match_price = limit_itr->sell_price;
usd_for_sale = limit_itr->amount_for_sale();
}
else return margin_called;

match_price.validate();
const call_order_object& call_order = ( before_core_hardfork_1270 ? *call_price_itr : *call_collateral_itr );

// Feed protected (don't call if CR>MCR) https://github.com/cryptonomex/graphene/issues/436
if( after_hardfork_436 && ( bitasset.current_feed.settlement_price > ~call_itr->call_price ) )
if( ( !before_core_hardfork_1270 && bitasset.current_maintenance_collateralization < call_order.collateralization() )
|| ( before_core_hardfork_1270
&& after_hardfork_436 && bitasset.current_feed.settlement_price > ~call_order.call_price ) )
return margin_called;

const limit_order_object& limit_order = *limit_itr;
price match_price = limit_order.sell_price;
// There was a check `match_price.validate();` here, which is removed now because it always passes

// Old rule: margin calls can only buy high https://github.com/bitshares/bitshares-core/issues/606
if( before_core_hardfork_606 && match_price > ~call_itr->call_price )
if( before_core_hardfork_606 && match_price > ~call_order.call_price )
return margin_called;

margin_called = true;

auto usd_to_buy = call_itr->get_debt();

if( usd_to_buy * match_price > call_itr->get_collateral() )
auto usd_to_buy = call_order.get_debt();
if( usd_to_buy * match_price > call_order.get_collateral() )
{
elog( "black swan detected on asset ${symbol} (${id}) at block ${b}",
("id",mia.id)("symbol",mia.symbol)("b",head_num) );
Expand All @@ -1039,10 +1053,11 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa
}

if( !before_core_hardfork_834 )
usd_to_buy.amount = call_itr->get_max_debt_to_cover( match_price,
usd_to_buy.amount = call_order.get_max_debt_to_cover( match_price,
bitasset.current_feed.settlement_price,
bitasset.current_feed.maintenance_collateral_ratio );

asset usd_for_sale = limit_order.amount_for_sale();
asset call_pays, call_receives, order_pays, order_receives;
if( usd_to_buy > usd_for_sale )
{ // fill order
Expand Down Expand Up @@ -1103,17 +1118,18 @@ bool database::check_call_orders( const asset_object& mia, bool enable_black_swa
call_pays = order_receives;
order_pays = call_receives;

auto old_call_itr = call_itr;
if( filled_call && before_core_hardfork_343 )
++call_itr;
++call_price_itr;
// when for_new_limit_order is true, the call order is maker, otherwise the call order is taker
fill_call_order(*old_call_itr, call_pays, call_receives, match_price, for_new_limit_order );
if( !before_core_hardfork_343 )
call_itr = call_price_index.lower_bound( call_min );
fill_call_order( call_order, call_pays, call_receives, match_price, for_new_limit_order );
if( !before_core_hardfork_1270 )
call_collateral_itr = call_collateral_index.lower_bound( call_min );
else if( !before_core_hardfork_343 )
call_price_itr = call_price_index.lower_bound( call_min );

auto next_limit_itr = std::next( limit_itr );
// when for_new_limit_order is true, the limit order is taker, otherwise the limit order is maker
bool really_filled = fill_limit_order( *limit_itr, order_pays, order_receives, true, match_price, !for_new_limit_order );
bool really_filled = fill_limit_order( limit_order, order_pays, order_receives, true, match_price, !for_new_limit_order );
if( really_filled || ( filled_limit && before_core_hardfork_453 ) )
limit_itr = next_limit_itr;

Expand Down

0 comments on commit a0225fb

Please sign in to comment.