Same SQL as live, against any past day — just add ?asof=YYYY-MM-DD. Point-in-time across the historical window, with signal-fire history (/signals/.../history) and ticker snapshots (/tickers/{t}/history) for the full backtest pipeline. No backtest engine to build.
GET /v2/scan?asof=
Pass the same WHERE clause you’d use live, plus an asof=YYYY-MM-DD parameter. We return the tickers that matched at that moment, with point-in-time prices, volumes, and signal flags. Loop over a range of dates to build a triggers-and-outcomes table.
-- same WHERE clause, against history
GET /v2/scan
?q=rsi_oversold
AND volume_unusual_2x
AND day_change_pct > 0
&asof=2025-12-31| date | ticker | rsi_14 | day_change_pct | +5d |
|---|---|---|---|---|
| 2025-02-14 | SOFI | 28.4 | +2.1% | +6.4% |
| 2025-03-22 | PLTR | 29.8 | +3.4% | +11.2% |
| 2025-05-09 | CRWD | 27.1 | +1.8% | −2.3% |
| 2025-07-16 | NET | 29.5 | +4.2% | +7.8% |
| 2025-09-03 | SQ | 26.9 | +2.7% | +3.1% |
| + 42 more · 64% positive +5d | ||||
endpoints you’ll use
A real backtest needs the screen at a past date, point-in-time snapshots, and forward-return time series. All three on the same schema.
/v2/scan?asof=YYYY-MM-DDRun any SQL screen against historical state. Returns the tickers that matched on that day.
Docs →/v2/tickers/.../historyFull snapshot of one ticker at a past date: price, indicators, flags, fundamentals. For entry sizing and risk eval.
Docs →/v2/signals/.../historyTime series for any signal × ticker. For forward returns, MAE/MFE, holding-period analysis.
Docs →/v2/rulesSave the backtested screen as a named rule. Promote to live with zero rewrite.
Docs →why this works
Every named flag — breakout, rsi_oversold, volume_unusual_2x, golden_cross_today — is stored as a point-in-time series. Ask when did this fire for any signal × ticker × interval and get the firings back as JSON.
Signal values are stored as they would have been visible at the close of each historical day. No survivorship bias, no forward-fill of indicators. Depth scales with plan (1 year on Hobby, 5 on Pro, all-time on Scale).
Validate a thesis without writing a new query. The exact WHERE clause you’d wire to a webhook is the same one you backtest with — just add ?asof=YYYY-MM-DD.
Once your screen holds up across regimes, save it as a named rule and reference it from /webhooks. One source of truth from research to production.
comparison
Python engine, infra-heavy
One HTTP call, no engine
works with your agent
Hand the strategy-iteration loop to an agent. The same WHERE clause that runs live also backtests with one extra parameter, so the agent can validate hundreds of variants against history before any of them touch real capital.
ship it