RC2_ASSIGN_LHS
תוכן זה אינו זמין עדיין בשפה שלך.
Assignment must target a single local name or a single
self.xxx. Tuple unpacking is not supported.
What it means
An assignment in execute() (or in a helper) has a left-hand side the transpiler can’t turn into one storage slot. There are exactly three legal targets: a local name (x = …), a scalar state slot (self.x = …), and an element of a class-body collection (self.x[i] = … / self.x[k] = …). Anything else — unpacking into several names, chained targets, a subscript into something that isn’t a declared list or dict — has no single slot to write to, so it is refused rather than guessed at.
Why it happens
The most common shape is tuple unpacking, which reads as one statement but is really two writes:
class Bad(Strategy): trade = Symbol() sizing = FixedCapital()
def execute(self): high, low = self.trade.high, self.trade.low # ❌ — two targets, one statement if self.trade.is_flat: self.buy(self.trade)Chained targets (a = b = 0) are refused for the same reason.
Subscript writes into an undeclared slot
self.x[i] = … requires x to be declared as a list or dict in the class body. There is no execute()-side discovery for collections — a bare first write carries no element type, so there is nothing to declare from:
class Bad2(Strategy): trade = Symbol() sizing = FixedCapital()
def execute(self): self.recent_highs[0] = self.trade.high # ❌ — recent_highs was never declared if self.trade.is_flat: self.buy(self.trade)The same diagnostic fires when the slot exists but is a scalar: with last_high = 0.0 in the class body, self.last_high[0] = … is “subscript assignment is only valid on lists and dicts.”
How to fix it
One target per assignment; declare collections in the class body and write them by index or key.
class Good(Strategy): trade = Symbol() sizing = FixedCapital() recent_highs = [0.0]*5
def execute(self): high = self.trade.high # ✅ one name per statement low = self.trade.low
for i in range(4): # ✅ index write into a declared list self.recent_highs[i] = self.recent_highs[i+1] self.recent_highs[4] = high
if high - low > 0 and self.trade.is_flat: self.buy(self.trade)Two near misses
Both of these look like RC2_ASSIGN_LHS and are not:
self.capital = 100000—capitalis a computed strategy property, not a slot you own. Assigning to it isRC2_STATE_RESERVED, and the same goes forinitial_capital,bar_count, andready.self.stop_loss = 2.0— this is not an error at all, which is the trap.stop_lossis a method, and assigning to the name quietly creates an unrelated persistent-state slot calledstop_losswhile your stop is never set. Call it instead:self.stop_loss(2.0). See Exit Rules.
Related
- Persistent State — what a state slot is and how each kind is declared.
- For Loops — the loop-and-index idiom the fix above uses.
RC2_ASSIGN_RHS— the mirror image: a legal target with nothing on the right.RC2_STATE_REBIND_COLLECTION— a declared collection re-assigned whole instead of mutated.RC2_STATE_AUGASSIGN_UNINIT— the same “no slot to write to” story for+=.