Monitor DEX Liquidity Pools and Detect Arbitrage Signals with Python
Monitor DEX Liquidity Pools and Detect Arbitrage Signals with Python
Cross-DEX arbitrage opportunities exist because different pools have different reserve ratios. Here's how to detect them programmatically.
Architecture
Pool Monitor → Price Calculator → Spread Detector → Signal Generator
↓ ↓ ↓ ↓
Web3 RPC AMM Math Cross-DEX Compare Alert/Execute
Pool Monitor
from web3 import Web3
from typing import Dict, List
import time
# Uniswap V2 Pair ABI (minimal)
PAIR_ABI = [
{
"constant": True,
"inputs": [],
"name": "getReserves",
"outputs": [
{"name": "reserve0", "type": "uint112"},
{"name": "reserve1", "type": "uint112"},
{"name": "blockTimestampLast", "type": "uint32"}
],
"type": "function"
},
{
"constant": True,
"inputs": [],
"name": "token0",
"outputs": [{"name": "", "type": "address"}],
"type": "function"
}
]
class PoolMonitor:
def __init__(self, rpc_url: str):
self.w3 = Web3(Web3.HTTPProvider(rpc_url))
self.pools: Dict[str, dict] = {}
self.price_history: Dict[str, list] = {}
def add_pool(self, name: str, pair_address: str,
token0_decimals: int = 18,
token1_decimals: int = 6):
"""Register a liquidity pool to monitor."""
contract = self.w3.eth.contract(
address=pair_address, abi=PAIR_ABI
)
self.pools[name] = {
'contract': contract,
'token0_decimals': token0_decimals,
'token1_decimals': token1_decimals,
}
self.price_history[name] = []
def get_pool_state(self, name: str) -> dict:
"""Fetch current reserves and calculate price."""
pool = self.pools[name]
reserves = pool['contract'].functions.getReserves().call()
r0 = reserves[0] / (10 ** pool['token0_decimals'])
r1 = reserves[1] / (10 ** pool['token1_decimals'])
price = r1 / r0 if r0 > 0 else 0
tvl = r1 * 2 # Approximate TVL in token1 terms
return {
'reserve0': r0,
'reserve1': r1,
'price': price,
'tvl': tvl,
'timestamp': time.time(),
}
def scan_arbitrage(self, min_spread_bps: int = 10) -> List[dict]:
"""Find arbitrage opportunities across pools."""
prices = {}
for name in self.pools:
try:
state = self.get_pool_state(name)
prices[name] = state
self.price_history[name].append(state)
except Exception as e:
print(f"Error reading {name}: {e}")
opportunities = []
pool_names = list(prices.keys())
for i in range(len(pool_names)):
for j in range(i + 1, len(pool_names)):
p1 = prices[pool_names[i]]['price']
p2 = prices[pool_names[j]]['price']
if p1 == 0 or p2 == 0:
continue
spread_bps = abs(p1 - p2) / min(p1, p2) * 10000
if spread_bps >= min_spread_bps:
buy_on = pool_names[i] if p1 < p2 \
else pool_names[j]
sell_on = pool_names[j] if p1 < p2 \
else pool_names[i]
opportunities.append({
'buy_on': buy_on,
'sell_on': sell_on,
'spread_bps': round(spread_bps, 2),
'buy_price': min(p1, p2),
'sell_price': max(p1, p2),
})
return opportunities
# Usage
monitor = PoolMonitor('https://ethereum-rpc.publicnode.com')
# Add ETH/USDC pools on different DEXes
# monitor.add_pool('uniswap_v2', '0xB4e16d...')
# monitor.add_pool('sushiswap', '0x397FF1...')
# Scan for opportunities
# opps = monitor.scan_arbitrage(min_spread_bps=20)
# for opp in opps:
# print(f"Buy on {opp['buy_on']}, sell on {opp['sell_on']}: "
# f"{opp['spread_bps']} bps spread")
Profitability Filter
def is_profitable(
spread_bps: float,
trade_size_usd: float,
gas_price_gwei: float = 30,
) -> dict:
"""Check if an arbitrage is profitable after costs."""
# Estimate gas: ~300k for a 2-swap arb
gas_cost_eth = 300_000 * gas_price_gwei * 1e-9
gas_cost_usd = gas_cost_eth * 3500 # Rough ETH price
# DEX fees (0.3% per swap, 2 swaps)
fee_cost = trade_size_usd * 0.003 * 2
# Gross profit
gross_profit = trade_size_usd * spread_bps / 10000
# Net profit
net_profit = gross_profit - gas_cost_usd - fee_cost
return {
'gross_profit': round(gross_profit, 2),
'gas_cost': round(gas_cost_usd, 2),
'fee_cost': round(fee_cost, 2),
'net_profit': round(net_profit, 2),
'profitable': net_profit > 0,
}
This cross-pool monitoring approach is used in the market data layer of ClawDUX's strategy verification system, where real liquidity conditions are factored into strategy performance evaluation.
The core logic discussed in this article has been integrated into the ClawDUX API. Access ClawDUX-core for full permissions, or browse the marketplace to discover verified trading strategies.