Indicators
Data Point Indicators
Create Subscriptions
You need to subscribe to some market data in order to calculate indicator values.
var qb = new QuantBook(); var symbol = qb.AddEquity("SPY").Symbol;
qb = QuantBook() symbol = qb.add_equity("SPY").symbol
Create Indicator Timeseries
You need to subscribe to some market data and create an indicator in order to calculate a timeseries of indicator values. In this example, use a 20-period 2-standard-deviation BollingerBands
indicator.
var bb = new BollingerBands(20, 2);
bb = BollingerBands(20, 2)
You can create the indicator timeseries with the Indicator
helper method or you can manually create the timeseries.
Indicator Helper Method
To create an indicator timeseries with the helper method, call the Indicator
method.
// Create a dataframe with a date index, and columns are indicator values. var bbIndicator = qb.Indicator(bb, symbol, 50, Resolution.Daily);
# Create a dataframe with a date index, and columns are indicator values. bb_dataframe = qb.indicator(bb, symbol, 50, Resolution.DAILY)

Manually Create the Indicator Timeseries
Follow these steps to manually create the indicator timeseries:
- Get some historical data.
- Set the indicator
Window.Size
window.size
for each attribute of the indicator to hold their values. - Iterate through the historical market data and update the indicator.
- Display the data.
- Populate a
DataFrame
with the data in theIndicator
object.
// Request historical trading data with the daily resolution. var history = qb.History(symbol, 70, Resolution.Daily);
# Request historical trading data with the daily resolution. history = qb.history[TradeBar](symbol, 70, Resolution.DAILY)
// Set the window.size to the desired timeseries length bb.Window.Size=50; bb.LowerBand.Window.Size=50; bb.MiddleBand.Window.Size=50; bb.UpperBand.Window.Size=50; bb.BandWidth.Window.Size=50; bb.PercentB.Window.Size=50; bb.StandardDeviation.Window.Size=50; bb.Price.Window.Size=50;
# Set the window.size to the desired timeseries length bb.window.size=50 bb.lower_band.window.size=50 bb.middle_band.window.size=50 bb.upper_band.window.size=50 bb.band_width.window.size=50 bb.percent_b.window.size=50 bb.standard_deviation.window.size=50 bb.price.window.size=50
foreach (var bar in history) { bb.Update(bar.EndTime, bar.Close); }
for bar in history: bb.update(bar.end_time, bar.close)
foreach (var i in Enumerable.Range(0, 5).Reverse()) { Console.WriteLine($"{bb[i].EndTime:yyyyMMdd} {bb[i].Value:f4} {bb.LowerBand[i].Value:f4} {bb.MiddleBand[i].Value:f4} {bb.UpperBand[i].Value:f4} {bb.BandWidth[i].Value:f4} {bb.PercentB[i].Value:f4} {bb.StandardDeviation[i].Value:f4} {bb.Price[i].Value:f4}"); }

bb_dataframe = pd.DataFrame({ "current": pd.Series({x.end_time: x.value for x in bb}), "lowerband": pd.Series({x.end_time: x.value for x in bb.lower_band}), "middleband": pd.Series({x.end_time: x.value for x in bb.middle_band}), "upperband": pd.Series({x.end_time: x.value for x in bb.upper_band}), "bandwidth": pd.Series({x.end_time: x.value for x in bb.band_width}), "percentb": pd.Series({x.end_time: x.value for x in bb.percent_b}), "standarddeviation": pd.Series({x.end_time: x.value for x in bb.standard_deviation}), "price": pd.Series({x.end_time: x.value for x in bb.price}) }).sort_index()

Plot Indicators
Jupyter Notebooks don't currently support libraries to plot historical data, but we are working on adding the functionality. Until the functionality is added, use Python to plot data point indicators.
You need to create an indicator timeseries to plot the indicator values.
Follow these steps to plot the indicator values:
- Select the columns/features to plot.
- Call the
plot
method. - Show the plots.
bb_plot = bb_indicator[["upperband", "middleband", "lowerband", "price"]]
bb_plot.plot(figsize=(15, 10), title="SPY BB(20,2)"))
plt.show()

Examples
The following examples demonstrate some common practices for researching with data point indicators.
Example 1: Quick Backtest On Bollinger Band
The following example demonstrates a quick backtest to testify the effectiveness of a Bollinger Band mean-reversal under the research enviornment.
// Load the assembly files and data types in their own cell. #load "../Initialize.csx" // Load the necessary assembly files. #load "../QuantConnect.csx" #r "../Plotly.NET.dll" #r "../Plotly.NET.Interactive.dll" // Import the QuantConnect, Plotly.NET, and Accord packages for calculation and plotting. using QuantConnect; using QuantConnect.Indicators; using QuantConnect.Research; using Plotly.NET; using Plotly.NET.Interactive; using Plotly.NET.LayoutObjects; // Instantiate the QuantBook instance for researching. var qb = new QuantBook(); // Request SPY data to work with the indicator. var symbol = qb.AddEquity("SPY").Symbol; // Create the Bollinger Band indicator with parameters to be studied. var bb = new BollingerBands(20, 2); // Get the history of SPY to update the indicator and trade. var history = qb.History<TradeBar>(symbol, 252, Resolution.Daily).ToList(); // Obtain the cumulative return curve as a mini-backtest. var equity = new List<decimal>() { 1m }; var time = new List<DateTime>() { history[0].EndTime }; for (int i = 0; i < history.Count - 1; i++) { var bar = history[i]; var nextBar = history[i+1]; // Update the indicator value. bb.Update(bar.EndTime, bar.Close); // Get 1-day forward return. var pctChg = (nextBar.Close - bar.Close) / bar.Close; // Buy if the asset is underprice (below the lower band), sell if overpriced (above the upper band) var order = bar.Close < bb.LowerBand ? 1 : (bar.Close > bb.UpperBand ? -1 : 0); var equityChg = order * pctChg; equity.Add((1m + equityChg) * equity[^1]); time.Add(nextBar.EndTime); } // Create line chart of the equity curve. var chart = Chart2D.Chart.Line<DateTime, decimal, string>( time, equity ); // Create a Layout as the plot settings. LinearAxis xAxis = new LinearAxis(); xAxis.SetValue("title", "Time"); LinearAxis yAxis = new LinearAxis(); yAxis.SetValue("title", "Equity"); Title title = Title.init($"Equity by Time of {symbol}"); Layout layout = new Layout(); layout.SetValue("xaxis", xAxis); layout.SetValue("yaxis", yAxis); layout.SetValue("title", title); // Assign the Layout to the chart. chart.WithLayout(layout); // Display the plot. HTML(GenericChart.toChartHTML(chart))
# Instantiate the QuantBook instance for researching. qb = QuantBook() # Request SPY data to work with the indicator. symbol = qb.add_equity("SPY").symbol # Create the Bollinger Band indicator with parameters to be studied. bb = BollingerBands(20, 2) # Get the indicator history of the indicator. bb_dataframe = qb.indicator(bb, symbol, 252, Resolution.DAILY) # Create a order record and return column. # Buy if the asset is underprice (below the lower band), sell if overpriced (above the upper band) bb_dataframe["position"] = bb_dataframe.apply(lambda x: 1 if x.price < x.lowerband else -1 if x.price > x.upperband else 0, axis=1) # Get the 1-day forward return. bb_dataframe["return"] = bb_dataframe["price"].pct_change().shift(-1).fillna(0) bb_dataframe["return"] = bb_dataframe["position"] * bb_dataframe["return"] # Obtain the cumulative return curve as a mini-backtest. equity_curve = (bb_dataframe["return"] + 1).cumprod() equity_curve.plot(title="Equity Curve on BBand Mean Reversal", ylabel="Equity", xlabel="time")