Generate code in 3 minutes
Enter your idea and AI generates runnable code.
In QuantConnect, SPAN (Standard Portfolio Analysis of Risk) margining is enabled by default for Futures. The LEAN engine automatically sources CME SPAN margin data to model buying power and margin requirements for supported futures contracts.
You do not need to implement the SPAN logic manually. Instead, you simply add the Future security, and the BuyingPowerModel attached to that security will utilize the historical SPAN margin data available in the LEAN data library.
Below is a complete algorithm demonstrating how to trade Futures with SPAN margining and how to programmatically check the margin requirements before placing a trade.
# region imports
from AlgorithmImports import *
# endregion
class SpanMarginingExampleAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2023, 1, 1)
self.set_end_date(2023, 6, 1)
self.set_cash(100000)
# 1. Add the Future.
# LEAN automatically attaches a FutureMarginModel which uses SPAN data.
self._future = self.add_future(
Futures.Indices.SP_500_E_MINI,
Resolution.MINUTE,
data_normalization_mode=DataNormalizationMode.RAW
)
# Filter for contracts expiring within 90 days
self._future.set_filter(0, 90)
self._contract_symbol = None
def on_data(self, slice: Slice):
# Wait for the chain to populate
if self._contract_symbol is None:
for chain in slice.future_chains:
# Select the front month contract
contracts = list(chain.value)
if len(contracts) == 0:
continue
self._contract_symbol = sorted(contracts, key=lambda x: x.expiry)[0].symbol
return
# Ensure we have data for the specific contract
if not slice.contains_key(self._contract_symbol):
return
# Simple logic: Buy if not invested
if not self.portfolio.invested:
# 2. Check SPAN Margin Requirements before trading
# We can query the Buying Power Model to see the required margin for 1 contract
security = self.securities[self._contract_symbol]
# Create parameters for 1 unit (Long)
# InitialMarginParameters(security, quantity)
margin_params = InitialMarginParameters(security, 1)
# Get the requirement
margin_req = security.buying_power_model.get_initial_margin_requirement(margin_params)
self.log(f"Contract: {self._contract_symbol}")
self.log(f"Price: {security.price}")
self.log(f"SPAN Initial Margin Requirement (1 contract): ${margin_req.value}")
# Check if we have enough available buying power
if self.portfolio.margin_remaining > margin_req.value:
self.market_order(self._contract_symbol, 1)
else:
self.log("Insufficient margin to place trade.")
def on_securities_changed(self, changes: SecurityChanges):
# Handle contract rollovers or expirations here if necessary
for removed in changes.removed_securities:
if removed.symbol == self._contract_symbol:
self.liquidate(removed.symbol)
self._contract_symbol = None
self.add_future(...), LEAN assigns the FutureMarginModel. This model looks up the historical SPAN margin requirements provided by the data feed (e.g., CME data) for the specific date and contract.security.buying_power_model.get_initial_margin_requirement(parameters). This is useful for dynamic position sizing based on actual risk rather than notional value.Q: Do I need to import a specific library to calculate SPAN?
A: No. The LEAN engine handles the calculation internally using its data libraries. You only need to add the Future security using add_future.
Q: Does this work for all Futures contracts?
A: It works for major futures contracts supported by QuantConnect (e.g., CME, CBOT, NYMEX, COMEX) where margin data is available in the data library.
Q: Can I override the SPAN margin with a custom fixed margin?
A: Yes. If you want to simulate a brokerage that offers fixed intraday margins (e.g., $500 per contract), you can set a custom buying power model:
self.securities[symbol].set_buying_power_model(SecurityMarginModel(30.0)) # 30x leverage
However, for accurate backtesting of institutional strategies, keeping the default SPAN model is recommended.
Q: How does the algorithm handle margin calls with SPAN?
A: If your portfolio equity drops below the Maintenance Margin (derived from SPAN data), LEAN triggers a margin call. You can manage this via the on_margin_call_warning and on_margin_call event handlers.