DEV Community

Sergei B
Sergei B

Posted on AI-assisted

The backtest used a 0.06% fee. What was my account actually paying?

I develop trading bots. Our historical tests used a fee of 0.06% per side. When I checked the executions from one of my live accounts, though, the volume-weighted fee rate actually paid was about 0.0801%.

That looks like a small difference. But fees apply to every fill, and a bot can generate a lot of them. I wanted to answer two questions: where did the different rate come from, and how much would it change one backtest?

What the account actually paid

I took a Bybit crypto futures execution export covering August 29 to October 25, 2026. It contained 3,204 trade executions. Those are fills, not completed trades: a single order can fill in several parts.

The executed notional was about 323,731.67 USDT. Trading fees totalled about 259.44 USDT.

To calculate the average rate, I divided the fees paid by the executed notional:

259.44 / 323,731.67 × 100% ≈ 0.0801%.

Funding payments for holding futures positions were excluded from that calculation. I used the fees charged on exchange executions, rather than adding up selected fee-related fields in the bot's database.

This account had two rates: 0.036% for maker fills and 0.1% for taker fills. Maker executions add liquidity to the order book; taker executions remove it. Roughly 31% of the executed notional was maker and 69% taker. That mix produced the average fee rate.

A limit order does not necessarily pay the maker rate. If it executes immediately against orders already resting in the book, it can be a taker execution.

One Bybit account's fee schedule and its separately calculated volume-weighted fee rate

Unchanged excerpt from my Bybit fee page, English interface, October 26, 2026: futures, standard crypto, Regular User. The average rate below was calculated separately from executions, August 29 – October 25. MNT discount display is off.

One account is not the whole exchange

Bybit says that rates may vary by region and VIP level, and directs users to their own fee page after identity verification. Bybit's fee schedule and explanation.

One more detail. Bybit's fee page shows rates in two places. The "My fee level" card for futures shows 0.036% maker and 0.1% taker for my account — the same rates recorded on the trade executions in the period I checked. But the general fee table in the English interface lists 0.02% and 0.055% for the same "Regular User" tier. It is easy to look at the wrong place, which is why I check my account's rate against executions.

My result does not mean that every customer pays 0.0801%. Another account, with a different fee schedule and execution mix, may pay less.

Freqtrade had not calculated some incorrect global average, either. We had explicitly supplied 0.06%, and it used that value. Custom backtest fees are documented in the Freqtrade manual. The question was whether the assumption matched the account, not whether the software could do the arithmetic.

One strategy, three fee rates

For the experiment, I used one strategy, a starting balance of 2,500 USDT and the same historical dataset with one-minute detail. The window ran from January 1, 2024 to December 31, 2024 at 00:00 UTC. The final day of December was not included.

Only the fee changed between scenarios. The 0.08% rate approximated the measured average for my account. I also tested 0.044% as a lower-cost scenario, not as a claim about the rate paid by everyone else. That is roughly what the same 31/69 split gives under Bybit's base futures table: 0.02% maker and 0.055% taker.

Fee per side Backtest return Difference from the baseline Closed trades
0.044% +175.94% +60.82 USDT 4,070
0.06% +173.51% Baseline 3,936
0.08% +156.29% −430.34 USDT 3,790

Return here means the test's final profit divided by its starting balance. The USDT column is the difference between final backtest results, not simply the extra fees charged. These percentages describe the stated historical window; they are not a forecast.

I also reran the original 0.06% case to check the baseline itself. All 3,936 trade records matched the old result exactly, including the nested order records.

Returns and closed-trade counts for three backtests with different fee assumptions

All bars start at zero. The balance, data and settings were unchanged; only the flat fee changed. These are historical backtest returns, not live-account returns.

For completeness, the engine-reported drawdowns were 10.38%, 11.11% and 10.85%, respectively. That is its max_drawdown_account metric, not a separately reconstructed mark-to-market drawdown including all open positions. I am not using those three figures as a measure of the strategy's full risk.

Why subtracting extra fees was not enough

On a fixed list of fills, changing the fee rate gives a straightforward cost recalculation. But that answers a narrow question: what would those same fills have cost at another rate?

In our reruns, the trade set changed too: one scenario produced 3,790 closed trades and another 4,070.

So, in this experiment, subtracting a different fee bill from the old result would not have reproduced the new run. I did not trace why each individual trade changed here. The summary figures therefore do not establish, for example, that trades all closed later.

What to check in your own test

Start with the fee schedule for your account and instrument. Then check the fees actually charged on executions and compare them with the rate supplied to the backtest. Weight the average by executed notional; do not simply average the maker and taker rates.

If the rates differ, keep two checks separate: repricing the old fill list and rerunning the strategy. They answer different questions.

This experiment has limits. It covers one strategy and one historical window. Each run used a flat fee rather than a maker/taker classification for every simulated fill. The 0.08% scenario therefore does not recreate my account in every detail. It did not test slippage or order-book queue position. The strategy code is private, so readers cannot fully reproduce these particular runs without it.

The practical conclusion is specific: a 0.06% assumption is not automatically wrong because my account pays more, and my account's rate is not universal. What matters is whether the test's assumptions match the conditions of the account.

Top comments (0)