I'm trying to port a PineScript indicator to the TakeProfit trading platform, but I'm running into type errors. When trying to use Bollinger Bands, I get this error:
Error: [internal] cannot create variable of type <class 'tuple[indie.Series[float], indie.Series[float], indie.Series[float]]'>
My code tries to access the Bollinger Bands results like this:
bb_result = Bb.new(self.close, length, mult)
bb_lower = bb_result[0][0] # Extract the float value from the lower band
bb_upper = bb_result[2][0] # Extract the float value from the upper band
Here's my Indie version of the indicator:
#indie:lang_version = 4
from math import isnan
from indie import indicator, SeriesF, MutSeriesF, plot, param, color, plot_style, line_style, Plot
from indie.algorithms import Sma, Tr, Bb, Highest, Lowest, LinReg
def mean(s1: SeriesF, s2: SeriesF, s3: SeriesF) -> float:
return s1[0] / 4 + s2[0] / 4 + s3[0] / 2
def nan_to_zero(val: float) -> float:
return 0 if isnan(val) else val
@indicator('Squeeze Momentum')
@param.int('length', default=20, min=1, title='BB Length')
@param.float('mult', default=1.5, title='BB MultFactor')
@param.int('length_kc', default=20, min=1, title='KC Length')
@param.float('mult_kc', default=1.5, title='KC MultFactor')
@param.bool('use_true_range', default=True, title='Use TrueRange (KC)')
@plot(style=plot_style.HISTOGRAM, line_width=4)
@plot(line_style=line_style.SOLID, line_width=4) # TODO: use markers
def Main(self, length, mult, length_kc, mult_kc, use_true_range):
# Get Bollinger Bands components individually
bb_result = Bb.new(self.close, length, mult)
bb_lower = bb_result[0][0] # Extract the float value from the lower band
bb_upper = bb_result[2][0] # Extract the float value from the upper band
# Calculate KC bands
ma = Sma.new(self.close, length_kc)[0]
# Calculate range based on user preference
range_val = None
if use_true_range:
range_val = Tr.new()
else:
range_val = MutSeriesF.new(self.high[0] - self.low[0])
# Calculate the moving average of the range
range_ma = Sma.new(range_val, length_kc)[0]
# Calculate KC bands
kc_upper = ma + range_ma * mult_kc
kc_lower = ma - range_ma * mult_kc
# Determine squeeze conditions
sqz_on = (bb_lower > kc_lower) and (bb_upper < kc_upper)
sqz_off = (bb_lower < kc_lower) and (bb_upper > kc_upper)
no_sqz = (sqz_on == False) and (sqz_off == False)
# Calculate momentum value
highest_high = Highest.new(self.high, length_kc)
lowest_low = Lowest.new(self.low, length_kc)
close_sma = Sma.new(self.close, length_kc)
momentum_val = self.close[0] - mean(highest_high, lowest_low, close_sma)
val_series = MutSeriesF.new(momentum_val)
val = LinReg.new(val_series, length_kc)
# Determine colors based on momentum
bcolor = color.BLACK # Default initialization
if val[0] > 0:
if val[0] > nan_to_zero(val[1]):
bcolor = color.LIME
else:
bcolor = color.GREEN
else:
if val[0] < nan_to_zero(val[1]):
bcolor = color.RED
else:
bcolor = color.MAROON
# Determine squeeze state color
scolor = color.GRAY
if no_sqz:
scolor = color.OLIVE
elif sqz_on:
scolor = color.NAVY
# Return the plot values and colors
return Plot(val[0], color=bcolor), Plot(0, color=scolor)
What I've tried
I've tried to:
Access Bollinger Bands values directly
Use different methods of unpacking the Bb.new() results
Store the result in a variable and access via indexing
Use the [0] index to extract float values
But I'm still getting the same error.
Questions
How do I correctly access the upper and lower Bollinger Bands in Indie platform?
Is there a specific way to handle the return type of Bb.new()?
Environment
- Indie version: 4