Skip to content

Live Trading Deployment

Overview

Deploying a trading system from backtest to live production is a critical transition. It requires rigorous validation, risk controls, monitoring, and a phased rollout to ensure the system behaves as expected with real money.

Difficulty advanced

Deployment Pipeline

Stages

1. Backtest → Historical data, simulated execution
2. Paper Trade → Live data, simulated execution
3. Shadow Trade → Live data, simulated + real execution comparison
4. Small Capital → Live data, real execution, limited capital
5. Full Production → Live data, real execution, full capital

Transition Criteria

Stage Duration Success Criteria
Backtest 1-4 weeks Sharpe > 1, Max DD < 15%, Profit factor > 1.3
Paper Trade 2-4 weeks Matches backtest within 10%, no system errors
Shadow Trade 1-2 weeks Slippage modeled accurately, no critical bugs
Small Capital 4-8 weeks Risk-adjusted returns consistent, all risk controls work
Full Production Ongoing Stable operation, continuous monitoring

Architecture Components

                    ┌─────────────────────────────────────┐
                    │          Monitoring & Alerting      │
                    │  (Prometheus, Grafana, PagerDuty)    │
                    └──────────────────┬──────────────────┘
                    ┌──────────────────▼──────────────────┐
                    │         Risk Management             │
                    │  (Position limits, VaR, Kill switch) │
                    └──────────────────┬──────────────────┘
┌─────────────┐     ┌──────────────────▼──────────────────┐     ┌─────────────┐
│ Market Data │────►│         Trading Engine              │────►│   Gateway   │
│  Feed       │     │  (Signal generation, order logic)    │     │ (FIX/OUCH)  │
└─────────────┘     └──────────────────┬──────────────────┘     └──────┬──────┘
                                       │                               │
                    ┌──────────────────▼──────────────────┐     ┌──────▼──────┐
                    │       Portfolio Manager             │     │  Exchange   │
                    │  (Positions, P&L, reconciliation)   │     │             │
                    └──────────────────┬──────────────────┘     └─────────────┘
                    ┌──────────────────▼──────────────────┐
                    │         Data Storage                │
                    │  (Tick data, orders, fills, logs)    │
                    └─────────────────────────────────────┘

Pre-Deployment Checklist

System Validation

  • [ ] Backtest reproducible (same results from same code)
  • [ ] Paper trade results match backtest expectations
  • [ ] All edge cases tested (gaps, halts, disconnects)
  • [ ] Error handling verified (exchange errors, network failures)
  • [ ] Order state management correct (pending, filled, canceled, partial)
  • [ ] Position reconciliation accurate
  • [ ] P&L calculation verified against broker statement

Risk Controls

  • [ ] Maximum position size limits enforced
  • [ ] Maximum order size limits enforced
  • [ ] Daily loss limit (circuit breaker) active
  • [ ] Maximum drawdown limit active
  • [ ] Position concentration limits set
  • [ ] Fat-finger protection (reasonable order sizes)
  • [ ] Kill switch implemented and tested

Infrastructure

  • [ ] Server co-location or low-latency connection
  • [ ] Redundant internet connections
  • [ ] Backup power (UPS, generator)
  • [ ] Monitoring dashboards configured
  • [ ] Alerting rules set (latency, errors, P&L thresholds)
  • [ ] Log rotation and archival configured
  • [ ] Database backups automated

Compliance

  • [ ] Trading licenses/registrations in place
  • [ ] Exchange memberships active
  • [ ] Regulatory reporting configured
  • [ ] Audit trail logging enabled
  • [ ] Data retention policy implemented

Deployment Script

import logging
from typing import Dict, List, Optional
from datetime import datetime

logger = logging.getLogger('trading_system')

class DeploymentManager:
    """Manage live trading deployment."""

    def __init__(self, config: Dict):
        self.config = config
        self.mode = config.get('mode', 'paper')  # paper, shadow, live
        self.capital_limit = config.get('capital_limit', 10000)
        self.running = False

    def pre_flight_checks(self) -> Dict:
        """Run pre-deployment checks."""
        checks = {}

        # Check market data connection
        checks['market_data'] = self._check_market_data()

        # Check exchange connectivity
        checks['exchange'] = self._check_exchange()

        # Check risk management system
        checks['risk_system'] = self._check_risk_system()

        # Check portfolio reconciliation
        checks['reconciliation'] = self._check_reconciliation()

        # Check monitoring
        checks['monitoring'] = self._check_monitoring()

        # All checks passed?
        checks['all_passed'] = all(checks.values())

        return checks

    def start(self):
        """Start trading system."""
        checks = self.pre_flight_checks()

        if not checks['all_passed']:
            failed = [k for k, v in checks.items() if not v]
            logger.error(f"Pre-flight checks failed: {failed}")
            raise RuntimeError("Pre-flight checks failed")

        self.running = True
        logger.info(f"Trading system started in {self.mode} mode")

        if self.mode == 'live':
            logger.warning(f"Capital limit: ${self.capital_limit}")

    def stop(self, reason: str = "Manual stop"):
        """Stop trading system gracefully."""
        self.running = False

        # Flatten all positions or maintain based on policy
        logger.info(f"Trading system stopped: {reason}")

    def emergency_stop(self):
        """Kill switch - immediate stop and cancel all orders."""
        self.running = False
        logger.critical("EMERGENCY STOP ACTIVATED")

        # Cancel all open orders
        self._cancel_all_orders()

        # Optionally flatten positions
        if self.config.get('flatten_on_emergency', False):
            self._flatten_positions()

    def _check_market_data(self) -> bool:
        """Verify market data feed is working."""
        try:
            # Subscribe to test symbol
            # Verify data is flowing
            # Check timestamp freshness
            return True
        except Exception as e:
            logger.error(f"Market data check failed: {e}")
            return False

    def _check_exchange(self) -> bool:
        """Verify exchange connectivity."""
        try:
            # Send test logon
            # Verify sequence numbers
            # Check latency
            return True
        except Exception as e:
            logger.error(f"Exchange check failed: {e}")
            return False

    def _check_risk_system(self) -> bool:
        """Verify risk management is active."""
        return True

    def _check_reconciliation(self) -> bool:
        """Verify position reconciliation."""
        return True

    def _check_monitoring(self) -> bool:
        """Verify monitoring is active."""
        return True

    def _cancel_all_orders(self):
        """Cancel all open orders."""
        pass

    def _flatten_positions(self):
        """Close all open positions."""
        pass


class PaperTradingEngine:
    """Paper trading for pre-live validation."""

    def __init__(self, strategy, initial_capital: float = 100000):
        self.strategy = strategy
        self.capital = initial_capital
        self.positions = {}
        self.orders = []
        self.fills = []

    def process_market_data(self, data: Dict):
        """Process incoming market data."""
        # Generate signals
        signals = self.strategy.on_data(data)

        # Generate orders
        for signal in signals:
            order = self._create_paper_order(signal)
            self.orders.append(order)

            # Simulate fill
            fill = self._simulate_fill(order, data)
            if fill:
                self.fills.append(fill)
                self._update_position(fill)

    def _simulate_fill(self, order: Dict, market_data: Dict) -> Optional[Dict]:
        """Simulate order fill with realistic slippage."""
        current_price = market_data.get('price')

        # Add slippage
        slippage = current_price * 0.001  # 10bps
        if order['side'] == 'buy':
            fill_price = current_price + slippage
        else:
            fill_price = current_price - slippage

        return {
            'order_id': order['id'],
            'price': fill_price,
            'quantity': order['quantity'],
            'side': order['side'],
            'timestamp': datetime.utcnow(),
            'commission': fill_price * order['quantity'] * 0.0001
        }

    def get_performance(self) -> Dict:
        """Calculate paper trading performance."""
        total_pnl = sum(f['price'] * f['quantity'] * 
                       (1 if f['side'] == 'sell' else -1) 
                       for f in self.fills)
        total_commission = sum(f.get('commission', 0) for f in self.fills)

        return {
            'capital': self.capital,
            'realized_pnl': round(total_pnl - total_commission, 2),
            'n_trades': len(self.fills),
            'n_orders': len(self.orders),
            'fill_rate': len(self.fills) / len(self.orders) if self.orders else 0
        }

Monitoring and Alerting

Key Metrics to Monitor

MONITORING_METRICS = {
    'system': {
        'cpu_usage': 'Alert if > 80%',
        'memory_usage': 'Alert if > 85%',
        'disk_usage': 'Alert if > 90%',
        'network_latency': 'Alert if > 10ms to exchange',
    },
    'trading': {
        'orders_per_second': 'Alert if abnormal spike',
        'order_rejection_rate': 'Alert if > 1%',
        'fill_rate': 'Alert if < 80%',
        'slippage': 'Alert if > 2x expected',
        'position_reconciliation': 'Alert if mismatch',
    },
    'risk': {
        'daily_pnl': 'Alert if < daily_limit',
        'drawdown': 'Alert if > threshold',
        'position_size': 'Alert if > max_position',
        'concentration': 'Alert if > max_concentration',
    },
    'data': {
        'market_data_latency': 'Alert if > 100ms',
        'data_gap': 'Alert if any gap detected',
        'quote_staleness': 'Alert if > 1s without update',
    }
}

Logging

import logging
import json

def setup_logging(log_level: str = 'INFO'):
    """Configure structured logging."""
    logging.basicConfig(
        level=getattr(logging, log_level),
        format='%(asctime)s | %(levelname)s | %(name)s | %(message)s',
        handlers=[
            logging.FileHandler('trading_system.log'),
            logging.StreamHandler()
        ]
    )

    # Log all orders
    order_logger = logging.getLogger('orders')
    order_logger.setLevel(logging.INFO)
    order_logger.addHandler(logging.FileHandler('orders.log'))

    # Log all fills
    fill_logger = logging.getLogger('fills')
    fill_logger.setLevel(logging.INFO)
    fill_logger.addHandler(logging.FileHandler('fills.log'))

    # Log risk events
    risk_logger = logging.getLogger('risk')
    risk_logger.setLevel(logging.WARNING)
    risk_logger.addHandler(logging.FileHandler('risk.log'))

Rollback Plan

If something goes wrong in production:

1. Immediate: Activate kill switch
2. Cancel all open orders
3. Assess situation (positions, P&L, system state)
4. Decide: flatten positions or hold
5. Fix the issue
6. Test fix in paper trading
7. Gradual restart (small capital first)
8. Monitor closely for 24+ hours

Checklist

  • [ ] All pre-flight checks pass
  • [ ] Paper trading results satisfactory
  • [ ] Risk controls tested and verified
  • [ ] Monitoring and alerting active
  • [ ] Kill switch tested
  • [ ] Rollback plan documented
  • [ ] Operations team briefed
  • [ ] Emergency contacts available
  • [ ] Capital limits set appropriately
  • [ ] Post-deployment review scheduled

References

  1. Ernest Chan, E.P. (2013). Algorithmic Trading: Winning Strategies and Their Rationale. Wiley.
  2. Jansen, S. (2020). Machine Learning for Algorithmic Trading (2nd ed.). Packt.
  3. SEC. (2023). "Market Access Rule (Rule 15c3-5)." Securities and Exchange Commission.