QuantConnect / Lean

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

Wrong margin information when using Bybit #7816

Open arodus opened 5 months ago

arodus commented 5 months ago

It seems like the margin calculation(s) and therefore the order size calculation is not correct. I'm not sure if it also affects other crypto exchanges but it's true for Bybit. There are two factors which come into play:

  1. The CryptoFutureMarginModel uses 5% as a default margin rate, while for bybit the base rate is 0.5%. This can be manually changed in the algorithm but it still would be good to have it as a default.
  2. QC is using the available margin based on the used maintenance margin for calculating position sizes. While bybit isn't using the MM for position size changes but instead the available initial margin (which is based on the position entry price)

Expected Behavior

The available Initial Margin should be used for order size calculations instead of the available maintenance margin. This screenshot represents approximately the same state as the algorithm below (The entry price differs by 1k but it doesn't change that much). You can see that the initial margin is 70% utilized while the maintenance margin is only at 5% utilization. As the MM is made available and is used for order size calculations. image

Actual Behavior

2024-02-14 19:00:00 MR: 957.0000 MU: 0 Portfolio: 957.0000 Holdings: 0 IMU: 0 IMR: 957.0000
OrderID: 1 EventID: 1 Symbol: BTCUSDT Status: Submitted Quantity: 0.146
OrderID: 1 EventID: 2 Symbol: BTCUSDT Status: Filled Quantity: 0.146 FillQuantity: 0.146 FillPrice: ₮51821.8 OrderFee: 4.16129054 USDT
2024-02-14 19:00:00 Holding info: Cost: 7565.9828 Value: 7565.9828 Quantity: 0.146
2024-02-14 19:00:00 MR: 910.84750492 MU: 37.8299140 Portfolio: 948.67741892 Holdings: 7565.9828 IMU: 756.59828 IMR: 192.07913892
2024-02-15 19:00:00 MR: 922.81113620 MU: 37.8900660 Portfolio: 960.70120220 Holdings: 7578.0132 IMU: 756.59828 IMR: 204.10292220
2024-02-16 19:00:00 MR: 922.81113620 MU: 37.8900660 Portfolio: 960.70120220 Holdings: 7578.0132 IMU: 756.59828 IMR: 204.10292220
2024-02-17 19:00:00 MR: 922.81113620 MU: 37.8900660 Portfolio: 960.70120220 Holdings: 7578.0132 IMU: 756.59828 IMR: 204.10292220

The margin calculation in this log is already correct due to manually setting the BuyingPowerModel with a margin rate of 0.5% but the margin available is "wrong". For ByBit

Reproducing the Problem

public class Example : QCAlgorithm
{

    private CryptoFuture _btc;

    public override void Initialize()
    {
        SetStartDate(2024, 02, 14); // Set Start Date
        SetEndDate(2024, 02, 16); // Set End Date
        SetBrokerageModel(new BybitBrokerageModel(AccountType.Margin));

        SetAccountCurrency("USDT", 957);

        // On bybit the base margin rate is 0.5% compared to the 5% which is set as the default in the CryptoFutureMarginModel
        _btc = AddCryptoFuture("BTCUSDT", Resolution.Daily, Market.Bybit, leverage: 10);
        _btc.SetBuyingPowerModel(new CryptoFutureMarginModel(10, 0.005m));

    }

    public override void OnData(Slice data)
    {
        if (!Portfolio.Invested)
        {
            PrintInfo();
            var order = MarketOrder(_btc.Symbol, 0.146m);
            Log($"Holding info: Cost: {_btc.Holdings.HoldingsCost} Value: {_btc.Holdings.HoldingsValue} Quantity: {_btc.Holdings.Quantity}");
        }
        PrintInfo();
    }

    private void PrintInfo()
    {
        Portfolio.LogMarginInformation();
        Log($"MR: {Portfolio.MarginRemaining} MU: {Portfolio.TotalMarginUsed} Portfolio: {Portfolio.TotalPortfolioValue} Holdings: {Portfolio.TotalHoldingsValue} IMU: {InitialMarginUsed()} IMR: {Portfolio.TotalPortfolioValue - InitialMarginUsed()}");
    }

    private decimal InitialMarginUsed()
    { var reserved = 0m;
        foreach (var (_,security) in Portfolio.Securities)
        {
            if(!security.Invested) continue;
            reserved +=  (security.QuoteCurrency.ConversionRate * security.SymbolProperties.ContractMultiplier * security.Holdings.AveragePrice * security.Holdings.AbsoluteQuantity * 0.1m);
        }

        return reserved;

    }

System Information

n/a

Checklist

Martin-Molinero commented 5 months ago

Probably related to https://github.com/QuantConnect/Lean/issues/7604 too

arodus commented 5 months ago

Ahhh... must have missed that issue, thanks @Martin-Molinero