diff --git a/Common/Securities/CryptoFuture/CryptoFuture.cs b/Common/Securities/CryptoFuture/CryptoFuture.cs
index 65e473dd1475..832c5439837d 100644
--- a/Common/Securities/CryptoFuture/CryptoFuture.cs
+++ b/Common/Securities/CryptoFuture/CryptoFuture.cs
@@ -60,7 +60,7 @@ public CryptoFuture(Symbol symbol,
cache,
new SecurityPortfolioModel(),
new ImmediateFillModel(),
- IsCryptoCoinFuture(quoteCurrency.Symbol) ? new BinanceCoinFuturesFeeModel() : new BinanceFuturesFeeModel(),
+ IsCryptoCoinFuture(symbol.ID.Market, quoteCurrency.Symbol) ? new BinanceCoinFuturesFeeModel() : new BinanceFuturesFeeModel(),
NullSlippageModel.Instance,
new ImmediateSettlementModel(),
Securities.VolatilityModel.Null,
@@ -83,16 +83,26 @@ public CryptoFuture(Symbol symbol,
/// True if the security is a crypto coin future
public bool IsCryptoCoinFuture()
{
- return IsCryptoCoinFuture(QuoteCurrency.Symbol);
+ return IsCryptoCoinFuture(Symbol.ID.Market, QuoteCurrency.Symbol);
}
///
/// Checks whether the security is a crypto coin future
///
+ /// The security market
/// The security quote currency
/// True if the security is a crypto coin future
- private static bool IsCryptoCoinFuture(string quoteCurrency)
+ private static bool IsCryptoCoinFuture(string market, string quoteCurrency)
{
+ // Binance coin-margined futures are nominally quoted in USD (e.g. BTCUSD_PERP) but settle in the base
+ // currency, so on Binance any quote currency other than one of its known USD-pegged stablecoins implies
+ // a coin-margined contract. Other venues, notably EU MiCA-compliant exchanges, quote linear (USD-margined)
+ // futures directly in fiat USD, so outside of Binance the quote currency alone can't be used this way.
+ if (market != Market.Binance)
+ {
+ return false;
+ }
+
return quoteCurrency != "USDT" && quoteCurrency != "BUSD" && quoteCurrency != "USDC";
}
diff --git a/Tests/Common/Securities/CryptoFuture/CryptoFutureMarginModelTests.cs b/Tests/Common/Securities/CryptoFuture/CryptoFutureMarginModelTests.cs
index 2f3d8cc246fb..330fbf401051 100644
--- a/Tests/Common/Securities/CryptoFuture/CryptoFutureMarginModelTests.cs
+++ b/Tests/Common/Securities/CryptoFuture/CryptoFutureMarginModelTests.cs
@@ -207,6 +207,42 @@ public void DefaultMarginModelDoesNotIncludeSupplementaryCollateral()
Assert.AreEqual(0, buyingPower.Value);
}
+ [Test]
+ public void BinanceUsdQuotedFutureIsCoinMargined()
+ {
+ var symbol = Symbol.Create("BTCUSD", SecurityType.CryptoFuture, Market.Binance);
+ var cryptoFuture = new QuantConnect.Securities.CryptoFuture.CryptoFuture(
+ symbol,
+ SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork),
+ new Cash("USD", 0, 1m),
+ new Cash("BTC", 0, 1m),
+ SymbolProperties.GetDefault("USD"),
+ ErrorCurrencyConverter.Instance,
+ RegisteredSecurityDataTypesProvider.Null,
+ new SecurityCache());
+
+ Assert.IsTrue(cryptoFuture.IsCryptoCoinFuture());
+ }
+
+ [Test]
+ public void NonBinanceUsdQuotedFutureIsNotCoinMargined()
+ {
+ // EU MiCA-compliant exchanges (e.g. Kraken Futures, OKX EU) quote linear, USD-margined
+ // futures directly in fiat USD rather than a stablecoin.
+ var symbol = Symbol.Create("BTCUSD", SecurityType.CryptoFuture, Market.Kraken);
+ var cryptoFuture = new QuantConnect.Securities.CryptoFuture.CryptoFuture(
+ symbol,
+ SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork),
+ new Cash("USD", 0, 1m),
+ new Cash("BTC", 0, 1m),
+ SymbolProperties.GetDefault("USD"),
+ ErrorCurrencyConverter.Instance,
+ RegisteredSecurityDataTypesProvider.Null,
+ new SecurityCache());
+
+ Assert.IsFalse(cryptoFuture.IsCryptoCoinFuture());
+ }
+
private static QCAlgorithm GetAlgorithm()
{
// Initialize algorithm