I'm developing an indicator in Indie. I’m trying to calculate Bollinger Bands and Keltner Channels, but I’m running into an error when adding a Series[float]
to a float
value.
Here’s the error message:
Error: 20:20 cannot apply operator
+
to operands of types: <class 'indie.Series[float]'> and <class 'float'>
Here’s the relevant code snippet:
sDev = StdDev.new(self.close, length)
mid_line_bb = Sma.new(self.close, length)
lower_band_bb = mid_line_bb + num_dev_dn * sDev[0] # <-- ERROR HERE
upper_band_bb = mid_line_bb + num_dev_up * sDev[0] # <-- ERROR HERE
What I’ve Tried:
sDev[0]
with MutSeriesF.new()
, but that caused another issue.sDev.value_or(0)
(which doesn’t seem to exist in Indie v4).I assume the issue is that mid_line_bb
is a Series[float]
, while sDev[0]
is a single float. How should I properly handle this type of mismatch in Indie?
The problem is that you cannot add a Series container with a float number, you must extract a specific value from the Series and perform an arithmetic operation with it.
You can extract the value from the Series using square brackets mid_line_bb[0]
or using the get method mid_line_bb.get(offset=0, default=0)
.
The source code of the BB algorithm on Indie may also help you:
# indie:lang_version = 5
from indie import algorithm, SeriesF, MutSeriesF
from indie.algorithms import Sma, StdDev
@algorithm
def Bb(self, src: SeriesF, length: int, mult: float) -> tuple[SeriesF, SeriesF, SeriesF]:
'''Bollinger Bands'''
middle = Sma.new(src, length)[0]
dev = mult * StdDev.new(src, length)[0]
lower = middle - dev
upper = middle + dev
return MutSeriesF.new(lower), MutSeriesF.new(middle), MutSeriesF.new(upper)
If we adapt this to your example, we will get the following indicator code:
# indie:lang_version = 5
from indie import indicator, param
from indie.algorithms import StdDev, Sma
@indicator('Std dev', overlay_main_pane=True)
@param.int('length', default=5)
@param.float('num_dev_dn', default=1.0)
@param.float('num_dev_up', default=1.0)
def Main(self, length, num_dev_dn, num_dev_up):
sDev = StdDev.new(self.close, length)
mid_line_bb = Sma.new(self.close, length)
lower_band_bb = mid_line_bb[0] + num_dev_dn * sDev[0]
upper_band_bb = mid_line_bb[0] + num_dev_up * sDev[0]
return mid_line_bb[0], lower_band_bb, upper_band_bb
This code on Indie v4 would have looked the same, switching to v5 did not affect working with Series type.