Concept

Costs & fees

How commissions, slippage and position sizing are modelled.

Real trading costs money, and a backtest that ignores that is lying to you. The engine charges fees on every fill and applies slippage against the trade direction, so a simulated fill is never better than a live order would have got.

Fees & slippage#

  • Exchange style percentage fees are charged on every fill: entries, exits, and partial fills alike.
  • Slippage is configurable and always applied against the trade direction: entries fill slightly worse than the signal price, never better.

Say the costs in the sentence#

You don't need a settings panel to charge costs, state them in the query and the parser routes them for you:

  • One flat rate: "… with a 0.1% trading fee", "… with commission of 0.1%", or "… with 10 bps fees", all charge the same single rate on every fill (bps convert automatically).
  • Maker and taker rates: "… with maker fees of 0.05% and taker fees of 0.1%": two rates, charged per fill by side.
  • Both together: "… with 0.1% fees and 0.05% slippage" sets the neighbouring knob in the same breath.
  • Explicitly free: "… with no fees" records a real zero rather than an unstated default.

A single-sided rate ("0.05% taker fees" with no maker rate given) is treated as one flat rate, the engine never invents the missing side. And a maker/taker schedule needs both legs: a half-stated or out-of-bounds schedule is refused with a clarification instead of being guessed, because guessing would silently make the run cheaper than you asked for.

Which fills pay which rate#

With a maker/taker schedule set, bar-close entries and every forced exit (stop, blow-up, end-of-data) pay the taker leg, they cross the book. Resting limit fills pay the maker leg. A run that charges fees through a schedule counts as a costed run everywhere, including the grade: it will not be flagged as "graded without transaction costs".

Execution realism#

Three optional models make fills more conservative. All are off unless set, an untouched run is unchanged, and every run is stamped with the fill-model version it executed under, so results stay comparable across upgrades.

  • Bid/ask spread (spreadBps): a half-spread charged on taker fills and waived on maker fills, crossing the book costs the spread; resting in it doesn't.
  • Volume-capped fills (maxBarVolumePct): a fill may not exceed the set share of the bar's volume. Trades that get sized down say so (volume_cap vs affordability), so a smaller position is always attributable.
  • Market impact (marketImpactK): charges more the larger a share of the bar's volume your order takes. Impact requires the volume cap, without a fill cap the share is unbounded and so is the number, so the engine refuses impact-without-cap with a named warning rather than producing one.
Funding isn't a modelled cost

On perpetual futures, funding is available as a queryable signal (funding rate, aggregated funding rate) you can trade on, but it is not charged against P&L as a holding cost. If a strategy holds perps for long stretches, budget for funding yourself.

Position sizing & liquidation#

How much you commit per trade shapes the equity curve more than almost anything else.

  • Sizing modes: risk based (risk a fixed % of equity per trade against your stop distance), % of equity, and fixed sizing, all with an affordability cap, so a position can never be larger than the account can actually pay for.
  • Leveraged futures include a liquidation model, and spot shorts carry a margin style liquidation backstop.
  • Equity can never go below zero. A blow up terminates the run rather than letting the simulation trade with money that no longer exists.
Set costs to match your venue

Fees and slippage are inputs, not fixed constants. Model the fee tier and typical slippage of the exchange you'd actually trade on. A strategy that only works at zero cost isn't a strategy.

See how sizing is expressed in a query under entry & exit logic, and how it's scored in the Metrics reference.