---
title: "CFD"
description: "Learn how to request and handle cfd in the research environment in QuantConnect"
canonical: https://www.quantconnect.com/docs/v2/research-environment/datasets/cfd
markdown: https://www.quantconnect.com/docs/v2/research-environment/datasets/cfd.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/04%20Research%20Environment/03%20Datasets/18%20CFD
modified: 2026-10-29
index: https://www.quantconnect.com/llms.txt
---

# CFD

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Research Environment](https://www.quantconnect.com/docs/v2/research-environment.md) > Datasets > CFD

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

## Introduction

This page explains how to request, manipulate, and visualize historical CFD data.

## Create Subscriptions

Follow these steps to subscribe to a CFD security:

1. Create a `QuantBook`.
   ```python
   qb = QuantBook()
   ```
2. (Optional) [Set the time zone](https://www.quantconnect.com/docs/v2/research-environment/initialization.md#04-Set-Time-Zone) to the [exchange time zone](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/time-modeling/time-zones.md#03-Exchange-Time-Zone).
   ```python
   qb.set_time_zone(TimeZones.UTC)
   ```
3. Call the `add_cfd` method with a ticker and then save a reference to the CFD `Symbol`.
   ```python
   spx = qb.add_cfd("SPX500USD").symbol
   usb = qb.add_cfd("USB10YUSD").symbol
   ```

To view all of the available contracts, see [Supported Assets](https://www.quantconnect.com/docs/v2/writing-algorithms/datasets/quantconnect/cfd-data.md#09-Supported-Assets).

## Get Historical Data

You need a [subscription](https://www.quantconnect.com/docs/v2/research-environment/datasets/cfd.md#03-Create-Subscriptions) before you can request historical data for a security. On the time dimension, you can request an amount of historical data based on a trailing number of bars, a trailing period of time, or a defined period of time. On the security dimension, you can request historical data for a single CFD contract, a subset of the contracts you created subscriptions for in your notebook, or all of the contracts in your notebook.

### Trailing Number of Bars

To get historical data for a number of trailing bars, call the `history` method with the `Symbol` object(s) and an integer.

```python
# DataFrame
single_history_df = qb.history(spx, 10)
subset_history_df = qb.history([spx, usb], 10)
all_history_df = qb.history(qb.securities.keys(), 10)

# Slice objects
all_history_slice = qb.history(10)

# QuoteBar objects
single_history_quote_bars = qb.history[QuoteBar](spx, 10)
subset_history_quote_bars = qb.history[QuoteBar]([spx, usb], 10)
all_history_quote_bars = qb.history[QuoteBar](qb.securities.keys(), 10)
```

The preceding calls return the most recent bars, excluding periods of time when the exchange was closed.

### Trailing Period of Time

To get historical data for a trailing period of time, call the `history` method with the `Symbol` object(s) and a `timedelta`.

```python
# DataFrame of quote data (CFD data doesn't have trade data)
single_history_df = qb.history(spx, timedelta(days=3))
subset_history_df = qb.history([spx, usb], timedelta(days=3))
all_history_df = qb.history(qb.securities.keys(), timedelta(days=3))

# DataFrame of tick data
single_history_tick_df = qb.history(spx, timedelta(days=3), Resolution.TICK)
subset_history_tick_df = qb.history([spx, usb], timedelta(days=3), Resolution.TICK)
all_history_tick_df = qb.history(qb.securities.keys(), timedelta(days=3), Resolution.TICK)

# Slice objects
all_history_slice = qb.history(timedelta(days=3))

# QuoteBar objects
single_history_quote_bars = qb.history[QuoteBar](spx, timedelta(days=3), Resolution.MINUTE)
subset_history_quote_bars = qb.history[QuoteBar]([spx, usb], timedelta(days=3), Resolution.MINUTE)
all_history_quote_bars = qb.history[QuoteBar](qb.securities.keys(), timedelta(days=3), Resolution.MINUTE)

# Tick objects
single_history_ticks = qb.history[Tick](spx, timedelta(days=3), Resolution.TICK)
subset_history_ticks = qb.history[Tick]([spx, usb], timedelta(days=3), Resolution.TICK)
all_history_ticks = qb.history[Tick](qb.securities.keys(), timedelta(days=3), Resolution.TICK)
```

The preceding calls return the most recent bars or ticks, excluding periods of time when the exchange was closed.

### Defined Period of Time

To get historical data for a specific period of time, call the `history` method with the `Symbol` object(s), a start `datetime`, and an end `datetime`. The start and end times you provide are based in the [notebook time zone](https://www.quantconnect.com/docs/v2/research-environment/initialization.md#04-Set-Time-Zone).

```python
start_time = datetime(2021, 1, 1)
end_time = datetime(2021, 2, 1)

# DataFrame of quote data (CFD data doesn't have trade data)
single_history_df = qb.history(spx, start_time, end_time)
subset_history_df = qb.history([spx, usb], start_time, end_time)
all_history_df = qb.history(qb.securities.keys(), start_time, end_time)

# DataFrame of tick data
single_history_tick_df = qb.history(spx, start_time, end_time, Resolution.TICK)
subset_history_tick_df = qb.history([spx, usb], start_time, end_time, Resolution.TICK)
all_history_tick_df = qb.history(qb.securities.keys(), start_time, end_time, Resolution.TICK)

# QuoteBar objects
single_history_quote_bars = qb.history[QuoteBar](spx, start_time, end_time, Resolution.MINUTE)
subset_history_quote_bars = qb.history[QuoteBar]([spx, usb], start_time, end_time, Resolution.MINUTE)
all_history_quote_bars = qb.history[QuoteBar](qb.securities.keys(), start_time, end_time, Resolution.MINUTE)

# Tick objects
single_history_ticks = qb.history[Tick](spx, start_time, end_time, Resolution.TICK)
subset_history_ticks = qb.history[Tick]([spx, usb], start_time, end_time, Resolution.TICK)
all_history_ticks = qb.history[Tick](qb.securities.keys(), start_time, end_time, Resolution.TICK)
```

The preceding calls return the bars or ticks that have a timestamp within the defined period of time.

## Resolutions

The following table shows the available resolutions and data formats for CFD subscriptions:

| Resolution | TradeBar | QuoteBar | Trade Tick | Quote Tick |
| --- | --- | --- | --- | --- |
| `TICK` | Not supported | Not supported | Not supported | Supported✓ |
| `SECOND` | Not supported | Supported✓ | Not supported | Not supported |
| `MINUTE` | Not supported | Supported✓ | Not supported | Not supported |
| `HOUR` | Not supported | Supported✓ | Not supported | Not supported |
| `DAILY` | Not supported | Supported✓ | Not supported | Not supported |

## Markets

The only market available for CFD contracts is `Market.OANDA`.

## Data Normalization

The data normalization mode doesn't affect data from history request. If you change the data normalization mode, it won't change the outcome.

## Wrangle Data

You need some [historical data](https://www.quantconnect.com/docs/v2/research-environment/datasets/cfd.md#04-Get-Historical-Data) to perform wrangling operations. The process to manipulate the historical data depends on its data type. To display `pandas` objects, run a cell in a notebook with the `pandas` object as the last line. To display other data formats, call the `print` method.

### DataFrame Objects

If the `history` method returns a `DataFrame`, the first level of the `DataFrame` index is the [encoded CFD Symbol](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/security-identifiers.md#02-Encoding-Symbols) and the second level is the `end_time` of the data sample. The columns of the `DataFrame` are the data properties.

| symbol | time | askclose | askhigh | asklow | askopen | bidclose | bidhigh | bidlow | bidopen | close | high | low | open |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| SPX500USD 8I | 2021-01-04 00:01:00 | 3700.150 | 3700.750 | 3699.850 | 3700.350 | 3699.550 | 3700.150 | 3699.250 | 3699.750 | 3699.850 | 3700.450 | 3699.550 | 3700.050 |
| SPX500USD 8I | 2021-01-04 00:02:00 | 3701.250 | 3701.650 | 3700.050 | 3700.150 | 3700.650 | 3701.050 | 3699.450 | 3699.550 | 3700.950 | 3701.350 | 3699.750 | 3699.850 |
| SPX500USD 8I | 2021-01-04 00:03:00 | 3702.450 | 3703.150 | 3701.050 | 3701.250 | 3701.850 | 3702.550 | 3700.450 | 3700.650 | 3702.150 | 3702.850 | 3700.750 | 3700.950 |
| SPX500USD 8I | 2021-01-04 00:04:00 | 3703.850 | 3704.250 | 3702.250 | 3702.450 | 3703.250 | 3703.650 | 3701.650 | 3701.850 | 3703.550 | 3703.950 | 3701.950 | 3702.150 |
| SPX500USD 8I | 2021-01-04 00:05:00 | 3704.650 | 3705.050 | 3703.650 | 3703.850 | 3704.050 | 3704.450 | 3703.050 | 3703.250 | 3704.350 | 3704.750 | 3703.350 | 3703.550 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| USB30YUSD 8I | 2021-01-29 23:56:00 | 167.450 | 167.520 | 167.380 | 167.410 | 166.950 | 167.020 | 166.880 | 166.910 | 167.200 | 167.270 | 167.130 | 167.160 |
| USB30YUSD 8I | 2021-01-29 23:57:00 | 167.380 | 167.480 | 167.320 | 167.450 | 166.880 | 166.980 | 166.820 | 166.950 | 167.130 | 167.230 | 167.070 | 167.200 |
| USB30YUSD 8I | 2021-01-29 23:58:00 | 167.310 | 167.420 | 167.250 | 167.380 | 166.810 | 166.920 | 166.750 | 166.880 | 167.060 | 167.170 | 167.000 | 167.130 |
| USB30YUSD 8I | 2021-01-29 23:59:00 | 167.250 | 167.350 | 167.190 | 167.310 | 166.750 | 166.850 | 166.690 | 166.810 | 167.000 | 167.100 | 166.940 | 167.060 |
| USB30YUSD 8I | 2021-01-30 00:00:00 | 167.190 | 167.290 | 167.130 | 167.250 | 166.690 | 166.790 | 166.630 | 166.750 | 166.940 | 167.040 | 166.880 | 167.000 |

To select the historical data of a single CFD, index the `loc` property of the `DataFrame` with the CFD `Symbol`.

```python
all_history_df.loc[spx]  # or all_history_df.loc['SPX500USD']
```

| time | askclose | askhigh | asklow | askopen | bidclose | bidhigh | bidlow | bidopen | close | high | low | open |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2021-01-04 00:01:00 | 3700.150 | 3700.750 | 3699.850 | 3700.350 | 3699.550 | 3700.150 | 3699.250 | 3699.750 | 3699.850 | 3700.450 | 3699.550 | 3700.050 |
| 2021-01-04 00:02:00 | 3701.250 | 3701.650 | 3700.050 | 3700.150 | 3700.650 | 3701.050 | 3699.450 | 3699.550 | 3700.950 | 3701.350 | 3699.750 | 3699.850 |
| 2021-01-04 00:03:00 | 3702.450 | 3703.150 | 3701.050 | 3701.250 | 3701.850 | 3702.550 | 3700.450 | 3700.650 | 3702.150 | 3702.850 | 3700.750 | 3700.950 |
| 2021-01-04 00:04:00 | 3703.850 | 3704.250 | 3702.250 | 3702.450 | 3703.250 | 3703.650 | 3701.650 | 3701.850 | 3703.550 | 3703.950 | 3701.950 | 3702.150 |
| 2021-01-04 00:05:00 | 3704.650 | 3705.050 | 3703.650 | 3703.850 | 3704.050 | 3704.450 | 3703.050 | 3703.250 | 3704.350 | 3704.750 | 3703.350 | 3703.550 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2021-01-29 23:56:00 | 3700.550 | 3700.950 | 3700.150 | 3700.250 | 3699.950 | 3700.350 | 3699.550 | 3699.650 | 3700.250 | 3700.650 | 3699.850 | 3699.950 |
| 2021-01-29 23:57:00 | 3699.850 | 3700.650 | 3699.450 | 3700.550 | 3699.250 | 3700.050 | 3698.850 | 3699.950 | 3699.550 | 3700.350 | 3699.150 | 3700.250 |
| 2021-01-29 23:58:00 | 3698.750 | 3699.950 | 3698.350 | 3699.850 | 3698.150 | 3699.350 | 3697.750 | 3699.250 | 3698.450 | 3699.650 | 3698.050 | 3699.550 |
| 2021-01-29 23:59:00 | 3697.950 | 3698.850 | 3697.550 | 3698.750 | 3697.350 | 3698.250 | 3696.950 | 3698.150 | 3697.650 | 3698.550 | 3697.250 | 3698.450 |
| 2021-01-30 00:00:00 | 3697.250 | 3698.050 | 3696.850 | 3697.950 | 3696.650 | 3697.450 | 3696.250 | 3697.350 | 3696.950 | 3697.750 | 3696.550 | 3697.650 |

To select a column of the `DataFrame`, index it with the column name.

```python
all_history_df.loc[spx]['close']
```

```python
time
2021-01-04 00:01:00    3699.850
2021-01-04 00:02:00    3700.950
2021-01-04 00:03:00    3702.150
2021-01-04 00:04:00    3703.550
2021-01-04 00:05:00    3704.350
                         ...
2021-01-29 23:56:00    3700.250
2021-01-29 23:57:00    3699.550
2021-01-29 23:58:00    3698.450
2021-01-29 23:59:00    3697.650
2021-01-30 00:00:00    3696.950
Name: close, dtype: float64
```

If you request historical data for multiple CFD contracts, you can transform the `DataFrame` so that it's a time series of close values for all of the CFD contracts. To transform the `DataFrame`, select the column you want to display for each CFD contract and then call the [unstack](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.unstack.html) method.

```python
all_history_df['close'].unstack(level=0)
```

The `DataFrame` is transformed so that the column indices are the `Symbol` of each CFD contract and each row contains the close value.

| symbol time | SPX500USD 8I | USB30YUSD 8I |
| --- | --- | --- |
| 2021-01-04 00:01:00 | 3699.850 | 167.200 |
| 2021-01-04 00:02:00 | 3700.950 | 167.250 |
| 2021-01-04 00:03:00 | 3702.150 | 167.310 |
| 2021-01-04 00:04:00 | 3703.550 | 167.380 |
| 2021-01-04 00:05:00 | 3704.350 | 167.420 |
| ... | ... | ... |
| 2021-01-29 23:56:00 | 3700.250 | 167.200 |
| 2021-01-29 23:57:00 | 3699.550 | 167.130 |
| 2021-01-29 23:58:00 | 3698.450 | 167.060 |
| 2021-01-29 23:59:00 | 3697.650 | 167.000 |
| 2021-01-30 00:00:00 | 3696.950 | 166.940 |

### Slice Objects

If the `history` method returns `Slice` objects, iterate through the `Slice` objects to get each one. The `Slice` objects may not have data for all of your CFD subscriptions. To avoid issues, check if the `Slice` contains data for your CFD contract before you index it with the CFD `Symbol`.

```python
for slice in all_history_slice:
        if slice.quote_bars.contains_key(spx):
        quote_bar = slice.quote_bars[spx]
```

You can also iterate through each `QuoteBar` in the `Slice`.

```python
for slice in all_history_slice:
    for kvp in slice.quote_bars:
        symbol = kvp.key
        quote_bar = kvp.value
```

### QuoteBar Objects

If the `history` method returns `QuoteBar` objects, iterate through the `QuoteBar` objects to get each one.

```python
for quote_bar in single_history_quote_bars:
    print(quote_bar)
```

If the `history` method returns `QuoteBars`, iterate through the `QuoteBars` to get the `QuoteBar` of each CFD contract. The `QuoteBars` may not have data for all of your CFD subscriptions. To avoid issues, check if the `QuoteBars` object contains data for your security before you index it with the CFD `Symbol`.

```python
for quote_bars in all_history_quote_bars:
    if quote_bars.contains_key(spx):
        quote_bar = quote_bars[spx]
```

You can also iterate through each of the `QuoteBars`.

```python
for quote_bars in all_history_quote_bars:
    for kvp in quote_bars:
        symbol = kvp.key
        quote_bar = kvp.value
```

### Tick Objects

If the `history` method returns `TICK` objects, iterate through the `TICK` objects to get each one.

```python
for tick in single_history_ticks:
    print(tick)
```

If the `history` method returns `Ticks`, iterate through the `Ticks` to get the `TICK` of each CFD contract. The `Ticks` may not have data for all of your CFD subscriptions. To avoid issues, check if the `Ticks` object contains data for your security before you index it with the CFD `Symbol`.

```python
for ticks in all_history_ticks:
    if ticks.contains_key(spx):
        ticks = ticks[spx]
```

You can also iterate through each of the `Ticks`.

```python
for ticks in all_history_ticks:
    for kvp in ticks:
        symbol = kvp.key
        tick = kvp.value
```

The `Ticks` objects only contain the last tick of each security for that particular [timeslice](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/time-modeling/timeslices.md)

## Plot Data

You need some [historical CFD data](https://www.quantconnect.com/docs/v2/research-environment/datasets/cfd.md#04-Get-Historical-Data) to produce plots. You can use many of the [supported plotting libraries](https://www.quantconnect.com/docs/v2/research-environment/charting.md) to visualize data in various formats. For example, you can plot candlestick and line charts.

### Candlestick Chart

Follow these steps to plot candlestick charts:

1. Get some [historical data](https://www.quantconnect.com/docs/v2/research-environment/datasets/cfd.md#04-Get-Historical-Data).
   ```python
   history = qb.history(spx, datetime(2021, 11, 26), datetime(2021, 12, 8), Resolution.DAILY).loc[spx]
   ```
2. Import the `plotly` library.
   ```python
   import plotly.graph_objects as go
   ```
3. Create a `Candlestick`.
   ```python
   candlestick = go.Candlestick(x=history.index,
                                open=history['open'],
                                high=history['high'],
                                low=history['low'],
                                close=history['close'])
   ```
4. Create a `Layout`.
   ```python
   layout = go.Layout(title=go.layout.Title(text='SPX CFD OHLC'),
                      xaxis_title='Date',
                      yaxis_title='Price',
                      xaxis_rangeslider_visible=False)
   ```
5. Create the `Figure`.
   ```python
   fig = go.Figure(data=[candlestick], layout=layout)
   ```
6. Show the `Figure`.
   ```python
   fig.show()
   ```
   Candlestick charts display the open, high, low, and close prices of the security.

![Candlestick plot of SPY CFD OHLC](https://cdn.quantconnect.com/i/tu/researchhistorycfdonesecuritycandlestickplot.png)

### Line Chart

Follow these steps to plot line charts using built-in methods:

1. Get some historical data.
   ```python
   history = qb.history([spx, usb], datetime(2021, 11, 26), datetime(2021, 12, 8), Resolution.DAILY)
   ```
2. Select the data to plot.
   ```python
   pct_change = history['close'].unstack(0).pct_change().dropna()
   ```
3. Call the `plot` method on the `pandas` object.
   ```python
   pct_change.plot(title="Close Price %Change", figsize=(15, 10))
   ```
4. Show the plot.
   ```python
   plt.show()
   ```
   Line charts display the value of the property you selected in a time series.

![Line chart of CFDs close price return%](https://cdn.quantconnect.com/i/tu/research-env-cfd-plot.jpg)

## Examples

The following examples demonstrate some common practices for applying the CFD dataset.

### Example 1: 5-Minute Candlestick Plot

The following example studies the candlestick pattern of the XAUUSD. To study the short term pattern, we consolidate the data into 5 minute bars and plot the 5-minute candlestick plot, using the mid prices.

```python
# Import plotly library for plotting.
import plotly.graph_objects as go

# Create a QuantBook
qb = QuantBook()

# Request XAUUSD's historical data.
symbol = qb.add_cfd("XAUUSD").symbol
history = qb.history(symbol,
    start=qb.time - timedelta(days=182),
    end=qb.time,
    resolution=Resolution.MINUTE)

# Drop level 0 index (Symbol index) from the DataFrame
history = history.droplevel([0])

# Select the required columns to obtain the 5-minute OHLC data.
history = history[["open", "high", "low", "close"]].resample("5T").agg({
    "open": "first",
    "high": "max",
    "low": "min",
    "close": "last"
})

# Crete the Candlestick chart using the 5-minute windows.
candlestick = go.Candlestick(x=history.index,
                             open=history['open'],
                             high=history['high'],
                             low=history['low'],
                             close=history['close'])
# Create a Layout as the plot settings.
layout = go.Layout(title=go.layout.Title(text=f'{symbol} OHLC'),
                   xaxis_title='Date',
                   yaxis_title='Price',
                   xaxis_rangeslider_visible=False)
# Create the Figure.
fig = go.Figure(data=[candlestick], layout=layout)
# Display the plot.
fig.show()
```
