-
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
Implement BSIP 74: Margin Call Fee Ratio #2180
Conversation
Co-authored by John Jones
Co-authored by John Jones
Co-authored by John Jones Co-authored by Michel Santos
fill_order_operation alice_fill_op = histories.front().op.get<fill_order_operation>(); | ||
BOOST_CHECK(alice_fill_op.fee == asset(0)); | ||
// Alice's fill order's fill price should equal the expected match price | ||
BOOST_CHECK(~alice_fill_op.fill_price == expected_match_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.
@abitmore What do you think should be the fill_price
recorded in fill_order_operation
under these different maker and taker scenarios? I'm particularly curious about the two tests where target collateral ratio (TCR) are active.
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 it's fine to record the match_price
. It's used to generate price charts.
Actually I didn't get what your concerns were.
limit_receives = usd_to_buy.multiply_and_round_up( match_price ); // round up, in favor of limit order | ||
call_pays = usd_to_buy.multiply_and_round_up( call_pays_price ); // BSIP74; excess is fee. | ||
// Note: TODO: Due to different rounding, couldn't this potentialy be | ||
// one satoshi more than the blackswan check above? Can this bite us? |
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.
@abitmore — Wanting to call attention to this question. It's not a new issue — old code uses multiply_and_round_up seemingly without problem — but since we do a black swan check above at line 1226 using multiply-and-round-down, is there a possibility that with the exact right price feed we could end up with call_pays being one satoshi more than the collateral in the call order? I expect this would eventually cause an exception to be thrown, perhaps preventing a feed_update_operation or other operation that can move the call order price from confirming?
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.
Thanks for the question.
As you've noticed, the blackswan check above at line 1226 is only for pre-hf-1270 (or even earlier, pre-hf-338) scenarios.
After hf-1270, the effective check is the check_black_swan()
call at line 1187:
bitshares-core/libraries/chain/db_market.cpp
Line 1187 in 11aa1be
while( !check_for_blackswan( mia, enable_black_swan, &bitasset ) // TODO perhaps improve performance by passing in iterators |
The code inside check_black_swan()
reads:
bitshares-core/libraries/chain/db_update.cpp
Line 224 in ed6b6d8
highest = bitasset.current_feed.max_short_squeeze_price(); |
bitshares-core/libraries/chain/db_update.cpp
Lines 247 to 251 in ed6b6d8
auto least_collateral = call_ptr->collateralization(); | |
if( ~least_collateral >= highest ) | |
{ | |
wdump( (*call_ptr) ); | |
elog( "Black Swan detected on asset ${symbol} (${id}) at block ${b}: \n" |
I think it guarantees that the rounding-up here won't make the call order pay more collateral than it has.
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.
Thanks. The code looks mostly good, except a few minor issues. I haven't reviewed test cases so far, will do later.
call_pays_price = call_match_price; | ||
} else { | ||
call_match_price = ~sell_abd->current_feed. | ||
margin_call_order_price(sell_abd->options.extensions.value.margin_call_fee_ratio); |
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.
Potential performance improvement to do in the future: save the prices to the bitasset_data
object when feeds or MCFR changed.
limit_receives = usd_to_buy.multiply_and_round_up( match_price ); // round up, in favor of limit order | ||
call_pays = usd_to_buy.multiply_and_round_up( call_pays_price ); // BSIP74; excess is fee. | ||
// Note: TODO: Due to different rounding, couldn't this potentialy be | ||
// one satoshi more than the blackswan check above? Can this bite us? |
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.
Thanks for the question.
As you've noticed, the blackswan check above at line 1226 is only for pre-hf-1270 (or even earlier, pre-hf-338) scenarios.
After hf-1270, the effective check is the check_black_swan()
call at line 1187:
bitshares-core/libraries/chain/db_market.cpp
Line 1187 in 11aa1be
while( !check_for_blackswan( mia, enable_black_swan, &bitasset ) // TODO perhaps improve performance by passing in iterators |
The code inside check_black_swan()
reads:
bitshares-core/libraries/chain/db_update.cpp
Line 224 in ed6b6d8
highest = bitasset.current_feed.max_short_squeeze_price(); |
bitshares-core/libraries/chain/db_update.cpp
Lines 247 to 251 in ed6b6d8
auto least_collateral = call_ptr->collateralization(); | |
if( ~least_collateral >= highest ) | |
{ | |
wdump( (*call_ptr) ); | |
elog( "Black Swan detected on asset ${symbol} (${id}) at block ${b}: \n" |
I think it guarantees that the rounding-up here won't make the call order pay more collateral than it has.
bool fill_call_order( const call_order_object& order, const asset& pays, const asset& receives, | ||
const price& fill_price, const bool is_maker ); | ||
const price& fill_price, const bool is_maker, const asset& margin_fee = asset(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.
The default value changes old data.
The old code stores asset(0,pays.asset_id)
to the fee
field of the virtual fill_order_operation
, but the new code will store asset(0,asset_id_type(0))
which could have a different asset ID.
bitshares-core/libraries/chain/db_market.cpp
Lines 923 to 924 in ed6b6d8
push_applied_operation( fill_order_operation( order.id, order.borrower, pays, receives, | |
asset(0, pays.asset_id), fill_price, is_maker ) ); |
bitshares-core/libraries/chain/db_market.cpp
Lines 1003 to 1004 in 11aa1be
push_applied_operation( fill_order_operation( order.id, order.borrower, pays, receives, | |
margin_call_fee, fill_price, is_maker ) ); |
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.
The test cases are mostly fine.
IMO we need a test case for scenario:
- asset owner reducing MCFR triggers new matching and filling of margin calls and limit orders.
fill_order_operation alice_fill_op = histories.front().op.get<fill_order_operation>(); | ||
BOOST_CHECK(alice_fill_op.fee == asset(0)); | ||
// Alice's fill order's fill price should equal the expected match price | ||
BOOST_CHECK(~alice_fill_op.fill_price == expected_match_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.
I think it's fine to record the match_price
. It's used to generate price charts.
Actually I didn't get what your concerns were.
516cd33
to
d90e835
Compare
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.
The new test case looks good. Thanks.
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.
Thanks.
Code looks good. Waiting for CI results.
An implementation of BSIP74 for #2129