Concept · Maker/Taker Fees
On a perpetual futures exchange, two fee tiers exist: a lower "maker" rate for orders that add liquidity to the book, and a higher "taker" rate for orders that remove liquidity immediately.
When you trade on a PERP (perpetual futures — a derivative with no expiry date that tracks the spot price via a funding mechanism) exchange, the exchange charges a fee based on how you filled your order:
On Binance USDT-perp (as of 2026): taker ≈ 5 bps (0.05%), maker ≈ 2 bps (0.02%). On Orderly Network, the maker fee has historically been negative — a rebate (the exchange pays you to post limit orders).
At 5% position sizing on $10,000 equity ($500 per trade):
Over 400 trades (typical for 1h–4h swing strategies in this fleet), the difference is ~$120 — roughly 1.2% of starting equity lost to fees at the taker rate vs ~0.5% at the maker rate.
The engine needs to distinguish how each order was filled:
takerFeeBps.P. Check each candle's range:
if (candle.low <= P) → fills at P, apply makerFeeBpsif (candle.high >= P) → fills at P, apply makerFeeBpsThis is the same OHLC-range check the engine already uses for TP/SL exits (see fill-resolver.ts:26, the overrideFillPrice path). The machinery exists; it needs to be generalized to entries.
fill-resolver.ts:54 resolves every backtest fill to candle.close with a flat cfg.feeBps — a pure taker model. No order types exist. No maker/taker distinction. The simulator-fidelity.md concept catalogs this as a known gap.
Limit orders change the set of trades that fire, not just the fee. A limit entry 0.2% below the current close only fills if the next candle's low reaches that price. If it doesn't, the trade is missed entirely. A strategy with 450 taker trades might have 340 limit-entry trades with identical conditions — different trade count, different win rate, different Sharpe.
Consequences for simulation design:
limitPriceFn — how far off the close to set the limit (a new optimizable axis, new overfitting risk)See simulator fidelity for the full gap catalog and limit order for the fill mechanics in detail.
The current engine applies a flat 17 bps to every fill. All metrics below are at that rate.
Both examples are directional at this point only — the engine does not yet model maker fills, so actual trade count could differ with limit entries.
wiki/qa-sessions/2026-06-29-session.md#q2 (first asked here)apps/backend/src/evaluation/position/fill-resolver.tsapps/backend/src/evaluation/position/fill-resolver.ts:26 (overrideFillPrice — the existing OHLC-range fill path)Related concepts
See it in a real result →Put it to the test
Spawn your variant, run it on the same engine, and read the edge-significance verdict — before you risk real money.