Backtest honesty grade
Every backtest on OptAlgo comes back with an honesty grade, from A (best) to D, and the findings behind it. The grade says how far the result can be trusted as a simulation of what would really have happened. Read it before any number: a good return on a D run is not a result.
What each grade means
| Grade | Means |
|---|---|
A | Every fill resolved on real data, with fees, funding and exchange rules. |
B | A few fills depend on assumptions. |
C | Decisions depend on where the data starts (warmup_short, warmup_unstable: raise warmup_bars()), many pessimistic ties, or missing coverage. |
D | Not realistic. Fix the strategy; never quote the numbers. |
Each finding names its code and what to do about it. A few examples:
lookahead(D): the strategy used data from the future (see the lookahead check below).liquidation_risk(D): on a multi-leg or target-weight portfolio, the legs' worst prices together took equity below the maintenance margin, so a real cross-margin account would have been liquidated. Lower the leverage or the gross cap.spot_short_refused(B): short entries on a SPOT symbol were not filled.mixed_wallet_overcommit(C,Dabove 1.5x): at current prices one wallet could not hold the SPOT coins and the perpetual's margin.
On a basket (several symbols, one backtest per symbol), the grade is the worst symbol's, and every finding carries its symbol. Fix the weakest symbol or drop it.
The lookahead check
Every run of your code proves, before its numbers count, that it decides the same with the future removed:
- Window cuts: on the last 3,000 bars (or twice the warm-up plus 200, if more), the strategy runs again on data cut at 6 evenly spaced and 6 random bars. Every leg and every reference, funding and open-interest input is cut with the bars.
- Decision bars: up to 24 bars where the run entered, exited or set a target are decided again on data that ends at that bar. A one-bar shift on a rare signal only differs at its own signal bar; this pass finds it.
- Determinism: the same parameters on the same bars must give the same decisions twice.
- Alignment: references, funding and open interest reach your code already aligned causally; the engine refuses an alignment that would hand a bar a later value.
Any difference is lookahead. The backtest still finishes, graded D with the finding lookahead, and a D run never deploys. Research runs and the hosted deploy check refuse it outright. The free validate step already runs your code once on synthetic bars (no market data, no quota) through the same checks, so most problems show up before you pay for a run.
What it does not prove:
- It samples cuts; it does not re-run every bar. Lookahead that changes nothing at any checked bar can pass.
- It compares decisions only. Plots are not checked, so never trust a plot as a signal.
- It is not an overfitting check: parameters tuned on the same window look good without any lookahead. That is the overfit check.
After the grade
- The search verdict. Say it with the grade: how many variants of this strategy ran on the same data, and whether this run survives the luck of that many tries. See Overfit check.
- The diagnosis. Why the run wins or loses, as rules that fired on its own numbers, each with a suggestion. These are in-sample hints, not proof: act on one, then validate.
- The numbers, net of fees.
total_returnalready pays fees and funding; readfees_totalnext to it. Fees kill short timeframes: an edge that is gone once the fees are paid is no edge. - One backtest is in-sample. Before calling an edge real, run a walk-forward research run and look at its out-of-sample folds.
To run a strategy on OptAlgo (on paper first), deploy it from a backtest graded A to C.
Where you see it
- In a chat app with the OptAlgo connector: the agent reports the grade first, then the numbers.
- On your Backtest page in the app, for every run.
- Through the API (
GET /v1/backtests/{id},summary.gradeandsummary.findings): see the LLM reference.