book
Checkout our new book! Hands on AI Trading with Python, QuantConnect, and AWS Learn More arrow

VIX Central

VIX Central Contango

Introduction

The VIX Central Contango dataset by VIX Central tracks VIX Futures (VX) contango data. The data covers 12 Futures contracts closest to expiry/maturity, starts in June 2010, and is delivered on a daily frequency. The dataset is created by QuantConnect downloading data from VIX Central website, which collects and analyses VIX and VX (VIX Futures) data.

Contango and Backwardation are terms used to describe if participants in the Futures market are overpaying or underpaying relative to the "spot" price of the underlying commodity when trading a Futures contract ("spot" price is the price of the actual commodity/asset at a given moment in time). Contango and backwardation can be used to determine forward-looking expectations of the commodity's spot price by the time the Future has expired/matured and is set to be delivered by participants of the Futures market. As Futures near their expiration/maturity date, contango and backwardation curves tend to converge on the spot price of the commodity at the time of expiration.

For more information about the VIX Central Contango dataset, including CLI commands and pricing, see the dataset listing.

About the Provider

VIX Central was founded by Eli Mintz in 2012 with goal of displaying historical VIX term structures in a simple and intuitive interface. VIX Central provides access to real-time and historical VIX data for individual investors.

Getting Started

The following snippet demonstrates how to request data from the VIX Central Contango dataset:

using QuantConnect.DataSource;

_datasetSymbol = AddData<VIXCentralContango>("VIX", Resolution.Daily).Symbol;
from QuantConnect.DataSource import *

self.dataset_symbol = self.add_data(VIXCentralContango, "VIX", Resolution.DAILY).symbol

Data Summary

The following table describes the dataset properties:

PropertyValue
Start DateJune 2010
Asset Coverage1 Futures Chain with 12 contracts
Data DensityRegular
ResolutionDaily
TimezoneNew York

Requesting Data

To add VIX Central Contango data to your algorithm, call the AddDataadd_data method. Save a reference to the dataset Symbol so you can access the data later in your algorithm.

class VixCentralContangoAlgorithm(QCAlgorithm):
 
    def initialize(self) -> None:
        self.set_start_date(2014, 1, 1)
        self.set_end_date(2018, 1, 1)
        self.set_cash(25000)
 
        self.dataset_symbol = self.add_data(VIXCentralContango, "VX", Resolution.DAILY).symbol
namespace QuantConnect
{
    public class VixCentralContangoAlgorithm : QCAlgorithm
    {
        private Symbol _datasetSymbol;

        public override void Initialize()
        {
            SetStartDate(2014, 1, 1);
            SetEndDate(2018, 1, 1);
            SetCash(25000);

            _datasetSymbol = AddData<VIXCentralContango>("VX", Resolution.Daily).Symbol;
        }
    }
}

Accessing Data

To get the current VIX Central Contango data, index the current Slice with the dataset Symbol. Slice objects deliver unique events to your algorithm as they happen, but the Slice may not contain data for your dataset at every time step. To avoid issues, check if the Slice contains the data you want before you index it.

def on_data(self, slice: Slice) -> None:
    if slice.contains_key(self.dataset_symbol):
        data_point = slice[self.dataset_symbol]
        self.log(f"{self.dataset_symbol} front month at {slice.time}: {data_point.front_month}")
public override void OnData(Slice slice)
{
    if (slice.ContainsKey(_datasetSymbol))
    {
        var dataPoint = slice[_datasetSymbol];
        Log($"{_datasetSymbol} front month at {slice.Time}: {dataPoint.FrontMonth}");
    }
}

Historical Data

To get historical VIX Central Contango data, call the Historyhistory method with the dataset Symbol. If there is no data in the period you request, the history result is empty.

# DataFrame
history_df = self.history(self.dataset_symbol, 100, Resolution.DAILY)

# Dataset objects
history_bars = self.history[VIXCentralContango](self.dataset_symbol, 100, Resolution.DAILY)
var history = History<VIXCentralContango>(_datasetSymbol, 100, Resolution.Daily);

For more information about historical data, see History Requests.

Remove Subscriptions

To remove your subscription to VIX Central Contango data, call the RemoveSecurityremove_security method.

self.remove_security(self.dataset_symbol)
RemoveSecurity(_datasetSymbol);

Example Applications

The VIX Central Contango dataset enables you to explore VIX Future contracts pricing data. Examples include the following strategies:

  • Determining forward-looking expectations by Futures market participants of the underlying commodity's spot price by the time of expiration/maturity
  • Creating cash-and-carry arbitrage strategies by trading the spread/convergence of the contango/backwardation curves as a Future nears expiration/maturity

Classic Algorithm Design

The following example algorithm buys SPY when the percentage change between contract F2 and F1 (Contango_F2_Minus_F1) is positive. Otherwise, it remains in cash.

from AlgorithmImports import *
from QuantConnect.DataSource import *

class VixCentralContangoAlgorithm (QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2014,1,1) 
        self.set_end_date(2018,1,1)  
        self.set_cash(25000)
        # SPY as market representative for macroeconomy indicator trading
        self.spy = self.add_equity("SPY", Resolution.DAILY).symbol
        # Request VIX Contango data for trade signal generation
        self.contango = self.add_data(VIXCentralContango, "VX", Resolution.DAILY).symbol

    def on_data(self, slice: Slice) -> None:
        # Trade base on the updated VIX contango data
        contango_data = slice.Get(VIXCentralContango, self.contango)
        ratio = contango_data.contango_f2_minus_f1 if contango_data else 0

        # Bet the market will go up if F2 - F1 price percentage change is positive, meaning the near-term market volatility is expected to be low
        if not self.portfolio.invested and ratio > 0:
            self.market_order(self.spy, 100)
        # Liqudiate otherwise to avoid excessive market volatility
        elif ratio < 0:
            self.liquidate()
using QuantConnect.DataSource;

namespace QuantConnect
{
    public class VixCentralContangoAlgorithm : QCAlgorithm
    {
        private Symbol _spy;
        private Symbol _contango;

        public override void Initialize()
        {
            SetStartDate(2014, 1, 1);
            SetEndDate(2018, 1, 1);
            SetCash(25000);
            // SPY as market representative for macroeconomy indicator trading
            _spy = AddEquity("SPY", Resolution.Daily).Symbol;
            // Request VIX Contango data for trade signal generation
            _contango = AddData<VIXCentralContango>("VX", Resolution.Daily).Symbol;
        }
    
        public override void OnData(Slice slice)
        {
            // Trade base on the updated VIX contango data
            var contangoData = slice.Get<VIXCentralContango>(_contango);
            var ratio = contangoData?.Contango_F2_Minus_F1 ?? 0;

            // Bet the market will go up if F2 - F1 price percentage change is positive, meaning the near-term market volatility is expected to be low
            if (!Portfolio.Invested && ratio > 0)
            {
                MarketOrder(_spy, 100);
            }
            // Liqudiate otherwise to avoid excessive market volatility
            else if(ratio < 0)
            {
                 Liquidate();
            }
        }
    }
}

Framework Algorithm Design

The following example algorithm buys SPY when the percentage change between contract F2 and F1 (Contango_F2_Minus_F1) is positive. Otherwise, it remains in cash.

from AlgorithmImports import *
from QuantConnect.DataSource import *

class VixCentralContangoAlgorithm (QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2014,1,1) 
        self.set_end_date(2018,1,1)  
        self.set_cash(25000)
        
        self.universe_settings.resolution = Resolution.DAILY
        # Include SPY as market representative for macroeconomy indicator trading
        symbols = [Symbol.create("SPY", SecurityType.EQUITY, Market.USA)]
        self.add_universe_selection(ManualUniverseSelectionModel(symbols))   
        # Custom alpha model that emit insights base on VIX contango data
        self.add_alpha(ContangoAlphaModel(self))
        # Equal weighting investment to evenly dissipate the capital concentration risk on non-systematic risky event
        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel())

class ContangoAlphaModel(AlphaModel):

    def __init__(self, algorithm: QCAlgorithm) -> None:
        self.symbols = []
        # Request VIX Contango data for trade signal generation
        self.contango = algorithm.add_data(VIXCentralContango, "VX", Resolution.DAILY).symbol

        # Historical data
        history = algorithm.history(VIXCentralContango, self.contango, 60, Resolution.DAILY)
        algorithm.debug(f"We got {len(history.index)} items from our history request")
        
    def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]:
        insights = []

        # Trade base on the updated VIX contango data
        contango_data = slice.Get(VIXCentralContango, self.contango)
        ratio = contango_data.contango_f2_minus_f1 if contango_data else 0

        # Bet the market will go up if F2 - F1 price percentage change is positive, meaning the near-term market volatility is expected to be low
        if not algorithm.portfolio.invested and ratio > 0:
            for symbol in self.symbols:
                insights += [Insight.price(symbol, Expiry.ONE_MONTH, InsightDirection.UP)]
        # Liqudiate otherwise to avoid excessive market volatility
        elif ratio < 0:
            for symbol in self.symbols:
                insights += [Insight.price(symbol, Expiry.ONE_MONTH, InsightDirection.FLAT)]

        return insights
        
    def on_securities_changed(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
        for symbol in [x.symbol for x in changes.removed_securities]:
            if symbol in self.symbols: 
                self.symbols.pop(symbol)

        self.symbols += [x.symbol for x in changes.added_securities]
using QuantConnect.DataSource;

namespace QuantConnect
{
    public class VixCentralContangoAlgorithm : QCAlgorithm
    {
        public override void Initialize()
        {
            SetStartDate(2014, 1, 1);
            SetEndDate(2018, 1, 1);
            SetCash(25000);

            UniverseSettings.Resolution = Resolution.Daily;
            // Include SPY as market representative for macroeconomy indicator trading
            var symbols = new[] {QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA)};
            AddUniverseSelection(new ManualUniverseSelectionModel(symbols));
            // Custom alpha model that emit insights base on VIX contango data
            AddAlpha(new ContangoAlphaModel(this));
            // Equal weighting investment to evenly dissipate the capital concentration risk on non-systematic risky event
            SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
        }
    }

    public class ContangoAlphaModel : AlphaModel
    {
        private Symbol _contango;
        private List<Symbol> _symbols;

        public ContangoAlphaModel(QCAlgorithm algorithm)
        {
            _symbols = new List<Symbol>();
            // Request VIX Contango data for trade signal generation
            _contango = algorithm.AddData<VIXCentralContango>("VX", Resolution.Daily).Symbol;

            // Historical data
            var history = algorithm.History<VIXCentralContango>(_contango, 60, Resolution.Daily);
            algorithm.Debug($"We got {history.Count()} items from our history request");
        }

        public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice)
        {
            var insights = new List<Insight>();

            // Trade base on the updated VIX contango data
            var contangoData = slice.Get<VIXCentralContango>(_contango);
            var ratio = contangoData?.Contango_F2_Minus_F1 ?? 0;

            // Bet the market will go up if F2 - F1 price percentage change is positive, meaning the near-term market volatility is expected to be low
            if (!algorithm.Portfolio.Invested && ratio > 0)
            {
                foreach (var symbol in _symbols)
                {
                    insights.Add(Insight.Price(symbol, Expiry.OneMonth, InsightDirection.Up));
                }
            }
            // Liqudiate otherwise to avoid excessive market volatility
            else if (ratio < 0)
            {
                foreach (var symbol in _symbols)
                {
                    insights.Add(Insight.Price(symbol, Expiry.OneMonth, InsightDirection.Flat));
                }
            }
        	
            return insights;
        }

        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
        {
            foreach (var symbol in changes.RemovedSecurities.Select(x=> x.Symbol))
            {
                _symbols.Remove(symbol);
            }
            _symbols.AddRange(changes.AddedSecurities.Select(x=> x.Symbol));
        }
    }
}

Data Point Attributes

The VIX Central Contango dataset provides VIXCentralContango objects, which have the following attributes:

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: