דלגו לתוכן
פתיחת RaamTrade

RC2_STATE_REBIND_COLLECTION

תוכן זה אינו זמין עדיין בשפה שלך.

Cannot rebind a class-body-declared list or dict. Mutate elements via index or key writes instead.

What it means

A persistent-state list or dict slot is set up once at warmup, and re-applied at the start of every walk-forward window. Inside execute() the contract is mutate, not re-assign: index writes (self.vals[i] = …) and key writes (self.counts[k] = …) update the slot’s contents, whereas re-assignment would throw the buffer away and build a fresh one on every bar.

The same rule covers augmented assignment applied to the slot itself — self.vals += … is a rebind, not an element update.

Why it happens

class Bad(Strategy):
trade = Symbol()
sizing = FixedCapital()
nq_highs = [0.0]*5
def execute(self):
self.nq_highs = [1.0, 2.0, 3.0, 4.0, 5.0] # ❌ re-assignment in execute()
if self.trade.is_flat:
self.buy(self.trade)

This is nearly always a bug. The author believes the buffer persists across bars; the rebind silently resets it every bar.

How to fix it

Mutate through the subscript:

class Good(Strategy):
trade = Symbol()
sizing = FixedCapital()
nq_highs = [0.0]*5
def execute(self):
# Shift the buffer left, then write the newest high at the right edge.
for i in range(4):
self.nq_highs[i] = self.nq_highs[i+1]
self.nq_highs[4] = self.trade.high
if self.trade.close > self.nq_highs[0] and self.trade.is_flat:
self.buy(self.trade, reason="Break above the 5-bar high")

To clear the buffer back to a known state, do it element by element:

class Resettable(Strategy):
trade = Symbol()
sizing = FixedCapital()
nq_highs = [0.0]*5
def execute(self):
if self.trade.is_flat and self.bar_count > 1000:
for i in range(5):
self.nq_highs[i] = 0.0 # ✅ element-by-element reset

Scalars are different

Re-assigning scalar state IS allowed:

class ScalarOK(Strategy):
trade = Symbol()
sizing = FixedCapital()
up_count = 0
def execute(self):
self.up_count = 0 # ✅ scalar re-assignment is fine
if self.trade.close > self.trade.open:
self.up_count = self.up_count + 1

The asymmetry is deliberate. self.scalar = value has one unambiguous meaning; self.list = [...] mid-execute() almost always means the author forgot the buffer was supposed to survive the bar.