CFD

Requesting Data

Introduction

Request Contract for Difference (CFD) data in your algorithm to receive a feed of contract prices in the OnData method. QuantConnect supports CFD trading with OANDA and Interactive Brokers.

OANDA Subscriptions

To create a CFD subscription, in the Initialize method, call the AddCfd method. The AddCfd method returns a Cfd Security object, which contains a Symbol. Save a reference to the Symbol so you can use it in OnData to access the security data in the Slice.

_symbol = AddCfd("XAUUSD").Symbol;
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 AddCfd method and set the market parameter to Market.InteractiveBrokers. The AddCfd method returns a Cfd Security object, which contains a Symbol. Save a reference to the Symbol so you can use it in OnData to access the security data in the Slice.

_symbol = AddCfd("SPY", market: Market.InteractiveBrokers).Symbol;
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 all the CFD assets IB supports in live trading, 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.

var securityType = LiveMode ? SecurityType.Cfd : SecurityType.Equity;
var market = LiveMode ? Market.InteractiveBrokers : Market.USA;
_symbol = QuantConnect.Symbol.Create("SPY", securityType, Market.InteractiveBrokers);
AddSecurity(_symbol);
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:

ResolutionTradeBarQuoteBarTrade TickQuote Tick
Tickgreen check
Second
green check
Minute
green check
Hour
green check
Daily
green check

The default resolution for CFD subscriptions is Resolution.Minute. To change the resolution, pass a resolution argument to the AddCfd method.

_symbol = AddCfd("XAUUSD", Resolution.Daily).Symbol;
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 fillForward argument to false when you create the security subscription.

_symbol = AddCfd("XAUUSD", fillForward: false).Symbol;
self.symbol = self.AddCfd("XAUUSD", fillForward=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 AddCfd method.

_symbol = AddCfd("XAUUSD", leverage: 35).Symbol;
self.symbol = self.add_cfd("XAUUSD", leverage=35).symbol

Data Normalization

The data normalization mode doesn't affect the data that LEAN passes to OnData 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.

Example

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.

public class EtfCfdSwapMovingAverageCrossAlgorithm : QCAlgorithm
{
    public override void Initialize()
    {
        SetStartDate(2022, 9, 28);
        SetCash(100000);
                
        var tickers = new[] {"SPY", "BND", "GLD", "QQQ"};
        var securityType = LiveMode ? SecurityType.Cfd : SecurityType.Equity;
        foreach (var ticker in tickers)
        {
            var equity = AddEquity(ticker, Resolution.Daily);
            equity["smaFast"] = SMA(equity.Symbol, 50);
            equity["smaSlow"] = SMA(equity.Symbol, 200);
            equity["targetVehicle"] = LiveMode ? AddCfd(ticker, Resolution.Daily, market: Market.InteractiveBrokers).Symbol : equity.Symbol;
        }
    }
    
    public override void OnData(Slice data)
    {
        foreach (var security in Securities.Values)
        {
            var targetVehicle = security["targetVehicle"] as Symbol;
            if ((SimpleMovingAverage)security["smaFast"]  > (SimpleMovingAverage)security["smaSlow"])
            {
                SetHoldings(targetVehicle, 0.25m);
            }
            else
            {
                SetHoldings(targetVehicle, 0m);
            }
        }   
    }
}
class EtfCfdSwapMovingAverageCrossAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2022, 9, 28)
        self.set_cash(100000)

        tickers = ["SPY", "BND", "GLD", "QQQ"]
        security_type = SecurityType.CFD if self.live_mode else SecurityType.EQUITY
        for ticker in tickers:
            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):
        for security in self.securities.values:
            if security.sma_fast > security.sma_slow:
                self.set_holdings(security.target_vehicle, 0.25)
            else:
                self.set_holdings(security.target_vehicle, 0)
    

Properties

The AddCfd method returns a Cfd object, which have the following properties:

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: