For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

# Must be real number, not LinesOperation

• Hi there, I'm attempting to make a custom stochastic of my own after browsing a couple on these forums. I'm gonna jump straight into the code.

class MyStochastic(bt.Indicator):
lines = ('Stoc', 'MyStoch',)

def __init__(self):

self.f = math.degrees(1.44 * 3.14159 / 10)
self.a1 = math.exp(-self.f)
self.b1 = 2 * self.a1 * math.cos(self.f)
self.c2 = self.b1
self.c3 = -self.a1 * self.a1
self.c1 = 1 - self.c2 - self.c3

super(MyStochastic,self).__init__()

def prenext(self):
self.HighestC = bt.indicators.Highest(period=9)
self.LowestC = bt.indicators.Lowest(period=9)
self.l.Stoc[0] = (self.data[0]-self.LowestC/(self.HighestC-self.LowestC))
self.lines.MyStoch[0] = self.c1*(self.l.Stoc[0]+self.l.Stoc[0])/2 + self.c2*self.l.Stoc[0] + self.c3*self.l.Stoc[0]

def nextstart(self):
self.HighestC = bt.indicators.Highest(period=9)
self.LowestC = bt.indicators.Lowest(period=9)
self.l.Stoc[0] = (self.data[0]-self.LowestC/(self.HighestC-self.LowestC))
self.lines.MyStoch[0] = self.c1*(self.l.Stoc[0]+self.l.Stoc[-1])/2 + self.c2*self.l.MyStoch[-1] + self.c3*self.l.MyStoch[-1]

def next(self):
self.HighestC = bt.indicators.Highest(period=9)
self.LowestC = bt.indicators.Lowest(period=9)
self.l.Stoc[0] = (self.data[0]-self.LowestC/(self.HighestC-self.LowestC))
self.lines.MyStoch[0] = self.c1*(self.l.Stoc[0]+self.l.Stoc[-1])/2 + self.c2*self.l.MyStoch[-1] + self.c3*self.l.MyStoch[-2]

Here's just a quick description of why I have it setup the way it is:
Using the three sections (prenext, nextstart, next) allow me to initialize the lines properly. This is a fix that the user @Guwop seemed unable to find. I have confirmed the effectiveness of this method with other recursive indicators before this one.

I use the super(MyStochastic,self).init() because I also utilize the Highest and Lowest indicators, and it is my understanding that under these circumstances that including super() is necessary.

Here is the error message I receive upon running...

<ipython-input-12-4e36424d155e> in prenext(self)
75         self.HighestC = bt.indicators.Highest(period=9)
76         self.LowestC = bt.indicators.Lowest(period=9)
---> 77         self.l.Stoc[0] = ((self.data[0]-self.LowestC)/(self.HighestC-self.LowestC))
78         self.lines.MyStoch[0] = self.c1*(self.l.Stoc[0]+self.l.Stoc[0])/2 + self.c2*self.l.Stoc[0] + self.c3*self.l.Stoc[0]
79

220             value (variable): value to be set
221         '''
--> 222         self.array[self.idx + ago] = value
223         for binding in self.bindings:
224             binding[ago] = value

TypeError: must be real number, not LinesOperation

I'm not quite sure what it is that separates the values of self.l.Stoc[0] from self.l.MyStoch[0], because as I have mentioned previously, in other recursive indicators of mine, setting values to a lines object in the same manner as MyStoch has been no problem. Additionally, I have swapped out self.data[0] for an integer and receive the same error. I'd appreciate any help. Love the platform by the way. Thanks!

• Consider declaring indicators once in __init__:

self.HighestC = bt.indicators.Highest(self.data, period=9)
self.LowestC = bt.indicators.Lowest(self.data, period=9)

and then use

self.l.Stoc[0] = (self.data[0]-self.LowestC[0])/(self.HighestC[0]-self.LowestC[0])

• Alternatively in __init__ only:

HighestC = bt.indicators.Highest(self.data, period=9)
LowestC = bt.indicators.Lowest(self.data, period=9)
self.l.Stoc = (self.data-LowestC)/(HighestC-LowestC)

• @adrtod Yes that worked! Thank you very much. If it isn't too much to ask, would you mind explaining why it works that way? From what I had thought, init is a def that is only called once, and so the values for Highest/Lowest would only be calculated once, and not change with new data. Obviously this is not the case... does this mean that init is in fact called more than once?

• __init__ is called only once and only declares the indicators as objects, no computation is done during __init__ but they are handled automatically.
The same applies when using operators to combine indicators, see https://www.backtrader.com/docu/concepts.html#operators-using-natural-constructs

• @adrtod, Thank you for the explanation it's all making sense now - especially considering how the declarative approach to indicators is setup.

• Overtaken by @adrtod. Glad to see someone with such an intimate knowledge of things.

});