diff --git a/bsip-0033.md b/bsip-0033.md new file mode 100644 index 0000000..4fe4e4b --- /dev/null +++ b/bsip-0033.md @@ -0,0 +1,136 @@ + BSIP: 0033 + Title: Maker Orders With Better Prices Take Precedence + Author: Abit More + Status: Draft + 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: To be done + +# Abstract + +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. + +# Motivation + +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](https://github.com/bitshares/bitshares-core/issues/625) and other +threads. + +Another scenario is described in [Bitshares-core +issue #453](https://github.com/bitshares/bitshares-core/issues/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. + +# Rationale + +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`. +Note: `feed_price` here is in terms of debt/collateral, aka "how much debt per +collateral". + +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 + + +# Specifications + +## Matching a taker limit order + +New limit order is being processed in `apply_order(...)` function of `database` +class. + +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: +1. 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 `2` which means the new order is completely filled; +2. if reach the end (MSSP), which means the new order is still unfilled, + call `check_call_orders(..)` function or an equivalent; +3. check if `new_order_object` still exist, if yes, redo step one but set the + maximum possible price of the market as end price. + +## Matching taker margin call orders + +For [bitshares-core +issue #453](https://github.com/bitshares/bitshares-core/issues/453), +in `check_call_orders(...)` function of `database` class, +iterator `limit_itr` will move forward when variable `filled_limit` is `true`. +`filled_limit` will be set to `true` when a limit order get completely filled. +However, since `filled_limit` is declared out of the `while` block, +it doesn't get reset to `false` after `limit_itr` moved forward. That means +after the first limit order get completedly filled, `filled_limit` will always +be `true`, so `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. + +# Discussion + +[to be added if any] + +# Summary for Shareholders + +[to be added if any] + +# Copyright + +This document is placed in the public domain. + +# See Also + +* https://github.com/bitshares/bitshares-core/issues/625 +* https://github.com/bitshares/bitshares-core/issues/453 +* https://bitsharestalk.org/index.php?topic=25926.0