Backtests
Use the Test button (Running code) in the QuantCraft IDE to open Run backtest. There you set symbols, price data, optional fundamentals, the simulation window, starting balance and fill costs, and (if your script uses them) input parameters for a single run. The engine invokes your strategy lifecycle callbacks. Results appear in Test results; OHLCV explains bar shapes.
At the top of the modal body you can Load or Save to reuse a run preset (.qcs). Everything else is grouped into up to three tabs so you can work through the form before you start the backtest.
Run backtest modal tabs
| Tab | What you set |
|---|---|
| Script | Shown only when the script declares params.NAME inputs. Parameter values, plus Optimize (brute-force grid or genetic search). See Input parameters and Optimization. |
| Symbol & data | Price feed (Alpaca or QuantCraft B2), symbols, asset type, primary timeframe, additional timeframes for rt.get_bar, optional min bars (Alpaca), Include fundamentals, and Include Fama-French factors (Premium / free-data when available). |
| Simulation | Start / end date, warmup bars, starting balance, commission and slippage models. See Account model. |
Clock / primary symbol: There is no primary-symbol control in the modal. The bar clock uses a SYMBOL constant in your script (if that ticker is in the loaded list), otherwise the first loaded symbol. See Strategy lifecycle.
Timer / on_timer: The Run backtest modal does not set a timer interval. on_timer is for forward / bulk / chart-forward runs that expose a timer control — not IDE backtests.
Price source (Alpaca vs. B2)
On the Symbol & data tab, choose the price feed:
- Alpaca — intraday and daily-style Alpaca timeframes are available (requires Alpaca connectivity / credentials as configured in the app).
- QuantCraft B2 — only daily (
d), weekly (w), and monthly (m) OHLCV timeframes are available. You must be signed in to QuantCraft so a session token can be sent for B2 OHLCV (and for fundamentals when enabled).
The choice is saved in run presets (.qcs) as ohlcvSource ("alpaca" or "b2").
Bar timeframe and asset class (Alpaca only)
When the price source is Alpaca, you can set:
| Field | Purpose |
|---|---|
| Bar timeframe | Candle resolution for the run — e.g. 1 Day, 1 Hour, 4 Hour, 1 Week, and several minute bars (1 / 5 / 15 / 30 min). |
| Asset class | US equity or Crypto — drives which symbol list you search and how Alpaca fetches data. |
| Min bars (optional) | If set, after the date range is applied the engine keeps only the N most recent bars. Leave empty to use the full range implied by your start and end dates. |
When the price source is B2, you only choose B2 timeframe: Daily, Weekly, or Monthly (no intraday on B2).
Additional timeframes (optional)
Use Additional timeframes on Symbol & data to load extra bar sizes alongside your primary timeframe. In strategy code, read them with rt.get_bar(Timeframe.X, shift) — see OHLCV and bar data and Strategy lifecycle.
- Multi-select any extra timeframes your strategy needs (e.g. daily when your primary bar is 5-minute).
- The primary timeframe is also available via
rt.get_barwithout listing it under Additional timeframes. - Returns
Noneif that timeframe has no buffer for the run or data is unavailable. - Settings can be saved in run presets (.qcs) under
secondaryTimeframes.
Symbols
On Symbol & data, choose one or more tickers for the run:
- With Alpaca, the list comes from your Alpaca asset universe (equity vs. crypto follows Asset class). You can search and multi-select.
- With B2, the list comes from the same catalog as fundamentals paths on the server.
Rules:
- At least one symbol is required.
- Symbols are normalized to uppercase for the run.
- Valid characters: letters, digits,
.and-(typical for exchange suffixes likeBRK.BorRHM.XETRA).
The first symbol in your selection order is the default clock symbol unless your strategy sets a top-level SYMBOL = "..." that matches a loaded ticker. The modal has no separate primary-symbol control.
Fundamentals (optional)
On Symbol & data, check Include fundamentals when your strategy reads the fundamentals argument in on_bar / on_tick (backtest), or in on_timer on a forward run, or uses fundamentals-aware logic.
The checkbox is available for Premium users (or when free-data access is enabled) and when fundamentals features are turned on for your build. When fundamentals are on:
- You must be signed in (QuantCraft token is sent to load B2 fundamentals files).
- Pick one or more fundamentals bundles from the multi-select (paths like
fundamentals/AAPL.json.gz). The dialog shows the normalized path under each selection.
Important: OHLCV symbols and fundamentals symbols are independent. You can backtest RNMBY on Alpaca while loading RHM.XETRA fundamentals — the UI reminds you that in that case you must pass the correct ticker into fundamentals.current(..., symbol="RHM.XETRA") (or equivalent) in code.
When multiple fundamentals bundles are selected, the engine builds a per-path map. The primary fundamentals bundle used for bar-aligned snapshots defaults to the first OHLCV symbol in your symbol list unless the engine applies another rule; use explicit symbol= on fundamentals.current / get_data_with_offset when you need a specific bundle.
Fama-French factors (optional)
On Symbol & data, tick Include Fama-French factors (global) when your strategy reads global monthly factor returns via fama_french.qc. See Fama-French factors for the full API.
When factors are on:
- You need Premium (or free-data access when enabled) and must be signed in.
- The checkbox is on by default when the data gate allows it. Uncheck to skip factor data for that run.
- OHLCV symbols, fundamentals bundles, and Fama-French factors are independent — enable any combination you need.
- There is no
factors=callback argument — importquantcraft.fama_frenchand readfama_french.qcinside callbacks (on_init,on_bar,on_tick, …).
Simulation — dates, balance, and fill costs
All of the following live on the Simulation tab:
| Field | Purpose |
|---|---|
| Start date | Required. First UTC calendar day included in the execution window (YYYY-MM-DD). |
| End date | Required. Last UTC calendar day included. Must be on or after the start date. |
| Warmup bars (indicators) | Extra bars loaded before the start date (same timeframe as your bars) so moving averages and similar indicators have history. Callbacks still run only between start and end dates. Default is 45; enter 0 to disable extra warmup. |
| Starting balance | Required. Initial cash for the simulated PaperAccount. |
| Commission / slippage | How fills are adjusted for trading costs — see below and Account model. |
The Run backtest modal does not configure a timer interval.
on_timeris only available on forward runs (chart forward test, bulk forward / Quant Cloud) whentimerIntervalMsis set. See Strategy lifecycle.
Optional default stop-loss / take-profit / risk sizing can still appear in .qcs presets when present, but the Run backtest modal does not currently expose SL/TP / risk inputs. Configure those in code or via presets if your helpers support them — see Account model and Run presets (.qcs).
Commission and slippage
| Setting | Purpose |
|---|---|
| Commission model | Per share (default), per trade, or zero |
| Commission cost | Cost per share or flat fee per order ($) — default per-share cost is often 0 until you set a non-zero value |
| Minimum trade cost | Floor per order when using per-share commission ($) |
| Slippage model | Volume share (default), fixed spread, or zero |
| Volume limit / Price impact | Volume-share slippage parameters (volume_limit also caps fill qty) |
| Spread | Total spread per share for fixed-spread slippage ($) |
Simulation settings can be saved in run presets (.qcs).
Script parameters (single run)
If your strategy imports from quantcraft.inputs import params (legacy from ide.inputs_module import params or from quantcraft.inputs_module import params still works) and references params.NAME, the dialog shows a Script tab with one row per discovered name: Parameter, Type (int / float / str / bool), and Value.
Fill every row before you start — values are required for each declared parameter. They are sent on the wire as strings and coerced by the engine before your file loads, so params.PERIOD (for example) is already the correct Python type when your module executes.
On the same tab you can enable Optimize for grid or genetic search — see Optimization. Leave Optimize unchecked for a normal single backtest.
What happens when you start the run
The app validates the form (dates, symbols, balance, fundamentals if enabled, and script parameter types). On success it starts one backtest with the assembled configuration; progress and logs appear in the Output panel, and structured results open in Test Results.
Quick reference
| Topic | Where it’s set |
|---|---|
| Alpaca vs. B2 prices | Symbol & data → price feed (ohlcvSource in .qcs). |
| Timeframe | Primary timeframe (Alpaca) or B2 timeframe (d / w / m only). |
| Additional timeframes | Additional timeframes multi-select — for rt.get_bar(Timeframe.X, shift). |
| Asset class | US equity / Crypto (Alpaca only). |
| Truncate to last N bars | Min bars (Alpaca only, optional). |
| What to trade | Symbols (multi-select on Symbol & data). |
| Clock symbol | Script SYMBOL if loaded; else first symbol (no modal control). |
| Financial statements | Include fundamentals + fundamentals multi-select; requires sign-in. |
| Global factor returns | Include Fama-French factors (global) — see Fama-French factors. |
| Calendar window | Start date / End date on Simulation (required). |
| Indicator history before start | Warmup bars on Simulation. |
| Starting cash | Starting balance on Simulation. |
| Commission / slippage | Simulation tab — see Account model. |
on_timer | Not in Run backtest — forward runs with timerIntervalMs (Strategy lifecycle). |
on_tick | Backtest: four synthetic OHLC ticks per bar (no real tick history). Forward runs: every broker price update — see Strategy lifecycle. |
| Tunables in code | Script tab (params.*), single values per run (or Optimize). |
Tips
- If Alpaca symbols never load, open Trade once or confirm Alpaca connectivity; for B2, confirm you’re signed in and the symbol catalog loaded.
- Warmup only extends loaded history — it does not add trading days outside your date range.
- Do not expect
on_timerin the IDE backtest — there is no timer control on that modal. Useon_bar/on_tickinstead. Timers apply on forward runs whentimerIntervalMsis configured. on_tickin backtest uses synthetic OHLC from each bar (four calls per bar) — not real tick data. Test live tick logic on forward runs (Strategy lifecycle).- Match fundamentals bundles to the tickers you actually read in code when OHLCV and fundamentals tickers differ.
- Use Min bars sparingly — it is easy to accidentally shorten a run more than you intended.
