The largest release since the 6.4 line. The state engine has been rewritten end-to-end, the strategy simulator and request.security() reach trade-for-trade parity with TradingView on the previously diverging corpus strategies, and several Pine v6 surfaces are completed. 148 files changed.
State engine rewrite (slot-based per-instance state)
The module-global state scheme — mangled global names plus the FunctionType-keyed isolation cache — is replaced with compile-time slot layouts and runtime root state vectors:
Series/Persistent/varipvariables now live in compile-assigned slots of their scope's state vector; reads resolve through the scope chain.- Call sites are classified at transform time into fast / direct / uniform routes; carrier status is a fixpoint over the module call graph.
- Overload dispatch, Pine method dispatch and
inline_seriesare anchored per call site, so a site whose argument types vary across bars keeps separate state per implementation. - Both runners (chart and
request.security()children) drive every entry point — scriptmainand registered library mains — through its own root vector, keyed per qualified function so library registrations can't collide.
Correctness fixes that fell out of the rewrite:
- A
str/boolpersistent with a non-literal+=no longer emits float arithmetic and crashes. varipKahan compensation is carried with its companion across var rollback, so the pair can't desynchronize.- Deterministic call routing, independent of
sys.modulesimport order. - Stateful lib functions (
fixnan,math.random,math.sum,timeframe.change) ported to@pynesubmodules.
Module property routing
CallableModule and the hasattr-based runtime fallback are gone; module-property routing is now pure AST rewriting backed by an auto-generated, exhaustively tested registry (224 -> 1012 entries). Unknown names of known lib modules raise at transform time instead of failing at runtime, and a freshness test keeps the registry from going stale.
Performance
Per-bar hot-loop overhead cut in the runner and strategy engine: -18..-32% wall-clock on the benchmark strategies, -21% on the demo indicator. Behavior unchanged (suites pass, TV trades match bar-for-bar). Includes an idle fast path in process_orders, per-bar memoized time_tradingday, and a single-call timezone conversion in _set_lib_properties.
Strategy simulator — TradingView parity
Both previously diverging pyne-in-the-wild corpus strategies now match TV trade-for-trade.
- Trailing stops rewritten as an intrabar O-H-L-C / O-L-H-C path walk: same-bar activation, ride and rebound fill at the extreme -/+ offset; hard-stop and limit legs reached earlier on the path win.
strategy.exit(from_entry=)covers every same-ID entry, recomputing the leg reservation on each (re-)issue instead of freezing the first size.- Margin calls on fractional-lot symbols size the liquidation in lot units (was always whole contracts), so crypto backtests no longer force-close the whole position and halve the trade count vs TV. The bar-open margin call keeps TV's whole-contract sizing.
- Margin overshoot now depends on lot granularity: fractional-lot symbols fill-then-trim, whole-lot symbols reject the entry so the signal re-fires later.
- Offset-0 trailing leg: trailing arguments alongside stop/limit are legal and arm at 0 ticks;
trail_price-only exits are no longer dropped; trailing arguments withouttrail_offsetare ignored per Pine docs. - Position-flat close: the flattening trade size is snapped to
0.0so it is removed, fixing anNA-propagationTypeErrorin percent-of-equity sizing.
request.security()
- Deferred and mixed contexts unblocked: a deferred context resolving to the chart's own symbol+timeframe now gets result blocks (no deadlock); static subprocesses in scripts mixing static and deferred contexts are now spawned; double-spawn is guarded.
- Intraday HTF bars anchored to the session open (e.g. equities at 09:30 / 10:30 ...) instead of a pure UTC clock-floor, matching TV; zero overhead for 24/7, on-hour and session-aligned markets.
- Library mains run before
main()in security children, so scripts calling imported library functions no longer crash with "Exported proxy has not been initialized". - Config safety: security children no longer rewrite the script's
.tomlon import — multiple contexts could race and truncate the user's config (now disabled viaPYNE_SAVE_SCRIPT_TOML=0). request.securitycontexts from imported libraries are merged; deferred / same-context timeframe handling is more reliable.
Pine v6 built-ins
syminfo.mincontractplus the full Pine v6syminfonamespace (main_tickerid,expiration_date,current_contract,isin, therecommendations_*family, and more). Order sizes are floored to the symbol's real lot grid (BINANCE:BTCUSDT -> 1e-5). The CCXT provider derives the step from precision, andpyne data downloadrefines it from analyzed volume precision.chart.pointnamespace (new,now,from_index,from_time,copy) and Pine keyword params for drawings:line.newfirst_point/second_point,box.newtop_left/bottom_right,label.newpoint. Drawing coordinates widened toint | NA/float | NA.- Month-first date strings in
timestamp():"03-04-2023"resolves to March 4 with-,/or.separators and an optionalHH:MM[:SS]part; day-first dates are still rejected, as on TV. time/time_closeoverload handling extended forbars_backand chart-timeframe defaults;math.roundprecision guard fixed.
Transformer fixes
- Parameter default values are rewritten in the enclosing scope, fixing a
NameErrorwhen a parameter shadows a same-named lib module used in its own default. PersistentTransformerrewrites persistent references in attribute and subscript assignment targets (persistent_udt.field = ...).- Overload dispatch treats
Any(unannotated params, threaded closure vars) as a wildcard instead of crashing onisinstance(..., typing.Any).
CI
release.ymlcheckout / setup-python upgraded to Node 24 actions.