← Engineering notes

Your stop width decides what share of your risk goes to the exchange

Fees and slippage are a fixed toll per round trip, so the narrower the stop, the larger the share of your own risk budget that goes to the venue instead of the market — worked out at the 0.07% fee and 0.05% slippage this engine charges.

· 7 min read

A schematic of calipers measuring the gap between two reference lines on a flat price scale.

A stop is a budget. You decide in advance the largest amount a position is allowed to take from you, and the stop is where that decision gets enforced. What the framing leaves out is that opening and closing the position costs the same whether the budget is large or small.

So the cost is a fixed toll on a variable budget. The narrower the stop, the larger the share of the risk you sized for that never reaches the market at all. Here is that arithmetic with the constants this engine actually uses, so you can redo it with yours.

What a fill costs here

Costs are folded into the fill price rather than subtracted at the end:

fee: float = 0.0007
slippage: float = 0.0005

def _fill(price, side, entering, params):
    adverse    = 1.0 + params.slippage + params.fee
    favourable = 1.0 - params.slippage - params.fee
    if (side == "long") == entering:
        return price * adverse
    return price * favourable

Both fills go against the trade. A long buys at price × 1.0012 and sells at price × 0.9988; a short does the mirror image. Call the per-fill cost c = 0.0012 — 0.07% fee plus 0.05% slippage, which is what the guide footer and the backtest report footer both say, and it matches the two constants above.

A round trip with no price movement at all:

(1 - c) / (1 + c) - 1  =  0.9988 / 1.0012 - 1  =  -0.00239712

0.2397% of the notional you committed, per round trip. That figure does not know what your stop is. It is the same for a scalp and for a position you hold for three weeks, and the backtests run in the app carry it: the authoring path builds its parameters from the strategy and overrides only stake and leverage, so the two constants above are never replaced by something friendlier.

One correction while we are in this file. The docstring that explains why costs are not subtracted a second time says a double-count would have made every strategy look "about 0.28% worse per trade". The constants give 0.24% at 1x. The comment is the rounder number; the derivation above is the one to check your own arithmetic against.

The toll is fixed. The budget is not.

Take the stop as a distance in price, d. The share of the risk budget that goes to the venue is 0.239712 / d:

Stop, as a price distance Toll as a share of the budget Loss when the stop is hit (long)
0.25% 95.9% 0.3697%
0.50% 47.9% 0.6194%
1.00% 24.0% 1.1188%
2.00% 12.0% 2.1176%
3.00% 8.0% 3.1164%
5.00% 4.8% 5.1140%
10.00% 2.4% 10.1080%
15.00% 1.6% 15.1020%

The crossovers are worth naming, because they are where the decision changes character:

  • 0.2397% — the toll equals the entire budget. A stop this tight costs more to place and remove than the stop was ever going to let the market take.
  • 0.479% — the venue takes half of the budget.
  • 0.959% — a quarter.
  • 2.397% — a tenth. From here outward the toll is a rounding error on the risk decision, and stop width stops being a cost question.

The third column is not the budget plus 0.2397%, and the reason is the next section.

Leverage moves both numbers, and they cancel

A declared stoploss is a fraction of stake, so the engine divides it by leverage before comparing it to a price: at 2x, a -15% stop is a 7.5% adverse price move. Return on stake is then multiplied by the same leverage. Both sides scale together, so the share in the table above depends only on the stop's distance in price — a 15% stop at 2x and a 7.5% stop at 1x both hand 3.2% of the budget to the venue. Leverage changes what a stop-out costs you. It does not change who gets what fraction of it.

Where the toll actually shows up

The stop is measured from the entry price after _fill has been applied, which moves half the toll out of the loss column and into the trigger.

Work a 1% stop on a long:

raw entry        R
entry fill       R x 1.0012
stop price       R x 1.0012 x 0.99   =  R x 0.991188
exit fill        R x 0.991188 x 0.9988

market move to trigger   0.991188 - 1          = -0.8812%
realised loss            0.99 x 0.9988 - 1     = -1.1188%

A "1% stop" is tripped by a 0.8812% adverse move in the market, and books a 1.1188% loss. The gap between those two, 0.2376%, is the toll seen at the exit price level — 0.239712% × 0.991188, exactly. Half of it is a bigger loss than you declared; half is the stop arriving sooner than the number suggested. The money is identical either way, it just lands in a different column, and only one of those columns is in the report.

Two details that push the same direction: a short pays d + c(1 + d) where the long pays d + c(1 - d), so a 1% short stop books 1.1212%; and a bar that opens already past the stop fills at the open, not at the stop price, which is a cost no stop width controls.

Then you pay it more often

The second-order effect is the larger one. Model the price as a driftless random walk with per-hour return standard deviation σ. Expected time to first touch a barrier d away is (d / σ)² hours. This is a statement about price, not about any strategy — but the exponent is the point.

With σ = 0.30% per hour, purely as an illustration:

d = 1.0%   ->  (1.00 / 0.30)^2 = 11.1 h   ->  2.16 round trips/day  ->  0.52%/day in tolls
d = 0.5%   ->  (0.50 / 0.30)^2 =  2.8 h   ->  8.64 round trips/day  ->  2.07%/day in tolls

Halving the stop doubles the share taken out of each budget and quadruples the toll paid per day. Two different exponents hanging off one decision, and the second one is invisible in a per-trade cost figure.

The caveats are real: entries are not random, a stop is only one of three ways this engine closes a position, and a strategy with any edge is not a driftless walk. None of them change the sign or the order of magnitude of 1/d².

Funding pulls the other way

If the toll were the only cost, the conclusion would be "always widen the stop", and that is wrong. Perpetual funding settles every eight hours and is charged per settlement a position is open across, so it is a cost that grows with holding time — and a wider stop holds longer. The fill toll penalises frequency; funding penalises duration. Neither width escapes both.

Worth knowing when you read a report: a trade whose window no rate series covered is counted as uncovered, not charged zero, and the coverage is printed beside the result. An unmeasured cost and an absent cost are different claims.

The checkable part

Three things you can do with your own numbers in about a minute:

  1. Divide. Take your stop's distance in price — the declared stop divided by leverage — and divide 0.2397 by it. That percentage of your risk budget is the venue's, before the market has done anything.
  2. Substitute your venue. The round trip is (1 - c) / (1 + c) - 1 with c = fee + slippage per fill. Taker fees and a wider slippage assumption move the crossover points, not the shape.
  3. Re-run the same signals at a different width. Risk settings live in the backtest parameters rather than in the strategy document, so one computed signal stream replays at a dozen stop widths without recomputing a single indicator. Read the trade count and the cost share, not just the headline figure.

The number to distrust is the one you have never divided. "I risk 1% per trade" is a sentence about a budget; a quarter of it was spoken for before the trade started.

KONIS is quantitative trading infrastructure. Backtest declarative strategies against years of exchange data, run what survives on a managed runtime, and read the market through analytics while it runs.

Build and backtest free — no card

Technical software and market analytics, not financial, investment or trading advice. Nothing here is a recommendation to buy or sell anything. Backtested results are historical and do not indicate future results. Trading carries substantial risk, including total loss of capital.