CCXT Live Trading Guide¶
Updated: 2026-02-24
This guide explains how to use Backtrader + CCXT for cryptocurrency live trading.
1. Quick Start¶
1.1 Install Dependencies¶
pip install ccxt # REST API
pip install ccxtpro # WebSocket (optional but recommended)
```bash
### 1.2 Configure Exchange
- *Method A: Direct Parameters**
```python
import backtrader as bt
store = bt.stores.CCXTStore(
exchange='binance',
currency='USDT',
config={
'apiKey': 'your_api_key',
'secret': 'your_secret',
'enableRateLimit': True,
}
)
```bash
- *Method B: Using .env File (Recommended)**
Create a `.env` file:
```env
EXCHANGE_ID=binance
EXCHANGE_API_KEY=your_api_key
EXCHANGE_SECRET=your_secret
EXCHANGE_CURRENCY=USDT
```bash
```python
from backtrader.ccxt.config_helper import load_exchange_config
config = load_exchange_config()
store = bt.stores.CCXTStore(**config)
```bash
### 1.3 Minimal Live Trading Example
```python
import backtrader as bt
class SimpleStrategy(bt.Strategy):
params = (('period', 20),)
def __init__(self):
super().__init__()
self.sma = bt.indicators.SMA(self.data, period=self.p.period)
def next(self):
if self.data.close[0] > self.sma[0] and not self.position:
self.buy(size=0.001)
elif self.data.close[0] < self.sma[0] and self.position:
self.sell(size=0.001)
# Create engine
cerebro = bt.Cerebro()
# Create Store
store = bt.stores.CCXTStore(
exchange='binance',
currency='USDT',
config={
'apiKey': 'YOUR_KEY',
'secret': 'YOUR_SECRET',
'enableRateLimit': True,
}
)
# Add data feed (REST polling)
data = store.getdata(
dataname='BTC/USDT',
timeframe=bt.TimeFrame.Minutes,
compression=15,
ohlcv_limit=100,
drop_newest=True,
)
cerebro.adddata(data)
# Set Broker
broker = store.getbroker()
cerebro.setbroker(broker)
# Add strategy
cerebro.addstrategy(SimpleStrategy)
# Run
cerebro.run()
```bash
- --
## 2. Data Feed Configuration
### 2.1 REST Polling Mode (Default)
```python
data = store.getdata(
dataname='BTC/USDT',
timeframe=bt.TimeFrame.Minutes,
compression=15,
ohlcv_limit=100, # Number of bars per request
drop_newest=True, # Drop incomplete newest bar
historical=False, # False = live mode
backfill_start=True, # Backfill historical data on start
)
```bash
### 2.2 WebSocket Mode (Recommended, Low Latency)
Requires `ccxtpro`:
```python
data = store.getdata(
dataname='BTC/USDT',
timeframe=bt.TimeFrame.Minutes,
compression=1,
use_websocket=True, # Enable WebSocket
ws_reconnect_delay=5.0, # Reconnect delay (seconds)
ws_max_reconnect_delay=60.0, # Max reconnect delay
ws_health_check_interval=30.0, # Health check interval
backfill_start=True,
)
```bash
- *WebSocket Features**:
- Auto-reconnect (exponential backoff: 5s → 10s → 20s → ... → 60s)
- Automatic fallback to REST polling on disconnect
- Auto data backfill on reconnect (triggered when gap > 60s)
- Stale connection detection
### 2.3 Historical Data Mode
```python
from datetime import datetime
data = store.getdata(
dataname='BTC/USDT',
timeframe=bt.TimeFrame.Minutes,
compression=60,
historical=True, # Fetch historical data only
fromdate=datetime(2025, 1, 1),
todate=datetime(2025, 12, 31),
ohlcv_limit=500,
)
```bash
- --
## 3. Broker Configuration
### 3.1 Basic Configuration
```python
broker = store.getbroker(
debug=False, # Debug output
use_threaded_order_manager=True, # Background order checking (recommended)
max_retries=3, # API retry count
retry_delay=1.0, # Base retry delay (seconds)
)
cerebro.setbroker(broker)
```bash
### 3.2 ThreadedOrderManager
When enabled, order status checks run in a background thread without blocking the main strategy loop:
```python
broker = store.getbroker(
use_threaded_order_manager=True, # Enable
)
```bash
- *Advantages**:
- Strategy `next()` is not blocked by API latency
- Order updates delivered via thread-safe queue
- Auto-cleanup of completed/canceled orders
### 3.3 Error Handling
The broker has comprehensive built-in error handling:
| Scenario | Behavior |
|----------|----------|
| Network timeout | Auto-retry (up to 3 times, exponential backoff) |
| Exchange unavailable | Auto-retry |
| Insufficient balance | Reject order, notify strategy |
| Order not found | Mark as canceled, remove from tracking |
| Exchange disconnected | Skip API calls, wait for reconnect |
| ≥ 10 consecutive failures | Polling interval backs off from 3s to 30s |
- *Handling order notifications in your strategy**:
```python
class MyStrategy(bt.Strategy):
def notify_order(self, order):
if order.status in [order.Completed]:
print(f'Order completed: {order.executed.price}')
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
print(f'Order failed: {order.getstatusname()}')
```bash
- --
## 4. Exchange-Specific Configuration
### 4.1 Using ExchangeConfig
```python
from backtrader.ccxt.config import ExchangeConfig
# Get exchange default parameters
params = ExchangeConfig.get_params('binance')
# {'rateLimit': 1200, 'enableRateLimit': True, ...}
# Get fee structure
fees = ExchangeConfig.get_fees('binance')
# {'maker': 0.001, 'taker': 0.001}
# Merge user config with defaults
config = ExchangeConfig.merge_config('okx', {
'apiKey': 'your_key',
'secret': 'your_secret',
'password': 'your_passphrase',
})
```bash
### 4.2 Supported Exchanges
| Exchange | exchange_id | Special Configuration |
|----------|-------------|----------------------|
| Binance | `binance` | Futures require `defaultType: 'future'` |
| OKX | `okx` | Requires `password` (passphrase) |
| Bybit | `bybit` | Futures require `defaultType: 'linear'` |
| Bitget | `bitget` | Requires `password` |
| Gate.io | `gate` | — |
| Huobi | `huobi` | — |
### 4.3 Futures Trading Example (Binance)
```python
store = bt.stores.CCXTStore(
exchange='binance',
currency='USDT',
config={
'apiKey': 'your_key',
'secret': 'your_secret',
'enableRateLimit': True,
'options': {
'defaultType': 'future', # Futures mode
},
}
)
```bash
- --
## 5. Rate Limiting
### 5.1 Automatic Rate Limiting
CCXTStore automatically integrates RateLimiter:
```python
# Default: auto-configured based on exchange settings
store = bt.stores.CCXTStore(exchange='binance', ...)
# Custom RPM (requests per minute)
from backtrader.ccxt.ratelimit import RateLimiter
limiter = RateLimiter(requests_per_minute=600)
```bash
### 5.2 Adaptive Rate Limiting
```python
from backtrader.ccxt.ratelimit import AdaptiveRateLimiter
limiter = AdaptiveRateLimiter(
initial_rpm=1200, # Initial RPM
min_rpm=60, # Minimum RPM (when rate-limited)
max_rpm=2400, # Maximum RPM (gradually increases when no errors)
)
```bash
- --
## 6. Connection Management
### 6.1 ConnectionManager
Automatically manages connection health and reconnection:
```python
from backtrader.ccxt.connection import ConnectionManager
# Usually no need to create manually; CCXTStore manages it
# But you can register callbacks:
manager = store._connection_manager # If available
manager.on_disconnect(lambda: print("Exchange disconnected!"))
manager.on_reconnect(lambda: print("Reconnected"))
```bash
### 6.2 Reconnection Mechanism
```bash
Disconnect detected (health check failure)
│
├── Trigger disconnect callback
│
└── Reconnection loop (exponential backoff):
├── Attempt 1: wait 5s
├── Attempt 2: wait 10s
├── Attempt 3: wait 20s
├── ...
└── Maximum: wait 60s
│
└── Reconnection successful
├── Trigger reconnect callback
└── Backfill missing data
```bash
- --
## 7. Complete Live Trading Template
```python
import backtrader as bt
from datetime import datetime
class LiveStrategy(bt.Strategy):
params = (
('fast', 10),
('slow', 30),
('stake', 0.001),
)
def __init__(self):
super().__init__()
self.fast_sma = bt.indicators.SMA(self.data, period=self.p.fast)
self.slow_sma = bt.indicators.SMA(self.data, period=self.p.slow)
self.crossover = bt.indicators.CrossOver(self.fast_sma, self.slow_sma)
self.order = None
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
return
if order.status in [order.Completed]:
if order.isbuy():
print(f'[BUY] Price: {order.executed.price:.2f}, '
f'Size: {order.executed.size:.6f}')
else:
print(f'[SELL] Price: {order.executed.price:.2f}, '
f'Size: {order.executed.size:.6f}')
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
print(f'[ORDER FAILED] {order.getstatusname()}')
self.order = None
def next(self):
if self.order:
return
if not self.position:
if self.crossover > 0:
self.order = self.buy(size=self.p.stake)
else:
if self.crossover < 0:
self.order = self.sell(size=self.p.stake)
# === Configuration ===
cerebro = bt.Cerebro()
store = bt.stores.CCXTStore(
exchange='binance',
currency='USDT',
config={
'apiKey': 'YOUR_KEY',
'secret': 'YOUR_SECRET',
'enableRateLimit': True,
}
)
# WebSocket data feed
data = store.getdata(
dataname='BTC/USDT',
timeframe=bt.TimeFrame.Minutes,
compression=5,
use_websocket=True,
backfill_start=True,
ohlcv_limit=100,
drop_newest=True,
)
cerebro.adddata(data)
# Broker (with background order checking)
broker = store.getbroker(
use_threaded_order_manager=True,
max_retries=3,
)
cerebro.setbroker(broker)
# Strategy
cerebro.addstrategy(LiveStrategy)
# Run
print('Starting live trading...')
cerebro.run()
```bash
- --
## 8. FAQ
### Q: What if WebSocket connection fails?
Make sure `ccxtpro` is installed:
```bash
pip install ccxtpro
```bash
If the exchange doesn't support WebSocket, the system will automatically fall back to REST polling.
### Q: How do I view API call logs?
```python
broker = store.getbroker(debug=True)
data = store.getdata(..., debug=True)
```bash
### Q: Order stuck in Submitted status?
Possible causes:
1. Price too far from market (limit order)
2. Exchange API delay
3. Network issue preventing status update
Solution: Enable `use_threaded_order_manager=True` for continuous background status checking.
### Q: How do I trade multiple symbols?
```python
data_btc = store.getdata(dataname='BTC/USDT', ...)
data_eth = store.getdata(dataname='ETH/USDT', ...)
cerebro.adddata(data_btc)
cerebro.adddata(data_eth)
```bash
### Q: How do I handle funding rates?
Use `ccxtfeed_funding.py`:
```python
from backtrader.feeds.ccxtfeed_funding import CCXTFeedWithFunding
data = CCXTFeedWithFunding(
store=store,
dataname='BTC/USDT',
use_websocket=True,
)
```bash
- --
## 9. Reference
| Document | Path |
|----------|------|
| Architecture | `docs/ARCHITECTURE.md` |
| WebSocket Guide | `docs/WEBSOCKET_GUIDE.md` |
| Funding Rate Guide | `docs/FUNDING_RATE_GUIDE.md` |
| Environment Config | `CCXT_ENV_CONFIG.md` |
| Tests | `tests/new_functions/test_ccxt_*.py` |