The fee line eats the grid
Grid and DCA bots advertise small, steady profits. Each step's gross edge is often smaller than the round trip fees plus the spread, and a backtest without fees can get the sign of the result wrong.
A grid bot places buy and sell orders at fixed steps and collects the difference when price moves back and forth. The pitch is simple: every round trip earns one step. The arithmetic the pitch leaves out is what a round trip costs.
What one round trip pays#
- The exchange fee on the buy.
- The exchange fee on the sell.
- The spread, crossed once on the side that is not resting.
- Funding, if the inventory is a perpetual and is held across a funding time.
Add those up and you get the smallest step at which a round trip is not a loss.
def breakeven_step(fee_rate: float, spread: float, funding_per_step: float = 0.0) -> float:
"""Smallest grid step (as a fraction of price) at which one buy-sell round trip is not a loss.
A round trip pays the fee twice, crosses the spread once and pays whatever funding
accrues while the inventory is held."""
return 2 * fee_rate + spread + funding_per_step
step = 0.0015 # a hypothetical 0.15 percent grid
cost = breakeven_step(fee_rate=0.0006, spread=0.0002)
print(f"edge per round trip: {step - cost:+.4%}") # 0.15% minus 0.14% leaves +0.0100%These inputs are made up to show the shape. With them, a grid step that looks like 0.15 percent keeps a hundredth of a percent after costs. Nudge the fee up, or let the spread widen in a fast market, and the sign flips.
Why a backtest can lie about this#
A backtest that fills at the touched price and charges no fees will show a grid as a machine that prints one step per round trip. Put the fees and a realistic spread back in and the same grid can be a loss on every cycle. The sign of a result can change from this one line.
The other half of the risk is not in the arithmetic at all. A grid assumes price stays inside a range. When it leaves, the bot is left holding inventory on the wrong side, and no step size fixes that. That is a position limit and a stop problem, which is why a grid, like any other bot type, ends at the risk gate.
What we do with a grid request#
We ask for the exchange's real fee tier and the spread of the markets it will trade, compute the break even step, and refuse to build below it. Then we put a range limit and one stop over the whole thing.
This is how trading software can be built. It is not investment advice. Trading crypto assets, especially with leverage, carries a risk of losing money, and results from tests or simulations do not guarantee anything in live markets. The studio builds trading software and tooling. It does not manage anyone's money, hold client funds or trade on anyone's behalf.
The best of a hundred coin flips looks like talent
Try enough strategies and one of them will look brilliant, even when every one is a coin toss. The number of tries is part of the result, and it is the part nobody prints.
Slippage is a fee nobody prints
The exchange prints its fee. It does not print the spread, the thin book or the stop that fills worse than its trigger. A test that leaves them out is flattering itself.
Start from the task, not the strategy
A trading bot project begins with what the bot is for, what it may lose and what it must never do. The signal comes last, and it is the smallest part of the work.