Skip to content
Open RaamTrade

RC2_IND_BODY

Indicator class body assignment <name> must be Param(), Series(), a known indicator, or a literal default for persistent state.

What it means

An indicator’s class body is a declaration list, not code that runs. It is read once at compile time to build four things and nothing else:

Shape What it declares
period = Param(20, min=2, max=200) A tunable number the optimizer can sweep.
buffer = Series(period) A rolling buffer, sized from a Param.
fast = SMA(period) A child indicator, computed for you each bar.
prev = 0 Persistent state, with its initial value.

Anything else — arithmetic, a function call, a list, a comprehension — is an expression that would have to be evaluated, and there is no bar to evaluate it against. The class body is processed before the first bar exists.

Why it happens

The classic case is precomputing a constant from a Param:

class MyEMA(Indicator):
position = ON_CHART
period = Param(20, min=2, max=200)
alpha = 2 / (period + 1) # ❌ arithmetic, not a declaration
buffer = Series(period)
def compute(self, close):
self.buffer.add(close)
return sum(self.buffer) / len(self.buffer)

The same code covers a child indicator declared without its period — fast = SMA() — and one whose on= points at a child declared below it. Child indicators, like everything else here, resolve in source order.

How to fix it

Move the arithmetic into compute(), where the value is a local and self.period is readable.

class MyEMA(Indicator):
position = ON_CHART
period = Param(20, min=2, max=200)
buffer = Series(period)
def compute(self, close):
self.buffer.add(close)
average = sum(self.buffer) / len(self.buffer)
alpha = 2 / (self.period + 1)
return alpha * close + (1 - alpha) * average

Recomputing alpha every bar costs nothing — the graph engine folds it — and it keeps the one place a Param is read inside the code that runs, which is what makes optimization sweeps take effect.

If the value was meant to survive across bars rather than be derived each bar, it is persistent state: declare it as a bare literal (alpha = 0.0) and assign it in compute().