Backtesting
RoboQuant runs the compiled .rqc artifact for your strategy against historical CME data. The Backtest tab combines execution controls, a live progress stream, chart replay, strategy logs, trades, and performance analysis in one view.
How a run works
.rq source → Compile → .rqc artifact
↓
Backtest request → isolated worker pod
↓
Historical bars, ticks, and optional L2 depth
↓
Compiled engine → orders, fills, equity, logs, drawings
↓
Stored result → chart, Replay, metrics, trades, analysis
The artifact is loaded before any data is processed. Parameters are injected when the run starts, so changing a parameter does not require recompilation.
Starting a backtest
From Strategies → Backtest:
- Select the compiled entry artifact.
- Choose the symbol, timeframe, start date, and end date.
- Choose a fill model.
- Set starting capital, commission, slippage, and leverage.
- Review the parameters generated from
#[param(...)]fields. - Click Run for the fastest result or Replay to watch the strategy progress across the chart.
Every saved run records the selected entry file, parameters, date range, data source, L2 setting, capital, commissions, slippage, and leverage. Reopening a run restores that configuration.
Fill models
| Fills setting | Market timing | Data used | Best for |
|---|---|---|---|
| OHLCV | Orders execute with bar-level simulation | Historical bars | Fast research and hourly/daily systems |
| Tick | Triggers and fills follow the historical trade tape | Individual trade prints | Intrabar entries, SL/TP, and trailing-stop behavior |
| Order Book (L2) — bar | Market orders walk the depth snapshot at the bar event | Bars + MBP-10 depth | Bar strategies where liquidity and order size matter |
| Order Book (L2) — tick | Tick timing plus depth-walked market fills | Trade tape + MBP-10 depth | Highest-fidelity short-window execution research |
Tick and L2 data are available only for supported CME symbols and covered dates. L2 coverage is a recent rolling window and is intended for short, usually single-day studies. The engine reports average levels walked and slippage cost when book fills are used.
Limit and stop orders use their trigger semantics. Market orders walk visible depth when L2 is enabled; if the visible ladder cannot fill the requested size, the run uses the configured fallback slippage model.
Bar, tick, and timer behavior
| Strategy hook | Required run data | Behavior |
|---|---|---|
on_bar | Any fill model | Runs at each completed bar |
on_tick | Tick or L2 tick | Runs for each trade print; the strategy must return true from wants_ticks |
on_timer | Tick or L2 tick | Runs on the simulated timer grid set in on_init |
on_trade | Any fill model | Runs for order, fill, position, and close transactions |
In tick mode, ctx.bar(0) is the forming bar as known at that tick. Indicators still read the last completed bar. This prevents final-bar values from leaking into earlier tick decisions.
Run vs Replay
Both buttons execute the same engine and produce the same final result.
- Run computes without pacing the chart and is best when you only need the result.
- Replay streams bars, intrabar tick substeps, indicators, trades, stop/target rails, trailing-stop movement, drawings, equity, and logs while the run computes.
Replay speed is a display control; it does not change execution results. A tick replay uses its actual intrabar event timestamps, so entries and exits appear at their real point inside the candle instead of being snapped to the candle boundary.
Results
The summary includes core measures such as:
| Category | Examples |
|---|---|
| Return | Net P&L, total return, monthly returns |
| Risk | Max drawdown, Sharpe, Sortino |
| Trade quality | Win rate, profit factor, average trade, largest win/loss |
| Excursion | MAE and MFE where available |
| Statistical context | Alpha, beta, and probabilistic Sharpe where available |
| Execution | Trade list, commissions, slippage, L2 levels walked |
| Diagnostics | Strategy logs, drawings summary, engine errors |
The result chart includes entries and exits, equity and drawdown curves, and strategy drawings. Multi-symbol results retain the executing symbol on every trade and store candles per leg.
Metrics describe a historical simulation, not a forecast. Always compare them with costs, trade count, exposure, regime concentration, and out-of-sample behavior.
Costs and contracts
The engine applies the instrument contract specification automatically. Order size is a contract count; P&L uses the configured point multiplier.
Commission is charged on each side:
commission = flat per trade
+ per-contract charge × contracts
+ percent charge × price × contracts × multiplier
Use per-contract commission for futures. Percentage commission is primarily for legacy spot-style runs. Slippage is applied according to the selected fill model; L2 market fills use the real visible ladder before falling back to the configured percentage.
Multi-symbol backtests
Compiled MultiStrategy artifacts run across a list of symbols with one merged on_bars timeline.
- The first symbol is the primary chart symbol.
- Every leg needs data for the requested timeframe and date range.
- Orders and account reads are addressed by symbol name.
- Results include per-leg trades and OHLC series.
- Multi-symbol execution is OHLCV bar mode only; tick and L2 modes are rejected.
See Strategies → Multi-symbol strategies for the authoring pattern.
Optimization
The Optimize tab uses the same artifact, data, costs, and execution engine as a normal backtest. Parameters come from the artifact's #[param(...)] schema.
Search methods
| Optimizer | Use it for |
|---|---|
| Grid Search | Exhaustive, reproducible sweeps over a manageable parameter space |
| Bayesian (TPE) | Efficient search when the full grid is large |
| Genetic (CMA-ES) | Continuous or irregular search spaces |
| Multi-Objective (Pareto / NSGA-II) | Trade-offs such as Sharpe versus drawdown instead of one winning score |
Validation methods
| Validation | What it does |
|---|---|
| Single | Scores every trial over the full selected history |
| IS / OOS | Optimizes on the first portion and validates on the untouched remainder |
| Walk-Forward | Repeats rolling in-sample optimization and out-of-sample validation |
Market universes
The market selector can build a symbol × timeframe matrix for any search and validation method. Every parameter candidate is evaluated independently on every selected market case, then receives one aggregate score. The same parameters are shared across the whole matrix; this searches for a robust configuration rather than a different optimum per symbol.
The Optimize tab uses a dispersion-adjusted objective by default:
maximize metric: score = weighted mean − 0.25 × standard deviation
minimize metric: score = weighted mean + 0.25 × standard deviation
Results retain each market's metrics alongside the aggregate mean, dispersion, and worst case. A failed market invalidates the candidate by default. The planned evaluation count is the number of parameter candidates multiplied by the number of symbol/timeframe cases, so widening either axis increases runtime and is included in the 10,000-evaluation safety limit. One optimization can contain at most 40 market cases.
Market-universe optimization is distinct from a multi-symbol portfolio strategy: a market universe runs the ordinary strategy independently on several markets, while a MultiStrategy trades several symbols together in one account. The two modes cannot be combined. Multi-market matrices currently use OHLCV bars; tick optimization remains available for a single market case.
Pareto search currently uses Single validation. Multi-symbol optimization also uses bar data; uneven multi-leg walk-forward windows are not supported. Tick optimization is supported for single-symbol strategies but can be substantially slower because every trial replays the tape.
Optimizer results include best parameters, full-grid or trial distributions, parameter heatmaps/surfaces, and walk-forward or Pareto views where applicable. A promising optimum should be re-run as a normal backtest with the exact selected configuration before deployment.
Data universe
The dashboard exposes RoboQuant's licensed CME futures universe: equity-index, interest-rate, FX, livestock, and crypto futures roots. CME is the only market-data source; availability still varies by symbol, timeframe, and data type.
Historical lookup follows this order inside the platform:
- Local Parquet cache in the worker.
- Resampling from cached minute data when possible.
- RoboQuant's S3 Parquet store.
- The configured upstream provider for environments that enable it.
If a date range is outside stored coverage, the run fails with a data-availability error instead of silently changing the dates.
Reproducibility checklist
Before comparing two runs, confirm that both use the same:
- compiled artifact version;
- symbol list, timeframe, and date range;
- fill model and L2 setting;
- capital, leverage, commission, and slippage;
- strategy parameters;
- validation split, when optimizing.
Related docs
- Strategies — authoring compiled strategies
- Runtime reference — hooks and API details
- Live deployment — run the same artifact on Tradovate