-
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
Conversation
For: * #338 Margin call order fills at price of matching limit_order * #343 Inconsistent sorting of call orders between matching against a limit order and a force settle order * #453 Multiple limit order and call order matching issue * #606 Undercollateralized short positions should be called regardless of asks
Be consistent with check_call_orders().
{ | ||
wlog( "Cull_small issue occurred at block #${block}", ("block",head_block_num()) ); | ||
limit_itr = next_limit_itr; | ||
if( filled_limit ) ++limit_itr; |
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.
Note:
- the code block here, including
++limit_itr
here and below, has been refactored in a later commit, we'll need to review again. - there are test cases about the
cull_small
issue after hard fork in commits for BSIP35.
const asset_object& a = *itr; | ||
++itr; | ||
// be here, next_maintenance_time should have been updated already | ||
db.check_call_orders( a, true, false ); // allow black swan, and call orders are taker |
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 in check_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 in check_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.
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
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Is that still correct after HF_CORE_338?
The call will always be matched at the squeeze price, even if the limit order offers a better price. A call could have sufficient collateral to fill the limit order at its price, but insufficient collateral to fill at MSQP.
Important for understanding: check_for_blackswan is only called from check_call_orders.
check_call_orders currently always uses limit order price for filling call. That shouldn't be the case, though, if I understand BSIP-32 correctly.
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.
Answer to previous remark:
After HF_625, check_call_orders is only ever called with the maker flag set to false. IOW after HF 338, check_call_orders is always taker, which means using the limit order price is correct, assuming that HF 338 and HF 625 happen simultaneously.
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.
In short, this change is correct.
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 comment
The 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.
libraries/chain/db_market.cpp
Outdated
* 3 - both were filled | ||
*/ | ||
template<typename OrderType> | ||
int database::match( const limit_order_object& usd, const OrderType& core, const price& match_price ) | ||
int database::match( const limit_order_object& usd, const limit_order_object& core, const price& match_price ) | ||
{ | ||
assert( usd.sell_price.quote.asset_id == core.sell_price.base.asset_id ); |
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.
Better turn these assert()s into FC_ASSERT()s 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.
Actually we need to carefully review all assert()
s and FC_ASSERT()
s as mentioned in #679 and #511 (comment).
For this one, if it would cause a chain halt, most probably would be caused by FBA buyback.
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.
You replaced the template method with two specific implementations. The implementation for limit_order uses assert(), as did the template, but the implementation for call_order uses FC_ASSERT, which is different from the original. IMO we should stay consistent, either change both or none.
libraries/chain/db_market.cpp
Outdated
// the first param is a new order, thus taker | ||
result |= fill_order( core, core_pays, core_receives, true, match_price, true ) << 1; // the second param is maker | ||
result |= fill_limit_order( usd, usd_pays, usd_receives, false, match_price, false ); // the first param is taker | ||
result |= fill_limit_order( core, core_pays, core_receives, true, match_price, true ) << 1; // the second param is maker | ||
assert( result != 0 ); |
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.
assert() -> FC_ASSERT()
libraries/chain/db_market.cpp
Outdated
@@ -643,8 +800,11 @@ bool database::check_call_orders(const asset_object& mia, bool enable_black_swan | |||
bool filled_limit = false; |
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.
Please add an FC_ASSERT to check_call_orders that ensures that for_new_limit_order is only true before HF 338 / 625 (see my remark on check_for_blackswan).
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.
Similar as commented above, actually we need to carefully review all assert()
s and FC_ASSERT()
s as mentioned in #679 and #511 (comment), also be careful when adding new FC_ASSERT()
s. Actually I want to get rid of all FC_ASSERT()
s or catch them properly when processing post-transaction jobs in _apply_block()
.
For this one, if we add a FC_ASSERT()
here then caused a chain halt, probably would be caused by clear_expired_feeds
or FBA buyback.
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.
After HF 388, check_call_orders / check_for_blackswan only operate correctly if the maker flag is false. Adding the suggested FC_ASSERT would enforce that this condition holds even if a future change mistakenly calls check_call_orders with the flag set to true.
General question (not rhetorical): what is worse, a chain halt or a chain operating with undefined and/or wrong behaviour?
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.
IMHO at most times a chain halt is worse, but negative impact of undefined/wrong behavior is unbounded and sometimes is even worse. So I don't have a clear answer. I slightly tend to avoid chain halt.
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 the opposite, especially because wrong behaviour can go unnoticed for a long time.
We need more opinions. :-) @xeroc @oxarbitrage @ryanRfox
libraries/chain/db_maint.cpp
Outdated
} | ||
if( !abd || abd->is_prediction_market ) // nothing to do with PM's; check !abd just to be safe | ||
continue; | ||
db.modify( call_obj, [&]( call_order_object& call ) { |
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.
Please capture only abd
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.
Done.
Please add/modify a test to cover this code path: https://sonarcloud.io/component?id=BitShares-develop%3Adevelop%3Alibraries%2Fchain%2Fdb_market.cpp&line=561 (Create a large limit order that is only partially filled by a margin call.) |
@pmconrad done changes for this:
//Update: |
This is a subset of changes on the market engine, cherry-picked from #641, including changes related to #338 #343 #453 #606 #625 #649, aka
Please review.