QuantConnect / Lean

Lean Algorithmic Trading Engine by QuantConnect (Python, C#)
https://lean.io
Apache License 2.0
9.11k stars 3.15k forks source link

CryptoFuture Maintenance Margin #7604

Open ChengYen-Tang opened 8 months ago

ChengYen-Tang commented 8 months ago

Expected Behavior

The initial margin changes with leverage, but TotalMarginUsed is always the same. Is this correct?

Actual Behavior

self.AddCryptoFuture("BTCUSDT", leverage=1) image

self.AddCryptoFuture("BTCUSDT", leverage=10) image

Reproducing the Problem

# region imports
import datetime
from AlgorithmImports import *
# endregion

class Crypto(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2022, 5, 1)  # Set Start Date
        self.SetEndDate(2022, 5, 2)  # Set End Date
        self.SetTimeZone(TimeZones.Utc)

        self.SetAccountCurrency("USDT")
        self.SetCash("USDT", 1000)  # Set Strategy Cash

        self.SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin)
        self.AddCryptoFuture("BTCUSDT", leverage=1)

    def OnData(self, data: Slice):
        security = self.Securities["BTCUSDT"]
        quantity = 0.002
        # Create an InitialMarginParameters object
        parameter = InitialMarginParameters(security, quantity)

        # Get the initial margin requirement
        initial_margin = security.BuyingPowerModel.GetInitialMarginRequirement(parameter)

        # Print the initial margin requirement
        self.Debug(initial_margin.Value)
        self.MarketOrder("BTCUSDT", quantity)

        self.Debug(f"Initial margin: {initial_margin.Value}, TotalMarginUsed: {self.Portfolio.TotalMarginUsed}, MarginRemaining: {self.Portfolio.MarginRemaining}")

System Information

  1. Python
  2. quantconnect cloud

Checklist

Martin-Molinero commented 7 months ago

Hey @ChengYen-Tang!

The initial margin changes with leverage, but TotalMarginUsed is always the same. Is this correct?

Correct this is the documented behavior by binance, can find more information in the following links for the different futures types:

The Maintenance Margin is calculated based on your positions at different notional value tiers. This means that the Maintenance Margin is always calculated in the same way, regardless of what leverage you select.

https://www.binance.com/en/support/faq/leverage-and-margin-of-usd%E2%93%A2-m-futures-360033162192

Maintenance margin calculations are done via a “Tax Bracket” setup. This means that the maintenance margin is always calculated the same way, regardless of what leverage the trader selects. Moving from one bracket to another will not cause the earlier bracket to change its leverage.

https://www.binance.com/en/support/faq/leverage-and-margin-in-coin-margined-futures-contracts-be2c7d9d95b04a7e8044ed02dd7dfe5c

The Lean CryptoFutureMarginModel does allow reducing the default maintenance margin through it's constructor arguments maintenanceMarginRate & maintenanceAmount, ref https://github.com/QuantConnect/Lean/blob/master/Common/Securities/CryptoFuture/CryptoFutureMarginModel.cs

Related https://github.com/QuantConnect/Lean/issues/7589#issuecomment-1828426928

ChengYen-Tang commented 7 months ago

Hi @Martin-Molinero,

I think you misunderstood what Binance maintenance margin means. TotalMarginUsed has nothing to do with maintenance margin

image https://www.binance.com/en/support/faq/leverage-and-margin-of-usd%E2%93%A2-m-futures-360033162192

so If we choose Cross Margin, Binance will automatically close the position when TotalMarginUsed + MarginRemaining < maintenance margin

ChengYen-Tang commented 7 months ago

To be precise, when the used margin(All position) + unused margin < maintenance margin, the automatic closing event will be triggered.

Position margin(initial margin) will dynamic change as leverage is adjusted:

https://github.com/QuantConnect/Lean/assets/32535494/f94fcc64-0563-439a-a634-211a941608f7

used margin = initial margin + Unrealized PNL available margin = unused margin + Unrealized PNL

PNL: https://www.binance.com/en/support/faq/how-to-use-binance-futures-calculator-360036498511

Long = (Exit Price - Entry Price) Quantity Short = (Entry Price - Exit Price) Quantity

image

fishstoryyy commented 6 months ago

Hi @Martin-Molinero

It does seem that the Lean cryptofuture margin calculation does not match the actual behavior of Binance. This is critical because it impacts the calculation of buying power. Agree with @ChengYen-Tang above that

used margin = initial margin + Unrealized PNL available margin = unused margin + Unrealized PNL

In other words, once a position is opened with X leverage, the position margin (i.e. initial margin) (NOT the maintenance margin) associated with that position will be deducted from the available margin in one's futures account, reducing the buying power. Additionally, the exchanges also deduct the initial margin associated with the pending/unfilled orders from the available margin to reduce buying power. This doesn't seem to be reflected in Lean either. Thanks for your response in advance.

jhonabreul commented 5 months ago

I think this algorithm reproduces the issue. For crypto futures, the calculated available margin for an order is not accounting for the existing position when the order goes in the same direction. If leverage is 10, we should not be able to buy more after calling SetHoldings(symbol, 10).

image
jhonabreul commented 5 months ago

Thank you @fishstoryyy and @ChengYen-Tang

Indeed, Binance does deduct the intial margin for an open position from the avialable margin.

There is a difference between what Binance and Lean consider as "maintenance margin":

Potential solution: the Crypto Futures Margin Model should be modified so that the maintenance margin is the same as the initial margin requirement and the remaining margin method should consider the existing positions of the security being traded as well as other securities' positions.

Also, it could include the PNL as Binance does and is mentioned here:

used margin = initial margin + Unrealized PNL available margin = unused margin + Unrealized PNL

arodus commented 5 months ago

@jhonabreul

Potential solution: the Crypto Futures Margin Model should be modified so that the maintenance margin is the same as the initial margin requirement Wouldn't this result in margin calls being executed when backtesting? As the initial margin used can reach 100% and can even be above that in some cases without the positions being liquidated.