Custom Indicators


LEAN supports over 100 pre-built indicators, but a custom indicator is an indicator you define. It receives input, performs some calculation, and sets its output value. Custom indicators are helpful when you want to achieve any of the following results:

  • Use an indicator that LEAN doesn't currently implement
  • Combine built-in indicators beyond the logic of Indicator Extensions
  • Create your own unique indicator for trading

Define Indicators

Custom indicators must implement the PythonIndicator class. The indicator must have an Update method and Name, Time, and Value attributes. The Update method must accept an IndicatorDataPoint, QuoteBar, or TradeBar and return a boolean that represents if the indicator is ready. The Time attribute represents the last time you updated the indicator and the Value attribute represents the current indicator value. The following definition provides an example of a custom simple moving average indicator.

Custom indicators subsclass the IndicatorBase<IndicatorDataPoint>, BarIndicator, or TradeBarIndicator class, depending on the indicator type. The following definition provides an example of a custom simple moving average indicator that inherits the IndicatorBase<IndicatorDataPoint> class. To view examples of indicators that inherit the BarIndicator or TradeBarIndicator class, see the AverageTrueRange or VolumeWeightedAveragePriceIndicator implementation in the LEAN GitHub repository.

public class CustomSimpleMovingAverage : IndicatorBase<IndicatorDataPoint>, IIndicatorWarmUpPeriodProvider
    private RollingWindow<decimal> _window;
    public override bool IsReady => _window.IsReady;
    public int WarmUpPeriod => _window.Size;

    public CustomSimpleMovingAverage(string name, int period) : base(name)
        _window = new RollingWindow<decimal>(period);

    protected override decimal ComputeNextValue(IndicatorDataPoint input)
        return _window.Sum() / _window.Size;

    public override void Reset()
class CustomSimpleMovingAverage(PythonIndicator):
    def __init__(self, name, period):
        self.Name = name
        self.WarmUpPeriod = period
        self.Time = datetime.min
        self.Value = 0
        self.queue = deque(maxlen=period)

    def Update(self, input: BaseData) -> bool:
        count = len(self.queue)
        self.Time = input.Time
        self.Value = sum(self.queue) / count
        return count == self.queue.maxlen

Create Indicators

You must define a custom indicator before you can create an instance of it.

To create a custom indicator, call the indicator constructor.

private CustomSimpleMovingAverage _sma;

_sma = new CustomSimpleMovingAverage("My SMA", 10);
self.custom_sma = CustomSimpleMovingAverage("My SMA", 10)


The process to update custom indicators is the same process you use to update manual indicators. For more information about updating manual indicators, see Manual Updates or Automatic Updates.

Warm Up Indicators

The process to warm up custom indicators is the same process you use to warm up manual indicators.


Demonstration Algorithms Python

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: