Triangular Arbitrage: Calculate the Fee Break-Even Before the Trade
TECH INSIGHT / EXPLAINED
A three-token cycle is profitable only if its executable output returns more of the starting token after every cost. Multiplying three displayed prices is a screening calculation, not an executable quote.
Make the units cancel
For A → B → C → A, define each rate as output units per input unit. The product then has units A/A. Buying an asset uses the ask; selling uses the bid. Reversing a quoted pair requires the appropriate inverse, not reusing the same number.
Use the full path as a log label and record the block or order-book snapshot behind it. Rates from three different moments do not form one coherent opportunity.
A worked fee budget
Here is a hypothetical 1.2% gross loop edge on 1,000 units. Each hop charges an assumed 0.3%; these are example fees, not a rate shared by every venue. After three fees and a gas bill worth two starting-token units, only 0.919296676 units remain.
from decimal import Decimal as D
start = D('1000')
gross_multiplier = D('1.012') # hypothetical, before trading fees
keep = D('0.997') ** 3
gas_in_start_token = D('2')
end = start * gross_multiplier * keep - gas_in_start_token
print(end) # 1000.919296676000
print(D(1) / keep - 1) # fee-only break-even: about 0.9054%Why 0.9% is only an approximation
The fee-only gross break-even multiplier is 1/(0.997³), so the required gross edge is about 0.9054%, before gas or price impact. If the quoted rates already include trading fees, applying 0.997 again double-counts them.
A finite-size AMM quote changes with input size. Estimate each next hop using the previous hop’s output; do not apply a tiny-trade spot rate to a large order. Likewise, CEX books require depth-aware fills and quantity rounding.
Execution changes the problem
An atomic on-chain route can revert as a whole, while still consuming gas. Separate exchange orders can leave inventory when only some legs fill. Those are different failure modes.
Record quoted output, minimum acceptable output, estimated and actual costs, and residual inventory. Reject stale quotes and include a margin for uncertainty. This arithmetic estimates a conditional result; it neither establishes how frequent opportunities are nor guarantees the result after submission.
Fixed gas makes trade size part of the condition
Keep the earlier assumptions and vary only starting quantity. The multiplier after trading fees but before gas is 1.002919296676, while fixed gas costs two units of the starting token. Hypothetical net change is therefore starting quantity × 0.002919296676 − 2. The following values are rounded to six decimal places and are calculated scenarios, not observed trades.
| Starting quantity | Net change after costs |
|---|---|
| 500 | −0.540352 |
| 1,000 | 0.919297 |
| 2,000 | 3.838593 |
The break-even starting amount in this simplified model is approximately 685.096522. It is not a usable minimum order recommendation. The calculation assumes unchanged conversion rates and gas costs at every size. In a finite pool, price impact changes those rates; in an order book, larger amounts consume different price levels. Requote the entire route for each proposed size.
A hop's output may not be a valid next order size
Suppose a synthetic exchange route leaves 12.3456 B after the first hop's fee, while the next order accepts increments of 0.01 B. Rounding down gives an orderable 12.34 B and leaves 0.0056 B in inventory. Rounding to the nearest increment, 12.35, would exceed the available balance. A valid quantity increment also does not prove that the order satisfies minimum notional requirements.
The Binance Spot filter specification distinguishes LOT_SIZE minimum, maximum and stepSize constraints from notional filters. An implementation must identify which filters apply to its order type and which asset pays the fee. Keep residual token quantities, their estimated valuation and their actual disposal constraints separate. Valuing every leftover at a displayed price does not turn that value into realized proceeds.
Connect the gas budget to the route's output floor
For an on-chain cycle, a check of starting-token quantity alone does not establish an all-cost result. Gas paid in another native asset needs a separate budget translated into starting-token units. Record route output, gas used, effective gas price, conversion price and conversion timestamp separately. Distinguish trading fees already embedded in output from gas paid outside the route.
A route can return slightly more starting tokens and still lose value after the external gas expense. A minimum-output setting constrains the acceptable output of that call; it does not guarantee inclusion or fix the conversion value of gas. Preserve higher-gas and reverted-route cases as separate outcomes instead of blending them into successful-route arithmetic.
Use boundary cases to validate the route
Test amounts immediately below and above relevant quantity boundaries, and a route where only one hop lacks sufficient depth. Compare fee-free and fee-bearing models to locate each deduction. Confirm that fee-inclusive quotes do not receive another fee multiplier. Reconciling every hop's input, output and remainder reveals more than applying one uniform percentage to all routes. The table and rounding example were executed locally using Python Decimal. They validate offline arithmetic, not the profitability or availability of an actual route.
Sources and further reading
Content and examples reviewed: 2026-10-01
댓글
댓글 쓰기