QQ 301, 3 min read

What the tool does not model

Each line is a statement about the code as written.

Fills and the market

  • No intrabar path. Fills happen at a bar's open (or a price the script supplies). The engine never looks inside a bar. It does not know whether the high or the low came first.
  • No order types. There are no limit, stop or take-profit orders in the engine. A script can compute a stop level and write an explicit exit price, and the engine will accept it without checking that the bar's range contained that price or that it was reachable before another level.
  • No gap handling for stops. Because stops are not modelled, a stop that would have been jumped by a gap is filled at whatever price the script wrote.
  • No partial fills, no rejections, no queue. Every trade fills in full.
  • Liquidity is not a constraint unless you turn it on. Size is unlimited by default. Only slippage_model: "sqrt_impact" makes size cost something, and it needs a real volume column.
  • Spread is a constant or a per-bar average. It does not widen at the open, around news or at rollover, unless your data's bid/ask columns carry that.
  • Latency is in whole bars. There is no sub-bar latency.

The account

  • No margin model. There is no margin requirement, margin call or stop-out level. The only liquidation is equity reaching zero. An explicit qty can be any size.
  • One currency. P&L is price difference × qty, in the quote currency of the instrument, added straight to the account. There is no conversion to a different account currency, no contract multiplier, no pip-value table and no lot-size rounding or minimum size.
  • Financing is a flat annual rate. No broker swap table, no triple-swap day, no dividends, no borrow fees or locate availability for shorts.
  • Commission is a percentage of notional only. No per-lot or per-trade fixed fee, no minimum ticket, no tiered schedule.
  • No taxes, no funding costs, no interest on idle cash.
  • One instrument's bars per run. df is one dataset. A script can read others through data[...], but trades are filled and marked on df's prices only. There is no shared-balance portfolio backtest in this build.

Data

  • No corporate actions. Splits, dividends and symbol changes are not adjusted for. The engine uses the prices in the file as they are.
  • No survivorship handling. If your dataset contains only instruments that still exist, the engine cannot know.
  • No session calendar. The engine does not know exchange hours or holidays. Annualisation in the results tiles assumes bars around the clock (3.4).
  • Provenance is recorded, not verified, for your own files. A file you import is labelled user-import. Nothing checks it against any source.

Statistics and validation

  • The Sharpe in the tiles and the Sharpe in the checks are different numbers (per-bar with a 365.25-day year, versus daily with sqrt(252)).
  • No risk-free rate anywhere in the Sharpe, Sortino or alpha calculations.
  • Monte Carlo resamples trades independently. Clustered losses are broken up.
  • SPA and Romano–Wolf over-reject, and the bootstrap interval under-covers on autocorrelated returns (4.6, with the measured numbers).
  • The trial registry and the holdout counter are local files keyed on the code hash. They count what the terminal saw. They cannot count variants you tried elsewhere, by hand, or under edited code, and they can be deleted.
  • No live comparison. live_tracking is a placeholder that always skips.
  • A passing verdict is not a forecast. Every check asks whether the backtest is evidence. None of them predicts next year.

Source. Fill prices backtest/runner.py:693-713; no range check on explicit prices (the only price checks are finite and > 0, backtest/runner.py:709-713, and positive after costs, backtest/runner.py:468-486). Sizing and P&L backtest/runner.py:1167-1212. Ruin backtest/runner.py:434-466. Sharpe backtest/runner.py:1605-1616 versus backtest/stats.py:537-555. Tool default bars engine/server.py:4343; plain backtest limit: 0 engine/server.py:4272. Live tracking backtest/institutional.py:238-239.