#!/bin/bash # ================================================================================================ # Paper Trading Deployment Script # ================================================================================================ # Purpose: Deploy 3-model ensemble (DQN + 2x PPO) to paper trading # Usage: bash scripts/deploy_paper_trading.sh # ================================================================================================ set -e # Exit on any error # ================================================================================================ # CONFIGURATION # ================================================================================================ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" CONFIG_FILE="$PROJECT_ROOT/config/paper_trading_config.yaml" CHECKPOINT_DIR="$PROJECT_ROOT/ml/trained_models/production" # Service endpoints API_GATEWAY="localhost:50051" TRADING_SERVICE="localhost:50052" ML_TRAINING_SERVICE="localhost:50054" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # ================================================================================================ # HELPER FUNCTIONS # ================================================================================================ print_header() { echo -e "${BLUE}========================================${NC}" echo -e "${BLUE}$1${NC}" echo -e "${BLUE}========================================${NC}" } print_success() { echo -e "${GREEN}✅ $1${NC}" } print_error() { echo -e "${RED}❌ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } print_info() { echo -e "${BLUE}ℹ️ $1${NC}" } check_command() { if ! command -v "$1" &> /dev/null; then print_error "Required command '$1' not found. Please install it first." exit 1 fi } # ================================================================================================ # PRE-FLIGHT CHECKS # ================================================================================================ print_header "Pre-Flight Checks" # Check required commands print_info "Checking required commands..." check_command docker check_command docker-compose check_command psql check_command curl print_success "All required commands available" # Check configuration file exists if [ ! -f "$CONFIG_FILE" ]; then print_error "Configuration file not found: $CONFIG_FILE" exit 1 fi print_success "Configuration file found: $CONFIG_FILE" # Check checkpoint directory exists if [ ! -d "$CHECKPOINT_DIR" ]; then print_error "Checkpoint directory not found: $CHECKPOINT_DIR" exit 1 fi print_success "Checkpoint directory found: $CHECKPOINT_DIR" # ================================================================================================ # CHECKPOINT VERIFICATION # ================================================================================================ print_header "Checkpoint Verification" print_info "Verifying model checkpoints..." # DQN epoch 30 DQN_CHECKPOINT="$CHECKPOINT_DIR/dqn/dqn_epoch_30.safetensors" if [ -f "$DQN_CHECKPOINT" ]; then SIZE=$(du -h "$DQN_CHECKPOINT" | cut -f1) print_success "DQN epoch 30: $SIZE" else print_error "DQN checkpoint not found: $DQN_CHECKPOINT" exit 1 fi # PPO epoch 130 (actor + critic) PPO_130_ACTOR="$CHECKPOINT_DIR/ppo/ppo_actor_epoch_130.safetensors" PPO_130_CRITIC="$CHECKPOINT_DIR/ppo/ppo_critic_epoch_130.safetensors" if [ -f "$PPO_130_ACTOR" ] && [ -f "$PPO_130_CRITIC" ]; then SIZE_ACTOR=$(du -h "$PPO_130_ACTOR" | cut -f1) SIZE_CRITIC=$(du -h "$PPO_130_CRITIC" | cut -f1) print_success "PPO epoch 130: actor=$SIZE_ACTOR, critic=$SIZE_CRITIC" else print_error "PPO epoch 130 checkpoints not found" exit 1 fi # PPO epoch 420 (actor + critic) PPO_420_ACTOR="$CHECKPOINT_DIR/ppo/ppo_actor_epoch_420.safetensors" PPO_420_CRITIC="$CHECKPOINT_DIR/ppo/ppo_critic_epoch_420.safetensors" if [ -f "$PPO_420_ACTOR" ] && [ -f "$PPO_420_CRITIC" ]; then SIZE_ACTOR=$(du -h "$PPO_420_ACTOR" | cut -f1) SIZE_CRITIC=$(du -h "$PPO_420_CRITIC" | cut -f1) print_success "PPO epoch 420: actor=$SIZE_ACTOR, critic=$SIZE_CRITIC" else print_error "PPO epoch 420 checkpoints not found" exit 1 fi # ================================================================================================ # SERVICE HEALTH CHECKS # ================================================================================================ print_header "Service Health Checks" print_info "Checking Docker services..." if ! docker-compose ps | grep -q "Up"; then print_error "Docker services are not running. Start with: docker-compose up -d" exit 1 fi print_success "Docker services running" # Trading Service HTTP health check (gRPC health probe may not be installed) print_info "Checking Trading Service (port 8081 HTTP)..." if curl -s http://localhost:8081/health > /dev/null 2>&1; then print_success "Trading Service healthy (HTTP)" else print_warning "Trading Service HTTP health check failed (may be gRPC-only)" fi # PostgreSQL health check print_info "Checking PostgreSQL..." if psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt -c "SELECT 1" > /dev/null 2>&1; then print_success "PostgreSQL healthy" else print_error "PostgreSQL unhealthy or not responding" exit 1 fi # Redis health check print_info "Checking Redis..." if redis-cli -h localhost -p 6379 PING > /dev/null 2>&1; then print_success "Redis healthy" else print_warning "Redis not responding (non-critical)" fi # Prometheus health check print_info "Checking Prometheus..." if curl -s http://localhost:9090/api/v1/targets > /dev/null 2>&1; then print_success "Prometheus healthy" else print_warning "Prometheus not responding (non-critical)" fi # Grafana health check print_info "Checking Grafana..." if curl -s http://localhost:3000/api/health > /dev/null 2>&1; then print_success "Grafana healthy" else print_warning "Grafana not responding (non-critical)" fi # ================================================================================================ # DATABASE TABLE VERIFICATION # ================================================================================================ print_header "Database Table Verification" print_info "Checking ensemble prediction tables..." TABLE_COUNT=$(psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt -t -c "SELECT COUNT(*) FROM pg_tables WHERE schemaname = 'public' AND tablename IN ('ensemble_predictions', 'model_performance_attribution', 'ab_test_experiments')" 2>/dev/null | tr -d ' ') if [ "$TABLE_COUNT" = "3" ]; then print_success "All ensemble tables exist (3/3)" else print_warning "Only $TABLE_COUNT/3 ensemble tables found" print_info "Tables may need to be created manually from migration 022" fi # ================================================================================================ # DEPLOYMENT SUMMARY # ================================================================================================ print_header "Deployment Summary" echo "" print_success "Paper trading infrastructure verified!" echo "" print_info "Configuration Details:" echo " - Config file: $CONFIG_FILE" echo " - Checkpoints: $CHECKPOINT_DIR" echo " - Virtual capital: \$100,000" echo " - Symbols: ES.FUT, NQ.FUT" echo " - Models: DQN epoch 30, PPO epoch 130, PPO epoch 420" echo " - Risk limits: Max position \$10K, max daily loss \$2K" echo "" print_info "Next Steps:" echo " 1. Run smoke test: bash tests/paper_trading_smoke_test.sh" echo " 2. Monitor Grafana: http://localhost:3000/d/ensemble-ml-prod" echo " 3. Check predictions: psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt" echo " SQL: SELECT COUNT(*) FROM ensemble_predictions WHERE timestamp > NOW() - INTERVAL '1 hour';" echo " 4. Monitor logs: docker logs foxhunt-trading-service -f" echo "" print_info "Phase 1 Success Criteria (7 days):" echo " - Sharpe ratio > 1.5" echo " - Win rate > 52%" echo " - Max drawdown < 10%" echo " - Simulated P&L > \$10,000" echo " - Zero model errors" echo " - Latency P99 < 50μs" echo "" print_header "Deployment Ready"