Performance
request.security in backtests
This release continues the request.security() work of 6.10.0. Outputs are
unchanged on the tested scripts; each optimisation has its own switch to turn
it off.
- Children run only the part of
main()they need. Every static context
used to re-run the wholemain()on every bar in its child process, with
only its own write taking effect. The child now runs a backward slice of
main(): the context's own expression and every statement it depends on,
including all persistent state carried across bars. Code the analysis cannot
model (try, comprehensions, unresolved collection targets) leaves that
context unsliced. Multi-context scripts run several times faster.
PYNE_NO_SECURITY_SLICE=1disables it. - One child process per feed group. Call sites whose arguments resolve to
the same feed used to spawn one child each, each loading the same data and
running its own slice ofmain(). Contexts whose signal arguments are
provably the same are now grouped at compile time and served by a single
child. This covers helper functions with a ternary between two calls and
security(...) if flag else na. Lower-timeframe contexts are never grouped.
Multi-call scripts on a shared timeframe run two to three times faster.
PYNE_NO_SECURITY_MERGE=1restores one child per context. - Developing-round skip.
request.security(sym, tf, x[k], lookahead_on)
withk >= 1has the same value on every chart bar of one higher-timeframe
period, so the developing round now runs only on the period's first chart
bar. The skip applies only when the context's write is reached on every bar
(no guard, no earlyreturnorraiseahead of it), and the sliced code declares
novaripand calls nota.valuewhen. On one corpus script the
run time went from 91 s to 20 s.PYNE_NO_SECURITY_DEV_SKIP=1disables it. - Cheaper rollback of a discarded re-execution (a developing re-tick, a
calc_on_order_fillsfill, a live intrabar tick). Function-instance state is
undone slot by slot instead of copying every series buffer back, and the
restore no longer deep-copies on every re-execution. A security-heavy
indicator went from 75 s to 31 s with the developing-round skip disabled, and
from 20 s to 15 s with it enabled.
Behaviour change
Module-level objects are read-only inside functions
A script may define anything at module level and read it anywhere, but writing
into a module-level object from inside a function now raises a SyntaxError
when the script is loaded. Rejected: a global statement, an assignment,
augmented assignment or del rooted at a module-level name, a mutating method
call on one (append, pop, clear, ...), and a mutating array.*,
matrix.* or map.* builtin on one. A local variable or parameter of the same
name shadows the module-level binding and is fine.
Such an object lives outside everything PyneCore rolls back, so a counter or
buffer kept at module level counted executions rather than bars whenever a bar
was re-executed (request.security developing bars, calc_on_order_fills,
live intrabar ticks). Keep bar-to-bar state in a Persistent (var) or an
IBPersistent (varip) inside the function instead. A write through an alias
or a parameter is not detected, and its behaviour is unpredictable. See
"Module-Level Objects Are Read-Only Inside Functions" in the scripting guide.
Fixes
Rollback keeps object identity
Arrays, maps, matrices and UDT instances are references in Pine, but the var
rollback (calc_on_order_fills re-executions, live intrabar ticks,
request.security developing re-ticks) replaced every slot with an independent
copy of its baseline. Two variables naming one object named two objects after
the first rollback, whether in the same scope, in a function instance or inside
a container. The restore now writes the saved content back into the same object,
recursively, with UDT cycles handled:
- Aliases survive a rollback.
- A discarded execution's mutation of an array held in a UDT field no longer
survives the rollback (UDTs were copied shallowly). - A
matrix.set()of a discarded execution no longer leaks into the restored
state (the snapshot shared the matrix's rows).
request.security
- Security children now receive the runner's programmatic input overrides.
They previously computed the context with the.tomlor source default
values. - A child that had already exited could leave the chart waiting forever:
its exit code was read before the process was reaped, and the resulting
Nonewas treated as a clean exit. The death is now always detected.
Drawings
polyline.newstores its own copy of the points. Clearing, refilling or
pushing to the caller's array afterwards, or mutating one of its
chart.pointobjects, no longer reshapes a polyline that was already drawn,
matching TradingView.
Live trading
- The broker's order event stream (
watch_orders) is reopened with bounded
backoff (1 s up to 30 s) after an unexpected error. Before, the stream ended
and fills and cancels were no longer pushed to the bot while the strategy
kept trading. A manual-intervention halt still stops it.