-
Notifications
You must be signed in to change notification settings - Fork 648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BSIP31-34 market engine improvements #829
Changes from all commits
10298ca
ceb480a
b2a86dd
adebe1e
c3d0acc
ea12aa8
0b6bbca
8005788
3f699c1
29925b1
462cf57
3e3c457
dbb2dce
145b0ad
c049b53
e5fc5d4
82765cb
8ea398d
9ab327a
a8391d8
98a2310
43d3795
22a2ecc
62b3a7b
e311769
cd7bb4b
5eb43de
d6cdc89
8dcd9ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -209,6 +209,20 @@ bool database::check_for_blackswan( const asset_object& mia, bool enable_black_s | |
const call_order_index& call_index = get_index_type<call_order_index>(); | ||
const auto& call_price_index = call_index.indices().get<by_price>(); | ||
|
||
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 ); | ||
|
||
if( call_itr == call_end ) return false; // no call orders | ||
|
||
price highest = settle_price; | ||
|
||
auto maint_time = get_dynamic_global_properties().next_maintenance_time; | ||
if( maint_time > HARDFORK_CORE_338_TIME ) | ||
// due to #338, we won't check for black swan on incoming limit order, so need to check with MSSP here | ||
highest = bitasset.current_feed.max_short_squeeze_price(); | ||
|
||
const limit_order_index& limit_index = get_index_type<limit_order_index>(); | ||
const auto& limit_price_index = limit_index.indices().get<by_price>(); | ||
|
||
|
@@ -217,38 +231,35 @@ bool database::check_for_blackswan( const asset_object& mia, bool enable_black_s | |
// stop when limit orders are selling too little USD for too much CORE | ||
auto lowest_possible_bid = price::min( mia.id, bitasset.options.short_backing_asset ); | ||
|
||
assert( highest_possible_bid.base.asset_id == lowest_possible_bid.base.asset_id ); | ||
FC_ASSERT( highest_possible_bid.base.asset_id == lowest_possible_bid.base.asset_id ); | ||
// NOTE limit_price_index is sorted from greatest to least | ||
auto limit_itr = limit_price_index.lower_bound( highest_possible_bid ); | ||
auto limit_end = limit_price_index.upper_bound( lowest_possible_bid ); | ||
|
||
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 ); | ||
|
||
if( call_itr == call_end ) return false; // no call orders | ||
|
||
price highest = settle_price; | ||
if( limit_itr != limit_end ) { | ||
assert( settle_price.base.asset_id == limit_itr->sell_price.base.asset_id ); | ||
highest = std::max( limit_itr->sell_price, settle_price ); | ||
FC_ASSERT( highest.base.asset_id == limit_itr->sell_price.base.asset_id ); | ||
highest = std::max( limit_itr->sell_price, highest ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is that still correct after HF_CORE_338? Important for understanding: check_for_blackswan is only called from check_call_orders. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Answer to previous remark: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In short, this change is correct. |
||
} | ||
|
||
auto least_collateral = call_itr->collateralization(); | ||
if( ~least_collateral >= highest ) | ||
{ | ||
wdump( (*call_itr) ); | ||
elog( "Black Swan detected: \n" | ||
" Least collateralized call: ${lc} ${~lc}\n" | ||
// " Highest Bid: ${hb} ${~hb}\n" | ||
" Settle Price: ${sp} ${~sp}\n" | ||
" Max: ${h} ${~h}\n", | ||
" Settle Price: ${~sp} ${sp}\n" | ||
" Max: ${~h} ${h}\n", | ||
("lc",least_collateral.to_real())("~lc",(~least_collateral).to_real()) | ||
// ("hb",limit_itr->sell_price.to_real())("~hb",(~limit_itr->sell_price).to_real()) | ||
("sp",settle_price.to_real())("~sp",(~settle_price).to_real()) | ||
("h",highest.to_real())("~h",(~highest).to_real()) ); | ||
FC_ASSERT( enable_black_swan, "Black swan was detected during a margin update which is not allowed to trigger a blackswan" ); | ||
globally_settle_asset(mia, ~least_collateral ); | ||
if( maint_time > HARDFORK_CORE_338_TIME && ~least_collateral <= settle_price ) | ||
// global settle at feed price if possible | ||
globally_settle_asset(mia, settle_price ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still struggling with the legitimacy of this, but tending to think it's ok. |
||
else | ||
globally_settle_asset(mia, ~least_collateral ); | ||
return true; | ||
} | ||
return false; | ||
|
@@ -257,20 +268,25 @@ bool database::check_for_blackswan( const asset_object& mia, bool enable_black_s | |
void database::clear_expired_orders() | ||
{ try { | ||
//Cancel expired limit orders | ||
auto head_time = head_block_time(); | ||
auto maint_time = get_dynamic_global_properties().next_maintenance_time; | ||
auto& limit_index = get_index_type<limit_order_index>().indices().get<by_expiration>(); | ||
while( !limit_index.empty() && limit_index.begin()->expiration <= head_block_time() ) | ||
while( !limit_index.empty() && limit_index.begin()->expiration <= head_time ) | ||
{ | ||
const limit_order_object& order = *limit_index.begin(); | ||
auto base_asset = order.sell_price.base.asset_id; | ||
auto quote_asset = order.sell_price.quote.asset_id; | ||
cancel_limit_order( order ); | ||
// check call orders | ||
// Comments below are copied from limit_order_cancel_evaluator::do_apply(...) | ||
// Possible optimization: order can be called by cancelling a limit order | ||
// if the canceled order was at the top of the book. | ||
// Do I need to check calls in both assets? | ||
check_call_orders( base_asset( *this ) ); | ||
check_call_orders( quote_asset( *this ) ); | ||
if( maint_time <= HARDFORK_CORE_606_TIME ) | ||
{ | ||
// check call orders | ||
// Comments below are copied from limit_order_cancel_evaluator::do_apply(...) | ||
// Possible optimization: order can be called by cancelling a limit order | ||
// if the canceled order was at the top of the book. | ||
// Do I need to check calls in both assets? | ||
check_call_orders( base_asset( *this ) ); | ||
check_call_orders( quote_asset( *this ) ); | ||
} | ||
} | ||
|
||
//Process expired force settlement orders | ||
|
@@ -330,7 +346,7 @@ void database::clear_expired_orders() | |
} | ||
|
||
// Has this order not reached its settlement date? | ||
if( order.settlement_date > head_block_time() ) | ||
if( order.settlement_date > head_time ) | ||
{ | ||
if( next_asset() ) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// bitshares-core issue #338 Fix "margin call order fills at price of matching limit_order" | ||
#ifndef HARDFORK_CORE_338_TIME | ||
#define HARDFORK_CORE_338_TIME (fc::time_point_sec( 1600000000 )) | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// bitshares-core issue #343 | ||
// Fix "Inconsistent sorting of call orders between matching against a limit order and a force settle order" | ||
#ifndef HARDFORK_CORE_343_TIME | ||
#define HARDFORK_CORE_343_TIME (fc::time_point_sec( 1600000000 )) | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// bitshares-core issue #453 Fix "Multiple limit order and call order matching issue" | ||
#ifndef HARDFORK_CORE_453_TIME | ||
#define HARDFORK_CORE_453_TIME (fc::time_point_sec( 1600000000 )) | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// bitshares-core issue #606 Fix "Undercollateralized short positions should be called regardless of asks" | ||
#ifndef HARDFORK_CORE_606_TIME | ||
#define HARDFORK_CORE_606_TIME (fc::time_point_sec( 1600000000 )) | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// bitshares-core issue #625 Fix "Potential erratic order matching issue involving margin call orders" | ||
#ifndef HARDFORK_CORE_625_TIME | ||
#define HARDFORK_CORE_625_TIME (fc::time_point_sec( 1600000000 )) | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps skip over PM's here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whether to skip over PM's here, the only logic difference might be the
check_black_swan()
call incheck_call_orders()
.Since we didn't fix #460 in this release (no BSIP for it so far), PM's will still suffer black swan events when there is a price feed change or matching logic change.
Although we didn't update
call_price
s of PM's, but we changed logic incheck_black_swan()
to check with MSSP, which is possible to trigger a black swan event. So the outcome is different if skip over PM's here.I'd suggest we trigger black swan events here (if there would be some) to be consistent (rather than triggering on a new but same price feed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps keep the old logic for PM's, don't trigger black swan event when there is no matching limit order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we agreed that #460 is a bug and doesn't need a BSIP.
We could fix #460 quickly by adding a HF-protected check in check_for_black_swan, then don't need to skip here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My opinion on #460 is here: #460 (comment). Aka not really a bug and not a quick fix to me.
So my recommendation in this release is to let PMs (still) have same behavior (on black swan events) as other MPAs, that said, we changed behavior of other MPAs, which will affect PMs as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok