Combining Indicators


This page explains how to create, update and visualize LEAN Composite indicators.


Working knowledge of C#.

If you use Python, you must understand how to work with pandas DataFrames and Series. If you are not familiar with pandas, refer to the pandas documentation.

Get Historical Data

Get some historical market data to warm-up and create a historical record of indicator values. For example, to get data for SPY, run:

var qb = new QuantBook();
var symbol = qb.AddEquity("SPY").Symbol;
var history = qb.History(symbol, 70, Resolution.Daily);
qb = QuantBook()
symbol = qb.AddEquity("SPY").Symbol
history = qb.History(symbol, 70, Resolution.Daily).loc[symbol]

Create Indicator Timeseries

Follow these steps to create an indicator timeseries:

  1. Create a composite indicator from base indicators. In this tutorial, we'll be using a 10-period SimpleMovingAverage of a 10-period RelativeStrengthIndex indicator.
  2. var rsi = new RelativeStrengthIndex(10);
    var sma = new SimpleMovingAverage(10);
    var smaOfRsi = IndicatorExtensions.Of(sma, rsi);
    rsi = RelativeStrengthIndex(10)
    sma = SimpleMovingAverage(10)
    sma_of_rsi = IndicatorExtensions.Of(sma, rsi)
  3. Create a RollingWindow for each attribute of the indicator to hold their values.
  4. In this example, save 50 data points.

    var time = new RollingWindow<DateTime>(50);
    var window = new Dictionary<string, RollingWindow<decimal>>();
    window["SMA Of RSI"] = new RollingWindow<decimal>(50);
    window["rollingsum"] = new RollingWindow<decimal>(50);
    window = {}
    window['time'] = RollingWindow[DateTime](50)
    window["SMA Of RSI"] = RollingWindow[float](50)
    window["rollingsum"] = RollingWindow[float](50)(50)
  5. Set handler methods to update the RollingWindows.
  6. smaOfRsi.Updated += (sender, updated) => 
        var indicator = (SimpleMovingAverage)sender;    // Use terminal indicator class.
        window["SMA Of RSI"].Add(updated);
    def UpdateSmaOfRsiWindow(sender: object, updated: IndicatorDataPoint) -> None:
        indicator = sender
        window["SMA Of RSI"].Add(updated.Value)
    sma_of_rsi.Updated += UpdateSmaOfRsiWindow

    When the indicators receive new data, the handler will add the new IndicatorDataPoints into the RollingWindows.

  7. Iterate the historical market data to update the indicators and the RollingWindows.
  8. foreach(var bar in history){
        // Update the base indicators, the composite indicator will update automatically when the base indicator is updated.
        rsi.Update(bar.EndTime, bar.Close);
    for time, row in history.iterrows():
        # Update the base indicators, the composite indicator will update automatically when the base indicator is updated.
        rsi.Update(time, row.close);
  9. Display the data.
  10. Console.WriteLine($"time,{string.Join(',', window.Select(kvp => kvp.Key))}");
    foreach (var i in Enumerable.Range(0, 5).Reverse())
        var data = string.Join(", ", window.Select(kvp => Math.Round(kvp.Value[i],6)));
        Console.WriteLine($"{time[i]:yyyyMMdd}, {data}");
  11. Convert the RollingWindows' data into pandas.DataFrame.
  12. sma_of_rsi_dataframe = pd.DataFrame(window).set_index('time')

Indicator Helper Method

Composite Indicator does not support qb.Indicator helper method to create an indicator timeseries.

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 historical Equity Options data.

You can call the in-built plot method of pandas.DataFrame to plot the indicators.

  1. Select the columns/features for plotting.
  2. sma_of_rsi_plot = sma_of_rsi_dataframe[["SMA Of RSI"]]
  3. Call plot to plot the indicator.
  4. sma_of_rsi_plot.plot(title="SPY SMA(10) of RSI(10)", figsize=(15, 10))
  5. Show the plots.

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: