Resample/VolTfStop bucket by raw provider timestamps — sub-second M1 stamp jitter mis-buckets bars #280
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Evidence (Pepperstone archive, UK100)
Provider M1 stamps carry up to ±1s jitter around minute boundaries. Measured over all 3120 weekdays 2014-08..2026-07 while running an offline session-anchored study: on ~55% of days the 09:00:00-Berlin minute bar is stamped 08:59:59.xxx. A
[t0, ..)window load misses it entirely; nearest-minute rounding recovered 1701 of 1709 otherwise-dropped days. Example (2024-07-15, offsets relative to 07:00:00 UTC): first bar stamped -0.6s, next at +60s — the nominal 09:00 candle exists but sits a hair before the minute mark.Mechanism
Resampledecides bucket membership by raw integer division of the cycle stamp:let bucket = ctx.now().0 / self.period_ns;(crates/aura-std/src/resample.rs:107).VolTfStop's internal resampler uses the identical pattern (crates/aura-std/src/vol_tf_stop.rs:93).crates/aura-ingest/src/lib.rs:41-43); no normalization/snapping exists anywhere in the pipeline.Session/SessionFrankfurtderive wall-clock from the same rawctx.now(), so the jitter also flips bars across session-open boundaries (bars_since_opensees 08:59:59.4 as pre-open).Impact
Coarse bars built inside a real backtest differ from the provider's nominal minutes on a majority of days: a bar stamped 59.4s early is aggregated into the previous 5m bucket, shifting every downstream open/close by one M1 bar around bucket boundaries. Any session-anchored strategy logic inherits the same off-by-one at the open. Silent — no error, plausible-looking bars.
Open design question (ledger-worthy, not prescribing here)
Where should normalization live?
Workaround used meanwhile: the scratch-project study node does nearest-minute rounding internally before bucketing.
(Found during a throwaway UK100 study in the external scratch project; the offline analysis and the node live there, not in this repo.)
Fork decision (autonomous, 2026-07-17): where time normalization lives.
Options considered:
Chosen: option 3.
Rationale:
Status: fix path settled — proceeding RED-first against the mis-bucketing symptom.