Fetching contributors…
Cannot retrieve contributors at this time
349 lines (258 sloc) 14.1 KB
BSIP: 0038
Title: Add target collateral ratio option to short positions
Author: Abit More <>
Status: Installed
Type: Protocol
Created: 2018-03-05
Replaces: 0035 (partly)
Worker: 1.14.100


When a short position is margin called, some of its collateral will be sold and some or all of its debt will be covered accordingly.

However, usually more collateral will be sold, in comparison to the minimum amount required to be sold to maintain the maintenance collateral ratio (MCR) requirement.

This BSIP proposes a protocol change to let shortes (borrowers) have control over selling how much collateral when being margin called.

This BSIP depends on BSIP 31.


As discussed in this forum post, current process gives manipulators big chance to short BTS and make money and increase the risk of black swan, thus hurts the BTS ecosystem. Many participants in the discussion agree that usually it's not really required to cover all debt (thus selling more collateral) when being margin called.

After BSIP 31 is in place, shorters will have more chance to not cover all debt on margin call, but it's not 100% guaranteed, and they can only accept the result passively.


Different shorters have different expectations when being margin called:

  • some want to close their short positions completely to cut losses;
  • some want to sell as little collateral as possible to keep remaining short positions as large as possible;
  • some want to sell more than minimum required collateral to reduce the possibility of being margin called again in the near future, but don't want to close their short positions completely.

With a new "target collateral ratio" option, all these expectations can be met.

In sections below, both a "margin call order" and a "call order" mean a short position in margin call territory.

The Definition of Target Collateral Ratio

For reference purpose, the collateral ratio of any given debt/short position describes the ratio between the available collateral (e.g. core toke BTS) to the debt that is owed (e.g. CNY, etc.) by the original borrower to the blockchain. It is defined to be a dimensionless value as CR = collateral / (debt / feed_price) where the price is measured in units of the debt asset / units of the collateral asset (e.g. CNY / BTS).

"Target collateral ratio" is an optional value which can be set onto a short position, when the position being automatically liquidized (margin called), sell no more than required collateral until collateral ratio of the position is higher than this value.

  • Default value: not set, which means to sell as much collateral as possible, which is same to current behavior.
  • When the value is set but below MCR, use MCR.
  • When matching a margin call order with a force settle order, ignore this option.
  • When checking for black swan or globally settling, ignore this option.

Why to use "higher than" but not "equal to", is due to an existing rule: if a short position's collateral ratio is equal to MCR, it will still be margin called.

The Math

Let prices described below be in terms of debt / collateral, e.g. how much CNY per BTS.

A margin call order can be matched with a limit order as either maker or taker, in any case, there would be a matching price. We can solve an equation as follows:

target_CR = new_collateral / ( new_debt / feed_price )
          = ( collateral - max_amount_to_sell ) * feed_price
            / ( debt - amount_to_get )
          = ( collateral - max_amount_to_sell ) * feed_price
            / ( debt - max_amount_to_sell * match_price )
max_amount_to_sell = (debt * target_CR - collateral * feed_price)
                     / (target_CR * match_price - feed_price)

The result is a rational number.

Then, the maximum debt it wants to cover can be calculated as:

max_debt_to_cover = max_amount_to_sell * match_price

The result is a rational number as well.

Rounding on Maximums Calculation

As described in BSIP 35, at last we need to convert the rational numbers to integers, so rounding is involved.

The first round

When calculating maximum debt to cover, the goal is to go over the specified target but not go too far beyond. That said, if a short position got matched with a big limit order, after partially filled, its collateral ratio should be just higher than specified target collateral ratio.

We may calculate like this: if max_debt_to_cover has no fractional component (e.g. 5.00 as opposed to 5.23), plus it by one Satoshi; otherwise, round it up. An effectively same approach is to round down then add one Satoshi onto the result:

max_debt_to_cover_int = round_down(max_debt_to_cover) + 1

With max_debt_to_cover_int in integer, max_amount_to_sell_int in integer can be calculated as:

max_amount_to_sell_int = round_up(max_debt_to_cover_int / match_price)

It's worth noting that we need to make sure the 2 integers always pair perfectly, they're either the full collateral amount and full debt amount, or have:

max_amount_to_sell_int == round_up(max_debt_to_cover_int / match_price)
max_debt_to_cover_int  == round_down(max_amount_to_sell_int * match_price)

For max_amount_to_sell_int above, we can adjust max_debt_to_cover_int with:

max_debt_to_cover_int = round_down(max_amount_to_sell_int * match_price)

Review the result

Due to rounding, it's not guaranteed that selling more collateral will always result in higher collateral ratio on remaining call order.

On one hand, it's not guaranteed that the pair of integers above will meet the requirements: after covered max_debt_to_cover_int, it's possible that collateral ratio of remaining order is still not higher than MCR or target_CR. In this case, the result is not acceptable. Generally, if we search upwards, we can find a new pair that meets the requirements, or hit the order's collateral or debt amount.

On the other hand, no matter if the pair above meets the collateral ratio requirement, it's possible that there exists a smaller pair which meets the requirement. However, it's not easy to find a perfect pair. If we search downwards, it's not easy to decide when to stop; if we start from a smaller pair then search upwards, it's not easy to decide where to start.

Favor performance over accuracy

Due to the difficulty mentioned above, in this BSIP we allow imperfect results, and don't describe or enforce how exactly to find better results.

The first implementation should be made with efforts. It will become consensus after approved by stake holders via voting. It will then be in effect until changed or replaced with a new BSIP.

Here are some guidelines about implementation.

When searching upwards, usually the real working pair is not far away, but it's not guaranteed due to rounding. For better performance, it's not good to search by adding one Satoshi every time. Can use a divergence sequence or other sublinear-time algorithm, that means it's possible that some good data will be skipped which may result in impefect result.

Rounding on Order Matching, and Edge Cases

Rounding rules about order matching are defined in BSIP 35.

Generally, when two orders got matched, the order matching engine will favor the larger order while rounding.

When a call order got matched with a limit order, if the call order has no target_CR option set but its debt is more than the limit order offered, or the call order has target_CR option set but max_debt_to_cover_int is more than the limit order offered, both means the call order is larger, according to the rounding rule, the call order's paid collateral will be rounded down, so its collateral ratio will increase after partially filled.

If the call order has target_CR option set and is covering the whole "maximum debt to cover", to be fair, we should consider that part of call order to be smaller and favor the limit order while rounding, otherwise the limit order may suffer an overall loss. That means the call order will be partially filled and its paid collateral will be rounded up, in this case, if the call order's collateral ratio was not too low, usually, partially filling will still lead to an increase in collateral ratio.

However, there are edge cases: if the call order's collateral ratio is already low, or its debt or collateral amount is tiny, rounding up paid collateral on partially filling will probably lead to a decrease in collateral ratio, in an extreme case it may even lead to a black swan event. This is against the intention of this BSIP. To solve this issue, if detected a decrease in collateral ratio when matching, we propose to ignore the target_CR option of corresponding call order, and re-evaluate the match.

The Revised Rounding Rules on Order Matching

So the rule for matching a limit order with a call order will be revised as follows with new rules in bold:

  • if the call order is receiving the whole debt amount, which means it's smaller and the short position will be closed after the match, round up its paying amount;
  • otherwise,
    • if the call order has target_collateral_ratio set and is receiving the maximum debt amount calculated with target_collateral_ratio, see the call order as smaller, try to round up its paying amount;
      • for edge cases, if the call order's collateral ratio would not increase after being partially filled due to the round-up (which may even cause a black swan event in an extreme scenario), see its target_collateral_ratio as "not set" for this time, re-apply the filling rules for this match.
    • otherwise, the call order is larger, round down its paying amount.
      • if the limit order would receive nothing, cancel it (it's smaller, so safe to cancel);
      • otherwise, calculate the amount that the limit order would pay as round_up(receiving_amount * match_price). After filled both orders, if the limit order still exists, the remaining amount might be too small, so cancel it.

When and How To Use the Option

The target_collateral_ratio option can to be set, updated or cleared when creating or updating a short position. When doing so, other rules still apply, E.G. can't update a short position to have too small collateral ratio.

For one account, different short positions (for different assets) can be set with different target_collateral_ratio.

For one short position,

  • if want to close it completely to cut losses when being margin called,

    • don't set or clear target_collateral_ratio option, because the option is optional so can be unset or cleared;
  • if want to sell as little collateral as possible when being margin called, to keep the remaining short position as large as possible,

    • set target_collateral_ratio to MCR or less;
  • if want to sell more than minimum required collateral when being margin called, to reduce the possibility of being margin called again in the near future, but don't want to completely close the short position,

    • set target_collateral_ratio to a value higher than MCR, E.G. 300%. The higher the value is, the more collateral will be listed for sale when it's margin called.



The call_order_object stores current status of a short position.

Need to add a new field into it:

  • optional<uint16_t> target_collateral_ratio;

Same to other collateral ratios, the actual ratio is the value divided by GRAPHENE_COLLATERAL_RATIO_DENOM aka 1000.

Due to the uint16_t data type, the new field's maximum value is 65535, which means 6553.5%.


The call_order_update_operation is used to open, update and close short positions. It contains an extensions field:

  • extensions_type extensions;

Need to override data type of this field so it can include the new "target collateral ratio" option.


The call_order_update_evaluator is used to evaluate and apply the call_order_udpate_operation. Need to add logic:

  • only allow target_collateral_ratio to be set after the hard fork;
  • set/update/clear target_collateral_ratio field of call_order_object accordingly. Specifically,
    • set or update the field if it presents in the operation and is valid,
    • clear the field if it doesn't present in the operation or is not valid.


The proposal_create_evaluator is used to evaluate and apply the proposal_create_operation, which can contain zero or more call_order_udpate_operation objects. Need to add logic:

  • only allow target_collateral_ratio to be set after the hard fork.

Call Order Matching and Filling

After a call order get matched with a limit order and about to fill,

  • if target_collateral_ratio is not set, process as before;
  • if target_collateral_ratio is set, compare it to MCR, use the bigger one (aka max(target_collateral_ratio,MCR)) to calculate maximum amount of debt to cover according to the equation described above, and apply the revised rounding rules, then process other logic as before.


The new option need to be presented and can be used in UI after the hard fork.

When there are call orders to be filled, if target_collateral_ratio option is set, UI need to show exact amount of collateral that another trader is able to buy and exact amount of debt that need to pay according to the equation described above. Note that this calculation will need to use the current feed_price.


With this BSIP, we provided a tool that can be used by shorters to keep their positions, however, it's not always the best strategy to keep as large position as possible, sometimes it's even more risky than just cutting losses. Nevertheless, how to use the tool, is up to the traders to decide.

Summary for Shareholders

"This is how it should work."


This document is placed in the public domain.

See Also