Paper Trading¶
Difficulty expert
Overview¶
Paper trading simulates live trading with real-time data but without real money. It's the critical bridge between backtesting and live trading.
Why Paper Trade¶
| Reason | Description |
|---|---|
| Validate Backtest | Confirm backtest results in live conditions |
| Test Infrastructure | Verify systems work in real-time |
| Build Confidence | Practice without financial risk |
| Refine Process | Improve execution and decision-making |
| Test Edge | Verify strategy works in current market regime |
Paper Trading Setup¶
class PaperTradingEngine:
"""Simulate live trading with real-time data."""
def __init__(self, strategy, initial_capital=100000):
self.strategy = strategy
self.capital = initial_capital
self.positions = {}
self.orders = []
self.fills = []
self.equity_curve = [initial_capital]
self.market_data = None
def on_market_data(self, data):
"""Process incoming market data."""
self.market_data = data
# Generate signals
signal = self.strategy.generate_signal(data)
if signal:
order = self.create_order(signal, data)
self.execute_order(order)
def create_order(self, signal, data):
"""Create order from signal."""
return {
'symbol': signal.symbol,
'side': signal.side,
'quantity': signal.quantity,
'price': data.current_price,
'timestamp': data.timestamp,
'type': 'paper'
}
def execute_order(self, order):
"""Simulate order execution."""
# Simulate slippage and commission
slippage = self.estimate_slippage(order)
commission = order.quantity * 0.005 # $0.005 per share
fill_price = order.price + slippage * (1 if order.side == 'BUY' else -1)
fill = {
**order,
'fill_price': fill_price,
'commission': commission,
'slippage': slippage
}
self.update_position(fill)
self.fills.append(fill)
def update_position(self, fill):
"""Update portfolio based on fill."""
cost = fill.quantity * fill.fill_price + fill.commission
if fill.side == 'BUY':
self.capital -= cost
self.positions[fill.symbol] = self.positions.get(fill.symbol, 0) + fill.quantity
else:
self.capital += cost
self.positions[fill.symbol] = self.positions.get(fill.symbol, 0) - fill.quantity
# Track equity
total_value = self.capital + self.calculate_position_value()
self.equity_curve.append(total_value)
Slippage Simulation¶
def simulate_slippage(order, market_data):
"""Realistic slippage simulation."""
base_slippage = 0.001 # 0.1% base
# Size impact
participation = order.quantity / market_data.avg_volume
size_impact = 0.5 * participation
# Volatility impact
vol_impact = market_data.volatility * 0.1
# Spread cost
spread_cost = market_data.spread / 2
total_slippage = base_slippage + size_impact + vol_impact + spread_cost
return total_slippage
Paper Trading Checklist¶
Before Going Live:
☐ Paper traded for minimum 3 months
☐ Results match backtest within 10-20%
☐ Infrastructure tested and stable
☐ Risk management verified
☐ Execution quality acceptable
☐ Emotional readiness confirmed
☐ Capital allocated and ready
Common Issues¶
| Issue | Cause | Solution |
|---|---|---|
| Overfilling | Assuming all orders fill | Use realistic fill rates |
| No slippage | Perfect execution assumed | Add slippage model |
| Perfect timing | Look-ahead in execution | Add realistic delay |
| Ignoring fees | No cost modeling | Include all costs |
| Short bias | Easy to short in simulation | Only short tradeable securities |
Transitioning to Live¶
Phase 1: Paper trade (3+ months)
Phase 2: Small live capital (10% of target)
Phase 3: Scale up gradually (25%, 50%, 100%)
Phase 4: Full deployment
Practical Guidelines¶
- Be Realistic — Simulate real conditions as closely as possible
- Track Everything — Paper trades should be logged like real trades
- Don't Over-Optimize — Paper trading is validation, not optimization
- Set Clear Criteria — Define what "good enough" means before going live
- Psychological Gap — Paper trading doesn't capture emotional pressure
- Time-Bounded — Don't paper trade forever; transition to live
- Compare to Backtest — Results should be similar but not identical
Next Steps¶
- Live Deployment — Going live
- Backtesting Engine — Prior stage
- Monitoring & Alerting — Live system monitoring