Index
Requesting Data
Introduction
Request Index data in your algorithm to receive a feed of Index prices in the OnData
on_data
method. For more information about the specific dataset we use for backtests, see the US Cash Indices dataset listing. To trade live with Index data, you can use one of the brokerage data providers.
Create Subscriptions
To create an Index subscription, in the Initialize
initialize
method, call the AddIndex
add_index
method. The AddIndex
add_index
method returns an Index
object, which contains a Symbol
symbol
property. Save a reference to the Symbol
symbol
so you can use it in OnData
on_data
to access the security data in the Slice
.
_symbol = AddIndex("VIX").Symbol;
self._symbol = self.add_index("VIX").symbol
To view the supported assets in the US Cash Indices dataset, see the Supported Indices.
Resolutions
The following table shows the available resolutions and data formats for Index subscriptions:
Resolution | TradeBar | QuoteBar | Trade Tick | Quote Tick |
---|---|---|---|---|
Tick TICK | ||||
Second SECOND | ||||
Minute MINUTE | ||||
Hour HOUR | ||||
Daily DAILY |
The default resolution for Index subscriptions is Resolution.Minute
Resolution.MINUTE
. To change the resolution, pass a resolution
argument to the AddIndex
add_index
method.
_symbol = AddIndex("VIX", Resolution.Daily).Symbol;
self._symbol = self.add_index("VIX", Resolution.DAILY).symbol
To create custom resolution periods, see Consolidating Data.
Supported Markets
The only market available for Indices is Market.USA
, so you don't need to pass a market
argument to the AddIndex
add_index
method.
_symbol = AddIndex("VIX", market: Market.USA).Symbol;
self._symbol = self.add_index("VIX", market=Market.USA).symbol
The brokerage models have a default market for each asset class. If you set a brokerage model, you may not need to specify the market to use.
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
fill_forward
argument to false when you create the security subscription.
_symbol = AddIndex("VIX", fillForward: false).Symbol;
self._symbol = self.add_index("VIX", fill_forward=False).symbol
Data Normalization
The data normalization mode doesn't affect the data that LEAN passes to OnData
on_data
or the data from history request. If you change the data normalization mode, it won't change the outcome.
Examples
The following examples demonstrate some common practices for requesting Index data.
Example 1: VIX EMA Cross
The following algorithm adds daily VIX Index data and uses the Exponential Moving Average (EMA) indicator to create trading signals. The algorithm uses a 30-day slow EMA and a 15-day fast EMA. It enters a long SPY position when the fast EMA crosses above the slow EMA and liquidates the position when the fast EMA crosses below the slow EMA.
public class IndexDemoAlgorithm : QCAlgorithm { private ExponentialMovingAverage _emaFast, _emaSlow; private Symbol _vix, _spy; private decimal _tolerance; public override void Initialize() { // Add the daily VIX and SPY data. _vix = AddIndex("VIX", Resolution.Daily).Symbol; _spy = AddEquity("SPY", Resolution.Daily).Symbol; // Create fast and slow EMA indicators. _emaFast = EMA(_vix, 15); _emaSlow = EMA(_vix, 30); // Define a small tolerance to reduce trading churn. _tolerance = 0.00015m; } public override void OnData(Slice data) { // Check if the indicators is ready. if (!(_emaSlow.IsReady)) { return; } // When the fast VIX EMA crosses above the slow EMA, buy SPY. if (!Portfolio.Invested && (_emaFast.Current.Value > _emaSlow.Current.Value * (1 + _tolerance))) { SetHoldings(_spy, 0.8m); } // When the fast VIX EMA crosses below the slow EMA, liquidate the position. else if (Portfolio.Invested && (_emaFast.Current.Value < _emaSlow.Current.Value * (1 - _tolerance))) { Liquidate(_spy); } } }
class IndexDemoAlgorithm(QCAlgorithm): def initialize(self) -> None: # Add the daily VIX and SPY data. self._vix = self.add_index("VIX", Resolution.DAILY).symbol self._spy = self.add_equity("SPY", Resolution.DAILY).symbol # Create the fast and slow EMA indicators. self._ema_fast = self.ema(self._vix, 15) self._ema_slow = self.ema(self._vix, 30) # Define a small tolerance to reduce trading churn. self._tolerance = 0.00015 def on_data(self, slice: Slice) -> None: # Check if the indicators are ready. if not self._ema_slow.is_ready: return # When the fast VIX EMA crosses above the slow EMA, buy SPY. if (not self.portfolio.invested and self._ema_fast.current.value > self._ema_slow.current.value * (1 + self._tolerance)): self.set_holdings(self._spy, 0.8) # When the fast VIX EMA crosses below the slow EMA, liquidate the position. elif (self.portfolio.invested and self._ema_fast.current.value < self._ema_slow.current.value * (1 - self._tolerance)): self.liquidate(self._spy)