Skip to content

engine: opt-in security_range_start_na_warmup flag for TV deep-backtest HTF warmup parity#81

Merged
luisleo526 merged 1 commit into
mainfrom
fix/security-range-start-na-warmup
Jul 9, 2026
Merged

engine: opt-in security_range_start_na_warmup flag for TV deep-backtest HTF warmup parity#81
luisleo526 merged 1 commit into
mainfrom
fix/security-range-start-na-warmup

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

What

Adds an opt-in run flag security_range_start_na_warmup (via the existing syminfo_metadata channel, no C-ABI change): when set with a range-start timestamp, every request.security HTF series (1) begins aggregation at the range start instead of the feed start, and (2) its embedded lookback EMA follows TV built-in warmup semantics — na until length HTF bars have accumulated, then seeded with the SMA of the first length values. Plain security expressions read na until the first completed HTF bar. Default OFF; behavior with the flag unset is byte-identical (proven: 252/252 corpus artifacts byte-compare clean vs main).

Why

TradingView's deep backtest truncates chart and request.security history at the applied range start, and TV's built-in lookback ta.* return na until length bars accumulate. The engine's EMA seeds at the first value and the security aggregator warms from feed start, so any long-lookback HTF ta.* direction gate diverges for months inside a comparison window. Feed trimming cannot reproduce this (a truncated-seed EMA is never na).

Evidence

  • New test test_security_range_start_na_warmup (16 checks) fails without the fix, passes with it; flag-off byte-identity guarded.
  • ctest 82/82; corpus gate ran 252, ok=252, tiers unchanged (239/12/1), engine_trades byte-diff 0/252.
  • Downstream validation harness (private) full sweep: 13 tier moves up, 0 down; every mover won via the new candidate.

🤖 Generated with Claude Code

…parity

TradingView's deep backtest truncates every request.security series at the
applied range start, and TV's *built-in* ta.ema returns na until `length`
values accumulate, then seeds with the SMA of those first `length` values --
unlike this engine's default EMA, which src-seeds on the first bar and is
never na. A strategy gating direction on a long-lookback HTF ta.* therefore
diverges from TV across the whole warmup window: TV's gate is na (comparisons
-> false) for `length` HTF bars while the engine's gate has a real value from
day one.

Add an opt-in run flag `security_range_start_na_warmup` carrying the range
start in epoch-ms, plumbed on the existing syminfo_metadata channel (the same
path as bar_index_offset -- no new C ABI or run_strategy.py surface). When set,
each request.security series:
  (a) aggregates from range_start_ms instead of the feed start (pre-range
      input bars are dropped from the security aggregation);
  (b) its embedded lookback ta.ema na-warms per TV built-in semantics -- na
      until `length` values accumulate, then seed = SMA of the first `length`
      values, then the ordinary EMA recursion; and
  (c) plain security expressions read na until the first completed HTF bar
      from the range start (a consequence of (a), counting the partial first
      bucket as HTF bar 1).

Scope is the security-evaluator path only: the na-warm mode is a thread-local
flag raised solely around request.security evaluation, so security-embedded
EMAs latch it on their first compute() while chart-timeframe EMAs keep the
default src-seed. ta.sma/ta.rma/ta.highest already na-warm from series start
and are untouched. Behavior is byte-identical when the flag is unset.

Tests: a new engine-level test pins na-until-length + SMA-first-length seed +
range-start trim (flag on) and byte-identical src-seed (flag off); it fails
without the fix. Full ctest 82/82. Corpus byte-identical with the flag unused
(252 ok / 0 fail; excellent=239 strong=12 anomaly=1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@luisleo526 luisleo526 merged commit 68748df into main Jul 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant