strategy-dev

Arbitrage — your first cross-exchange spot arb, eyes-open

Worked example: $50 manual scan on ATOM/USDT between Binance and Kraken — and why most retail arb fails

10 min · advanced

What you'll have when finished

  • Understand WHY most retail arb opportunities are illusory after fees
  • Configure your first arbitrage schedule with realistic params
  • Run a manual scan + execute and read the result correctly
  • Recognize and resolve an OPEN LEG event when it happens
  • Decide whether arbitrage is actually worth your time vs other strategies

Before you start

  • OPEN LEG (only one side fills) IS GOING TO HAPPEN. Plan how you'll resolve it BEFORE you deploy.
  • Cross-exchange arbitrage is dominated by HFTs running co-located servers with zero-fee tiers. Your retail edge is narrow.
  • Start with $20-50 max position per attempt. NOT $1000. Blast radius matters.
  • Most retail arb deployments end up unprofitable after fees + slippage + OPEN LEG cleanup. Be willing to abandon if results are bad after 30+ attempts.

Walkthrough

  1. Honest expectations before you start

    **Cross-exchange arbitrage is one of the LEAST profitable bots on the platform for retail users.** Read that twice. The market reality: - **HFTs dominate liquid pairs** — BTC/USDT spreads between Binance and Coinbase close in milliseconds - **Retail latency is 100-500ms** — by the time your order reaches the exchange, the spread is gone - **Fees eat marginal spreads** — 0.1% × 2 legs = 0.2% just to break even; most "opportunities" are below this - **OPEN LEG cleanup is expensive** — when one side fills and the other doesn't, you eat the spread + closeout cost **Where retail can still win (sometimes):** - Less-popular pairs (ATOM, NEAR, mid-cap alts) that HFTs don't bother with - "Stale price" moments after news events when one exchange lags - Exchange-specific outages or maintenance creating temporary anomalies **Why bother then?** Because when it works, it works cleanly. And it's instructive — running this teaches you about execution latency, fee math, and the limits of automation. Just don't expect it to be your primary income. For our worked example: **$50 max position on ATOM/USDT, Binance vs Kraken, manual frequency.** Small enough to limit blast radius; less-popular pair where HFTs are scarce.

    Success criteria: Read the honest expectations · Set realistic profit target (≤ break-even is acceptable for learning)

  2. Verify you have both exchanges connected + funded

    Arbitrage requires: 1. **TWO exchanges connected** in Settings → Connections, both with SPOT TRADING enabled 2. **Base asset (ATOM) inventory on Exchange B** (the side you'll SELL from) 3. **Quote asset (USDT) inventory on Exchange A** (the side you'll BUY from) Why both inventories: when the bot fires, it BUYS on Exchange A (spending USDT, receiving ATOM) AND simultaneously SELLS on Exchange B (giving ATOM, receiving USDT). If Exchange B has no ATOM, the SELL leg fails — instant OPEN LEG. **Pre-flight check:** - Open Settings → Connections; verify both exchanges show green status - Open CEX Trading → All Balances tab; confirm USDT on Binance ≥ $50, and ATOM on Kraken ≥ $50 worth If you don't have inventory on both sides, deposit/transfer first. The bot ASSUMES you have it.

    Success criteria: Both exchanges connected (green) · USDT on Binance ≥ $50 · ATOM on Kraken ≥ $50 worth

  3. Create the schedule with conservative params

    Navigate to **CEX Trade → Arbitrage → + New Schedule**. Read the **amber high-risk banner** at the top. Then fill the form: - **Schedule name:** "ATOM arb Bin/Kr test" - **Symbol:** ATOM/USDT (the searchable dropdown only shows pairs tradable on BOTH exchanges) - **Exchange A:** Binance - **Exchange B:** Kraken - **Min net spread % (after fees):** **0.5** (conservative — only fire when 0.5%+ net profit available) - **Taker fee % (per leg):** **0.1** (verify YOUR actual taker fee on each exchange; if you're VIP it might be 0.075% or lower) - **Max position per attempt ($):** **50** (small blast radius) - **Max trades / hour:** **3** (rate limit — prevents runaway in spread anomalies) - **IOC slippage tolerance %:** **0.15** (slightly wider than the 0.1% default — gives more fills, accepts slightly worse prices) - **Frequency:** **Manual only** (you click Scan + Execute — no automation yet) - **Enabled:** **UNCHECKED** (default — keep it that way until you've seen 5+ clean manual fires) Click **Create Schedule**.

    Success criteria: All params set conservatively · Frequency = Manual · Enabled = OFF

  4. Run a manual Scan and READ the result honestly

    In the schedule list, click your new "ATOM arb Bin/Kr test" entry. The scan/execute panel appears. Click **Scan** (not Execute Now — scan first). The panel shows: - **Buy Price (Binance):** e.g. $10.42 - **Sell Price (Kraken):** e.g. $10.45 - **Gross Spread:** 0.29% - **Fees:** 0.2% (2 × 0.1%) - **Net Spread:** 0.09% - **Meets your 0.5% threshold:** ❌ NO In this example, the gross spread is 0.29% but net is only 0.09% after fees. Below your 0.5% threshold, so the bot WOULD NOT fire if you clicked Execute Now. **This is the expected result 90% of the time.** Don't click Execute when threshold isn't met — you'll lose money to fees. Click Scan again 5 minutes later. And again. After 20-30 scans across an hour, you'll typically see one moment where Net Spread > 0.5%. THAT'S when you fire. **For learning purposes:** the FIRST time you see a "✅ MEETS THRESHOLD" result, screenshot it. You can study the buy/sell prices, the timing, and whether you can predict when these windows open.

    Success criteria: Ran manual Scan at least 10 times · Saw one ✅ MEETS THRESHOLD result OR confirmed your threshold is too aggressive for this pair

  5. Execute Now — what actually happens

    When you see a "✅ MEETS THRESHOLD" scan result, click **Execute Now**. What the bot does behind the scenes: 1. **Computes order sizes** — $50 ÷ buy price = X ATOM to buy on Binance, Y ATOM to sell on Kraken 2. **Fires both IOC orders IN PARALLEL** via CCXT - BUY IOC on Binance, priced at buy_price × (1 + iocSlippagePct) - SELL IOC on Kraken, priced at sell_price × (1 - iocSlippagePct) 3. **Waits ~1-2 seconds** for fill confirmations 4. **Records the result** in History **The 9 possible result statuses:** - **CLEAN FILL** — both legs filled at acceptable prices. Goal achieved. - **PARTIAL** — both legs filled but with worse slippage than expected. Lower profit but still a win. - **IMBALANCED** — both filled but at different sizes (one exchange had less liquidity). Small open position remains; resolve manually. - **OPEN LEG ⚠** — **only one side filled**. You now have an unbalanced position. **CRITICAL: resolve immediately.** See next step. - **UNFILLED** — neither leg filled (spread closed in the milliseconds between scan and execute). No P&L impact. - **NO TRADE** — sanity check failed (threshold no longer met). Bot refused to fire. - **RATE LIMITED** — exchange API throttled. Wait a minute, retry. - **SKIPPED** — max trades/hour hit. Wait until the window resets. - **ERROR** — exchange-side error (e.g. insufficient balance). Check the message.

    Success criteria: Clicked Execute when threshold met · Read the result status correctly · Identified if it's CLEAN / PARTIAL / OPEN LEG / etc.

  6. Resolving an OPEN LEG (the moment that defines whether arb is for you)

    If the History row shows **OPEN LEG ⚠**, you have an unbalanced position. ACT IMMEDIATELY. **Scenario A: BUY filled, SELL didn't (you bought ATOM on Binance but the Kraken sell failed)** You now have extra ATOM on Binance you didn't want. Options: 1. **Sell it back on Binance** at market — accept the spread loss. Fast, clean. 2. **Hold it** if you actually want ATOM exposure — converts the failed arb into an unplanned spot purchase. Only do this if you'd be happy holding ATOM. 3. **Try to sell on Kraken** (where the original SELL was meant to go) — requires moving the ATOM via withdrawal, which takes 10-30 min and has transfer fees. Usually not worth it. **Scenario B: SELL filled, BUY didn't (you sold ATOM on Kraken but the Binance buy failed)** You now have a short position effectively (you owe ATOM somewhere). Options: 1. **Buy ATOM back on Kraken** at market — accept the spread loss. Fast, clean. 2. **Buy on Binance** (where the original BUY was meant to go) — also works but the position is held on different exchanges. **The hard truth:** OPEN LEG cleanup typically costs 0.2-1.0% of the position. So a single OPEN LEG can eat 2-5 successful arb cycles. This is why retail arb is so unprofitable in practice. **Set a personal rule:** if you have 3+ OPEN LEG events in your first 20 attempts, ABANDON the schedule. Either your IOC slippage is too tight, or your exchange pair has too much latency mismatch, or both. Stop bleeding.

    Success criteria: Have a personal OPEN LEG protocol · Know to act IMMEDIATELY (not wait for reversal) · Set a kill-criterion: ≥3 OPEN LEGs in 20 attempts → abandon

  7. After 30+ attempts — make the honest call

    Track results in Trading Journal for at least 30 attempts. Then sit down and compute: - **Cumulative gross P&L** = sum of (CLEAN FILL + PARTIAL profits) minus (OPEN LEG cleanup costs) - **Time invested** = scans + executes + cleanup work × your hourly value - **Stress cost** = how much did this feature stress you out vs other bots? If gross P&L is positive but time-adjusted P&L is negative, **abandon arbitrage** and use the time on Grid Bot or Smart Trade. Those scale better. If gross P&L is positive AND time-adjusted P&L is positive, **scale slowly** — bump max position from $50 to $100, then $200, watching for OPEN LEG frequency to stay low. If gross P&L is negative, **definitely abandon**. Or change pair (try less liquid ones HFTs ignore). Or change threshold (require higher net spread). Or change exchanges (some pairs are tighter on certain exchange pairings). **Most retail traders ultimately abandon CEX arbitrage** — the math is hostile. That's fine; the experience teaches you about latency, fees, and the limits of automation. Use it as a learning project; don't expect a steady income.

    Success criteria: Completed 30+ attempts · Honestly computed P&L · Decided to scale / continue / abandon based on data

What's next

**Try DEX-side arbitrage** ([DEX Arbitrage](/dex-arbitrage)) — different problem space. Fewer HFTs (DEX latency is generally worse than CEX, so co-location matters less), but gas costs replace exchange fees. Often more accessible for retail. **Combine with Conditional Bot** — activate arb schedule ONLY during High Volatility regime, when spreads are wider. Pause during calm markets when spreads are HFT-dominated. **Try statistical arb (pairs trading)** via [Portfolio Analytics → Pairs Trading tab](/portfolio-analytics?tab=pairs). Different math — you bet on the mean reversion of a SPREAD between two correlated assets rather than instant price differences. For the general cross-exchange + cross-venue arbitrage framework (including DEX/CEX combinations), see [cex-dex-arbitrage-workflow](/learning-library?guide=cex-dex-arbitrage-workflow).