Indicators

Custom Resolutions

Introduction

This page explains how to create and update indicators with data of a custom resolution.

Prerequisites

Working knowledge of C#.

Working knowledge of Python and pandas. If you are not familiar with pandas, refer to the pandas documentation.

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.AddEquity("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.

Follow these steps to create an indicator timeseries:

  1. Get some historical data.
  2. var history = qb.History(symbol, 70, Resolution.Daily);
    history = qb.History[TradeBar](symbol, 70, Resolution.Daily)
  3. Create a data-point indicator.
  4. In this example, use a 20-period 2-standard-deviation BollingerBands indicator.

    var bb = new BollingerBands(20, 2);
    bb = BollingerBands(20, 2)
  5. Create a RollingWindow for each attribute of the indicator to hold their values.
  6. var time = new RollingWindow<DateTime>(50);
    var window = new Dictionary<string, RollingWindow<decimal>>();
    window["bollingerbands"] = new RollingWindow<decimal>(50);
    window["lowerband"] = new RollingWindow<decimal>(50);
    window["middleband"] = new RollingWindow<decimal>(50);
    window["upperband"] = new RollingWindow<decimal>(50);
    window["bandwidth"] = new RollingWindow<decimal>(50);
    window["percentb"] = new RollingWindow<decimal>(50);
    window["standarddeviation"] = new RollingWindow<decimal>(50);
    window["price"] = new RollingWindow<decimal>(50);
    
    window = {}
    window['time'] = RollingWindow[DateTime](50)
    window["bollingerbands"] = RollingWindow[float](50)
    window["lowerband"] = RollingWindow[float](50)
    window["middleband"] = RollingWindow[float](50)
    window["upperband"] = RollingWindow[float](50)
    window["bandwidth"] = RollingWindow[float](50)
    window["percentb"] = RollingWindow[float](50)
    window["standarddeviation"] = RollingWindow[float](50)
    window["price"] = RollingWindow[float](50)
    
  7. Attach a handler method to the indicator that updates the RollingWindow objects.
  8. bb.Updated += (sender, updated) => 
    {
        var indicator = (BollingerBands)sender;
        time.Add(updated.EndTime);
        window["bollingerbands"].Add(updated);
        window["lowerband"].Add(indicator.LowerBand);
        window["middleband"].Add(indicator.MiddleBand);
        window["upperband"].Add(indicator.UpperBand);
        window["bandwidth"].Add(indicator.BandWidth);
        window["percentb"].Add(indicator.PercentB);
        window["standarddeviation"].Add(indicator.StandardDeviation);
        window["price"].Add(indicator.Price);
    };
    def UpdateBollingerBandWindow(sender: object, updated: IndicatorDataPoint) -> None:
        indicator = sender
        window['time'].Add(updated.EndTime)
        window["bollingerbands"].Add(updated.Value)
        window["lowerband"].Add(indicator.LowerBand.Current.Value)
        window["middleband"].Add(indicator.MiddleBand.Current.Value)
        window["upperband"].Add(indicator.UpperBand.Current.Value)
        window["bandwidth"].Add(indicator.BandWidth.Current.Value)
        window["percentb"].Add(indicator.PercentB.Current.Value)
        window["standarddeviation"].Add(indicator.StandardDeviation.Current.Value)
        window["price"].Add(indicator.Price.Current.Value)
    
    bb.Updated += UpdateBollingerBandWindow

    When the indicator receives new data, the preceding handler method adds the new IndicatorDataPoint values into the respective RollingWindow.

  9. Create a TradeBarConsolidator to consolidate data into the custom resolution.
  10. var consolidator = new TradeBarConsolidator(TimeSpan.FromDays(7));
    consolidator = TradeBarConsolidator(timedelta(days=7))
  11. Attach a handler method to feed data into the consolidator and updates the indicator with the consolidated bars.
  12. consolidator.DataConsolidated += (sender, consolidated) =>
    {
        bb.Update(consolidated.EndTime, consolidated.Close);
    };
    consolidator.DataConsolidated += lambda sender, consolidated: bb.Update(consolidated.EndTime, consolidated.Close)

    When the consolidator receives 7 days of data, the handler generates a 7-day TradeBar and update the indicator.

  13. Iterate through the historical market data and update the indicator.
  14. foreach(var bar in history)
    {
        consolidator.Update(bar);
    }
    for bar in history:
        consolidator.Update(bar)
  15. Display the data.
  16. 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}");
    }
  17. Populate a DataFrame with the data in the RollingWindow objects.
  18. bb_dataframe = pd.DataFrame(window).set_index('time')

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 indicators.

Follow these steps to plot the indicator values:

  1. Select the columsn to plot.
  2. df = bb_dataframe[['lowerband', 'middleband', 'upperband', 'price']]
  3. Call the plot method.
  4. df.plot()
  5. Show the plot.
  6. plt.show()

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: