CFD
Requesting Data
Introduction
Request Contract for Difference (CFD) data in your algorithm to receive a feed of contract prices in the on_data
method. QuantConnect supports CFD trading with OANDA and Interactive Brokers.
OANDA Subscriptions
To create a CFD subscription, in the initialize
method, call the add_cfd
method. The add_cfd
method returns a Cfd
Security object, which contains a symbol
property. Save a reference to the symbol
so you can use it in on_data
to access the security data in the Slice
.
self._symbol = self.add_cfd("XAUUSD").symbol
To view the supported CFD contracts, see Supported Assets. For more information about the specific dataset we use for backtests, see the OANDA CFD dataset listing. To trade OANDA CFDs live, use our QuantConnect data provider.
Interactive Brokers Subscriptions
To create a CFD subscription for Interactive Brokers (IB), in the initialize
method, call the add_cfd
method and set the market
parameter to Market.INTERACTIVE_BROKERS
. The add_cfd
method returns a Cfd
Security object, which contains a symbol
property. Save a reference to the symbol
so you can use it in on_data
to access the security data in the Slice
.
self._symbol = self.add_cfd("SPY", market=Market.INTERACTIVE_BROKERS).symbol
Historical data for backtesting IB CFDs is unavailable.
In live trading, include the Interactive Brokers data provider when you deploy the algorithm to access IB CFD data. You can use this data provider for paper or real-money accounts. IB provides data for Indexes, Metals, Forex, and Global Stock CFDs. To view the Index and Forex CFD products that IB supports in live trading, see the Interactive Brokers Supported Contracts. To view the Equity CFD products, see the Products Search page on the IB website.
If you live in the EU and can't trade US ETFs due to regulation, you can trade their CFD equivalents in live mode.
security_type = SecurityType.CFD if self.live_mode else SecurityType.EQUITY market=Market.INTERACTIVE_BROKERS if self.live_mode else Market.USA self._symbol = Symbol.create("SPY", security_type, market) self.add_security(self._symbol)
Resolutions
The following table shows the available resolutions and data formats for CFD subscriptions:
Resolution | TradeBar | QuoteBar | Trade Tick | Quote Tick |
---|---|---|---|---|
TICK | ![]() | |||
SECOND | ![]() | |||
MINUTE | ![]() | |||
HOUR | ![]() | |||
DAILY | ![]() |
The default resolution for CFD subscriptions is Resolution.MINUTE
. To change the resolution, pass a resolution
argument to the add_cfd
method.
self._symbol = self.add_cfd("XAUUSD", Resolution.DAILY).symbol
To create custom resolution periods, see Consolidating Data.
Fill Forward
Fill forward means if there is no data point for the current slice, LEAN uses the previous data point. Fill forward is the default data setting. If you disable fill forward, you may get stale fills or you may see trade volume as zero.
To disable fill forward for a security, set the fill_forward
argument to false when you create the security subscription.
self._symbol = self.add_cfd("XAUUSD", fill_forward=False).symbol
Margin and Leverage
LEAN models buying power and margin calls to ensure your algorithm stays within the margin requirements. The specific margin available depends on your brokerage destination. To change the amount of leverage you can use for a CFD contract, pass a leverage
argument to the add_cfd
method.
self._symbol = self.add_cfd("XAUUSD", leverage=35).symbol
Data Normalization
The data normalization mode doesn't affect the data that LEAN passes to on_data
or the data from history request. If you change the data normalization mode, it won't change the outcome.
Interactive Brokers Stock CFDs apply corporate actions to the price of the asset, including paying dividends in cash to your account. This behavior is not modeled today and splits in live trading will result in price discontinuities. You should monitor the underlying Equity for events and use the underlying Equity for indicators.
Examples
The following examples demonstrate some common practices for requesting CFD data.
Example 1: SMA Crossing
The following strategy purchases ETFs when their fast-moving average crosses over the slow-moving average. In live mode, the strategy purchases their CFD equivalents.
class EtfCfdSwapMovingAverageCrossAlgorithm(QCAlgorithm): def initialize(self) -> None: self.set_start_date(2022, 9, 28) self.set_cash(100000) # Request the data to feed into indicators and trade. # In live mode, request CFD data for trading. # CFD is more useful in non-trading hours to reduce slippage when market prices jump at market opening. tickers = ["SPY", "BND", "GLD", "QQQ"] security_type = SecurityType.CFD if self.live_mode else SecurityType.EQUITY for ticker in tickers: # Create fast and slow-moving average indicators to trade SAM cross trend-following strategy. equity = self.add_equity(ticker, Resolution.DAILY) equity.sma_fast = self.sma(equity.symbol, 50) equity.sma_slow = self.sma(equity.symbol, 200) equity.target_vehicle = self.add_cfd(ticker, Resolution.DAILY, market=Market.INTERACTIVE_BROKERS).symbol if self.live_mode else equity.symbol def on_data(self, data: Slice) -> None: for security in self.securities.values(): # Trade the SMA cross on the updated SMA indicator signals. # If fast MA is above slow MA, the price is in an uptrend, and we buy. if security.sma_fast > security.sma_slow: self.set_holdings(security.target_vehicle, 0.25) # Else, the price is in a downtrend, and we are short. else: self.set_holdings(security.target_vehicle, 0)