Triangular arbitrage: where the algorithm loses profit
Triangular arbitrage looks like a risk-free operation: the algorithm spots a discrepancy between three pairs and completes a closed cycle within a single venue.
On paper, profit is calculated from the latest trades, but a chain of three pairs executes sequentially — and each leg changes the conditions for the next.
The first source of losses is slippage during execution. By the time the second leg reaches the order book, the best price has already been taken by neighboring bots, and the order fills at lower levels.
On narrow pairs, even a small volume moves the quote by tenths of a percent, and there are three such shifts in the cycle, and they add up.
The second is exchange fees. They are paid on each leg, plus the spread, plus the transfer of funds between exchanges if the cycle is cross-exchange.
The difference the algorithm captures is often comparable to the total costs, so calculation using top quotes shows profit where there is none.
The third and most dangerous is partial order execution combined with venue response latency.
While the third leg waits for confirmation, the price moves away, and half the chain remains open: instead of a closed cycle, we get a directional position that the market can turn against us.
Next we analyze how this is closed: where to set liquidity filters, how to calculate profit taking into account costs on all three legs, and what to do with legs that did not fill.
What automatic real-time cycle search provides
Manual cycle search is limited by trader attention: while one triangle is being calculated, the price in the other two legs has already moved.
Automatic cycle search works differently — the system continuously iterates triangles across three instruments, calculates the result taking into account fees, spread, and available order book depth, and discards cycles where costs eat up the difference.
The key metric here is not “how many cycles were found,” but the share of profitable cycles — the share of those that reached closing of all three legs with a positive result.
The system's reaction speed determines whether the signal reaches the order book: between calculation and placing the first leg there is a window in which the price changes.
Therefore, the three orders are constructed in parallel, not sequentially, and the remaining legs are recalculated immediately upon partial execution — the cycle either closes entirely or is unwound with a minimal residual.
A separate part of the work is accounting for exchange limits: on Binance, the request rate is recalculated dynamically, and the pace is reduced in advance, not after a block.
Risk control per trade is set before launch: volume limit per cycle, limit per instrument and per exchange, prohibition of overlapping triangles. If one leg did not fill, an exit rule triggers — reversing into the market or canceling the remainder.
The execution log records each leg: send time and fill time, actual price, volume, and rejection reason. From it, you can see exactly where the result is lost — in latency, in fees, or in liquidity.
Execution modes: comparison of approaches to trades
The autonomy of the system is a variable, not a property. The same triangular arbitrage can be run in three modes: from monitoring cycles to full auto-execution. The difference lies in who makes the entry decision and how many checks stand between the signal and the order.
| Mode | When it fits | What limits it |
|---|---|---|
| Monitoring mode | Initial hypothesis validation, unfamiliar venues, thin pairs | Manual trades — reaction lags, the discrepancy window closes before entry |
| Semi-automatic execution | The bot calculates the cycle and prepares orders, a human confirms | Confirmation adds latency, some cycles do not survive the wait |
| Full auto-execution | Proven scenarios, stable liquidity | A configuration error is replicated without stopping — strict limits are required |
Regardless of the mode, we build the system with position limits: a cap on the volume of one cycle, on volume per venue, and on total volume across all pairs.
In a distributed system, monitoring and execution nodes are separated — a failure of one venue does not stop the remaining cycles, and the signal queue continues to be processed.
We make mode switching a parameter, not a rewrite of the logic. You start with monitoring, enable trade confirmation, then remove it for scenarios that have performed without discrepancies.
How the algorithm is built: stages of engineering work
The cost of an error in an arbitrage chain is not an incorrect calculation, but a leg left hanging without closing: slippage and latency between venues eat up the spread faster than the signal arrives.
Therefore, we build the algorithm in stages, and each stage ends with an artifact that informs the decision to move on.
- Venue audit. We select exchanges with the required pairs, comparable liquidity, and predictable fees. We check withdrawal limits, deposit methods, and the stability of the quote stream — the chain should not run into the venue's infrastructure.
- Cycle scheme. We build a graph of pairs of the form A→B→C→A and cut off chains where fees eat up the spread. For each cycle, we fix the entry threshold and allowable slippage.
- Mathematical model. We calculate position size taking into account taker and maker fees, order book depth, and latency between venues. We determine how volume is distributed across legs and where the stop is placed.
- Historical validation. We run on accumulated data with real fees, rejections, and delays. We look at how many cycles survive after costs and remove false signals.
- Execution system. Order submission, partial execution control, and emergency leg closing logic. Separately, we define stop rules for balance discrepancies.
- Launch on small volumes. Operation on the real market with limited position size: we compare actual costs with modeled ones and adjust entry thresholds.
- Handover to operation. We deliver the system with settings, alerts, and a stop procedure, and train the client's team.
The sequence does not allow moving to live trading until the model is confirmed by market costs.
What is included in the delivery: code, configurations, procedures
Project delivery is not a demonstration of a successful cycle on screen, but a package with which your engineers can independently launch, maintain, and develop the system.
We hand over each artifact in the form in which we use it ourselves: with a description of parameters, applicability boundaries, and the procedure for actions during deviations.
- System source code — modules for market data collection, cycle calculation, order planning and placement, and balance accounting. A repository with change history and reproducible build, without closed dependencies that you cannot maintain on your own.
- Configuration files — profitability thresholds, limits on the size of one position and total volume of open positions, response wait time limits, lists of trading pairs and venues. Separated by environment, so a test run physically cannot send a real order.
- Monitoring dashboard — active cycles, rejected signals with the reason for rejection, status of data channels, execution latency, and the discrepancy between calculated and actual trade results.
- Operations procedure — startup and shutdown order, actions for balance discrepancies, data stream interruption, or a series of rejected orders, and the procedure for rolling back to the previous version.
- Key access rights — role separation scheme: trading keys without withdrawal rights, separate accounts for test and production systems, rotation and revocation procedure.
- Parameter description and decision log — why this calculation horizon and entry threshold were chosen, which hypotheses were tested and why they were rejected.
Acceptance follows a checklist: we launch the system on your infrastructure, run typical failures, and make sure the procedure allows your team to recover without us.
Case study: from manual trades to an autonomous system
The client was a team running triangular arbitrage manually: the trader kept the order books of three exchanges in front of them, calculated the chain A→B→C→A in a spreadsheet, and managed to assemble a cycle only when the discrepancy lasted several minutes.
Across 40+ pairs, a manual pass took 40–60 seconds, some routes were not checked at all, and the discrepancy closed before the order could leave.
A separate pain point was partially executed cycles: one leg filled, two did not, and the position hung in the wrong currency until manual review.
We built an autonomous system: streaming order books from exchanges converge into a route graph, the calculation accounts for fees, limits, and slippage on each leg, and orders are sent as a batch with a strict time limit.
Before sending, the system checks liquidity across all legs — if at least one fails, the cycle is discarded before the trade, not after. To filter out broken quotes, we connected CoinGecko as an independent source for rate verification.
What changed in the first month: the time from detecting a discrepancy to placing an order — 1–2 seconds instead of 40–60, the share of executed cycles grew from 55% to 88% by filtering out illiquid routes, and the failure class “hanging leg” did not recur even once.
Manual cycles were left only as a control mode for testing new routes — the main flow runs autonomously.
How triangular arbitrage differs from cross-exchange arbitrage
Triangular arbitrage closes within a single venue: three legs — A→B, B→C, C→A — execute in its own order book, and settlement occurs in the exchange's single unit of account. The asset does not leave the venue's system: there is no blockchain transfer between legs, only orders.
A cross-exchange cycle is structured fundamentally differently. One leg is closed on the first exchange, the second on the second, and between them the position must be physically transferred. This transfer is the source of all differences — in risk, speed, and cost.
It also creates transfer risk: while the asset is moving over the network, it is neither in the trading balance nor under management.
Crediting depends on network load, the number of confirmations, and the venue's internal deposit rules, and the network fee is charged for each such operation.
The speed of closing a cycle differs for the same reason. Within a venue, three legs are sent almost simultaneously, the window is measured in seconds, and the rate discrepancy closes on a single balance.
During a transfer, the window is set not by the trader but by the network: while waiting, the spread collapses, and the cycle closes at different prices.
Therefore, a cross-exchange scheme is built not on transferring for each trade, but on pre-funded balances on both venues — then the transfer fades into the background.
Triangular does not require such preparation, but is stricter about order book depth and fee levels, while the cross-exchange variant is sensitive specifically to transfer cost and time.
Technical concerns before starting work
Before starting, we discuss not only the triangle search logic, but also system behavior during a failure. Below are the most frequently asked questions: resilience under load, venue limits, and protection of access keys.
What happens during a volatility spike or loss of connection to a venue?
The quote stream goes through a queue with a limit on concurrent requests, orders are sent idempotently — a retry does not create a duplicate.
If the connection breaks, the strategy enters passive mode: positions are reconciled with actual balances and trade history before resuming, and a discrepancy stops trading instead of “chasing” the market.
How does the system react to changes in venue rules?
Fees, tick size, and minimum order size are read from the venue configuration rather than hardcoded. If the rules shift, the triangle stops being profitable — the calculation is recalculated before the order is placed, and signals with outdated parameters are discarded.
How is access key protection implemented?
Keys are stored in a secure secrets vault, issued separately for each venue and strategy, and rotated on schedule. Withdrawal rights are disabled for trading keys, access is restricted by a whitelist of addresses — a leak does not give access to the balance.
Who stops trading, and how are withdrawal limits taken into account?
There is a manual stop and automatic triggers: a series of venue failures, an abnormal spread, drawdown beyond the threshold, loss of connection longer than a specified window.
Withdrawal limits are taken into account in the reserve: the system will not send an asset if this would violate the venue's daily limit or leave the strategy without working capital.
Let's discuss the task and come back with a work plan
To start on triangular arbitrage, we need an agreed picture of the task: exchanges and pairs in scope, position volume constraints, and who on the client side accepts the result. Below is what will be required from you and what the first step looks like.
- Task definition: list of exchanges, trading pairs and systems, allowable drawdown, limits on position size and number of simultaneous trades.
- Access and data: keys with read and trade rights only, without withdrawal; access to quote streams and trade history.
- Cost model: fees by volume tier, spread and order book depth for each pair — the entry threshold for a trade depends on them.
- Infrastructure: where the execution system is hosted, what communication channels and execution latency requirements exist.
- Work plan: task analysis, prototype on historical data, test system, transition to live mode, support.
- Timeline estimate: by stages, with checkpoints after the prototype and after the test run.
- Approval procedure: person responsible for acceptance, readiness criteria, stop and rollback rules in case of deviation from calculated profitability.
Describe the task and current infrastructure — we will come back with a timeline estimate and a stage-by-stage work plan.







