Eventually every serious arbitrageur reaches the same conclusion: manual trading doesn't scale. You can monitor 5–10 pairs, the exchange goes into maintenance exactly when a good spread appears, and the frustrating reality is that a bot you could build in a weekend would do in one night what takes you a month manually.
This article is a practical guide to automation: from architecture to a working first bot.
Why Automate Arbitrage
Three main reasons to move from manual to automated arbitrage:
Speed. A bot reacts to a spread appearing in milliseconds. A human reacts in 10–30 seconds at best. On fast pairs, that's the difference between profit and a missed opportunity.
Scale. A manual trader realistically monitors 5–15 pairs. A bot monitors 500+ pairs across 10 exchanges simultaneously, 24 hours a day, without fatigue or concentration errors.
Discipline. A bot never breaks its own rules: it always respects the minimum spread threshold, always checks liquidity, never enters a trade "because it feels right."
Arbitrage Bot Architecture
Every arbitrage bot consists of four core components.
Component 1: Data Layer
Fetches prices, volumes, and order book state from exchanges in real time.
Two data retrieval methods:
REST API (polling): the bot requests prices from the exchange every N seconds.
- Simple to implement
- Latency depends on polling frequency
- Exchanges impose rate limits on requests
- Good for starting out and for slower strategies
WebSocket (streaming): the exchange pushes price updates as they happen.
- Data arrives in real time (10–100ms latency)
- More complex to implement
- Less aggressive on API rate limits
- Required for fast strategies
WebSocket example (Python, Binance):
import websocket
import json
def on_message(ws, message):
data = json.loads(message)
symbol = data['s'] # trading pair
price = float(data['c']) # current price
print(f"{symbol}: {price}")
ws = websocket.WebSocketApp(
"wss://stream.binance.com:9443/ws/ethusdt@ticker",
on_message=on_message
)
ws.run_forever()
Component 2: Strategy Layer
Analyzes data and determines: is there an arbitrage opportunity right now?
For cross-exchange arbitrage:
def find_opportunity(prices: dict, threshold: float = 0.004) -> dict | None:
"""
prices = {'binance': {'ETH/USDT': {'ask': 2484.0, 'bid': 2483.5}},
'bybit': {'ETH/USDT': {'ask': 2501.0, 'bid': 2500.5}}}
threshold = minimum net spread (0.4%)
"""
for pair in prices['binance']:
if pair not in prices['bybit']:
continue
buy_price = prices['binance'][pair]['ask'] # buy on Binance
sell_price = prices['bybit'][pair]['bid'] # sell on Bybit
gross_spread = (sell_price - buy_price) / buy_price
net_spread = gross_spread - 0.002 # subtract fees (2 × 0.1%)
if net_spread >= threshold:
return {
'pair': pair,
'buy_exchange': 'binance',
'sell_exchange': 'bybit',
'buy_price': buy_price,
'sell_price': sell_price,
'net_spread': net_spread
}
return None
For triangular arbitrage:
def check_triangle(prices: dict, base: str = 'USDT') -> dict | None:
"""
Checks route: USDT → A → B → USDT
"""
fee = 0.001 # 0.1% fee
for coin_a in prices:
for coin_b in prices:
if coin_a == coin_b:
continue
pair1 = f"{coin_a}/{base}" # USDT → A
pair2 = f"{coin_b}/{coin_a}" # A → B
pair3 = f"{coin_b}/{base}" # B → USDT
if not all(p in prices for p in [pair1, pair2, pair3]):
continue
step1 = (1 / prices[pair1]['ask']) * (1 - fee)
step2 = step1 * prices[pair2]['bid'] * (1 - fee)
step3 = step2 * prices[pair3]['bid'] * (1 - fee)
profit = step3 - 1.0 # profit per $1
if profit > 0.001: # minimum 0.1% after fees
return {
'route': f"{base}→{coin_a}→{coin_b}→{base}",
'profit_pct': profit * 100
}
return None
Component 3: Execution Layer
Places orders on exchanges.
import ccxt
class OrderExecutor:
def __init__(self):
self.exchanges = {
'binance': ccxt.binance({
'apiKey': 'YOUR_API_KEY',
'secret': 'YOUR_SECRET',
'options': {'defaultType': 'spot'}
}),
'bybit': ccxt.bybit({
'apiKey': 'YOUR_API_KEY',
'secret': 'YOUR_SECRET'
})
}
def execute_arbitrage(self, opportunity: dict, amount_usdt: float):
buy_ex = self.exchanges[opportunity['buy_exchange']]
sell_ex = self.exchanges[opportunity['sell_exchange']]
pair = opportunity['pair']
amount_coins = amount_usdt / opportunity['buy_price']
try:
buy_order = buy_ex.create_market_buy_order(pair, amount_coins)
sell_order = sell_ex.create_market_sell_order(pair, amount_coins)
return {
'success': True,
'buy_order': buy_order,
'sell_order': sell_order
}
except Exception as e:
return {'success': False, 'error': str(e)}
Component 4: Risk Management & Logging Layer
Controls position sizes, maximum losses, and records all actions.
class RiskManager:
def __init__(self, max_position_usdt: float = 1000,
daily_loss_limit: float = 50):
self.max_position = max_position_usdt
self.daily_loss_limit = daily_loss_limit
self.daily_pnl = 0.0
def can_trade(self, amount: float) -> tuple[bool, str]:
if amount > self.max_position:
return False, f"Position limit exceeded: {amount} > {self.max_position}"
if self.daily_pnl < -self.daily_loss_limit:
return False, f"Daily loss limit reached: {self.daily_pnl}"
return True, "OK"
def update_pnl(self, profit: float):
self.daily_pnl += profit
Libraries and Tools
CCXT — the core library for crypto bots
CCXT (CryptoCurrency eXchange Trading Library) is an open-source library with a unified API for 100+ exchanges. Instead of learning each exchange's API separately — one interface for all of them.
pip install ccxt
Supported exchanges: Binance, Bybit, OKX, KuCoin, Gate.io, Kraken, Coinbase, and 100+ others.
Core operations:
import ccxt
exchange = ccxt.binance({'apiKey': '...', 'secret': '...'})
# Get current price
ticker = exchange.fetch_ticker('ETH/USDT')
print(ticker['ask'], ticker['bid'])
# Get order book
orderbook = exchange.fetch_order_book('ETH/USDT', limit=20)
print(orderbook['asks'][:5]) # top 5 asks
# Place market order
order = exchange.create_market_buy_order('ETH/USDT', 0.1) # buy 0.1 ETH
Other useful Python libraries
| Library | Purpose |
|---|---|
ccxt |
Exchange connectivity |
asyncio |
Async execution (multiple exchanges in parallel) |
aiohttp |
Async HTTP requests |
websockets |
WebSocket connections |
pandas |
Data analysis and logging |
sqlalchemy |
Database storage |
python-telegram-bot |
Telegram notifications |
JavaScript/TypeScript alternative
Node.js is also popular for trading bots — especially if you plan DeFi/Web3 integration.
const ccxt = require('ccxt');
const binance = new ccxt.binance({
apiKey: 'YOUR_KEY',
secret: 'YOUR_SECRET'
});
async function getSpread(pair) {
const ticker = await binance.fetchTicker(pair);
return { ask: ticker.ask, bid: ticker.bid };
}
Ready-Made Solutions vs Custom Development
You don't have to build a bot from scratch. Here's the full spectrum of options:
Option 1: Ready-made arbitrage bots (SaaS)
Platforms like Cryptohopper, 3Commas, and Bitsgap offer arbitrage strategies without programming.
Pros: fast start, no coding, customer support.
Cons: monthly subscription ($30–150), limited flexibility, no full control over strategy logic.
Best for: traders who want automation without code.
Option 2: Open-source bots with configuration
Freqtrade and Hummingbot are open-source trading bot frameworks with arbitrage support.
# Install Hummingbot
pip install hummingbot
# Launch
hummingbot
Hummingbot has built-in cross_exchange_market_making and arbitrage strategies — configurable without deep coding knowledge.
Pros: free, large community, flexible configuration.
Cons: learning curve, some advanced features are paid.
Option 3: Build your own
Maximum flexibility and control. Realistic for anyone with basic Python or JavaScript knowledge.
Minimum arbitrage bot: 200–400 lines of code.
Development time: 1–2 weekends for a basic version.
Step-by-Step Plan: From Zero to Working Bot
Step 1: Learn your chosen exchange's API (3–5 days)
Start with one exchange. Binance and Bybit have excellent English documentation.
What to learn:
- REST API: how to fetch tickers, order books, trade history
- WebSocket: how to subscribe to price updates
- Trading API: how to place and cancel orders
- Rate limits: how many requests per second are allowed
Practice: write a script that prints ETH/USDT price from Binance every 5 seconds.
Step 2: Spread monitoring (3–5 days)
Add a second exchange. Write a script that:
- Fetches prices from both exchanges simultaneously (asyncio)
- Calculates the spread
- Prints all pairs with spread > 0.5% to the console
This isn't a bot yet — just monitoring. Run it for 2–3 days and observe how frequently opportunities appear.
Step 3: Paper trading (1 week)
Add decision logic but without real orders. The bot should:
- Identify an opportunity
- Calculate position size accounting for fees
- Log the "trade" to a file or database
- Track hypothetical P&L
After a week — analyze the log: how accurate were the signals? How many opportunities per day? What would the real result have been?
Step 4: Live trading with minimal capital
Connect real API keys and trade with $100–200. The goal is not profit — it's verifying the system works in live conditions.
Verify:
- Orders execute correctly
- Balances update properly
- Bot handles errors correctly (no connection, insufficient balance)
- Logging works as expected
Step 5: Optimization and scaling
After 2–4 weeks of successful live trading:
- Add more pairs and exchanges
- Optimize speed (WebSocket instead of REST)
- Add additional risk checks
- Gradually increase position sizes
Infrastructure: Where to Run Your Bot
Option 1: Local computer
Pros: free, easy to debug.
Cons: depends on your internet and power, must keep computer running 24/7.
Best for: development and testing only.
Option 2: VPS (Virtual Private Server)
A cloud server runs 24/7 independently. Cost: $5–20/month.
Recommended providers:
- DigitalOcean (Droplet from $6/month)
- Hetzner (from €4/month — excellent price/quality ratio)
- AWS/Google Cloud (more powerful, more expensive)
Minimum requirements for an arbitrage bot:
- 1–2 CPU
- 1–2 GB RAM
- 20 GB SSD
- Server location: ideally close to exchange data centers (Tokyo or Singapore for Binance/Bybit)
Basic server setup (Ubuntu):
# Install Python
sudo apt update && sudo apt install python3 python3-pip -y
# Install dependencies
pip3 install ccxt asyncio aiohttp
# Run bot in background
nohup python3 arbitrage_bot.py > bot.log 2>&1 &
# Monitor logs
tail -f bot.log
Option 3: Docker container
For more professional deployment — package the bot in Docker.
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "bot.py"]
API Key Security
This is a critical aspect that's often overlooked.
Security rules:
1. Never give the bot withdrawal permissions. When creating an API key, disable the "Withdraw" permission. The bot should only trade, never withdraw.
2. IP whitelist. Bind the API key to your server's IP address. Even if the key is stolen — it won't work from another IP.
3. Never store keys in code. Use environment variables:
import os
api_key = os.environ.get('BINANCE_API_KEY')
secret = os.environ.get('BINANCE_SECRET')
4. Separate keys for separate bots. If one bot is compromised — others remain safe.
5. Monitor activity. Set up Telegram notifications for every trade — anomalous activity will be immediately visible.
Monitoring and Notifications
The bot should report on its own activity. Minimum notification set:
import requests
def send_telegram(message: str, bot_token: str, chat_id: str):
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
requests.post(url, json={
'chat_id': chat_id,
'text': message,
'parse_mode': 'HTML'
})
# Usage
send_telegram(
f"✅ Trade: ETH Binance→Bybit\n"
f"Profit: +$12.40 (0.41%)\n"
f"Volume: $3,000",
bot_token="...",
chat_id="..."
)
What to notify:
- Every executed trade (with profit/loss)
- Execution errors
- Daily loss limit reached
- Bot restart
- Low balance on any exchange
Common Mistakes When Building an Arbitrage Bot
Mistake 1: No API error handling Exchanges occasionally return errors: no connection, insufficient balance, rate limit exceeded. Without handling, the bot crashes and potentially leaves an open position.
try:
order = exchange.create_market_buy_order(pair, amount)
except ccxt.InsufficientFunds:
log.error("Insufficient balance")
except ccxt.NetworkError:
log.error("Connection error — retrying")
time.sleep(5)
# retry logic
Mistake 2: Race conditions on data Data from two exchanges may be out of sync. A price fetched 500ms ago is already stale. Always check the timestamp of received data.
Mistake 3: No loss limit
A bot without daily loss constraints can lose all capital due to a single bug. Always implement daily_loss_limit.
Mistake 4: Testing only on historical data Backtesting on historical data doesn't account for slippage, API delays, and competition. Always run paper trading in real time before going live.
Mistake 5: Starting with large capital Begin with $100–200. The first weeks are debugging, not earning.
Conclusion
Automating arbitrage isn't complicated if you go step by step. A first working bot can be built in a weekend with basic Python knowledge. Key principles:
- Start with one strategy on two exchanges
- Monitoring first → paper trading → real money
- API key security is a priority from day one
- Loss limits are mandatory
- Log everything
SpreadScan provides ready-to-use spread and liquidity data — eliminating the need to build the data collection layer yourself and letting you focus on strategy logic.
This article is for educational purposes only. Crypto trading involves risk. Always test strategies thoroughly before using real capital.
Frequently Asked Questions
Which programming language is best for an arbitrage bot? Python is the best starting choice: excellent ccxt library, simple syntax, large community. JavaScript/TypeScript is strong for DeFi/Web3 integration. C++ offers maximum speed for HFT — but that's a professional-level specialization.
How much does it cost to build an arbitrage bot? Self-built: only your time (1–4 weeks for a basic version). Via freelancer: $500–3,000 for a basic bot. Ready-made SaaS solutions: $30–150/month.
Do I need special servers for an arbitrage bot? To start — no. A $5–10/month VPS is sufficient. For high-frequency strategies requiring sub-10ms reaction times, co-location servers near exchange data centers are needed — but that's a professional-level requirement.
Is it safe to give a bot API keys? With proper setup — yes. The critical rules: disable withdrawal permission, bind the key to your server's IP address, never store keys in plaintext code.
What is Hummingbot and is it worth using? Hummingbot is a free open-source trading bot framework with arbitrage support. A good choice for those who want automation without writing everything from scratch. It has built-in strategies and a configuration interface.
How do I prevent the bot from losing money on bad trades? Implement three layers: minimum spread threshold (skip everything below), maximum position size per trade, and daily loss limit. These three controls catch the majority of runaway loss scenarios.