Point-in-time backtests.
On Chalk.
This live demo shows how you can backtest results that hold up in live trading, with Chalk. Tune a strategy and see how much the leak inflates returns, against a benchmark.
Compare a valid backtest with one that saw the future
Both curves use the same synthetic prices and strategy. Their information timing differs.
Try this experiment · expected results
1Read the recorded comparison
Keep the default strategy and compare the solid point-in-time curve with the dashed date-joined curve.
Expected: The dashed curve uses that day’s close before trading and can overstate performance.
2Inspect one rebalance
Compare the inputs available at 09:30 with the later closing values in the timing example.
Expected: The row-level evidence explains the gap; changing strategy settings does not remove the timing requirement.
Hold the 8 tickers with the highest total return over the lookback. Long only, equal weight, from 40 synthetic tickers.
Checking the live backend…
Growth of $1, after costs
Recorded run · 2026-10-15| Weekly · 3 months · 5 bps | Total | CAGR | Sharpe | Max DD | Turnover/yr | Costs |
|---|---|---|---|---|---|---|
| Point in time | 46% | 11.3% | 0.63 | −41% | 26.1× | 4.6% |
| Leaky (date join) | 119% | 24.9% | 1.21 | −34% | 27.5× | 4.8% |
| Benchmark | 64% | 15.0% | 0.85 | −34% | – | – |
Reading each day's close before trading made momentum look better by 13.6 percentage points a year and moved its Sharpe from 0.63 to 1.21. The leaky run beats the benchmark; the real one does not.
The leaky signal already knows how the day it trades on will close, so it buys what is about to rise. The more often you rebalance, the more those few hours are worth: try daily.
The 40 tickers and their prices are synthetic, generated from a fixed seed with planted trend, choppy and sell-off regimes. Nothing here is market data or investment advice. The features, offline queries and portfolio math are real and run on Chalk.
What one rebalance saw
TKR01 at the 09:30 rebalance on Tuesday, 5 March 2024. Both rows are real output from the demo's offline queries; only the input time differs.
Built on Chalk
Time travel for every signal, the compute to trade on it, and a record of each run.
One definition, research to production
The signal you backtest is the feature your live strategy queries. No second pipeline to rebuild the windows, and no drift between the two.
Windows as of any moment
30, 91 and 182-day windows end at each row's input time, to the second, so a rebalance only ever sees closes that had printed.
Checkable, row by row
Output the time of the last close each signal read next to its input time. In the recorded run, zero point-in-time rows read the future.
Backtests are datasets
Each offline query is saved as a named dataset with its own id, so a backtest can be re-read, compared and audited later.
Backtest your own signals
Define bars with the time each one became known, write signals as windowed aggregations that filter on chalk_now, and run one offline query with an input time per rebalance.
To use your own data, swap the synthetic resolver for a SQL resolver over your bars table. The signals, the query and the portfolio code do not change.
# The signals, on a branch of your environment
cd chalk_project
chalk apply --branch strategy-backtest
# Both offline queries and every backtest; writes results/summary.json
cd ..
./record_run.py --branch strategy-backtest
# The live re-run API, as a Chalk scaling group with a workload identity
./deploy.py --branch strategy-backtestImplementation details
How the example works
Stamp bars when they print
Each daily bar carries the moment its close printed, 16:00 New York, not the trading date it belongs to. A 09:30 decision cannot see it.
Signals filter on chalk_now
Momentum, rolling volatility and the mean-reversion z-score are windowed aggregations over bars with ts <= chalk_now. The same definitions serve live trading.
One offline query per backtest
Every ticker at every rebalance is one input row, with its input time set to the decision. The recorded run reads 36,520 rows in under 30 seconds.
Trade it with costs
A Chalk scaling group turns signals into weights, trades at the open, charges basis points on turnover and reports the equity curve, Sharpe and drawdown.
More capabilities
Compute next to the data
The portfolio step runs in a Chalk scaling group that authenticates with its workload identity. No client secret in the container.
Numbers you can trade
The leaky backtest of the default strategy claimed 24.9% a year. Point in time, it made 11.3%, behind the benchmark's 15.0%.
Trust the Sharpe your backtest reports
Signals on bars, quotes, filings or alternative data, at any frequency. Talk to an engineer about computing them point in time, for research and production alike.