book
Checkout our new book! Hands on AI Trading with Python, QuantConnect, and AWS Learn More arrow

Indicators

Plotting Indicators

Introduction

LEAN provides helper methods to make it simple to create indicator plots.

Plot Update Events

To plot all of the values of some indicators, in the initialize method, call the plot_indicator method. The method plots each indicator value as the indicator updates. The method accepts up to four indicators.

Select Language:
symbol = self.add_equity("SPY")
sma_short = self.sma(symbol, 10)
sma_long = self.sma(symbol, 20)
self.plot_indicator("<chartName>", sma_short, sma_long)

Plot Current Values

To plot the current value of indicators, call the plot method. The method accepts up to four indicators.

Select Language:
# In Initialize
symbol = self.add_equity("SPY")
sma_short = self.sma(symbol, 10)
sma_long = self.sma(symbol, 20)

# In OnData
self.plot("<chartName>", sma_short, sma_long)

View Charts

The following table describes where you can access your charts, depending on how to deploy your algorithms:

LocationAlgorithm Lab AlgorithmsCLI Cloud AlgorithmsCLI Local Algorithms
Backtest results pagegreen checkgreen check
Live results pagegreen checkgreen check
/backtests/read endpointgreen checkgreen check
/live/read endpointgreen checkgreen check
ReadBacktest methodgreen checkgreen check
ReadLiveAlgorithm methodgreen checkgreen check
Local JSON file in your <projectName> / backtests / <timestamp> or <projectName> / live / <timestamp> directorygreen checkgreen check

Chart Limits

Not all indicators share the same base type(T), so you may not be able to plot them together since some indicators require points while others require TradeBars.

Select Language:
# Plot indicators that extend the "Indicator" type
self.plot_indicators("All Indicator Values", sma, rsi)
self.plot("Current Indicator Values", sma, rsi); 

# Plot indicators that extend the "TradeBarIndicator" type
self.plot_indicators("All Indicator Values", atr, aroon)
self.plot("Current Indicator Values", atr, aroon); 

If your indicator plots are complex, call the plot method with one indicator and plot its current.value property. For more information about plotting, see Charting.

Examples

The following examples demonstrate some common practices for plotting indicators.

Example 1: SMA Ribbon

The following algorithm trades simple moving average (SMA) crossings, which involves five SMA indicators to form an SMA ribbon. To visualize the ribbon, it plots each indicator with a different color.

Select Language:
class PlottingIndicatorAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2019, 1, 1)
        self.set_end_date(2021, 7, 1)
        
        # Add SPY data to update indicators and trade.
        self._spy = self.add_equity("SPY", Resolution.DAILY).symbol

        # Create a chart to plot the ribbon. To better visualize the plot, use different colors per series.
        chart = Chart("Ribbon")
        chart.add_series(Series("Price", SeriesType.CANDLE, "$"))
        chart.add_series(Series("SMA10", SeriesType.LINE, "$", Color.VIOLET))
        chart.add_series(Series("SMA20", SeriesType.LINE, "$", Color.BLUE))
        chart.add_series(Series("SMA30", SeriesType.LINE, "$", Color.GREEN))
        chart.add_series(Series("SMA40", SeriesType.LINE, "$", Color.YELLOW))
        chart.add_series(Series("SMA50", SeriesType.LINE, "$", Color.RED))

        # Create 5 SMA indicators to create the SMA ribbon.
        self._smas = {n: self._create_sma(n) for n in [10, 20, 30, 40, 50]}

    def _create_sma(self, n: int) -> SimpleMovingAverage:
        sma = self.sma(self._spy, n, Resolution.DAILY)
        # Plot the indicator value to create the ribbon when the indicator updates.
        sma.updated += lambda sender, point: self.plot("Ribbon", f"SMA{n}", point.value)
        # Warm up the indicator so it's ready to use immediately.
        self.warm_up_indicator(self._spy, sma)
        return sma

    def on_data(self, slice: Slice) -> None:
        bar = slice.bars.get(self._spy)
        if bar:
            # Plot the candlestick when you get the daily bar.
            self.plot("Ribbon", "Price", bar.open, bar.high, bar.low, bar.close)

            # Follow strong upward trend.
            if self._is_uptrend(bar.close, self._smas):
                self.set_holdings(self._spy, 1)
            # Follow strong downward trend.
            elif self._is_downtrend(bar.close, self._smas):
                self.set_holdings(self._spy, -1)
            # Liquidate positions if the trend is less deterministic.
            else:
                self.liquidate()

    def _is_uptrend(self, price: float, smas: List[SimpleMovingAverage]) -> bool:
        # Uptrend occurs when price is above all SMAs and shorter SMAs are above longer SMAs.
        smas_list = [x[1].current.value for x in sorted(smas.items(), key=lambda x: x[0])]
        return all([smas_list[i] < smas_list[i-1] for i in range(1, len(smas_list))]) and price > smas_list[0]

    def _is_downtrend(self, price: float, smas: List[SimpleMovingAverage]) -> bool:
        # Downtrend occurs when price is below all SMAs and shorter SMAs are below longer SMAs.
        smas_list = [x[1].current.value for x in sorted(smas.items(), key=lambda x: x[0])]
        return all([smas_list[i] > smas_list[i-1] for i in range(1, len(smas_list))]) and price < smas_list[0]

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: