---
title: "Plotting Indicators"
description: "LEAN provides helper methods to make it simple to create indicator plots."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/plotting-indicators
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/plotting-indicators.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/28%20Indicators/05%20Plotting%20Indicators
modified: 2026-11-02
index: https://www.quantconnect.com/llms.txt
---

# Plotting Indicators

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Indicators > Plotting Indicators

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

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

```python
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.

```python
# 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:

| Location | Algorithm Lab Algorithms | CLI Cloud Algorithms | CLI Local Algorithms |
| --- | --- | --- | --- |
| [Backtest results page](https://www.quantconnect.com/docs/v2/cloud-platform/backtesting/results.md) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) |  |
| [Live results page](https://www.quantconnect.com/docs/v2/cloud-platform/live-trading/results.md) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) |  |
| [/backtests/read endpoint](https://www.quantconnect.com/docs/v2/cloud-platform/api-reference/backtest-management/read-backtest/backtest-statistics.md) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) |  |
| [/live/read endpoint](https://www.quantconnect.com/docs/v2/cloud-platform/api-reference/live-management/read-live-algorithm/live-algorithm-statistics.md) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) |  |
| [ReadBacktest method](https://www.quantconnect.com/docs/v2/research-environment/meta-analysis/backtest-analysis.md) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) |  |
| [ReadLiveAlgorithm method](https://www.quantconnect.com/docs/v2/research-environment/meta-analysis/live-analysis.md) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) |  |
| Local `JSON` file in your `<projectName> / backtests / <timestamp>` or `<projectName> / live / <timestamp>` directory |  | ![green check](https://cdn.quantconnect.com/i/tu/check.png) | ![green check](https://cdn.quantconnect.com/i/tu/check.png) |

## 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`.

```python
# 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](https://www.quantconnect.com/docs/v2/writing-algorithms/charting.md).

## Examples

The following examples demonstrate some common practices for plotting indicators.

### Example 1: SMA Ribbon

The following algorithm trades [simple moving average](https://www.quantconnect.com/docs/v2/writing-algorithms/indicators/supported-indicators/simple-moving-average.md) (SMA) crossings, which involves five SMA indicators to form an SMA ribbon. To visualize the ribbon, it plots each indicator with a different color.

```python
class PlottingIndicatorAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)

        # 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]
```
