Skip to content

CryptoFuture.IsCryptoCoinFuture() incorrectly classifies USD-quoted linear futures as coin-margined, breaking EU MiCA-compliant exchanges #9574

Description

@ypsik

CryptoFuture.IsCryptoCoinFuture() hardcodes a whitelist of quote currencies (USDT, BUSD, USDC) to distinguish linear from coin-margined futures. This breaks any exchange that quotes linear perpetual futures in USD instead of USDT — which is exactly the case for EU MiCA-regulated exchanges.

Background / Regulatory Context

Under EU MiCA, compliant exchanges are restricted from offering stablecoins such as USDT or USDC as settlement currencies for derivatives — only fiat currencies are permitted. As a result, exchanges such as Kraken Futures and OKX EU quote their linear perpetual futures in USD (fiat) rather than USDT or USDC. Binance and Bybit have already withdrawn from EU futures markets due to MiCA compliance requirements, so going forward, any EU-compliant futures exchange will always quote in fiat USD — making this a structural blocker for EU exchange integration.

I have been implementing community brokerage connectors for Kraken Futures and OKX EU. This bug in LEAN core is a hard blocker that prevents me from proceeding with either connector.

Root Cause

In Common/Securities/CryptoFuture/CryptoFuture.cs:

private static bool IsCryptoCoinFuture(string quoteCurrency)
{
    return quoteCurrency != "USDT" && quoteCurrency != "BUSD" && quoteCurrency != "USDC";
}

This method assumes only USDT/BUSD/USDC-quoted futures are linear. Any fiat USD-quoted future is incorrectly classified as coin-margined/inverse, regardless of its actual contract type. This affects:

  • CryptoFutureHolding.GetQuantityValue()HoldingsValue and UnrealizedProfit use the inverse formula (quantity / price in base currency instead of price * quantity in quote currency), producing a value equal to Quantity instead of the correct notional USD value.
  • CryptoFutureMarginModel.GetCollateralCash() → collateral is incorrectly attributed to base currency (e.g. XBT) instead of quote currency (USD), breaking margin calculations.
  • SecurityPortfolioManager.TotalPortfolioValue → completely wrong, causing incorrect position sizing in live trading.

Impact

  • TotalPortfolioValue shows a BTC position as worth 2.8 USD instead of ~163,000 USD.
  • Position sizing is off by a factor equal to the current BTC price.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions