Asset Classes
Futures
Trades
To get historical trade data, call the History<TradeBar> method with a security's Symbol.
To get historical trade data, call the history method with the TradeBar type and a security's Symbol.
This method returns a DataFrame with columns for the open, high, low, close, and volume.
public class FutureTradeBarHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Get the Symbol of a security.
var future = AddFuture(Futures.Indices.SP500EMini);
var symbol = FuturesChain(future.Symbol).First().Symbol;
// Get the 5 trailing daily TradeBar objects of the security.
var history = History<TradeBar>(symbol, 5, Resolution.Daily);
// Iterate through each TradeBar and calculate its dollar volume.
foreach (var bar in history)
{
var t = bar.EndTime;
var dollarVolume = bar.Close * bar.Volume;
}
}
} class FutureTradeBarHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Get the Symbol of a security.
future = self.add_future(Futures.Indices.SP_500_E_MINI)
symbol = list(self.futures_chain(future.symbol))[0].symbol
# Get the 5 trailing daily TradeBar objects of the security in DataFrame format.
history = self.history(TradeBar, symbol, 5, Resolution.DAILY)
| close | high | low | open | volume | |||
|---|---|---|---|---|---|---|---|
| expiry | symbol | time | |||||
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-12 17:00:00 | 6058.75 | 6087.75 | 6055.50 | 6082.25 | 1152801.0 |
| 2024-12-13 17:00:00 | 6051.25 | 6084.75 | 6041.25 | 6077.25 | 1027682.0 | ||
| 2024-12-16 17:00:00 | 6076.50 | 6090.50 | 6064.75 | 6072.50 | 378263.0 | ||
| 2024-12-17 17:00:00 | 6052.00 | 6063.50 | 6040.75 | 6052.75 | 278531.0 | ||
| 2024-12-18 17:00:00 | 5872.25 | 6074.50 | 5840.00 | 6050.25 | 335048.0 |
# Calculate the daily returns. daily_returns = history.close.pct_change().iloc[1:]
expiry symbol time
2024-12-20 13:30:00 ES YOGVNNAOI1OH 2024-12-13 17:00:00 -0.001238
2024-12-16 17:00:00 0.004173
2024-12-17 17:00:00 -0.004032
2024-12-18 17:00:00 -0.029701
Name: close, dtype: float64
If you intend to use the data in the DataFrame to create TradeBar objects, request that the history request returns the data type you need.
Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame.
To get a list of TradeBar objects instead of a DataFrame, call the history[TradeBar] method.
# Get the 5 trailing daily TradeBar objects of the security in TradeBar format.
history = self.history[TradeBar](symbol, 5, Resolution.DAILY)
# Iterate through the TradeBar objects and access their volumes.
for trade_bar in history:
t = trade_bar.end_time
volume = trade_bar.volume
Quotes
To get historical quote data, call the History<QuoteBar> method with a security's Symbol.
To get historical quote data, call the history method with the QuoteBar type and a security's Symbol.
This method returns a DataFrame with columns for the open, high, low, close, and size of the bid and ask quotes.
The columns that don't start with "bid" or "ask" are the mean of the quote prices on both sides of the market.
public class FutureQuoteBarHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Get the Symbol of a security.
var future = AddFuture(Futures.Indices.SP500EMini);
var symbol = FuturesChain(future.Symbol).First().Symbol;
// Get the 5 trailing minute QuoteBar objects of the security.
var history = History<QuoteBar>(symbol, 5, Resolution.Minute);
// Iterate through the QuoteBar objects and calculate the spread.
foreach (var bar in history)
{
var t = bar.EndTime;
var spread = bar.Ask.Close - bar.Bid.Close;
}
}
} class FutureQuoteBarHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Get the Symbol of a security.
future = self.add_future(Futures.Indices.SP_500_E_MINI)
symbol = list(self.futures_chain(future.symbol))[0].symbol
# Get the 5 trailing minute QuoteBar objects of the security in DataFrame format.
history = self.history(QuoteBar, symbol, 5, Resolution.MINUTE)
| askclose | askhigh | asklow | askopen | asksize | bidclose | bidhigh | bidlow | bidopen | bidsize | close | high | low | open | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| expiry | symbol | time | ||||||||||||||
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-12 17:00:00 | 6058.75 | 6087.75 | 6055.75 | 6082.50 | 19.0 | 6058.50 | 6087.50 | 6055.50 | 6082.25 | 52.0 | 6058.625 | 6087.625 | 6055.625 | 6082.375 |
| 2024-12-13 17:00:00 | 6051.50 | 6085.00 | 6041.50 | 6077.50 | 59.0 | 6051.25 | 6084.75 | 6041.25 | 6077.25 | 1.0 | 6051.375 | 6084.875 | 6041.375 | 6077.375 | ||
| 2024-12-16 17:00:00 | 6076.75 | 6090.75 | 6064.75 | 6072.50 | 10.0 | 6076.50 | 6090.50 | 6064.50 | 6072.25 | 7.0 | 6076.625 | 6090.625 | 6064.625 | 6072.375 | ||
| 2024-12-17 17:00:00 | 6052.25 | 6063.50 | 6041.00 | 6053.00 | 12.0 | 6052.00 | 6063.25 | 6040.50 | 6052.75 | 1.0 | 6052.125 | 6063.375 | 6040.750 | 6052.875 | ||
| 2024-12-18 17:00:00 | 5872.75 | 6074.75 | 5840.25 | 6050.25 | 2.0 | 5872.25 | 6074.50 | 5840.00 | 6050.00 | 1.0 | 5872.500 | 6074.625 | 5840.125 | 6050.125 |
# Calculate the spread at each minute. spread = history.askclose - history.bidclose
expiry symbol time
2024-12-20 13:30:00 ES YOGVNNAOI1OH 2024-12-12 17:00:00 0.25
2024-12-13 17:00:00 0.25
2024-12-16 17:00:00 0.25
2024-12-17 17:00:00 0.25
2024-12-18 17:00:00 0.50
dtype: float64
If you intend to use the data in the DataFrame to create QuoteBar objects, request that the history request returns the data type you need.
Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame.
To get a list of QuoteBar objects instead of a DataFrame, call the history[QuoteBar] method.
# Get the 5 trailing minute QuoteBar objects of the security in QuoteBar format.
history = self.history[QuoteBar](symbol, 5, Resolution.MINUTE)
# Iterate through each QuoteBar and calculate the dollar volume on the bid.
for quote_bar in history:
t = quote_bar.end_time
bid_dollar_volume = quote_bar.last_bid_size * quote_bar.bid.close
Ticks
To get historical tick data, call the History<Tick> method with a security's Symbol and Resolution.Tick.
To get historical tick data, call the history method with a security's Symbol and Resolution.TICK.
This method returns a DataFrame that contains data on bids, asks, and last trade prices.
public class FutureTickHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Get the Symbol of a security.
var future = AddFuture(Futures.Indices.SP500EMini);
var symbol = FuturesChain(future.Symbol).First().Symbol;
// Get the trailing 2 days of ticks for the security.
var history = History<Tick>(symbol, TimeSpan.FromDays(2), Resolution.Tick);
// Select the ticks that represent trades, excluding the quote ticks.
var trades = history.Where(tick => tick.TickType == TickType.Trade);
}
} class FutureTickHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Get the Symbol of a security.
future = self.add_future(Futures.Indices.SP_500_E_MINI)
symbol = list(self.futures_chain(future.symbol))[0].symbol
# Get the trailing 2 days of ticks for the security in DataFrame format.
history = self.history(symbol, timedelta(2), Resolution.TICK)
| askprice | asksize | bidprice | bidsize | lastprice | openinterest | quantity | |||
|---|---|---|---|---|---|---|---|---|---|
| expiry | symbol | time | |||||||
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.001 | NaN | NaN | NaN | NaN | 6052.75 | NaN | 1.0 |
| 2024-12-17 09:30:00.001 | 0.0 | 0.0 | 6052.75 | 33.0 | 6052.75 | NaN | 0.0 | ||
| 2024-12-17 09:30:00.001 | 6053.0 | 11.0 | 0.00 | 0.0 | 6053.00 | NaN | 0.0 | ||
| 2024-12-17 09:30:00.001 | 6053.0 | 10.0 | 0.00 | 0.0 | 6053.00 | NaN | 0.0 | ||
| 2024-12-17 09:30:00.001 | 6053.0 | 9.0 | 0.00 | 0.0 | 6053.00 | NaN | 0.0 |
# Select the rows in the DataFrame that represent trades. Drop the bid/ask columns since they are NaN. trade_ticks = history[history.quantity > 0].dropna(axis=1)
| lastprice | quantity | |||
|---|---|---|---|---|
| expiry | symbol | time | ||
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-17 09:30:00.001 | 6052.75 | 1.0 |
| 2024-12-17 09:30:00.002 | 6053.00 | 1.0 | ||
| 2024-12-17 09:30:00.002 | 6053.00 | 2.0 | ||
| 2024-12-17 09:30:00.003 | 6052.75 | 1.0 | ||
| 2024-12-17 09:30:00.003 | 6052.75 | 3.0 |
If you intend to use the data in the DataFrame to create Tick objects, request that the history request returns the data type you need.
Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame.
To get a list of Tick objects instead of a DataFrame, call the history[Tick] method.
# Get the trailing 2 days of ticks for the security in Tick format.
history = self.history[Tick](symbol, timedelta(2), Resolution.TICK)
# Iterate through each quote tick and calculate the quote size.
for tick in history:
if tick.tick_type == TickType.Quote:
t = tick.end_time
size = max(tick.bid_size, tick.ask_size)
Ticks are a sparse dataset, so request ticks over a trailing period of time or between start and end times.
Slices
To get historical Slice data, call the Historyhistory method without passing any Symbol objects.
This method returns Slice objects, which contain data points from all the datasets in your algorithm.
If you omit the resolution argument, it uses the resolution that you set for each security and dataset when you created the subscriptions.
public class SliceHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 1);
SetEndDate(2024, 12, 31);
// Add some securities and datasets.
AddFuture(Futures.Indices.SP500EMini);
// Get the historical Slice objects over the last 5 days for all the subcriptions in your algorithm.
var history = History(5, Resolution.Daily);
// Iterate through each historical Slice.
foreach (var slice in history)
{
// Iterate through each TradeBar in this Slice.
foreach (var kvp in slice.Bars)
{
var symbol = kvp.Key;
var bar = kvp.Value;
}
}
}
} class SliceHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 1)
self.set_end_date(2024, 12, 31)
# Add some securities and datasets.
self.add_future(Futures.Indices.SP_500_E_MINI)
# Get the historical Slice objects over the last 5 days for all the subcriptions in your algorithm.
history = self.history(5, Resolution.DAILY)
# Iterate through each historical Slice.
for slice_ in history:
# Iterate through each TradeBar in this Slice.
for symbol, trade_bar in slice_.bars.items():
close = trade_bar.close
Continuous Contract Prices
To get historical trade, quote, or tick data for the continuous contract, use the symbolSymbol property of the Future object when you make the history request.
public class FutureContinuousContractHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Add the Future and specify the contract rollover settings.
var future = AddFuture(
Futures.Indices.SP500EMini,
dataMappingMode: DataMappingMode.OpenInterest,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
contractDepthOffset: 0
);
// Get the 5 trailing daily TradeBar objects of the continuous contract.
var history = History<TradeBar>(future.Symbol, 5, Resolution.Daily);
// Iterate through each TradeBar and calculate its dollar volume.
foreach (var bar in history)
{
var t = bar.EndTime;
var dollarVolume = bar.Close * bar.Volume;
}
}
} class FutureContinuousContractHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Add the Future and specify the contract rollover settings.
future = self.add_future(
Futures.Indices.SP_500_E_MINI,
data_mapping_mode=DataMappingMode.OPEN_INTEREST,
data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
contract_depth_offset=0
)
# Get the 5 trailing daily TradeBar objects of the continuous contract.
history = self.history(TradeBar, future.symbol, 5, Resolution.DAILY)
| close | high | low | open | volume | |||
|---|---|---|---|---|---|---|---|
| expiry | symbol | time | |||||
| 1899-12-30 | /ES | 2024-12-12 17:00:00 | 6132.582256 | 6161.935651 | 6129.292651 | 6156.368628 | 1152801.0 |
| 2024-12-13 17:00:00 | 6124.990860 | 6158.899093 | 6114.869000 | 6151.307698 | 1027682.0 | ||
| 2024-12-16 17:00:00 | 6150.548558 | 6164.719163 | 6138.655372 | 6146.499814 | 378263.0 | ||
| 2024-12-17 17:00:00 | 6125.750000 | 6137.390140 | 6114.362907 | 6126.509140 | 278531.0 | ||
| 2024-12-18 17:00:00 | 5939.500000 | 6148.000000 | 5906.500000 | 6124.000000 | 2009987.0 |
# Calculate the daily returns. daily_returns = history.close.pct_change().iloc[1:]
expiry symbol time
1899-12-30 /ES 2024-12-13 17:00:00 -0.001238
2024-12-16 17:00:00 0.004173
2024-12-17 17:00:00 -0.004032
2024-12-18 17:00:00 -0.030404
Name: close, dtype: float64
Symbol Changes
To get historical symbol change data, call the History<SymbolChangedEvent> method with the continuous contract Symbol.
To get historical symbol change data, call the history method with the SymbolChangedEvent type and the continuous contract Symbol.
This method returns a DataFrame that contains the old and new Symbol for each rollover.
public class FutureSymbolChangeEventsHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Add the Future and specify the contract rollover settings.
var future = AddFuture(
Futures.Indices.SP500EMini,
dataMappingMode: DataMappingMode.OpenInterest,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
contractDepthOffset: 0
);
// Get the contract rollovers for the trailing year.
var history = History<SymbolChangedEvent>(future.Symbol, TimeSpan.FromDays(365));
// Iterate through each rollover and select the Symbol of each contract.
foreach (var symbolChangedEvent in history)
{
var t = symbolChangedEvent.EndTime;
var oldSymbol = symbolChangedEvent.OldSymbol;
var newSymbol = symbolChangedEvent.NewSymbol;
}
}
} class FutureSymbolChangeEventsHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Add the Future and specify the contract rollover settings.
future = self.add_future(
Futures.Indices.SP_500_E_MINI,
data_mapping_mode=DataMappingMode.OPEN_INTEREST,
data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
contract_depth_offset=0
)
# Get the contract rollovers for the trailing year.
history = self.history(SymbolChangedEvent, future.symbol, timedelta(365))
| newsymbol | oldsymbol | |||
|---|---|---|---|---|
| expiry | symbol | time | ||
| 1899-12-30 | /ES | 2024-03-13 | ES YJHOAMPYKQGX | ES YGT6HGVF2SQP |
| 2024-06-19 | ES YLZ9Z50BJE2P | ES YJHOAMPYKQGX | ||
| 2024-09-18 | ES YOGVNNAOI1OH | ES YLZ9Z50BJE2P | ||
| 2024-12-18 | ES YQYHC5L1GPA9 | ES YOGVNNAOI1OH |
# Select the dates of each rollover. dates = list(history.index.levels[2])
If you intend to use the data in the DataFrame to create SymbolChangedEvent objects, request that the history request returns the data type you need.
Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame.
To get a list of SymbolChangedEvent objects instead of a DataFrame, call the history[SymbolChangedEvent] method.
# Get the rollovers of the continuous contract during the last 10 years in SymbolChangedEvent format.
history = self.history[SymbolChangedEvent](symbol, timedelta(10*365))
# Iterate through each SymbolChangedEvent object.
for symbol_changed_event in history:
t = symbol_changed_event.end_time
old_symbol = symbol_changed_event.old_symbol
new_symbol = symbol_changed_event.new_symbol
Open Interest
To get historical open interest data, call the History<OpenInterest> method with a security's Symbol.
To get historical open interest data, call the history method with the OpenInterest type and a security's Symbol.
This method returns a DataFrame with a single column.
public class FutureOpenInterestHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Get the Symbol of a security.
var future = AddFuture(Futures.Indices.SP500EMini);
var symbol = FuturesChain(future.Symbol).First().Symbol;
// Get the 5 trailing daily OpenInterest objects of the security.
var history = History<OpenInterest>(symbol, 5, Resolution.Daily);
// Iterate through each OpenInterest and get it's value.
foreach (var oi in history)
{
var t = oi.EndTime;
var openInterest = oi.Value;
}
}
} class FutureOpenInterestHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Get the Symbol of a security.
future = self.add_future(Futures.Indices.SP_500_E_MINI)
symbol = list(self.futures_chain(future.symbol))[0].symbol
# Get the 5 trailing daily OpenInterest objects of the security in DataFrame format.
history = self.history(OpenInterest, symbol, 5, Resolution.DAILY)
| openinterest | |||
|---|---|---|---|
| expiry | symbol | time | |
| 2024-12-20 13:30:00 | ES YOGVNNAOI1OH | 2024-12-14 19:00:00 | 1631020.0 |
| 2024-12-15 19:00:00 | 1625312.0 | ||
| 2024-12-16 19:00:00 | 965789.0 | ||
| 2024-12-17 19:00:00 | 687472.0 | ||
| 2024-12-18 19:00:00 | 556365.0 |
# Calculate the daily change in open interest. oi_delta = history.openinterest.diff().iloc[1:]
expiry symbol time
2024-12-20 13:30:00 ES YOGVNNAOI1OH 2024-12-15 19:00:00 -5708.0
2024-12-16 19:00:00 -659523.0
2024-12-17 19:00:00 -278317.0
2024-12-18 19:00:00 -131107.0
Name: openinterest, dtype: float64
If you intend to use the data in the DataFrame to create OpenInterest objects, request that the history request returns the data type you need.
Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame.
To get a list of OpenInterest objects instead of a DataFrame, call the history[OpenInterest] method.
# Get the 5 trailing daily OpenInterest objects of the security in OpenInterest format.
history = self.history[OpenInterest](symbol, 5, Resolution.DAILY)
# Iterate through the TradeBar objects and access their volumes.
for oi in history:
t = oi.end_time
open_interest = oi.value
Contracts
To get historical Futures contracts, call the History<FutureUniverse> method with the continuous contract Symbol.
The data this method returns contains information on all the currently tradable contracts, not just the contracts that pass your filter.
To get historical Futures contracts, call the history method with the FutureUniverse type and the continuous contract Symbol.
The data this method returns contains information on all the currently tradable contracts, not just the contracts that pass your filter.
If you pass flatten=True, this method returns a DataFrame with columns for the data point attributes.
public class FutureContractsHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Add a Future.
var future = AddFuture(Futures.Indices.SP500EMini);
// Get the daily contract data over the last two trading days.
var history = History<FutureUniverse>(future.Symbol, 2);
// Iterate through each day of the history.
foreach (var futureUniverse in history)
{
var t = futureUniverse.EndTime;
// Select the contract with the greatest open interest.
var mostOi = futureUniverse.Select(c => c as FutureUniverse).OrderByDescending(c => c.OpenInterest).First();
}
}
} class FutureContractsHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Add a Future.
future = self.add_future(Futures.Indices.SP_500_E_MINI)
# Get the daily contract data over the last two trading days.
history = self.history(FutureUniverse, future.symbol, 2, flatten=True)
| close | high | low | open | openinterest | value | volume | ||
|---|---|---|---|---|---|---|---|---|
| time | symbol | |||||||
| 2024-12-18 | ES YOGVNNAOI1OH | 6052.000 | 6063.500 | 6040.750 | 6052.750 | 687472.0 | 6052.000 | 278531.0 |
| ES YQYHC5L1GPA9 | 6125.750 | 6138.250 | 6114.250 | 6127.500 | 1902280.0 | 6125.750 | 997849.0 | |
| ES YTG30NVEFCW1 | 6185.250 | 6198.750 | 6173.500 | 6184.250 | 5044.0 | 6185.250 | 197.0 | |
| ES YVXOP65RE0HT | 6238.250 | 6258.000 | 6229.375 | 6238.250 | 20.0 | 6238.250 | 0.0 | |
| ES YYFADOG4CO3L | 6299.125 | 6313.000 | 6057.000 | 6071.500 | 1106.0 | 6299.125 | 0.0 | |
| 2024-12-19 | ES YOGVNNAOI1OH | 5872.250 | 6074.500 | 5840.000 | 6050.250 | 556365.0 | 5872.250 | 335048.0 |
| ES YQYHC5L1GPA9 | 5939.500 | 6148.000 | 5906.500 | 6124.000 | 2064361.0 | 5939.500 | 2009987.0 | |
| ES YTG30NVEFCW1 | 6001.250 | 6205.000 | 5966.000 | 6181.250 | 5096.0 | 6001.250 | 536.0 | |
| ES YVXOP65RE0HT | 6054.250 | 6450.750 | 5934.375 | 6243.375 | 20.0 | 6054.250 | 0.0 | |
| ES YYFADOG4CO3L | 6315.000 | 6315.000 | 6315.000 | 6315.000 | 1116.0 | 6315.000 | 10.0 | |
| ES Z0WW26QHBBPD | 6171.375 | 6379.625 | 6142.000 | 6368.375 | 0.0 | 6171.375 | 0.0 |
# Select the contract with the largest open interest each day.
most_oi = history.groupby('time').apply(lambda x: x.nlargest(1, 'openinterest')).reset_index(level=1, drop=True).openinterest
time symbol 2024-12-18 ES YQYHC5L1GPA9 1902280.0 2024-12-19 ES YQYHC5L1GPA9 2064361.0 Name: openinterest, dtype: float64
If you intend to use the data in the DataFrame to create FutureUniverse objects, request that the history request returns the data type you need.
Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame.
To get a list of FutureUniverse objects instead of a DataFrame, call the history[FutureUniverse] method.
# Get the 5 trailing daily FutureUniverse objects in FutureUniverse format.
history = self.history[FutureUniverse](future.symbol, 5, Resolution.DAILY)
# Iterate through the FutureUniverse objects and access their volumes.
for future_universe in history:
t = future_universe.end_time
most_oi = sorted(future_universe, key=lambda contract: contract.open_interest)[-1]
Contango
To get historical contango data for VX Futures, call the History<VIXCentralContango> method with the dataset Symbol.
To get historical contango data for VX Futures, call the history method with the dataset Symbol.
This method returns a DataFrame that contains the data point attributes.
public class VIXContangoHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Add the dataset and save a reference to its Symbol.
var symbol = AddData<VIXCentralContango>("VIX", Resolution.Daily).Symbol;
// Get the trailing 7 days of contango data
var history = History<VIXCentralContango>(symbol, 7, Resolution.Daily);
// Iterate each data point and access its attributes.
foreach (var dataPoint in history)
{
var t = dataPoint.EndTime;
var value = dataPoint.Contango_F2_Minus_F1;
}
}
} class VIXContangoHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Add the dataset and save a reference to its Symbol.
symbol = self.add_data(VIXCentralContango, "VIX", Resolution.DAILY).symbol
# Get the trailing 7 days of contango data in DataFrame format.
history = self.history(symbol, 7, Resolution.DAILY)
| contango_f2_minus_f1 | contango_f7_minus_f4 | contango_f7_minus_f4_div_3 | f1 | f2 | f3 | f4 | f5 | f6 | f7 | f8 | frontmonth | period | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| symbol | time | |||||||||||||
| VIX.VIXCentralContango | 2024-12-13 | 0.1314 | 0.0498 | 0.0166 | 14.4062 | 16.2991 | 17.1553 | 17.9005 | 18.2460 | 18.5583 | 18.7923 | 18.9500 | 12 | 1 days |
| 2024-12-14 | 0.1212 | 0.0497 | 0.0166 | 14.5190 | 16.2782 | 17.1250 | 17.9474 | 18.2993 | 18.5750 | 18.8390 | 19.0500 | 12 | 1 days | |
| 2024-12-17 | 0.1299 | 0.0457 | 0.0152 | 14.6997 | 16.6091 | 17.4592 | 18.1963 | 18.4965 | 18.7411 | 19.0282 | 19.1884 | 12 | 1 days | |
| 2024-12-18 | 0.0765 | 0.0389 | 0.0130 | 15.7483 | 16.9531 | 17.6666 | 18.2998 | 18.4996 | 18.7185 | 19.0108 | 19.1500 | 12 | 1 days |
# Calculate the changes in contango. contango_diff = history.f1.diff().iloc[1:]
symbol time
VIX.VIXCentralContango 2024-12-14 0.1128
2024-12-17 0.1807
2024-12-18 1.0486
Name: f1, dtype: float64
If you intend to use the data in the DataFrame to create VIXCentralContango objects, request that the history request returns the data type you need.
Otherwise, LEAN consumes unnecessary computational resources populating the DataFrame.
To get a list of dataset objects instead of a DataFrame, call the history[VIXCentralContango] method.
# Get the trailing 7 days of contango data in VIXCentralContango format.
history = self.history[VIXCentralContango](symbol, 7, Resolution.DAILY)
# Iterate through each VIXCentralContango object.
for data_point in history:
t = data_point.end_time
value = data_point.contango_f_2_minus_f_1
Indicators
To get historical indicator values, call the IndicatorHistoryindicator_history method with an indicator and the security's Symbol.
public class FuturesIndicatorHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Get the Symbol of a security.
var symbol = AddFuture(Futures.Indices.SP500EMini).Symbol;
// Get the 21-day SMA values of the security for the last 5 trading days.
var history = IndicatorHistory(new SimpleMovingAverage(21), symbol, 5, Resolution.Daily);
// Get the maximum of the SMA values.
var maxSMA = history.Max(indicatorDataPoint => indicatorDataPoint.Current.Value);
}
} class FuturesIndicatorHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Get the Symbol of a security.
symbol = self.add_future(Futures.Indices.SP_500_E_MINI).symbol
# Get the 21-day SMA values of the security for the last 5 trading days.
history = self.indicator_history(SimpleMovingAverage(21), symbol, 5, Resolution.DAILY)
To organize the data into a DataFrame, use the data_frame property of the result.
# Organize the historical indicator data into a DataFrame to enable pandas wrangling. history_df = history.data_frame
| current | rollingsum | |
|---|---|---|
| 2024-12-12 17:00:00 | 6150.577121 | 129162.119546 |
| 2024-12-13 17:00:00 | 6154.322490 | 129240.772299 |
| 2024-12-16 17:00:00 | 6162.919815 | 129421.316116 |
| 2024-12-17 17:00:00 | 6169.413410 | 129557.681602 |
| 2024-12-18 17:00:00 | 6166.050570 | 129487.061970 |
# Get the maximum of the SMA values. sma_max = history_df.current.max()
The IndicatorHistoryindicator_history method resets your indicator, makes a history request, and updates the indicator with the historical data.
Just like with regular history requests, the IndicatorHistoryindicator_history method supports time periods based on a trailing number of bars, a trailing period of time, or a defined period of time.
If you don't provide a resolution argument, it defaults to match the resolution of the security subscription.
To make the IndicatorHistoryindicator_history method update the indicator with an alternative price field instead of the close (or mid-price) of each bar, pass a selector argument.
// Get the historical values of an indicator over the last 30 days, applying the indicator to the security's volume. var history = IndicatorHistory(indicator, symbol, TimeSpan.FromDays(30), selector: Field.Volume);
# Get the historical values of an indicator over the last 30 days, applying the indicator to the security's volume. history = self.indicator_history(indicator, symbol, timedelta(30), selector=Field.VOLUME)
Some indicators require the prices of two securities to compute their value (for example, Beta).
In this case, pass a list of the Symbol objects to the method.
public class FuturesMultiAssetIndicatorHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 12, 19);
SetEndDate(2024, 12, 31);
// Add the target and reference securities.
var targetSymbol = AddFuture(Futures.Metals.Gold).Symbol;
var referenceSymbol = AddFuture(Futures.Indices.SP500EMini).Symbol;
// Create a 21-period Beta indicator.
var beta = new Beta("", targetSymbol, referenceSymbol, 21);
// Get the historical values of the indicator over the last 10 trading days.
var history = IndicatorHistory(beta, new[] {targetSymbol, referenceSymbol}, 10, Resolution.Daily);
// Get the average Beta value.
var avgBeta = history.Average(indicatorDataPoint => indicatorDataPoint.Current.Value);
}
} class FuturesMultiAssetIndicatorHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Add the target and reference securities.
target_symbol = self.add_future(Futures.Metals.GOLD).symbol
reference_symbol = self.add_future(Futures.Indices.SP_500_E_MINI).symbol
# Create a 21-period Beta indicator.
beta = Beta("", target_symbol, reference_symbol, 21)
# Get the historical values of the indicator over the last 10 trading days.
history = self.indicator_history(beta, [target_symbol, reference_symbol], 10, Resolution.DAILY)
# Get the average Beta value.
beta_avg = history.data_frame.mean()
If you already have a list of Slice objects, you can pass them to the IndicatorHistoryindicator_history method to avoid the internal history request.
var slices = History(new[] {symbol}, 30, Resolution.Daily);
var history = IndicatorHistory(indicator, slices);
Examples
The following examples demonstrate some common practices for trading Futures with historical data.
Example 1: Stock-Gold All-Weather Portfolio
The following algorithm constructs a monthly-rebalanced, risk-parity portfolio using S&P 500 E-Mini and Micro Gold Futures contracts. A risk-parity approach balances the contribution to risk from each asset class, helping reduce overall portfolio drawdowns and improve diversification. The position sizing is determined using 1-year of historical daily returns for the selected Futures universe.
public class FutureHistoricalDataAlgorithm : QCAlgorithm
{
private List<Future> _futures;
private IPortfolioOptimizer _optimizer;
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
SetCash(1_000_000);
SetSecurityInitializer(new BrokerageModelSecurityInitializer(BrokerageModel, new FuncSecuritySeeder(GetLastKnownPrices)));
// Select the future contracts representing various asset classes to diversify the portfolio.
_futures = [.. new[] { Futures.Indices.SP500EMini, Futures.Metals.MicroGold }
.Select(x => AddFuture(x,
fillForward: true,
extendedMarketHours: true,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
dataMappingMode: DataMappingMode.OpenInterest,
contractDepthOffset: 0))];
// Instantiate the optimizer to perform risk-parity optimization.
// Risk Parity portfolio can dissipate the risk of each crypto pair to reduce overall drawdown.
_optimizer = new RiskParityPortfolioOptimizer(0, 1);
// Set a scheduled event to rebalance the portfolio at the start of every month.
Schedule.On(
DateRules.MonthStart(),
TimeRules.AfterMarketOpen(_futures[0].Symbol, 1),
Rebalance
);
SetWarmUp(1);
}
private void Rebalance()
{
// Historical data request to get 1-year data for optimization.
var symbols = _futures.Select(x => x.Symbol).ToList();
var history = History<TradeBar>(symbols, 253, Resolution.Daily)
.Where(x => _futures.All(y => x.ContainsKey(y.Symbol)))
.ToList();
// Daily return on the universe members to calculate the optimized weights.
var returns = GetReturns(history, symbols);
// Calculate the optimized weights.
var weights = _optimizer.Optimize(returns);
// Rebalance the portfolio according to the optimized weights.
var targets = Enumerable.Range(0, weights.Length)
.Select(i => new PortfolioTarget(_futures[i].Mapped, Convert.ToDecimal(weights[i])/2))
.ToList();
SetHoldings(targets, liquidateExistingHoldings: true);
}
private double[,] GetReturns(List<DataDictionary<TradeBar>> history, List<Symbol> symbols)
{
// Create a 2d array of historical daily returns from historical price data.
var returns = new double[history.Count, symbols.Count];
for (int j = 0; j < symbols.Count; j++)
{
var lastPrice = 0m;
for (int i = 0; i < history.Count; i++)
{
var current = history[i][symbols[j]].Close;
if (i > 0)
{
returns[i, j] = (double)((current - lastPrice) / lastPrice);
}
lastPrice = current;
}
}
return returns;
}
} from Portfolio.RiskParityPortfolioOptimizer import RiskParityPortfolioOptimizer
class FuturesHistoricalDataAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(1_000_000)
# Select the future contracts representing various asset classes to diversify the portfolio.
self._futures = [self.add_future(
x,
fill_forward=True,
extended_market_hours=True,
data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
data_mapping_mode=DataMappingMode.OPEN_INTEREST,
contract_depth_offset=0
) for x in [Futures.Indices.SP_500_E_MINI, Futures.Metals.MICRO_GOLD]]
# Instantiate the optimizer to perform risk-parity optimization.
# Risk Parity portfolio can dissipate the risk of each crypto pair to reduce overall drawdown.
self._optimizer = RiskParityPortfolioOptimizer(0.0, 1.0)
# Set a scheduled event to rebalance the portfolio at the start of every month.
self.schedule.on(
self.date_rules.month_start(),
self.time_rules.after_market_open(self._futures[0].symbol, 1),
self.rebalance
)
def rebalance(self) -> None:
# Historical data request to get 1-year data for optimization.
history = self.history([x.symbol for x in self._futures], 253, Resolution.DAILY, extended_market_hours=True, fill_forward=True)\
.droplevel([0]).unstack(0).close.dropna()
# Daily return on the universe members to calculate the optimized weights.
returns = history.pct_change().dropna()
# Calculate the optimized weights.
weights = self._optimizer.optimize(returns)
# Rebalance the portfolio according to the optimized weights.
targets = [PortfolioTarget(future.mapped, size/2.0) for future, size in zip(self._futures, weights)]
self.set_holdings(targets, liquidate_existing_holdings=True)