A Backtest Can Know the Future: Event Time Is Not Receipt Time
An event recorded in the past was not necessarily available to the strategy at that moment. Check receipt time as well.
What was known at 12:00:00.500?
All quotes below are synthetic teaching values. The decision time is 12:00:00.500. Event timestamps and the time the data actually became available can differ.
| Quote | Event time | Receipt time | Synthetic value | Decision-time status |
|---|---|---|---|---|
| A | 12:00:00.350 | 12:00:00.400 | 100 | Available |
| B | 12:00:00.450 | 12:00:00.800 | 101 | Arrived late |
| C | 12:00:00.580 | 12:00:00.650 | 102 | Future event |
Actual pandas test results
| Join method | Selected row | Why it matters |
|---|---|---|
| backward | B · 101 | Prior event, but not yet received |
| nearest | B · 101 | Closest event, but not yet received |
| forward | C · 102 | Event happened after the decision |
| Event + receipt gates | A · 100 | Available before 12:00:00.500 |
Dual event/receipt gate: A selected
What must a real backtest check?
Require both event time and actual availability time to be on or before the decision time; then check symbol, venue, revision and staleness limits. Never silently fill a missing observation with later data.
Using a backward event-time join alone, or omitting the matched right-side timestamp in a DuckDB ASOF result, can obscure when a value was actually available. This public demonstration says nothing about the performance or implementation of our private coin engine.
Related note: Even the same second can contain future data →
Official documentation & reproducibility
pandas merge_asof · DuckDB ASOF JOIN
Tested with pandas 2.2.3 on three synthetic rows. Not a real market or backtest outcome.