# Custom “*recursive*” indicator in Python with backtrader

In the previous article (*Custom Indicator Development in Python with backtrader*) the development of a custom indicator was explore (the *Stochastic* indicator)

But some indicators have a particularity: ** they are recursive**. This requires some extra management, because recursion needs to be solved for the calculation of the first value to be delivered (or else one remains stuck in the classic chicken-egg problem)

Let’s use the well known *Exponential Moving Average* (aka *EMA*) as an example of how a recursive indicator is developed. To simplify things, this is how the *EMA* is calculated

`ema(0) = (1 — alpha) * ema(-1) + alpha * data`

Where `ema(0)`

is the current value and `ema(-1)`

is the previous value (hence the *recursion*)

Although an exponential smoothing takes into account all the past values of a series, the trading industry (and traders) tends to think in terms of the `period`

(or numbers of bars) to which the exponential smoothing is applied. The smoothing factor ( `alpha`

) can be calculated as follows

`alpha = 2 / (period + 1`

For those interested in further reading the article in the *Wikipedia* explains the details

The obvious impulse when creating the `EMA`

in *backtrader* would be to do the following

import backtrader as btclass MyEMA(bt.ind.PeriodN):

lines = ('ema',)

params = (('period', 30),)

plotinfo = dict(subplot=False) # plot in same axis as the data def __init__(self):

alph = 2.0 / (self.p.period + 1.0)

self.l.ema = (1 - alph) * self.l.ema(-1) + alph * self.data

Which creates the *recursion conundrum* because one needs the previous value to calculate the current one, and there is obviously no previous value at the beginning of the chain of calculations.

**Note**: the indicator subclasses `PeriodN`

which already knows what to do with a parameter `period`

to inform the platform about the minimum warm up period requirements

If one decided to run this code against the sample data in the *backtrader* distribution the graphical output would show the problem

**The solution: add a seed value**

`next`

is the standard method for the step by step calculations in all objects with *lines* in *backtrader*, but there is one additional method which comes to the rescue for our problem of setting a seed value

`nextstart`

which is called exactly once: when the minimum warmup period for the indicator is met. It defaults to delegating the work to`next`

but in this case it will seed the calculation

import backtrader as btclass MyEMA(bt.ind.PeriodN):

lines = ('ema',)

params = (('period', 30),)

plotinfo = dict(subplot=False) # plot in same axis as the data def __init__(self):

alph = 2.0 / (self.p.period + 1.0)

self.l.ema = (1 - alph) * self.l.ema(-1) + alph * self.data

def nextstart(self):

period = self.p.period # for readability

self.l.ema[0] = self.data.get(size=period) / period

But if we were to run this in the default execution mode *backtrader* uses (**runonce =True**) this would simple deliver no value and the chart, just like above, would also be empty.

Running it with `cerebro.run(runonce=False)`

does the magic as seen in this chart.

**Why this?**

- When running in the default mode,
*backtrader*calculates things in vectorized mode and this has a consequence:`self.l.ema(-1)`

is a made to be a vector of values (i.e.: an array) which is precalculated before being using for the calculation of`self.l.ema`

Which simply means that the declarative approach (we declared the calculation method during `__init__`

, hence the *declarative* nature) combined with *recursion* faces restrictions when working in *vectorized* mode.

**Can it be done?**

Yes it can. But in this case one can forego the declarative approach and perform all calculations manually using the dirtiest inner tricks known only to advanced *bactraders*

import backtrader as btclass MyEMA(bt.ind.PeriodN):

lines = ('ema',)

params = (('period', 30),)

plotinfo = dict(subplot=False) # plot in same axis as the data def oncestart(self, start, end):

# Calculate a seed value for the EMA

src, dst = self.data.array, self.line.array

period = self.p.period # for readability

dst[start] = sum(src[start - period + 1:end]) / period def once(self, start, end):

src, dst = self.data.array, self.line.array

alpha = 2.0 / (self.p.period + 1.0)

alpha1 = 1.0 - alpha ema1 = dst[start - 1]

for i in range(start, end):

dst[i] = ema1 = alpha1 * ema1 + src[i] * alpha

In this case the methods `oncestart`

and `once`

have been used (recall the parameter for *cerebro* is called`runonce`

and this allows the calculation of the indicator in the faster `runonce=True`

mode in *backtrader* without being worried about recursion problems.

Of course, one doesn’t usually write two different versions of an *Indicator*, but rather one. See the source code for the *ExponentialSmoothing* indicator which is used in *backtrader* (the *ExponentialMovingAverage* is a wrapper to make it part of the larger family of moving averages) See it here