moved execution server to chicago colo march 2024.
3 months data in.
latency dropped 67ms → 12ms average.
why chicago #
CME exchange location: chicago
my location: san diego
problem: 67ms average latency san diego → CME
solution: colocation in chicago = 12ms
55ms improvement = better fills.
the cost breakdown #
datacenter: equinix CH1 (chicago)
monthly: $175/month
breakdown:
- rack space (1U): $85
- power (200W): $45
- bandwidth (100mbps): $35
- remote hands: $10
total annual: $2,100
san diego electricity cost: $18/month
net increase: $157/month ($1,884/year)
the server #
hardware: dell poweredge r240
bought used on ebay: $800
specs:
- intel xeon e-2224 (4 cores, 3.4ghz)
- 32gb ecc ram
- 2x 500gb ssd (raid 1)
- dual gigabit ethernet
- remote management (idrac)
shipped to datacenter direct.
datacenter racked it ($50 one-time).
latency comparison #
before (san diego home):
avg latency: 67ms
p50: 65ms
p95: 89ms
p99: 124ms
after (chicago colo):
avg latency: 12ms
p50: 11ms
p95: 18ms
p99: 26ms
improvement: 55ms average (82% reduction)
real trading impact #
slippage improvement:
san diego avg: 2.4 ticks
chicago avg: 1.8 ticks
0.6 tick improvement = $180/month on current volume.
ROI: $180/month saves > $157/month cost
net positive after 1 year.
python monitoring setup #
import asyncio
import time
import statistics
from datetime import datetime
import redis
class LatencyMonitor:
"""
Monitor execution latency to exchanges
Track p50, p95, p99 over rolling windows
"""
def __init__(self, redis_client):
self.redis = redis_client
self.latencies = []
self.window_size = 1000 # Rolling window
async def ping_exchange(self, exchange_url):
"""
Measure round-trip time to exchange
"""
start = time.perf_counter()
# Send minimal request
async with aiohttp.ClientSession() as session:
try:
async with session.get(
exchange_url,
timeout=aiohttp.ClientTimeout(total=5)
) as response:
await response.text()
end = time.perf_counter()
latency_ms = (end - start) * 1000
return latency_ms
except Exception as e:
print(f"Ping failed: {e}")
return None
def add_latency(self, latency_ms):
"""
Add latency measurement to rolling window
"""
self.latencies.append(latency_ms)
# Keep only recent measurements
if len(self.latencies) > self.window_size:
self.latencies.pop(0)
# Store in Redis for Grafana
self.redis.lpush('latency_measurements', latency_ms)
self.redis.ltrim('latency_measurements', 0, self.window_size - 1)
def get_stats(self):
"""
Calculate latency statistics
"""
if not self.latencies:
return None
sorted_latencies = sorted(self.latencies)
n = len(sorted_latencies)
stats = {
'avg': statistics.mean(self.latencies),
'median': statistics.median(self.latencies),
'p50': sorted_latencies[int(n * 0.50)],
'p95': sorted_latencies[int(n * 0.95)],
'p99': sorted_latencies[int(n * 0.99)],
'min': min(self.latencies),
'max': max(self.latencies),
'count': n
}
return stats
async def monitor_loop(self, exchange_url, interval_seconds=60):
"""
Continuous monitoring loop
"""
while True:
latency = await self.ping_exchange(exchange_url)
if latency:
self.add_latency(latency)
stats = self.get_stats()
print(f"{datetime.now().isoformat()}")
print(f"Latency: {latency:.2f}ms")
print(f"Avg: {stats['avg']:.2f}ms")
print(f"P95: {stats['p95']:.2f}ms")
print(f"P99: {stats['p99']:.2f}ms")
print("---")
await asyncio.sleep(interval_seconds)
# Usage
redis_client = redis.Redis(host='localhost', port=6379, db=0)
monitor = LatencyMonitor(redis_client)
# Monitor CME latency every minute
asyncio.run(
monitor.monitor_loop(
exchange_url='https://cme.com/api/health',
interval_seconds=60
)
)
this runs 24/7 on chicago server.
grafana dashboard shows real-time latency.
network path comparison #
san diego path:
home → ISP → internet backbone → chicago → CME
hops: 18
latency: 67ms avg
chicago colo path:
datacenter → local exchange → CME
hops: 4
latency: 12ms avg
fewer hops = lower latency.
reliability improvement #
san diego (home internet):
uptime: 99.2% (comcast)
outages in 2023: 6 times
longest outage: 4 hours
chicago colo:
uptime: 99.95% (equinix SLA)
outages since march: 0
datacenter power + network > home internet.
remote management #
idrac (dell remote management):
- KVM over IP
- remote power cycling
- BIOS access
- OS installation
- monitoring (temps, fans, power)
accessed from san diego.
feels like server is local.
never needed “remote hands” service yet.
security setup #
firewall rules:
only allow:
- my home IP (ssh, idrac)
- exchange IPs (trading)
- monitoring (grafana cloud)
everything else blocked.
VPN required for emergency access.
2FA on all logins.
bandwidth usage #
allocated: 100mbps
actual usage: 8-12mbps avg
spikes: 40mbps during high vol
plenty of headroom.
100mbps adequate for my volume.
power consumption #
measured: 180W avg
allocated: 200W
cost: $45/month for 200W
efficient server = lower cost.
comparing to cloud (aws) #
aws equivalent:
c6i.xlarge in us-east-1 (closest to chicago):
- 4 vcpu
- 8gb ram
- $140/month (3yr reserved)
- network: $50/month estimate
- total: $190/month
equinix colo:
- dedicated hardware
- better latency
- $175/month
colo wins on performance + cost.
lessons learned #
1. location matters for futures
CME in chicago = chicago colo optimal.
2. latency compounds
55ms × 30 trades/month = 1.65 seconds saved.
better fills add up.
3. remote management essential
idrac saved 3 trips to chicago.
worth the hardware cost.
4. bandwidth overprovisioning
100mbps allocated, using 12mbps.
headroom for growth.
5. datacenter reliability
zero outages in 3 months.
home internet = 2 outages in same period.
ROI calculation #
costs:
colo: $157/month net increase
server: $800 one-time (amortized $22/month over 3 years)
total: $179/month
benefits:
slippage improvement: $180/month
reliability: $0 measured (but prevented 2 missed trading days)
net: $1/month positive
barely break-even on slippage alone.
reliability value hard to quantify.
worth it for serious trading.
when NOT to use colo #
don’t use colo if:
-
trading <10 times per month (latency doesn’t matter)
-
swing trading or longer holds (seconds don’t matter)
-
account <$100k (cost not justified)
-
no remote management experience (learning curve steep)
-
testing strategies (home is fine)
colo for serious automation only.
what NexusFi traders say #
found great infrastructure thread on NexusFi discussing colo vs cloud vs home.
consensus: colo for futures, cloud for stocks/options, home for testing.
matches my experience exactly.
future upgrades #
considering:
dual servers (active/standby failover)
10gbps network upgrade
chicago CH2 datacenter (even closer to CME)
current setup adequate.
not upgrading unless volume 10x.
tonight #
chicago colocation.
67ms → 12ms latency.
0.6 tick slippage improvement.
$157/month for reliability + speed.
worth it for serious algo trading.
11:42pm thursday. chicago colocation 3 months review. latency 67ms → 12ms (82% reduction). slippage improved 0.6 ticks = $180/month savings. colo cost $157/month net increase. barely break-even but reliability + speed worth it. zero outages vs 2 at home. dedicated hardware beats cloud for futures.
-AK