Skip to content

security: anchor HTF aggregation on the symbol clock (syminfo.timezone + session) - #159

Merged
luisleo526 merged 6 commits into
mainfrom
htf-session-anchor
Aug 23, 2026
Merged

security: anchor HTF aggregation on the symbol clock (syminfo.timezone + session)#159
luisleo526 merged 6 commits into
mainfrom
htf-session-anchor

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

Mechanism. TimeframeAggregator bucketed intraday targets on the raw epoch grid and calendar targets on UTC wall-clock — TV-correct only for 24x7 symbols. Session symbols anchor differently: TradingView groups intraday HTF buckets from the session open (09:30 equities, 17:00 ET forex) and D/W/M boundaries at symbol-local midnight / session-day. Every session-symbol request.security series was misaligned (AAPL probes: 240m 25.4%, D 56.1%, W 62.0% match).

Fix (generic; per-run config, no strategy-specific paths).

  • TimeframeAggregator(tz, session): RATIO buckets keyed on (local-midnight + session-open) arithmetic; CALENDAR periods decompose on the exchange clock.
  • Eager bucket completion at the period-final session close (RTH days never reach the old next-bar-crossing rule, so daily buckets ran a full session behind TV).
  • crosses_boundary/tf_change tz-aware forms keep historical projections, streaming replay, and the finer-TF publish gate on the same clock.
  • Per-run values ride existing runtime_overrides.timezone/session; defaults (UTC/empty) reduce to bit-identical integer math.

Evidence (engine @ 192bf15, codegen @ 726a0f4).

lane result
ETH scraped 396/396 excellent, 0 up / 0 down
ETH corpus 312/312 ok — 309 excellent / 2 strong / 1 anomaly, identical tiers, zero regressions
AAPL (tz+session) e+s 241→256 (+15); ups 30 / downs 26
EURUSD (tz+fx-session) e+s 307→307 held; ups 35 / downs 30
unit tests 133/133
probe (tie-carrier) trendmatrix-labs institutional-momentum-regime-engine: MATCH — 822/822 exact closed-trade identity, 100% price-exact

Probe-level: AAPL htf-bucket D 56→86%, 240m 25→61%; EURUSD 240m 13→76% under fx-session grid.

Known follow-ups (next round). EURUSD D/W read-back still diverges: TV exposes the completing HTF candle on the session-final bar with stale-by-two history reads (close[1] inside security); engine history-offset semantics run one bucket fresh — measured in ledger findings. Wrap-safe overnight eager-completion variant was tested and rejected at population level (net-negative), reverted.

Symbol-gate verdict: PASS (four-lane metric gate: tier + entry/exit/PnL p90 regression checks). PR-gate verdict: PASS.

…e + session)

TimeframeAggregator bucketed intraday targets on the raw epoch grid and
calendar targets on UTC wall-clock. That is TV-correct only for 24x7
symbols: for session symbols TradingView groups 240m buckets from the
session open (09:30 on equities) and D/W/M boundaries at symbol-local
midnight, so every session-symbol request.security series was misaligned
(AAPL probes: 240m 25.4%, D 56.1%, W 62.0% match).

The aggregator now takes the exchange tz + session and keys buckets on
(local-midnight + session-open) arithmetic; crosses_boundary/tf_change
gain tz-aware forms used by historical projections, streaming replay, and
the finer-TF publish gate so all boundary consumers move together.

tz=UTC / session empty-or-24x7 reduces to identical integer math: default
construction sites pass syminfo_.timezone/.session which stay at those
defaults unless runtime_overrides set them, so the ETH corpus regime is
bit-for-bit unchanged (133/133 unit tests green).
…+session)

Subtracting the session-open offset before the day-floor shifted each
session wholesale instead of anchoring it, making D/W/M grouping
tz-invariant. Calendar periods now decompose on the exchange clock only;
the session offset applies solely to intraday bucket grids.
On session symbols the next-bar-crossing rule never fires inside an RTH
day (16:00 close is far from midnight), so D/W/M buckets completed on the
NEXT session's first bar — every security series ran one session behind
TV (probe-htf-bucket-d: engine lvl on day M was close(M-2) all day where
TV refreshes to close(M-1) on M's final bar; 241 vs 180 round trips).

When the run declares a same-day session window, a bucket completes on
the bar whose close reaches the session end. 24x7/empty/wrapped windows
keep the crossing rule bit-for-bit.
The session-close rule fired on every day's final bar, completing weekly
buckets mid-week (W probe 62% -> 7.8%). Gate it on the next calendar day
starting a new period.
The anchor helpers paid ScopedTimezone+localtime_r+mktime on EVERY call
before consulting their day cache — session-symbol runs slowed enough to
tip ladder candidates over the sweep timeout. Offset is stable within a
UTC hour, so key the memo by hour before touching the slow path.
Hour keys still paid ScopedTimezone(setenv+tzset) ~24x/symbol-day per
thread — 50x slowdowns on multi-security strategies over 5y feeds.
Offsets change only at DST instants, which fall while session markets
are closed, so a per-UTC-day memo is exact for every traded bar.
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