BSIP: 0033 Title: Maker Orders With Better Prices Take Precedence Author: Abit More <https://github.com/abitmore> Status: Installed Type: Protocol Created: 2018-02-17 Discussion: https://github.com/bitshares/bitshares-core/issues/625, https://github.com/bitshares/bitshares-core/issues/453 Replaces: - Worker: 1.14.94
Currently, in BitShares, under certian circumstances, a taker order may be matched with a maker order which is not "on the top" of the order book. This behavior is unexpected and irritating for users.
This BSIP proposes a principle: always match taker orders with maker orders with the best prices (aka on the top of the order book) first.
As expected, when matching taker limit orders with maker limit orders, the maker limit orders with better prices will always be matched first.
For example, if trader A has a limit order selling 100 BTS at 0.1 USD per BTS, trader B has a limit order selling 100 BTS at 0.09 USD per BTS, which means B's limit order has a better price for the opposite side to buy. Now if trader C placed an order that buys 10 BTS at 0.105 USD per BTS, B's limit order will take precedence, A's limit order won't be matched.
However, when there are (maker) margin call orders in the market which have met the requirements that to be matched (able to be margin called), they always take precedence over the (maker) limit orders on the same side, no matter whether the limit orders provided better price.
For example, if trader A's margin call order is selling 100 BTS at no less than 0.1 USD per BTS, trader B has a limit order selling 100 BTS at 0.09 USD per BTS, which means B's limit order has a better price for the opposite side to buy. Now if trader C placed an order that buys 10 BTS at 0.105 USD per BTS, A's margin call order will take precedence, B's limit order won't be matched. That means C is forced to "buy high" when have chance to "buy low", which is unexpected.
Users have been confused by this behavior, as discussed in bitshares-core issue #625 and other threads.
Another scenario is described in Bitshares-core issue #453 that sometimes a taker margin call order may be matched with a maker limit order which is not on the top of the order book. This can be seen as a bug.
Always matching taker order (e.g. a buy) with a maker order which offered best price (aka lowest ask), is a simpler rule which most users would understand easily.
There is a parameter in price feed named MSSR, which stands for "maximum short
squeeze ratio". Maker price of margin call orders is MSSP, which stands for
"maximum short squeeze price", is calculated as
feed_price / MSSR.
feed_price here is in terms of debt/collateral, aka "how much debt per
That said, the price that margin call orders are offering is MSSP. The prices those limit orders are offering are the limit prices.
When placing a limit (e.g. buy) order with a price beyond the lowest sell, the order is expected to "walk the book", matching each order on the opposite side in turn, at that order's price, until the new limit order is completely filled, or there is no more sell order matching its price.
To meet the expectation,
- firstly, we need to match the limit buy order with the limit sell orders whose prices are lower than MSSP and prices can match the new order;
- then, if the new limit buy order hasn't been completely filled, match it with the margin calls if MSSP can match the new order's price;
- then, if the new limit buy order still hasn't been completely filled, match it with the rest sell orders until it's completely filled or no more sell order matching its price
Matching a taker limit order
New limit order is being processed in
apply_order(...) function of
Currently, in the function, firstly call orders will be checked and matched. After that, limit orders on the opposite side will be checked and matched.
Need to change the logic to:
- firstly, sort the limit orders on the opposite by
price, best price first, end at MSSP; check them one by one, calls
match(...)function until the return value is not
2which means the new order is completely filled;
- if reach the end (MSSP), which means the new order is still unfilled,
check_call_orders(..)function or an equivalent;
- check if
new_order_objectstill exist, if yes, redo step one but set the maximum possible price of the market as end price.
Matching taker margin call orders
check_call_orders(...) function of
limit_itr will move forward when variable
filled_limit will be set to
true when a limit order get completely filled.
filled_limit is declared out of the
it doesn't get reset to
limit_itr moved forward. That means
after the first limit order get completedly filled,
filled_limit will always
limit_itr will always move forward no matter whether current
limit order got completedly filled, so a taker call order may match
with a limit order that is not on the top of the order book.
To fix this, need to change the code to make sure
limit_itr always references
the limit order on the top of the order book when dereferencing.
[to be added if any]
Summary for Shareholders
[to be added if any]
This document is placed in the public domain.