Skip to content

v6.9.2

Latest

Choose a tag to compare

@wallneradam wallneradam released this 08 Sep 11:41
· 1 commit to main since this release

Two reported issues are fixed here, both of them regressions of earlier releases: na passed to an
int-typed argument crashed the run, and a ta.* call inside a loop with a per-iteration length had
become an order of magnitude slower.

Fixes

  • na at an integer argument raised instead of answering na (issue #79). The truncation
    added for int-typed arguments went through a bare int(), which NA.__int__ refuses by design,
    so 20 slots turned a legal script into a runtime crash — every table dimension and cell
    coordinate, plus str.replace and str.substring. table.new(position.top_left, na, na), a
    construct Pine's own documentation uses, died with TypeError: NA cannot be converted to int.
    Each slot now substitutes the concrete integer TradingView substitutes there, measured on
    TradingView: table dimensions and coordinates read na as 0 per argument; str.substring reads
    an na begin as 0 but an na end as the end of the source; str.replace reads an na
    occurrence as the first one. Two na guards were wrong alongside them: str.substring resolved
    its positions before an na source, and str.repeat tested x != x, which never sees a bare
    NA object.

  • A library's unexported overload could break its exported one. When a library exported one
    overload of a name and left another unexported, the once-per-run definition latch handed the
    name to the export and declared it global, so the unexported definition — rebuilt every bar —
    wrote over the module-level proxy the export decorator had registered. Method calls resolved
    against that proxy and asserted with "No such method" on the first bar; five scripts in the
    compatibility corpus died on it.

  • A state-carrying definition inside a compound statement crashed on its first call. The
    layout pass only walked the top level of each body, so such a definition was allocated a scope
    and rewritten to read its state vector, but never received the hidden state parameter.

  • Reversal close retries are throttled in the broker layer: markers are armed for every close
    outcome and retried after the stale window, so a rejected close no longer redispatches on the
    same bar.

Performance

  • ta.* in a loop with a per-iteration length (issue #80). Every iteration re-derived
    math.sum's window walk from the bar's starting state, one Series read per step. Twenty
    lengths 20..400 over 25369 bars took 36.6s, against 3.7s for the same loop at a constant length.
    The offsets a walk reads now travel as one native list, the re-baselines fold natively, and the
    eviction walk memoizes its state per step, so an iteration needing fewer steps reads its answer
    instead of re-walking. The same script now runs in 5.6s. A length that shrinks per iteration
    runs in 17.5s from 40.8s — its walk shares the tail of its input rather than the prefix of its
    fold, so it cannot memoize. Every plot value is unchanged: byte-identical output on eleven
    scripts covering all three loop shapes, na sources, sawtooth lengths and windows past the
    default lookback, and all 564 corpus scripts keep every metric.

    The rewrite also made an older defect visible: on an na bar the eviction walk read one offset
    below the ones that actually leave, so the newest leaving offset was subtracted twice and the
    oldest never, and the error stayed in the compensated accumulator for the rest of the run. The
    two ranges coincide on a stored bar, so nothing measured against TradingView moves.

  • A library defines its exports once per run, not once per bar. A library main is a per-bar
    entry point, so every bar allocated a fresh function object per export and ran the decorator
    over it, while call sites anchor on the stable module-level proxy and never used them. A
    20-export library drops from 8.1 to 2.6 us/bar.

Features

  • array.sort and array.sort_indices accept sort_field, Pine's third parameter naming a
    field of an object element. Measured on TradingView: the field is the sort key while the whole
    element moves, and the na rule reads the field's type — a numeric field puts na last
    ascending and first descending, a string field puts it first. The parameter works positionally
    and by name.