diff --git a/bsip-0073.md b/bsip-0073.md new file mode 100644 index 0000000..b31e7b9 --- /dev/null +++ b/bsip-0073.md @@ -0,0 +1,271 @@ + BSIP: 0073 + Title: Match force-settlement orders with margin calls and limit orders + Author: Abit More + Status: Draft + Type: Protocol + Created: 2019-06-09 + Discussion: https://github.com/bitshares/bsips/issues/181 + Worker: TBD + +# Abstract + +This BSIP proposes a protocol change to improve user experience (UX) of +force-settlements by trying to fill force-settlement orders +(*settle orders* in short) at a better price +and optionally fill them before expiration when certain conditions are met. + +# Motivation + +Force-settlements were designed for debt asset holders to convert an amount +of the debt asset into corresponding collateral asset at a fair price *when +there is nobody willing to buy back the debt at a fair price*. + +To mitigate malious behavior and market manipulation, a *delay* and a *price +offset* were designed. But the mechanism has flaws. +* If a positive *offset* is configured in the debt asset's options, + force-settlement requesters will always "buy expensive" even when there are + orders "selling low". This also leads to occasional spikes in the market + history charts. +* Force-settlement requesters have to wait for the *delay* even when there + appear traders buying the debt asset at a fair price in the market. + +These flaws have led to certain confusion and anger among market participants. + +# Rationale + +Actually, when a margin call appears, it means there is somebody +willing to buy back the debt. Thus, it makes sense to fill the margin calls +with the settle orders. + +Similarly, if there are limit orders selling the debt asset +below the feed price, +it makes sense to match the limit orders with the settle orders as well. + +When one of these opportunities appears, it makes sense to fill certain +settle orders immediately if it's desired by the owners of the settle orders. + +These changes would improve user experience (UX). + +# Specifications + +## Hard fork + +Since this is a protocol change, a hard fork is needed. A time will need to be +scheduled for applying the change, which is commonly known as "hard fork time". +In this document, terms "before the hard fork", "at the hard fork" and +"after the hard fork" may or may not be used to indicate things happen before +the scheduled time, at the scheduled time and after the scheduled time. + +## `settle_order_object` + +The `settle_order_object` stores current status of a force-settlement order. + +A new field is needed within it: + +* `bool fill_asap;` + +By default this field is set to `false`, which means the order will be +processed after the *delay* defined in the asset's options, which is current +behavior. + +If this field is set to `true`, the order will be filled or partially filled +when a debt position enters margin call territory. It will also be filled or +partially filled when someone places a limit order selling the collateral +asset below the feed price. + +If multiple settle orders with this field as `true` exist in the market, +when filling before the *delay*, the order which was created first will be +filled first. + +## `asset_settle_operation` + +The `asset_settle_operation` is used to request a force-settlement. It has +an `extensions` field: + +* `extensions_type extensions;` + +The data type of this field needs to be overridden so that it can include the +new `fill_asap` option. + +## `asset_settle_evaluator` + +The `asset_settle_evaluator` is used to evaluate and apply the +`asset_settle_operation`. New logic is needed: +* only allow `fill_asap` option to be set after the hard fork; +* if the `fill_asap` option is specified in an `asset_settle_operation`, when + creating a `settle_order_object` (note: it implies some conditions are met, + E.G. the asset is not globally settled), assign the value of the operation's + `fill_asap` field to the object's `fill_asap` field. +* if the `fill_asap` option is set to `true`, and if the feed price is valid, + after creation of the settle order object, try to match it against the order + book immediately. In other words, treat it as a taker limit order buying + at the feed price. + +## `proposal_create_evaluator` + +The `proposal_create_evaluator` is used to evaluate and apply the +`proposal_create_operation`, which can contain zero or more +`asset_settle_operation` objects. New logic is needed: +* only allow `fill_asap` to be set after the hard fork. + +## Matching and filling settle orders whose `fill_asap` field is `true` + +### When a new limit order is created + +If the new limit order is selling the collateral asset for the debt asset, and +its price is below the feed price (which implies the feed price is valid), +* current logic is to only match it with the limit orders on the opposite side + of the market; +* after the hard fork, the new logic would be: + * firstly match it with the limit orders on the opposite side whose buy + prices are higher than the feed price; + * secondly match it with the settle orders whose `fill_asap` options were + set to `true`. The matching price would be the feed price. In other words, + treat the settle orders as maker limit orders buying at the feed price; + * lastly match it with remaining limit orders on the opposite side. + +### When a debt position enters margin call territory + +If a margin call order appears, either due to the feed price changing, or due +to the amount of collateral or the amount of debt changing (which implies the +feed price is valid), +* current logic is to only match it with the limit orders on the opposite + side of the market and conditionally trigger a black swan event; +* after the hard fork, the new logic would be: + * firstly match it with the limit orders on the opposite side whose buy + prices are higher than the feed price; if this step triggers a black swan + event, apply the corresponding black swan processing logic to the market; + * secondly match it with the settle orders whose `fill_asap` options were + set to `true`. The matching price would be the feed price. In other words, + treat the settle orders as maker limit orders buying at the feed price; + * lastly match it with remaining limit orders on the opposite side (which + would possibly trigger a black swan event as well, but it's out of this + document's scope). + +### When the feed price changes + +When the feed price changes, either due to a new price being published, or due +to an old price expiring, or due to the asset's options changing, if the new +feed price is valid, and if the new feed price in the direction of "X debt +asset per collateral asset" is higher than the old feed price or the old feed +price was invalid, +* current logic doesn't handle settle orders, +* after the hard fork, the new logic would be: + * if there are limit orders selling the collateral asset below the new feed + price, and there are settle orders whose `fill_asap` options were `true`, + match the settle orders with the limit orders. In other words, treat + those settle orders as taker limit orders buying at the new feed price. + +### Do not update `force_settled_volume` when filling the `fill_asap` orders + +When a settle order is filled or partially filled due to having the +`fill_asap` option set to `true`, +it doesn't affect `force_settled_volume` (which indicates how much of the debt +asset has been force-settled in the current maintenance interval). + +## Processing settle orders after the delay + +Currently, when filling a settle order after the delay (note: it implies +some conditions are met, E.G. the feed price is valid and total settled volume +in the current maintenance interval doesn't exceed the maximum allowed volume), +the settle order will be matched against the debt position with the least +collateral ratio, the fill price in the direction of "X debt asset +per collateral asset" would be +`fill_price = feed_price * (1 + foce_settlement_offset)`. + +After the hard fork, when processing a settle order after the delay, +* firstly try to match it with the margin calls and the limit orders selling + below `fill_price`. In other words, treat it as a taker limit order buying + at `fill_price`. + Note: this step doesn't affect `force_settled_volume`. +* if the settle order still exists, process it with the logic before the + hard fork. + Note: this step does affect `force_settled_volume` as before. + +## Logic related to BSIP 71 (Prevent Global Settlement) + +The behaviors proposed in this BSIP would be impacted by BSIP 71. + +In general, this BSIP proposes that +* the settle orders whose `fill_asap` field is `true` will be treated as + limit orders buying at feed price when the market engine processing + limit orders or margin calls, and +* when processing a settle order after the delay, it will "buy the way up" + before being matched with a debt position that need to apply + `force_settlement_offset`. + +## API + +APIs which return `settle_order_object` need to return the new `fill_asap` +field in the `settle_order_object`. + +APIs which return a combined order book can combine settle orders whose +`fill_asap` is true with the limit orders on the same side of the market. + +## CLI + +Currently there is a `settle_asset` command in CLI which can be used to +create force-settlement orders. After the hard fork, we need a command in +CLI for users to create force-settlement orders with the new `fill_asap` +option. + +One option is to add an optional boolean parameter to the parameter list of +the existing `settle_asset` command, if it doesn't break existing client +applications which rely on that wallet API. Otherwise, a new command is +needed, E.G. `settle_asset_ext`. + +## GUI/UX + +Note: GUI changes here are only suggestions, formally they're not part of the +specification. + +The new `fill_asap` option needs to be presented and can be used in GUI after +the hard fork. + +When there are settle orders with `fill_asap` option set to `true`, the UI +can show them +as special buy orders which are buying at the feed price in the order book. + +# Discussion + +* With this BSIP, we provided a tool that can be used by debt asset holders to +convert their debt asset holdings into corresponding collateral asset more +conveniently and flexibly. +However, it's not guaranteed that a settle order will be filled at a better +price if the owner choose to fill it "as soon as possible". Market paticipants +should always make their own decisions on whether to use the new tool. + +* From the perspective of the debt asset owners (note: "asset owners" and +"asset holders" have different meanings), for the performance of the debt +assets, it could be more desirable to execute force-settlements against margin +calls than against market orders, because it would improve the overall +collateral ratio of the asset (although it's in the price of worse experience +for force-settlement requesters). In that sense it contradicts the goals of +BSIP 71 (Prevent Global Settlement). + +* The proposed functionality is mostly convenience for users. Manual selling on +the market is (almost) always available when it would be used automatically +by this proposal (exception: new incoming limit orders). + +* The proposed functionality complicates the market engine and possibly the +`get_order_book` call (see [bitshares/bitshares-core#1958]( +https://github.com/bitshares/bitshares-core/issues/1958)). +It is probably harmful for performance in the long run, which is particularly +undesirable for functionality that can mostly be emulated client-side. + +# Non-Technical Summary + +When force-settling a SmartCoin, the user currently has to wait for the +*settlement delay* before her tokens are exchanged for the collateral asset. +This BSIP introduces a new flag that allows settlement requests to be matched +with market orders during the waiting period, potentially resulting in faster +settlement and a better price. + +# Copyright + +This document is placed in the public domain. + +# See Also + +* https://github.com/bitshares/bsips/issues/181 +* https://github.com/bitshares/bitshares-ui/issues/1711