RC2_IND_BODY
תוכן זה אינו זמין עדיין בשפה שלך.
Indicator class body assignment
<name>must beParam(),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) * averageRecomputing 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().
Related
- Custom Indicators
Param()RC2_IND_PARAM— the assignment is aParam(), but its default is missing or not a literal.RC2_IND_SERIES— the assignment is aSeries(), but its capacity is not aParamreference.RC2_CLASS_BODY— the same rule on the strategy side.