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
Requesting Data
To add VIX Central Contango data to your algorithm, call the AddData
add_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 History
history
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.
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)); } } }