RC2_TIMEZONE_UNKNOWN
תוכן זה אינו זמין עדיין בשפה שלך.
astimezone(...)needs exactly one IANA timezone string literal, and must be chained straight to.hour,.minute,.month, or.weekday().
What it means
self.trade.timestamp.astimezone("<IANA>") re-expresses the bar’s timestamp in another region’s wall clock. Three rules make it checkable at compile time rather than at bar 40,000 of a backtest:
- One argument, an IANA id, as a literal. The id is validated while you type, so
"America/New_York"compiles and a typo does not. - No bare
astimezone(). In Python that means “the machine’s local timezone” — which on a server is a property of the deployment, not of the strategy. A strategy whose entries move when it is scheduled onto a different node is not a strategy. - Chained, not stored.
astimezone(...)is an access path, not a value: it must be followed immediately by.hour,.minute,.month, or.weekday().
Why it happens
A near-miss on the zone id — underscores and exact spelling matter:
class WrongZone(Strategy): trade = Symbol() sizing = FixedCapital()
def execute(self): if self.trade.timestamp.astimezone("America/New York").hour >= 10 and self.trade.is_flat: self.buy(self.trade)Python’s no-argument form, meaning “local time”:
class LocalTime(Strategy): trade = Symbol() sizing = FixedCapital()
def execute(self): if self.trade.timestamp.astimezone().hour >= 10 and self.trade.is_flat: self.buy(self.trade)Or the converted time saved to a variable to be reused — the natural refactor, and the one the language doesn’t allow:
class StoredZone(Strategy): trade = Symbol() sizing = FixedCapital()
def execute(self): ny_now = self.trade.timestamp.astimezone("America/New_York") if ny_now.hour >= 10 and self.trade.is_flat: self.buy(self.trade)Passing the zone through a variable (zone = "America/New_York" … astimezone(zone)) is refused for the same reason: a variable defeats the compile-time check.
How to fix it
Write the id as a literal and read the field off the end of the chain. Repeat the chain if you need two fields — it is a path, and paths are cheap.
class SessionClock(Strategy): trade = Symbol() sizing = FixedCapital()
def execute(self): ny_hour = self.trade.timestamp.astimezone("America/New_York").hour if ny_hour >= 10 and self.trade.timestamp.weekday() < 5 and self.trade.is_flat: self.buy(self.trade)The field can be stored in a local (ny_hour above is an ordinary number); only the conversion itself cannot.
If all you need is the bar’s own clock, you don’t need astimezone at all — self.trade.timestamp is already expressed in the slot’s session timezone:
class SessionLocal(Strategy): trade = Symbol(session=USEquityHourly) sizing = FixedCapital()
def execute(self): if self.trade.timestamp.hour >= 10 and self.trade.is_flat: self.buy(self.trade)It costs you the fast path
astimezone (like value_at) drops a strategy off the analyzed graph path onto the slower passthrough one. Reading the slot’s own day or month with self.trade.timestamp.weekday() or self.trade.timestamp.month does not — it keeps the fast path. That is invisible in a single backtest and very visible in an optimization or a walk-forward run — worth knowing before you reach for it in a hot condition.
Related
- OHLCV Access — bar time
- Sessions — the slot’s own timezone, which needs no conversion.
RC2_UNKNOWN_SESSION— the other “this name doesn’t resolve” refusal, on the slot’s own clock.