chore: Second cleanup wave - organize root directory

- Archive: 85 agent .txt files → docs/archive/agents/legacy_txt/
- Scripts: Move 110 shell scripts → scripts/ (keep deploy.sh in root)
- Models: Move 18 .safetensors → ml/models/checkpoints/training_artifacts/
- Delete: 34 directories (~33GB freed) - target/, coverage_*, test artifacts
- Build: Clean 14 build artifacts (.rlib, .o, .pid, binaries)
- Tests: Move 14 .rs files → tests/standalone/
- SQL: Move 5 files → sql/ (keep init-db*.sql for Docker)
- Wave 153: Archive to docs/archive/historical/wave153/
- Docs: Archive 9 markdown files to wave_d/reports/ and historical/

Total impact: ~34GB freed (both waves), root directory cleaned from 583 to ~40 essential files
Directory count reduced from 65 to 31 (52% reduction)
All historical data preserved in organized archive structure
This commit is contained in:
jgrusewski
2025-10-30 01:26:02 +01:00
parent 46fab7215c
commit 8d89fe80ff
424 changed files with 859 additions and 33479 deletions

41
scripts/DEPLOY_DQN_NOW.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/bash
# Quick DQN Deployment Script
# Date: 2025-10-24
# Purpose: Deploy DQN training to RunPod with correct binary selection
set -euo pipefail
echo "=========================================="
echo "RunPod DQN Training Deployment"
echo "=========================================="
echo ""
echo "Using: deploy_runpod_graphql.py (CORRECT script)"
echo "Binary: train_dqn"
echo "Dataset: ES_FUT_small.parquet (~13K bars)"
echo "GPU: RTX A4000 (16GB, $0.25/hr)"
echo "Expected time: ~1 minute"
echo "Expected cost: ~$0.004"
echo ""
# Deploy DQN training
python3 scripts/deploy_runpod_graphql.py \
--binary train_dqn \
--parquet-file /runpod-volume/test_data/ES_FUT_small.parquet \
--epochs 100 \
--gpu-type "NVIDIA RTX A4000" \
--pod-name foxhunt-dqn-training
echo ""
echo "=========================================="
echo "Deployment Complete"
echo "=========================================="
echo ""
echo "Next steps:"
echo "1. Copy the Pod ID from output above"
echo "2. Monitor training:"
echo " ssh root@POD_ID.ssh.runpod.io"
echo " nvidia-smi -l 1"
echo "3. Check models after training:"
echo " ls -lh /runpod-volume/models/"
echo "4. Terminate pod to stop billing"
echo ""

169
scripts/HYPEROPT_QUICK_MONITOR.sh Executable file
View File

@@ -0,0 +1,169 @@
#!/bin/bash
# Quick Monitoring Script for MAMBA-2 Hyperopt Deployment
# Pod ID: qlql87w5avv1q1
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/.env.runpod"
# Load environment
if [ -f "$ENV_FILE" ]; then
export $(grep -v '^#' "$ENV_FILE" | xargs)
else
echo "ERROR: .env.runpod not found"
exit 1
fi
POD_ID="qlql87w5avv1q1"
# Function to get pod status
check_status() {
echo "===================="
echo "POD STATUS CHECK"
echo "===================="
curl -s -X GET \
"https://rest.runpod.io/v1/pods/$POD_ID" \
-H "Authorization: Bearer $RUNPOD_API_KEY" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
print(f\"Status: {data.get('desiredStatus', 'UNKNOWN')}\")
print(f\"Cost: \${data.get('costPerHr', 0)}/hr\")
print(f\"GPU: {data.get('machine', {}).get('gpuDisplayName', 'TBD')}\")
print(f\"Created: {data.get('createdAt', 'N/A')}\")
runtime = data.get('runtime', {})
if runtime:
print(f\"Uptime: {runtime.get('uptimeInSeconds', 0)}s\")
print(f\"Ports: {runtime.get('ports', 'N/A')}\")
else:
print('Runtime: Pod still provisioning...')
"
echo ""
}
# Function to try SSH
try_ssh() {
echo "===================="
echo "SSH CONNECTION TEST"
echo "===================="
if ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 \
-p 19735 root@157.157.221.29 "echo 'Connected!'" 2>/dev/null; then
echo "✅ SSH is available!"
echo ""
echo "Connect with:"
echo " ssh -p 19735 root@157.157.221.29"
echo ""
return 0
else
echo "⏳ SSH not yet available (pod still initializing)"
echo ""
return 1
fi
}
# Function to show training logs (if SSH available)
show_logs() {
echo "===================="
echo "TRAINING LOGS (last 50 lines)"
echo "===================="
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-p 19735 root@157.157.221.29 \
"tail -50 /workspace/logs/*.log 2>/dev/null || echo 'No logs yet'" 2>/dev/null || \
echo "Cannot access logs (pod not ready)"
echo ""
}
# Function to check GPU
check_gpu() {
echo "===================="
echo "GPU UTILIZATION"
echo "===================="
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-p 19735 root@157.157.221.29 \
"nvidia-smi --query-gpu=name,memory.used,memory.total,utilization.gpu,temperature.gpu --format=csv,noheader" 2>/dev/null || \
echo "Cannot access GPU info (pod not ready)"
echo ""
}
# Function to check for critical success metric
check_losses() {
echo "===================="
echo "LOSS VALIDATION (CRITICAL)"
echo "===================="
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-p 19735 root@157.157.221.29 \
"grep -E 'Feature normalization|Epoch.*Loss' /workspace/logs/*.log 2>/dev/null | tail -20 || echo 'No training logs yet'" 2>/dev/null || \
echo "Cannot access logs (pod not ready)"
echo ""
echo "SUCCESS CRITERIA:"
echo " ✅ Train Loss < 1.0"
echo " ✅ Val Loss < 1.0"
echo " ❌ If losses > 1.0, FIX FAILED"
echo ""
}
# Main monitoring loop
main() {
while true; do
clear
echo "========================================"
echo "MAMBA-2 HYPEROPT MONITORING"
echo "Pod ID: $POD_ID"
echo "Time: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
echo "========================================"
echo ""
check_status
if try_ssh; then
check_gpu
check_losses
show_logs
echo "===================="
echo "NEXT ACTIONS"
echo "===================="
echo "1. Watch for 'Feature normalization' log line (confirms fix)"
echo "2. Verify losses < 1.0 (CRITICAL)"
echo "3. Monitor GPU utilization > 85%"
echo "4. Check epoch time ~10 min"
echo ""
echo "Press Ctrl+C to exit, or wait 60s for refresh..."
sleep 60
else
echo "Pod is still provisioning. Checking again in 30 seconds..."
sleep 30
fi
done
}
# Handle Ctrl+C gracefully
trap 'echo ""; echo "Monitoring stopped."; exit 0' INT
# Parse command line
case "${1:-}" in
status)
check_status
;;
ssh)
try_ssh && echo "To connect:" && echo "ssh -p 19735 root@157.157.221.29"
;;
logs)
show_logs
;;
gpu)
check_gpu
;;
losses)
check_losses
;;
*)
main
;;
esac

184
scripts/LEVEL_1_ROLLBACK_TEST.sh Executable file
View File

@@ -0,0 +1,184 @@
#!/bin/bash
# ================================================================================================
# Level 1 Rollback Test: Feature-Only Rollback (Zero Downtime, Target: <1 minute)
# Agent R1 - Rollback & Disaster Recovery Specialist
# ================================================================================================
#
# SCENARIO: Disable Wave D features without restarting services or database rollback
# EXPECTED: System falls back to Wave C (201 features) with zero downtime
#
# ================================================================================================
set -e # Exit on error
echo "===================================================================================================="
echo "LEVEL 1 ROLLBACK TEST: Feature-Only Rollback (Zero Downtime)"
echo "===================================================================================================="
echo ""
# Start timer
START_TIME=$(date +%s)
# Step 1: Verify current system state
echo "Step 1: Verifying current system state (Wave D active)"
echo "------------------------------------------------------------------------------------"
# Check if services are running
echo " ✓ Checking service health..."
SERVICE_COUNT=$(pgrep -f "api_gateway|trading_service|backtesting_service|ml_training_service" | wc -l)
if [ "$SERVICE_COUNT" -lt 1 ]; then
echo " ⚠ WARNING: No Foxhunt services detected. Skipping live service test."
SERVICES_RUNNING=false
else
echo " ✓ Found $SERVICE_COUNT Foxhunt service process(es) running"
SERVICES_RUNNING=true
fi
# Check database for regime tables
echo " ✓ Checking database for Wave D tables..."
REGIME_TABLES=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -tAc "SELECT COUNT(*) FROM information_schema.tables WHERE table_name IN ('regime_states', 'regime_transitions', 'adaptive_strategy_metrics');" 2>/dev/null || echo "0")
echo " ✓ Found $REGIME_TABLES Wave D tables in database"
# Check feature config
echo " ✓ Checking current feature configuration..."
FEATURE_CONFIG_PATH="./ml/src/features/config.rs"
if grep -q "enable_wave_d_regime: true" "$FEATURE_CONFIG_PATH" 2>/dev/null; then
echo " ✓ Wave D features currently ENABLED in code"
WAVE_D_ENABLED=true
else
echo " ⚠ Wave D features currently DISABLED in code (already rolled back?)"
WAVE_D_ENABLED=false
fi
echo ""
# Step 2: Create rollback configuration (disable Wave D features)
echo "Step 2: Creating rollback configuration (disable Wave D features)"
echo "------------------------------------------------------------------------------------"
# Backup current config
echo " ✓ Backing up current configuration..."
if [ -f "$FEATURE_CONFIG_PATH" ]; then
cp "$FEATURE_CONFIG_PATH" "$FEATURE_CONFIG_PATH.backup_$(date +%s)"
echo " ✓ Backup created: $FEATURE_CONFIG_PATH.backup_$(date +%s)"
fi
# Modify wave_d() function to return Wave C config (201 features)
echo " ✓ Modifying FeatureConfig::wave_d() to disable Wave D features..."
cat > /tmp/wave_d_rollback.sed << 'EOF'
# Find wave_d() function and change enable_wave_d_regime: true → false
/pub fn wave_d\(\) -> Self {/,/enable_wave_d_regime: true,/ {
s/enable_wave_d_regime: true,/enable_wave_d_regime: false,/
}
EOF
# Apply sed script
if [ -f "$FEATURE_CONFIG_PATH" ]; then
sed -i.rollback -f /tmp/wave_d_rollback.sed "$FEATURE_CONFIG_PATH" 2>/dev/null || {
echo " ⚠ WARNING: sed failed, using manual method"
# Fallback: create minimal config change
echo " ⚠ Manual rollback required: Set enable_wave_d_regime: false in wave_d() function"
}
echo " ✓ Configuration modified (Wave D features disabled)"
else
echo " ⚠ WARNING: $FEATURE_CONFIG_PATH not found, skipping config modification"
fi
# Verify change
if grep -q "enable_wave_d_regime: false" "$FEATURE_CONFIG_PATH" 2>/dev/null; then
echo " ✅ VERIFIED: Wave D features now DISABLED"
else
echo " ⚠ WARNING: Could not verify configuration change"
fi
echo ""
# Step 3: Rebuild services (optional - for hot-reload test)
echo "Step 3: Rebuilding services with Wave C configuration"
echo "------------------------------------------------------------------------------------"
echo " ⚠ NOTE: In production, this step would be replaced by hot-reload mechanism"
echo " ⚠ For testing, we rebuild services to validate Wave C fallback"
echo ""
REBUILD_START=$(date +%s)
echo " ✓ Building workspace (release mode)..."
cargo build --workspace --release 2>&1 | grep -E "Compiling|Finished|error" || echo " ✓ Build completed"
REBUILD_END=$(date +%s)
REBUILD_TIME=$((REBUILD_END - REBUILD_START))
echo " ✓ Build completed in ${REBUILD_TIME}s"
echo ""
# Step 4: Validate rollback
echo "Step 4: Validating Wave C fallback (201 features)"
echo "------------------------------------------------------------------------------------"
# Check feature count via compiled code
echo " ✓ Checking feature count in rollback configuration..."
FEATURE_COUNT=$(cargo run --release -p ml --example check_feature_count 2>/dev/null | grep -oP 'feature_count: \K\d+' || echo "unknown")
if [ "$FEATURE_COUNT" = "201" ]; then
echo " ✅ VERIFIED: Feature count = 201 (Wave C)"
elif [ "$FEATURE_COUNT" = "225" ]; then
echo " ❌ FAILED: Feature count = 225 (Wave D still active)"
echo " ⚠ Rollback did not take effect, manual intervention required"
else
echo " ⚠ WARNING: Could not determine feature count (got: $FEATURE_COUNT)"
echo " ⚠ Manual verification required"
fi
# Verify regime detection disabled
echo " ✓ Verifying regime detection disabled..."
if grep -q "enable_wave_d_regime: false" "$FEATURE_CONFIG_PATH" 2>/dev/null; then
echo " ✅ VERIFIED: Regime detection disabled in configuration"
else
echo " ❌ FAILED: Regime detection still enabled"
fi
# Database remains unchanged (Level 1 does NOT modify database)
echo " ✓ Database status: UNCHANGED (Wave D tables still exist)"
echo " ⚠ Note: Level 1 rollback preserves Wave D data for recovery"
echo ""
# Step 5: Calculate rollback time
echo "Step 5: Rollback Performance Metrics"
echo "------------------------------------------------------------------------------------"
END_TIME=$(date +%s)
TOTAL_TIME=$((END_TIME - START_TIME))
echo " • Total rollback time: ${TOTAL_TIME}s"
echo " • Rebuild time: ${REBUILD_TIME}s"
echo " • Target time: <60s"
if [ $TOTAL_TIME -lt 60 ]; then
echo " ✅ PASSED: Rollback completed within 60s target"
else
echo " ⚠ MISSED TARGET: Rollback took ${TOTAL_TIME}s (>60s)"
echo " ⚠ Note: Hot-reload mechanism would reduce this to <10s"
fi
echo ""
# Summary
echo "===================================================================================================="
echo "LEVEL 1 ROLLBACK TEST: SUMMARY"
echo "===================================================================================================="
echo ""
echo "Result:"
echo " • Wave D features: DISABLED (201 features active)"
echo " • Database: UNCHANGED (Wave D tables preserved)"
echo " • Services: REBUILD REQUIRED (or hot-reload in production)"
echo " • Rollback time: ${TOTAL_TIME}s (target: <60s)"
echo ""
echo "Recovery Path:"
echo " To re-enable Wave D:"
echo " 1. Restore configuration: cp $FEATURE_CONFIG_PATH.backup_* $FEATURE_CONFIG_PATH"
echo " 2. Rebuild services: cargo build --workspace --release"
echo " 3. Restart services"
echo ""
echo "===================================================================================================="
# Cleanup
rm -f /tmp/wave_d_rollback.sed
exit 0

238
scripts/LEVEL_2_ROLLBACK_TEST.sh Executable file
View File

@@ -0,0 +1,238 @@
#!/bin/bash
# ================================================================================================
# Level 2 Rollback Test: Database Rollback (Target: ~5 minutes)
# Agent R1 - Rollback & Disaster Recovery Specialist
# ================================================================================================
#
# SCENARIO: Rollback database migration 045 (regime detection tables)
# EXPECTED: All Wave D tables removed, services restart with Wave C configuration
#
# ================================================================================================
set -e # Exit on error
echo "===================================================================================================="
echo "LEVEL 2 ROLLBACK TEST: Database Rollback"
echo "===================================================================================================="
echo ""
# Start timer
START_TIME=$(date +%s)
# Step 1: Pre-rollback validation
echo "Step 1: Pre-rollback validation"
echo "------------------------------------------------------------------------------------"
# Check current database state
echo " ✓ Checking database for Wave D tables..."
REGIME_TABLES=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -tAc "
SELECT COUNT(*) FROM information_schema.tables
WHERE table_name IN ('regime_states', 'regime_transitions', 'adaptive_strategy_metrics');
" 2>/dev/null || echo "0")
echo " ✓ Found $REGIME_TABLES Wave D tables before rollback"
if [ "$REGIME_TABLES" -eq 0 ]; then
echo " ⚠ WARNING: No Wave D tables found. Migration 045 may not be applied."
echo " ⚠ Skipping Level 2 test (nothing to rollback)"
exit 1
fi
# Check for existing data
echo " ✓ Checking for existing Wave D data..."
REGIME_DATA=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -tAc "
SELECT COUNT(*) FROM regime_states;
" 2>/dev/null || echo "0")
echo " ✓ Found $REGIME_DATA regime_states records"
# Backup database (safety measure)
echo " ✓ Creating database backup..."
BACKUP_FILE="/tmp/foxhunt_backup_$(date +%s).sql"
PGPASSWORD=foxhunt_dev_password pg_dump -h localhost -U foxhunt -d foxhunt -f "$BACKUP_FILE" 2>/dev/null || {
echo " ⚠ WARNING: Backup failed, continuing anyway"
BACKUP_FILE=""
}
if [ -n "$BACKUP_FILE" ] && [ -f "$BACKUP_FILE" ]; then
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
echo " ✅ Backup created: $BACKUP_FILE ($BACKUP_SIZE)"
fi
echo ""
# Step 2: Stop services (graceful shutdown)
echo "Step 2: Stopping services (graceful shutdown)"
echo "------------------------------------------------------------------------------------"
SHUTDOWN_START=$(date +%s)
# Find and stop Foxhunt services
PIDS=$(pgrep -f "api_gateway|trading_service|backtesting_service|ml_training_service" || true)
if [ -n "$PIDS" ]; then
echo " ✓ Found service PIDs: $PIDS"
echo " ✓ Sending SIGTERM for graceful shutdown..."
kill -TERM $PIDS 2>/dev/null || true
# Wait up to 30s for graceful shutdown
for i in {1..30}; do
REMAINING=$(pgrep -f "api_gateway|trading_service|backtesting_service|ml_training_service" | wc -l)
if [ "$REMAINING" -eq 0 ]; then
echo " ✅ All services stopped gracefully in ${i}s"
break
fi
sleep 1
done
# Force kill if still running
REMAINING=$(pgrep -f "api_gateway|trading_service|backtesting_service|ml_training_service" | wc -l)
if [ "$REMAINING" -gt 0 ]; then
echo " ⚠ WARNING: Forcing shutdown of $REMAINING remaining processes"
kill -9 $(pgrep -f "api_gateway|trading_service|backtesting_service|ml_training_service") 2>/dev/null || true
fi
else
echo " ⚠ No services running"
fi
SHUTDOWN_END=$(date +%s)
SHUTDOWN_TIME=$((SHUTDOWN_END - SHUTDOWN_START))
echo " ✓ Shutdown completed in ${SHUTDOWN_TIME}s"
echo ""
# Step 3: Apply rollback migration
echo "Step 3: Rolling back database migration 045"
echo "------------------------------------------------------------------------------------"
MIGRATION_START=$(date +%s)
# Method 1: Use sqlx migrate revert (if sqlx-cli is installed)
if command -v sqlx &> /dev/null; then
echo " ✓ Using sqlx migrate revert..."
cd /home/jgrusewski/Work/foxhunt
DATABASE_URL="postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt" \
sqlx migrate revert --database-url "postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt" 2>&1 | grep -E "Applied|Reverted|error" || echo " ✓ Revert completed"
else
# Method 2: Direct SQL execution (fallback)
echo " ✓ Using direct SQL execution (sqlx not found)..."
PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -f /home/jgrusewski/Work/foxhunt/migrations/045_wave_d_regime_tracking.down.sql 2>&1 | grep -E "DROP|REVOKE|NOTICE|ERROR" || echo " ✓ Rollback SQL executed"
fi
MIGRATION_END=$(date +%s)
MIGRATION_TIME=$((MIGRATION_END - MIGRATION_START))
echo " ✓ Migration rollback completed in ${MIGRATION_TIME}s"
echo ""
# Step 4: Validate rollback
echo "Step 4: Validating database rollback"
echo "------------------------------------------------------------------------------------"
# Check tables removed
REMAINING_TABLES=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -tAc "
SELECT COUNT(*) FROM information_schema.tables
WHERE table_name IN ('regime_states', 'regime_transitions', 'adaptive_strategy_metrics');
" 2>/dev/null || echo "unknown")
if [ "$REMAINING_TABLES" = "0" ]; then
echo " ✅ VERIFIED: All Wave D tables removed"
else
echo " ❌ FAILED: $REMAINING_TABLES Wave D tables still exist"
echo " ⚠ Rollback did not complete successfully"
fi
# Check functions removed
REMAINING_FUNCTIONS=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -tAc "
SELECT COUNT(*) FROM information_schema.routines
WHERE routine_name IN ('get_latest_regime', 'get_regime_transition_matrix', 'get_regime_performance');
" 2>/dev/null || echo "unknown")
if [ "$REMAINING_FUNCTIONS" = "0" ]; then
echo " ✅ VERIFIED: All Wave D functions removed"
else
echo " ❌ FAILED: $REMAINING_FUNCTIONS Wave D functions still exist"
fi
# Check migration history
MIGRATION_VERSION=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -tAc "
SELECT version FROM _sqlx_migrations ORDER BY version DESC LIMIT 1;
" 2>/dev/null || echo "unknown")
echo " ✓ Latest migration version: $MIGRATION_VERSION (should be 44 after rollback)"
echo ""
# Step 5: Restart services with Wave C configuration
echo "Step 5: Restarting services with Wave C configuration"
echo "------------------------------------------------------------------------------------"
RESTART_START=$(date +%s)
# Ensure Wave C configuration is active (from Level 1 rollback)
echo " ✓ Verifying Wave C configuration..."
if grep -q "enable_wave_d_regime: false" /home/jgrusewski/Work/foxhunt/ml/src/features/config.rs 2>/dev/null; then
echo " ✅ Wave C configuration active"
else
echo " ⚠ WARNING: Wave D features still enabled in code"
echo " ⚠ Recommendation: Run Level 1 rollback first"
fi
# Rebuild services (if needed)
echo " ✓ Rebuilding services..."
cd /home/jgrusewski/Work/foxhunt
cargo build --release --workspace 2>&1 | grep -E "Compiling|Finished|error" || echo " ✓ Build completed"
echo " ⚠ NOTE: Manual service restart required for production"
echo " ⚠ Services NOT started automatically by this test script"
RESTART_END=$(date +%s)
RESTART_TIME=$((RESTART_END - RESTART_START))
echo " ✓ Rebuild completed in ${RESTART_TIME}s"
echo ""
# Step 6: Calculate rollback time
echo "Step 6: Rollback Performance Metrics"
echo "------------------------------------------------------------------------------------"
END_TIME=$(date +%s)
TOTAL_TIME=$((END_TIME - START_TIME))
echo " • Total rollback time: ${TOTAL_TIME}s"
echo " • Shutdown time: ${SHUTDOWN_TIME}s"
echo " • Migration time: ${MIGRATION_TIME}s"
echo " • Rebuild time: ${RESTART_TIME}s"
echo " • Target time: <300s (5 minutes)"
if [ $TOTAL_TIME -lt 300 ]; then
echo " ✅ PASSED: Rollback completed within 5-minute target"
else
echo " ⚠ MISSED TARGET: Rollback took ${TOTAL_TIME}s (>300s)"
fi
echo ""
# Summary
echo "===================================================================================================="
echo "LEVEL 2 ROLLBACK TEST: SUMMARY"
echo "===================================================================================================="
echo ""
echo "Result:"
echo " • Database tables removed: $REGIME_TABLES$REMAINING_TABLES"
echo " • Database functions removed: ✓ (get_latest_regime, get_regime_transition_matrix, get_regime_performance)"
echo " • Migration version: $MIGRATION_VERSION"
echo " • Services: STOPPED (manual restart required)"
echo " • Rollback time: ${TOTAL_TIME}s (target: <300s)"
echo ""
echo "Data Loss:"
echo " • regime_states: $REGIME_DATA records DELETED"
echo " • regime_transitions: DELETED"
echo " • adaptive_strategy_metrics: DELETED"
if [ -n "$BACKUP_FILE" ] && [ -f "$BACKUP_FILE" ]; then
echo " • Backup: $BACKUP_FILE ($BACKUP_SIZE)"
fi
echo ""
echo "Recovery Path:"
echo " To re-apply Wave D migration:"
echo " 1. Restore database: psql < $BACKUP_FILE (if needed)"
echo " 2. Re-apply migration: sqlx migrate run"
echo " 3. Re-enable Wave D features (reverse Level 1 rollback)"
echo " 4. Rebuild services: cargo build --workspace --release"
echo " 5. Restart services"
echo ""
echo "===================================================================================================="
exit 0

297
scripts/LEVEL_3_ROLLBACK_TEST.sh Executable file
View File

@@ -0,0 +1,297 @@
#!/bin/bash
# ================================================================================================
# Level 3 Rollback Test: Full Rollback to Wave C (Target: ~15 minutes)
# Agent R1 - Rollback & Disaster Recovery Specialist
# ================================================================================================
#
# SCENARIO: Complete redeployment to Wave C baseline (before Wave D)
# EXPECTED: System rolled back to last known good Wave C state
#
# ================================================================================================
set -e # Exit on error
echo "===================================================================================================="
echo "LEVEL 3 ROLLBACK TEST: Full Rollback to Wave C"
echo "===================================================================================================="
echo ""
# Start timer
START_TIME=$(date +%s)
# Configuration
WAVE_C_TAG="wave-c-baseline" # Git tag for Wave C baseline
WAVE_D_TAG="wave-d-v1.0" # Git tag for current Wave D deployment
BACKUP_DIR="/tmp/foxhunt_rollback_$(date +%s)"
# Step 1: Pre-rollback preparation
echo "Step 1: Pre-rollback preparation"
echo "------------------------------------------------------------------------------------"
# Create backup directory
mkdir -p "$BACKUP_DIR"
echo " ✓ Created backup directory: $BACKUP_DIR"
# Tag current Wave D state (if not already tagged)
cd /home/jgrusewski/Work/foxhunt
CURRENT_COMMIT=$(git rev-parse HEAD)
echo " ✓ Current commit: $CURRENT_COMMIT"
if ! git tag -l | grep -q "^$WAVE_D_TAG$"; then
git tag "$WAVE_D_TAG" "$CURRENT_COMMIT"
echo " ✓ Tagged Wave D deployment: $WAVE_D_TAG"
else
echo " ⚠ Tag $WAVE_D_TAG already exists"
fi
# Backup database
echo " ✓ Backing up database..."
BACKUP_FILE="$BACKUP_DIR/foxhunt_wave_d_backup.sql"
PGPASSWORD=foxhunt_dev_password pg_dump -h localhost -U foxhunt -d foxhunt -f "$BACKUP_FILE" 2>/dev/null || {
echo " ⚠ WARNING: Database backup failed"
BACKUP_FILE=""
}
if [ -n "$BACKUP_FILE" ] && [ -f "$BACKUP_FILE" ]; then
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
echo " ✅ Database backup created: $BACKUP_FILE ($BACKUP_SIZE)"
fi
# Backup .env files
echo " ✓ Backing up environment files..."
cp /home/jgrusewski/Work/foxhunt/.env "$BACKUP_DIR/.env.wave_d" 2>/dev/null || true
cp /home/jgrusewski/Work/foxhunt/.env.production "$BACKUP_DIR/.env.production.wave_d" 2>/dev/null || true
echo " ✓ Environment files backed up"
echo ""
# Step 2: Stop all services
echo "Step 2: Stopping all services"
echo "------------------------------------------------------------------------------------"
SHUTDOWN_START=$(date +%s)
# Stop Foxhunt services
PIDS=$(pgrep -f "api_gateway|trading_service|backtesting_service|ml_training_service|trading_agent_service" || true)
if [ -n "$PIDS" ]; then
echo " ✓ Stopping Foxhunt services (PIDs: $PIDS)..."
kill -TERM $PIDS 2>/dev/null || true
# Wait for graceful shutdown
for i in {1..30}; do
REMAINING=$(pgrep -f "api_gateway|trading_service|backtesting_service|ml_training_service|trading_agent_service" | wc -l)
if [ "$REMAINING" -eq 0 ]; then
echo " ✅ Services stopped in ${i}s"
break
fi
sleep 1
done
# Force kill if needed
REMAINING=$(pgrep -f "api_gateway|trading_service|backtesting_service|ml_training_service|trading_agent_service" | wc -l)
if [ "$REMAINING" -gt 0 ]; then
echo " ⚠ Forcing shutdown of $REMAINING processes..."
kill -9 $(pgrep -f "api_gateway|trading_service|backtesting_service|ml_training_service|trading_agent_service") 2>/dev/null || true
fi
else
echo " ⚠ No services running"
fi
SHUTDOWN_END=$(date +%s)
SHUTDOWN_TIME=$((SHUTDOWN_END - SHUTDOWN_START))
echo " ✓ Shutdown completed in ${SHUTDOWN_TIME}s"
echo ""
# Step 3: Rollback database (Level 2 rollback)
echo "Step 3: Rolling back database to Wave C state"
echo "------------------------------------------------------------------------------------"
MIGRATION_START=$(date +%s)
# Run Level 2 rollback (database migration revert)
echo " ✓ Executing database rollback..."
if [ -f "/home/jgrusewski/Work/foxhunt/migrations/045_wave_d_regime_tracking.down.sql" ]; then
PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt \
-f /home/jgrusewski/Work/foxhunt/migrations/045_wave_d_regime_tracking.down.sql \
2>&1 | grep -E "DROP|REVOKE|NOTICE|ERROR|Wave D" || echo " ✓ Database rollback completed"
else
echo " ⚠ WARNING: Down migration not found, attempting alternative method..."
# Use migration 046 if available
if [ -f "/home/jgrusewski/Work/foxhunt/migrations/046_rollback_regime_detection.sql" ]; then
PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt \
-f /home/jgrusewski/Work/foxhunt/migrations/046_rollback_regime_detection.sql \
2>&1 | grep -E "DROP|REVOKE|NOTICE|ERROR|Wave D" || echo " ✓ Alternative rollback completed"
fi
fi
# Verify database state
REGIME_TABLES=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -tAc "
SELECT COUNT(*) FROM information_schema.tables
WHERE table_name IN ('regime_states', 'regime_transitions', 'adaptive_strategy_metrics');
" 2>/dev/null || echo "unknown")
if [ "$REGIME_TABLES" = "0" ]; then
echo " ✅ Database rollback successful (Wave D tables removed)"
else
echo " ❌ Database rollback failed ($REGIME_TABLES Wave D tables remain)"
fi
MIGRATION_END=$(date +%s)
MIGRATION_TIME=$((MIGRATION_END - MIGRATION_START))
echo " ✓ Database rollback completed in ${MIGRATION_TIME}s"
echo ""
# Step 4: Checkout Wave C baseline code
echo "Step 4: Checking out Wave C baseline code"
echo "------------------------------------------------------------------------------------"
CHECKOUT_START=$(date +%s)
# Find Wave C baseline commit
if git tag -l | grep -q "^$WAVE_C_TAG$"; then
echo " ✓ Found Wave C tag: $WAVE_C_TAG"
WAVE_C_COMMIT=$(git rev-list -n 1 "$WAVE_C_TAG")
else
# Fallback: Find commit before Wave D Phase 3 (feature implementation)
echo " ⚠ No Wave C tag found, searching for baseline commit..."
WAVE_C_COMMIT=$(git log --all --oneline | grep -E "Wave C.*COMPLETE|WAVE_C.*IMPLEMENTATION.*COMPLETE" | head -1 | awk '{print $1}')
if [ -z "$WAVE_C_COMMIT" ]; then
# Ultimate fallback: commit before "Wave D Phase 3"
WAVE_C_COMMIT=$(git log --all --oneline --before="2025-10-17" | head -1 | awk '{print $1}')
fi
fi
echo " ✓ Wave C baseline commit: $WAVE_C_COMMIT"
# Stash current changes (if any)
if ! git diff-index --quiet HEAD --; then
echo " ✓ Stashing uncommitted changes..."
git stash push -m "Rollback: Stashing Wave D changes before rollback to Wave C"
fi
# Checkout Wave C baseline
echo " ✓ Checking out Wave C baseline..."
git checkout "$WAVE_C_COMMIT" 2>&1 | grep -E "HEAD|Previous|error" || echo " ✓ Checkout completed"
# Verify checkout
CURRENT_COMMIT=$(git rev-parse HEAD)
if [ "$CURRENT_COMMIT" = "$WAVE_C_COMMIT" ]; then
echo " ✅ Successfully checked out Wave C baseline"
else
echo " ❌ Checkout failed (HEAD: $CURRENT_COMMIT, Expected: $WAVE_C_COMMIT)"
fi
CHECKOUT_END=$(date +%s)
CHECKOUT_TIME=$((CHECKOUT_END - CHECKOUT_START))
echo " ✓ Git checkout completed in ${CHECKOUT_TIME}s"
echo ""
# Step 5: Rebuild services with Wave C codebase
echo "Step 5: Rebuilding services from Wave C codebase"
echo "------------------------------------------------------------------------------------"
REBUILD_START=$(date +%s)
# Clean build to ensure no Wave D artifacts
echo " ✓ Cleaning previous build artifacts..."
cd /home/jgrusewski/Work/foxhunt
cargo clean 2>&1 | grep -E "Removing|error" || echo " ✓ Clean completed"
# Rebuild entire workspace
echo " ✓ Rebuilding workspace (release mode)..."
cargo build --workspace --release 2>&1 | grep -E "Compiling|Finished|error" || echo " ✓ Build completed"
REBUILD_END=$(date +%s)
REBUILD_TIME=$((REBUILD_END - REBUILD_START))
echo " ✓ Rebuild completed in ${REBUILD_TIME}s"
echo ""
# Step 6: Smoke test Wave C deployment
echo "Step 6: Smoke testing Wave C deployment"
echo "------------------------------------------------------------------------------------"
# Check feature count
echo " ✓ Checking feature count..."
FEATURE_COUNT=$(cargo run --release -p ml --example check_feature_count 2>&1 | grep "Wave C: feature_count:" | grep -oP '\d+' || echo "unknown")
if [ "$FEATURE_COUNT" = "201" ]; then
echo " ✅ VERIFIED: Wave C feature count = 201"
elif [ "$FEATURE_COUNT" = "225" ]; then
echo " ❌ FAILED: Feature count = 225 (Wave D still active)"
else
echo " ⚠ WARNING: Could not verify feature count (got: $FEATURE_COUNT)"
fi
# Check for Wave D code
WAVE_D_CODE=$(grep -r "enable_wave_d_regime" /home/jgrusewski/Work/foxhunt/ml/src/features/ 2>/dev/null | wc -l)
if [ "$WAVE_D_CODE" -eq 0 ]; then
echo " ✅ VERIFIED: No Wave D code present"
else
echo " ⚠ WARNING: Wave D code references still exist ($WAVE_D_CODE occurrences)"
echo " ⚠ This may be expected if Wave C already had placeholders"
fi
# Test basic compilation
echo " ✓ Running basic compilation test..."
cargo check --workspace 2>&1 | grep -E "Checking|Finished|error" || echo " ✓ Check completed"
echo " ⚠ NOTE: Services NOT started automatically (manual start required)"
echo ""
# Step 7: Calculate rollback time
echo "Step 7: Rollback Performance Metrics"
echo "------------------------------------------------------------------------------------"
END_TIME=$(date +%s)
TOTAL_TIME=$((END_TIME - START_TIME))
echo " • Total rollback time: ${TOTAL_TIME}s"
echo " • Shutdown time: ${SHUTDOWN_TIME}s"
echo " • Database rollback time: ${MIGRATION_TIME}s"
echo " • Git checkout time: ${CHECKOUT_TIME}s"
echo " • Rebuild time: ${REBUILD_TIME}s"
echo " • Target time: <900s (15 minutes)"
if [ $TOTAL_TIME -lt 900 ]; then
echo " ✅ PASSED: Rollback completed within 15-minute target"
else
echo " ⚠ MISSED TARGET: Rollback took ${TOTAL_TIME}s (>900s)"
fi
echo ""
# Summary
echo "===================================================================================================="
echo "LEVEL 3 ROLLBACK TEST: SUMMARY"
echo "===================================================================================================="
echo ""
echo "Result:"
echo " • Git state: Wave C baseline ($WAVE_C_COMMIT)"
echo " • Database: Wave D tables removed ($REGIME_TABLES tables remain)"
echo " • Feature count: $FEATURE_COUNT (expected: 201)"
echo " • Services: STOPPED (manual restart required)"
echo " • Rollback time: ${TOTAL_TIME}s (~$((TOTAL_TIME / 60)) minutes)"
echo ""
echo "Data Loss:"
echo " • All Wave D regime detection data DELETED"
echo " • Wave D code changes REVERTED"
if [ -n "$BACKUP_FILE" ] && [ -f "$BACKUP_FILE" ]; then
echo " • Full backup: $BACKUP_FILE ($BACKUP_SIZE)"
fi
echo " • Backup directory: $BACKUP_DIR"
echo ""
echo "Recovery Path:"
echo " To re-deploy Wave D:"
echo " 1. Checkout Wave D tag: git checkout $WAVE_D_TAG"
echo " 2. Restore database (optional): psql < $BACKUP_FILE"
echo " 3. Re-apply migrations: sqlx migrate run"
echo " 4. Rebuild services: cargo build --workspace --release"
echo " 5. Restart all services"
echo ""
echo "Manual Steps Required:"
echo " 1. Start services: cargo run -p api_gateway &"
echo " 2. Verify health checks: curl http://localhost:8080/health"
echo " 3. Run integration tests: cargo test --workspace"
echo " 4. Monitor Grafana dashboards"
echo ""
echo "===================================================================================================="
exit 0

169
scripts/MAMBA2_POD_MONITOR.sh Executable file
View File

@@ -0,0 +1,169 @@
#!/bin/bash
# MAMBA-2 Fixed Binary Deployment Monitor
# Pod ID: 8e6o2r2snavgzf
# Expected completion: 2025-10-27 10:21 UTC (~81 minutes from 09:00)
set -euo pipefail
POD_ID="8e6o2r2snavgzf"
CHECKPOINT_DIR="/runpod-volume/models/mamba2_FIXED_sgd_bs512_lr5e4_shuffle_50ep"
echo "=================================="
echo "MAMBA-2 FIXED BINARY MONITOR"
echo "=================================="
echo "Pod ID: $POD_ID"
echo "GPU: RTX 4090 (24GB VRAM)"
echo "Cost: \$0.59/hr"
echo "Expected runtime: ~81 minutes"
echo "=================================="
echo ""
# Load RunPod credentials
if [ ! -f ".env.runpod" ]; then
echo "ERROR: .env.runpod not found"
exit 1
fi
source .env.runpod
if [ -z "$RUNPOD_API_KEY" ]; then
echo "ERROR: RUNPOD_API_KEY not set"
exit 1
fi
# Function to check pod status
check_status() {
echo "Checking pod status..."
curl -s -H "Authorization: Bearer $RUNPOD_API_KEY" \
"https://rest.runpod.io/v1/pods/$POD_ID" | python3 -m json.tool
echo ""
}
# Function to download results
download_results() {
echo "Downloading results from S3..."
aws s3 sync "s3://se3zdnb5o4/models/mamba2_FIXED_sgd_bs512_lr5e4_shuffle_50ep" \
"./local_models/mamba2_FIXED" \
--profile runpod \
--endpoint-url https://s3api-eur-is-1.runpod.io
echo ""
echo "Results downloaded to ./local_models/mamba2_FIXED/"
ls -lh "./local_models/mamba2_FIXED/"
}
# Function to verify training success
verify_training() {
echo "Verifying training success..."
if [ ! -d "./local_models/mamba2_FIXED" ]; then
echo "ERROR: Results not downloaded yet. Run with 'download' first."
return 1
fi
# Check for model checkpoint
if [ -f "./local_models/mamba2_FIXED/mamba2_model_epoch_50.safetensors" ]; then
echo "✅ Model checkpoint found"
ls -lh "./local_models/mamba2_FIXED/mamba2_model_epoch_50.safetensors"
else
echo "❌ Model checkpoint NOT found"
fi
# Check for metrics
if [ -f "./local_models/mamba2_FIXED/training_metrics.json" ]; then
echo "✅ Training metrics found"
cat "./local_models/mamba2_FIXED/training_metrics.json"
else
echo "❌ Training metrics NOT found"
fi
# Check for loss history
if [ -f "./local_models/mamba2_FIXED/loss_history.csv" ]; then
echo "✅ Loss history found"
echo "Last 10 epochs:"
tail -n 10 "./local_models/mamba2_FIXED/loss_history.csv"
else
echo "❌ Loss history NOT found"
fi
# Check training log for key indicators
if [ -f "./local_models/mamba2_FIXED/training.log" ]; then
echo "✅ Training log found"
echo ""
echo "Checking for success indicators..."
# Check optimizer
if grep -q "Optimizer: SGD" "./local_models/mamba2_FIXED/training.log"; then
echo "✅ SGD optimizer confirmed (not Adam)"
else
echo "❌ SGD optimizer NOT found (check for Adam)"
fi
# Check for zero gradients
if grep -q "grad: 0.0000" "./local_models/mamba2_FIXED/training.log"; then
echo "❌ Zero gradients detected (P0 fix failed)"
else
echo "✅ No zero gradients detected"
fi
# Check for E11 spike
if grep -q "E11" "./local_models/mamba2_FIXED/training.log" || \
grep -q "1e+11" "./local_models/mamba2_FIXED/training.log"; then
echo "❌ E11 spike detected (numerical instability)"
else
echo "✅ No E11 spike detected"
fi
else
echo "❌ Training log NOT found"
fi
}
# Main menu
case "${1:-status}" in
status)
check_status
;;
download)
download_results
;;
verify)
verify_training
;;
ssh)
echo "SSH to pod $POD_ID..."
echo "ssh root@$POD_ID.ssh.runpod.io"
echo ""
echo "Once connected, check training status:"
echo " cd $CHECKPOINT_DIR"
echo " tail -f training.log"
;;
jupyter)
echo "Jupyter URL: https://$POD_ID-8888.proxy.runpod.net"
echo ""
echo "Navigate to: $CHECKPOINT_DIR/training.log"
;;
all)
check_status
echo ""
echo "=================================="
read -p "Download results? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
download_results
echo ""
verify_training
fi
;;
*)
echo "Usage: $0 {status|download|verify|ssh|jupyter|all}"
echo ""
echo "Commands:"
echo " status - Check pod status via API"
echo " download - Download results from S3"
echo " verify - Verify training success (requires download first)"
echo " ssh - Show SSH command"
echo " jupyter - Show Jupyter URL"
echo " all - Status + download + verify (interactive)"
exit 1
;;
esac

56
scripts/QUICK_FIX_COMMANDS.sh Executable file
View File

@@ -0,0 +1,56 @@
#!/bin/bash
# Quick Fix Commands - Foxhunt Codebase Cleanup
# Total Estimated Time: 3.5 minutes
# Impact: Cosmetic improvements only, zero functional changes
set -e
echo "=========================================="
echo "Foxhunt Codebase Quick Fixes"
echo "Total Time: ~3.5 minutes"
echo "=========================================="
echo ""
echo "[1/3] Fixing 4 Clippy Deny-Level Errors (35 seconds)..."
echo "Files affected:"
echo " - services/stress_tests/src/metrics.rs"
echo " - trading-data/src/models.rs"
echo " - trading_engine/src/types/events.rs"
# Manual fixes required (clippy --fix may not handle all):
echo ""
echo "Manual fixes needed:"
echo "1. stress_tests/src/metrics.rs:144"
echo " BEFORE: let mean_u64 = (mean_micros as u64).min(u64::MAX);"
echo " AFTER: let mean_u64 = (mean_micros as u64);"
echo ""
echo "2. trading-data/src/models.rs:98"
echo " BEFORE: assert_eq!(order.quantity.to_f64(), 100000.0);"
echo " AFTER: assert_relative_eq!(order.quantity.to_f64(), 100_000.0, epsilon = 1e-6);"
echo ""
echo "3. trading_engine/src/types/events.rs (4 locations)"
echo " BEFORE: 150000.0, 100000.0, 500000.0, 400000.0"
echo " AFTER: 150_000.0, 100_000.0, 500_000.0, 400_000.0"
read -p "Press Enter after making manual fixes..."
echo ""
echo "[2/3] Formatting entire codebase (2 minutes)..."
cargo fmt --all
echo "✅ Formatting complete"
echo ""
echo "[3/3] Verifying compilation (1 minute)..."
cargo build --workspace --release --quiet
echo "✅ Compilation successful"
echo ""
echo "=========================================="
echo "✅ Quick fixes complete!"
echo "=========================================="
echo ""
echo "Next steps:"
echo "1. Review changes: git diff"
echo "2. Run tests: cargo test --workspace --lib"
echo "3. Commit: git commit -m 'chore: Apply clippy fixes and rustfmt'"
echo "4. Deploy to production"

53
scripts/analyze_clippy.sh Executable file
View File

@@ -0,0 +1,53 @@
#!/bin/bash
# Clippy Analysis Script for Wave 112 Agent 10
cd /home/jgrusewski/Work/foxhunt
echo "=== CLIPPY COMPREHENSIVE ANALYSIS ==="
echo ""
# Run clippy and save full output
timeout 300 cargo clippy --workspace --all-targets -- -D warnings 2>&1 > /tmp/clippy_full.txt
# Total error count
TOTAL_ERRORS=$(grep "error:" /tmp/clippy_full.txt | wc -l)
echo "Total Errors: $TOTAL_ERRORS"
echo ""
# Critical Safety Issues
echo "=== CRITICAL SAFETY ISSUES ==="
echo ""
echo "Unwrap/Panic Issues:"
grep -i "unwrap\|panic" /tmp/clippy_full.txt | grep "error:" | wc -l
echo ""
echo "Indexing/Slicing Panics:"
grep -i "indexing\|slicing" /tmp/clippy_full.txt | grep "error:" | wc -l
echo ""
echo "Dangerous Casts:"
grep -i "dangerous.*conversion\|cast.*wrap" /tmp/clippy_full.txt | grep "error:" | wc -l
echo ""
# Cosmetic Issues
echo "=== COSMETIC ISSUES ==="
echo ""
echo "Unnecessary hashes:"
grep "unnecessary hashes" /tmp/clippy_full.txt | wc -l
echo ""
echo "Integer suffix formatting:"
grep "integer type suffix" /tmp/clippy_full.txt | wc -l
echo ""
echo "Doc comments:"
grep "empty line after doc comment" /tmp/clippy_full.txt | wc -l
echo ""
echo "Must use attributes:"
grep "must_use" /tmp/clippy_full.txt | wc -l
echo ""
# Top 20 error types
echo "=== TOP 20 ERROR TYPES ==="
grep "error:" /tmp/clippy_full.txt | sed 's/.*error: //' | sed 's/\[.*//' | sort | uniq -c | sort -rn | head -20
# Critical files with most issues
echo ""
echo "=== FILES WITH MOST CRITICAL ISSUES ==="
grep -E "unwrap|panic|indexing|slicing|dangerous.*conversion" /tmp/clippy_full.txt | grep "error:" -A1 | grep "^ *-->" | sed 's/.*--> //' | sed 's/:.*//' | sort | uniq -c | sort -rn | head -20

71
scripts/apply_batch_size_fix.sh Executable file
View File

@@ -0,0 +1,71 @@
#!/bin/bash
# Apply batch_size_max 96→180 fix
set -e
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
echo "║ Applying batch_size_max Fix (96 → 180) ║"
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
echo ""
# Backup files
echo "1. Creating backups..."
cp ml/examples/hyperopt_mamba2_demo.rs ml/examples/hyperopt_mamba2_demo.rs.backup
cp ml/src/hyperopt/adapters/mamba2.rs ml/src/hyperopt/adapters/mamba2.rs.backup
echo " ✓ Backups created"
echo ""
# Apply changes to hyperopt_mamba2_demo.rs
echo "2. Updating hyperopt_mamba2_demo.rs..."
sed -i 's/default_value = "96"/default_value = "180"/' ml/examples/hyperopt_mamba2_demo.rs
sed -i 's/RTX A4000 16GB = 96/RTX A4000 16GB = 180/' ml/examples/hyperopt_mamba2_demo.rs
echo " ✓ Updated default to 180"
echo ""
# Apply changes to mamba2.rs
echo "3. Updating mamba2.rs adapter..."
sed -i 's/(4.0, 256.0),.*batch_size/(4.0, 180.0), \/\/ batch_size (validated safe for 16GB GPU)/' ml/src/hyperopt/adapters/mamba2.rs
echo " ✓ Updated bounds to (4.0, 180.0)"
echo ""
# Show changes
echo "4. Changes summary:"
echo ""
echo " hyperopt_mamba2_demo.rs:"
grep -A1 "batch_size_max" ml/examples/hyperopt_mamba2_demo.rs | grep "default_value"
echo ""
echo " mamba2.rs:"
grep "4.0, 180.0" ml/src/hyperopt/adapters/mamba2.rs || echo " (bounds updated)"
echo ""
# Verify
echo "5. Verification:"
if grep -q 'default_value = "180"' ml/examples/hyperopt_mamba2_demo.rs; then
echo " ✓ hyperopt_mamba2_demo.rs: UPDATED"
else
echo " ✗ hyperopt_mamba2_demo.rs: FAILED"
exit 1
fi
if grep -q '(4.0, 180.0)' ml/src/hyperopt/adapters/mamba2.rs; then
echo " ✓ mamba2.rs: UPDATED"
else
echo " ✗ mamba2.rs: FAILED"
exit 1
fi
echo ""
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
echo "║ ✅ FIX APPLIED ║"
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
echo ""
echo "Next steps:"
echo " 1. Rebuild: cargo build -p ml --release --features cuda"
echo " 2. Test: cargo run -p ml --example hyperopt_mamba2_demo --release --features cuda -- \\"
echo " --parquet-file test_data/ES_FUT_180d.parquet \\"
echo " --trials 1 --epochs 1 --batch-size-min 180 --batch-size-max 180"
echo " 3. Monitor: nvidia-smi --query-gpu=memory.used --format=csv -l 2"
echo ""
echo "Expected VRAM: ~7.7GB (48% of 16GB)"
echo "If stable, proceed with full hyperopt run."
echo ""

97
scripts/apply_ml_test_fixes.sh Executable file
View File

@@ -0,0 +1,97 @@
#!/bin/bash
# Apply systematic fixes to ML test modules
# This script adds common test imports to test modules
set -e
echo "=== Applying ML Test Compilation Fixes ==="
echo "This script will add common imports to test modules"
echo ""
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Counter
fixes_applied=0
# Function to add imports to a test module
fix_test_module() {
local file=$1
local needs_device=false
local needs_file=false
local needs_tempdir=false
# Check what imports are needed
if grep -q "Device" "$file" && ! grep -q "use candle_core::Device" "$file"; then
needs_device=true
fi
if grep -q "File\|Write\|Read" "$file" && ! grep -q "use std::fs::File" "$file"; then
needs_file=true
fi
if grep -q "tempdir" "$file" && ! grep -q "use tempfile::tempdir" "$file"; then
needs_tempdir=true
fi
# If any imports needed, apply fix
if [ "$needs_device" = true ] || [ "$needs_file" = true ] || [ "$needs_tempdir" = true ]; then
echo -e "${YELLOW}Fixing: $file${NC}"
# Find the test module line
test_mod_line=$(grep -n "^#\[cfg(test)\]" "$file" | head -1 | cut -d: -f1)
if [ ! -z "$test_mod_line" ]; then
# Calculate line after "mod tests {"
mod_tests_line=$((test_mod_line + 1))
# Build import string
imports=" use super::*;"
if [ "$needs_device" = true ]; then
imports="$imports\n use candle_core::{Device, DType};"
fi
if [ "$needs_file" = true ]; then
imports="$imports\n use std::fs::File;\n use std::io::Write;"
fi
if [ "$needs_tempdir" = true ]; then
imports="$imports\n use tempfile::tempdir;"
fi
# Apply fix (insert after mod tests { line)
awk -v modline="$mod_tests_line" -v imports="$imports" '
NR == modline && /^mod tests \{/ {
print $0
print imports
next
}
{print}
' "$file" > "$file.tmp" && mv "$file.tmp" "$file"
fixes_applied=$((fixes_applied + 1))
echo -e "${GREEN} ✓ Fixed${NC}"
fi
fi
}
# Find all Rust files with test modules
echo "Scanning for test modules..."
test_files=$(find ml/src -name "*.rs" -type f -exec grep -l "#\[cfg(test)\]" {} \;)
for file in $test_files; do
fix_test_module "$file"
done
echo ""
echo -e "${GREEN}=== Summary ===${NC}"
echo "Files processed: $(echo "$test_files" | wc -l)"
echo "Fixes applied: $fixes_applied"
echo ""
echo "Next steps:"
echo "1. Run: cargo check -p ml --lib"
echo "2. Check for remaining errors"
echo "3. Apply additional fixes as needed"

View File

@@ -0,0 +1,114 @@
#!/bin/bash
# Wave 112 Quick Start - Trading Engine Test Migration
# Auto-generated: 2025-10-05
set -e
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ WAVE 112: TRADING ENGINE TEST MIGRATION ║"
echo "║ Fix 246 Compilation Errors ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""
# Step 1: Verify current error count
echo "📊 STEP 1: Verifying error count..."
ERROR_COUNT=$(cargo test -p trading_engine --no-run 2>&1 | grep "^error" | wc -l)
echo " Current errors: $ERROR_COUNT"
echo " Expected: 246"
echo ""
if [ "$ERROR_COUNT" -eq 0 ]; then
echo "✅ No errors found! Tests already fixed."
echo " Running validation..."
cargo test -p trading_engine
exit 0
fi
# Step 2: Show error distribution
echo "📈 STEP 2: Error distribution..."
echo "┌────────┬───────┬─────────────────────────────────────────┐"
echo "│ Type │ Count │ Description │"
echo "├────────┼───────┼─────────────────────────────────────────┤"
cargo test -p trading_engine --no-run 2>&1 | \
grep "^error\[" | \
sed 's/:.*//' | \
sort | uniq -c | sort -rn | \
head -5 | \
awk '{printf "│ %-6s │ %5s │ %-39s │\n", $2, $1, "See WAVE112 plan for details"}'
echo "└────────┴───────┴─────────────────────────────────────────┘"
echo ""
# Step 3: Show affected files
echo "📁 STEP 3: Affected files..."
echo "┌─────────────────────────────────────┬────────┐"
echo "│ File │ Errors │"
echo "├─────────────────────────────────────┼────────┤"
cargo test -p trading_engine --no-run 2>&1 | \
grep "^ --> " | \
sed 's/:.*//' | \
sort | uniq -c | sort -rn | \
awk '{
file=$2;
gsub("trading_engine/tests/", "", file);
printf "│ %-35s │ %6s │\n", file, $1
}'
echo "└─────────────────────────────────────┴────────┘"
echo ""
# Step 4: Show execution plan
echo "🚀 STEP 4: Recommended execution plan..."
echo ""
echo "OPTION 1: Parallel (8-12 hours) ⚡ RECOMMENDED"
echo " Agent A: Fix audit_compliance.rs (206 errors)"
echo " Agent B: Fix async_audit_queue_tests.rs (22 errors)"
echo " Agent C: Fix remaining 4 files (18 errors)"
echo " Coord: Create helpers + validate"
echo ""
echo "OPTION 2: Single-threaded (24-36 hours)"
echo " Follow 6-phase plan in WAVE112_TEST_MIGRATION_PLAN.md"
echo ""
# Step 5: Show detailed documentation
echo "📚 STEP 5: Documentation..."
echo " - Detailed status: WAVE111_AGENT5_TRADING_ENGINE_STATUS.md"
echo " - Migration plan: WAVE112_TEST_MIGRATION_PLAN.md"
echo " - Quick summary: WAVE111_AGENT5_EXECUTIVE_SUMMARY.md"
echo ""
# Step 6: Show next commands
echo "🎯 STEP 6: Next commands..."
echo ""
echo "# Review documentation:"
echo "cat WAVE112_TEST_MIGRATION_PLAN.md"
echo ""
echo "# Start Phase 1 (API Analysis):"
echo "# 1. Read current API:"
echo "less trading_engine/src/compliance/audit_trails.rs"
echo ""
echo "# 2. Create test helper module:"
echo "mkdir -p trading_engine/tests/helpers"
echo "touch trading_engine/tests/helpers/mod.rs"
echo "touch trading_engine/tests/helpers/audit.rs"
echo ""
echo "# Start Phase 2 (Constructor Migration):"
echo "# See WAVE112_TEST_MIGRATION_PLAN.md Phase 2 for detailed steps"
echo ""
# Step 7: Validation commands
echo "🧪 STEP 7: Validation commands (post-fix)..."
echo ""
echo "# Check compilation (incremental):"
echo "cargo test -p trading_engine --test audit_compliance --no-run"
echo "cargo test -p trading_engine --test async_audit_queue_tests --no-run"
echo ""
echo "# Run full test suite:"
echo "cargo test -p trading_engine"
echo ""
echo "# Measure coverage:"
echo "cargo llvm-cov --package trading_engine --html"
echo ""
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ STATUS: Ready for Wave 112 execution ║"
echo "║ DECISION: Choose parallel (8-12h) or single (24-36h) ║"
echo "╚══════════════════════════════════════════════════════════════╝"

View File

@@ -0,0 +1,63 @@
#!/bin/bash
# Wave 113 Agent 34: Git Commit Verification Script
# Verifies Phase 1 commit and checks system state
echo "==================================================================="
echo "Wave 113 Agent 34: Git Commit Verification"
echo "==================================================================="
echo ""
echo "1. Recent Commit History"
echo "-------------------------------------------------------------------"
git log --oneline -5
echo ""
echo "2. Phase 1 Commit Details"
echo "-------------------------------------------------------------------"
git show --stat 876fa95 | head -40
echo ""
echo "3. Dependency Count Verification"
echo "-------------------------------------------------------------------"
echo "Expected: 933 crates (down from 942)"
CRATE_COUNT=$(cargo tree 2>/dev/null | wc -l)
echo "Actual: $CRATE_COUNT crates"
echo ""
echo "4. Security Audit Status"
echo "-------------------------------------------------------------------"
cargo audit 2>&1 | head -30
echo ""
echo "5. Production Readiness Impact"
echo "-------------------------------------------------------------------"
echo "Before Wave 113: 92.1% (8.29/9 criteria)"
echo "After Phase 1: 93.5% (8.42/9 criteria)"
echo "Improvement: +1.4%"
echo ""
echo "6. Files Changed Summary"
echo "-------------------------------------------------------------------"
git diff HEAD~1 --stat | tail -1
echo ""
echo "7. Current Git Status"
echo "-------------------------------------------------------------------"
git status --short
echo ""
echo "8. Phase 2 Status Check"
echo "-------------------------------------------------------------------"
echo "Looking for new test files in services/**/tests/..."
NEW_TESTS=$(find services -name "*.rs" -path "*/tests/*" -newer WAVE113_AGENT23_SECURITY_FIXES.md 2>/dev/null | wc -l)
echo "New test files created: $NEW_TESTS"
if [ $NEW_TESTS -eq 0 ]; then
echo "❌ Phase 2 (service coverage expansion) was NOT executed"
else
echo "✅ Phase 2 tests detected"
fi
echo ""
echo "==================================================================="
echo "Verification Complete"
echo "==================================================================="

View File

@@ -0,0 +1,259 @@
#!/bin/bash
# Wave 113 Clippy Fix Action Plan
# Based on Agent 10 analysis of 4,909 warnings
# DO NOT run automatically - this is a guide for manual fixes
set -e
echo "========================================="
echo "WAVE 113 CLIPPY FIX ACTION PLAN"
echo "========================================="
echo ""
echo "⚠️ WARNING: This script is a GUIDE only"
echo "⚠️ Review each change before applying"
echo ""
# Phase 1: Safety Comments (Priority 1 - 3-4 hours)
echo "PHASE 1: Add Safety Comments to Unsafe Blocks"
echo "----------------------------------------------"
echo "Files to fix:"
echo " - trading_engine/src/affinity.rs (4 blocks)"
echo " - trading_engine/src/lockfree/mpsc_queue.rs (5 blocks)"
echo " - trading_engine/src/lockfree/ring_buffer.rs (3 blocks)"
echo " - trading_engine/src/lockfree/small_batch_ring.rs (7 blocks)"
echo ""
echo "Template:"
echo " // SAFETY: [Explain invariants here]"
echo " // - Why the unsafe operation is sound"
echo " // - What invariants are maintained"
echo " // - References to external documentation if applicable"
echo " unsafe { ... }"
echo ""
echo "Example commands:"
echo " # Find all unsafe blocks"
echo " rg 'unsafe \{' --type rust"
echo ""
echo " # Check specific file"
echo " rg 'unsafe \{' trading_engine/src/affinity.rs"
echo ""
# Phase 2: Fix Unwrap Usage (Priority 1 - 30 minutes)
echo "PHASE 2: Fix unwrap_used (6 instances)"
echo "---------------------------------------"
echo "Strategy: Replace .unwrap() with proper error handling"
echo ""
echo "Find locations:"
echo " rg '\.unwrap\(\)' --type rust | grep -v test | grep -v '//' | head -10"
echo ""
echo "Fix pattern:"
echo " # Before:"
echo " let value = result.unwrap();"
echo ""
echo " # After (in functions returning Result):"
echo " let value = result?;"
echo ""
echo " # After (with context):"
echo " let value = result.expect(\"meaningful error message\");"
echo ""
# Phase 3: Audit Indexing (Priority 2 - 2-3 hours)
echo "PHASE 3: Audit Indexing Operations (286 instances)"
echo "---------------------------------------------------"
echo "Top files:"
echo " 1. adaptive-strategy/src/regime/mod.rs"
echo " 2. adaptive-strategy/src/microstructure/mod.rs"
echo " 3. adaptive-strategy/src/models/tlob_model.rs"
echo ""
echo "Strategy:"
echo " 1. For non-critical paths: Use .get() with error handling"
echo " 2. For hot paths: Keep indexing but add debug_assert!"
echo ""
echo "Find indexing:"
echo " rg '\[.*\]' adaptive-strategy/src/regime/mod.rs | head -20"
echo ""
echo "Fix pattern (safe):"
echo " # Before:"
echo " let val = arr[idx];"
echo ""
echo " # After (with error):"
echo " let val = arr.get(idx).ok_or(\"index out of bounds\")?;"
echo ""
echo "Fix pattern (hot path):"
echo " # Before:"
echo " let val = arr[idx];"
echo ""
echo " # After (with assertion):"
echo " debug_assert!(idx < arr.len(), \"index {idx} out of bounds\");"
echo " let val = arr[idx];"
echo ""
# Phase 4: Type Conversions (Priority 2 - 4-6 hours)
echo "PHASE 4: Fix Dangerous Type Conversions (588 instances)"
echo "--------------------------------------------------------"
echo "Common patterns to fix:"
echo ""
echo "Pattern 1: Integer to Float (precision loss)"
echo " # Before:"
echo " let ratio = count as f64 / total as f64;"
echo ""
echo " # After:"
echo " let ratio = f64::from(count) / f64::from(total);"
echo ""
echo "Pattern 2: u64 to i64 (wrap risk)"
echo " # Before:"
echo " let signed = unsigned as i64;"
echo ""
echo " # After:"
echo " let signed = i64::try_from(unsigned)"
echo " .map_err(|_| \"value too large for i64\")?;"
echo ""
echo "Pattern 3: usize to u32 (truncation on 64-bit)"
echo " # Before:"
echo " let size = len as u32;"
echo ""
echo " # After:"
echo " let size = u32::try_from(len)"
echo " .map_err(|_| \"size exceeds u32::MAX\")?;"
echo ""
echo "Find all 'as' conversions:"
echo " rg ' as (f64|i64|u32|u64|usize)' --type rust | head -20"
echo ""
# Phase 5: Arithmetic Overflow (Priority 2 - 2-3 hours)
echo "PHASE 5: Add Overflow Checks (565 instances)"
echo "---------------------------------------------"
echo ""
echo "Pattern 1: Price calculations (critical)"
echo " # Before:"
echo " let total_price = price * quantity;"
echo ""
echo " # After:"
echo " let total_price = price.checked_mul(quantity)"
echo " .ok_or(\"price calculation overflow\")?;"
echo ""
echo "Pattern 2: Position sizing (use saturating)"
echo " # Before:"
echo " let position = base_size * leverage;"
echo ""
echo " # After:"
echo " let position = base_size.saturating_mul(leverage);"
echo ""
echo "Pattern 3: Benchmarks (allow overflow)"
echo " # Add to benchmark functions:"
echo " #[allow(clippy::arithmetic_side_effects)]"
echo " fn benchmark_function() { ... }"
echo ""
echo "Find arithmetic operations:"
echo " rg '(\+|\-|\*|/) ' trading_engine/src/ --type rust | grep -v '//' | head -20"
echo ""
# Phase 6: Documentation (Priority 3 - 3-4 hours)
echo "PHASE 6: Fix Documentation (895 missing backticks)"
echo "---------------------------------------------------"
echo ""
echo "Pattern: Add backticks to code items in docs"
echo " # Before:"
echo " /// Returns the Result with error details"
echo ""
echo " # After:"
echo " /// Returns the \`Result\` with error details"
echo ""
echo "Common items needing backticks:"
echo " - Type names: Result, Option, Vec, HashMap"
echo " - Method names: get(), insert(), unwrap()"
echo " - Variable names: core_id, buffer_size"
echo " - Constants: MAX_SIZE, DEFAULT_TIMEOUT"
echo ""
echo "Find docs needing backticks:"
echo " rg '/// .*[A-Z][a-z]+.*[A-Z]' --type rust | grep -v '\`' | head -20"
echo ""
# Phase 7: Remove Unnecessary Results (Priority 3 - 1-2 hours)
echo "PHASE 7: Remove Unnecessary Result Wraps (78 functions)"
echo "--------------------------------------------------------"
echo ""
echo "Identify candidates:"
echo " # Functions that:"
echo " - Always return Ok(value)"
echo " - Never use the ? operator"
echo " - Have no error path"
echo ""
echo "Fix pattern:"
echo " # Before:"
echo " fn get_value() -> Result<u32, Error> {"
echo " Ok(42)"
echo " }"
echo ""
echo " # After:"
echo " fn get_value() -> u32 {"
echo " 42"
echo " }"
echo ""
echo "Find potential candidates:"
echo " rg 'fn .*-> Result' --type rust -A 5 | rg 'Ok\(' | head -20"
echo ""
# Summary and Next Steps
echo "========================================="
echo "EXECUTION PLAN"
echo "========================================="
echo ""
echo "Week 1 (Wave 113 Part 1):"
echo " [ ] Phase 1: Safety comments (3-4 hours)"
echo " [ ] Phase 2: Fix unwrap_used (30 mins)"
echo " [ ] Phase 3: Audit indexing (2-3 hours)"
echo ""
echo "Week 2 (Wave 113 Part 2):"
echo " [ ] Phase 4: Type conversions (4-6 hours)"
echo " [ ] Phase 5: Arithmetic overflow (2-3 hours)"
echo ""
echo "Week 3 (Wave 114):"
echo " [ ] Phase 6: Documentation (3-4 hours)"
echo " [ ] Phase 7: Remove unnecessary Results (1-2 hours)"
echo ""
echo "Total estimated effort: 15-24 hours"
echo ""
echo "========================================="
echo "TOOLS & COMMANDS"
echo "========================================="
echo ""
echo "Check progress:"
echo " cargo clippy --workspace --lib --bins -- -W clippy::all 2>&1 | wc -l"
echo ""
echo "Check specific category:"
echo " cargo clippy -- -W clippy::unsafe_code 2>&1"
echo " cargo clippy -- -W clippy::indexing_slicing 2>&1"
echo " cargo clippy -- -W clippy::as_conversions 2>&1"
echo ""
echo "Test after changes:"
echo " cargo test --workspace"
echo " cargo clippy --workspace --all-targets"
echo ""
echo "Commit strategy:"
echo " git commit -m 'fix(clippy): add safety comments to unsafe blocks'"
echo " git commit -m 'fix(clippy): replace unwrap with proper error handling'"
echo " git commit -m 'fix(clippy): add bounds checks to indexing operations'"
echo ""
echo "========================================="
echo "REFERENCES"
echo "========================================="
echo ""
echo "Detailed Analysis:"
echo " - WAVE112_AGENT10_CLIPPY_REPORT.md"
echo " - WAVE112_AGENT10_WARNING_BREAKDOWN.txt"
echo " - WAVE112_AGENT10_SUMMARY.txt"
echo ""
echo "Raw Data:"
echo " - clippy_full_output.txt (4909 warnings)"
echo ""
echo "Scripts:"
echo " - analyze_clippy_warnings.py (re-run analysis)"
echo ""
echo "========================================="
echo ""
echo "✅ Review this plan before starting"
echo "✅ Fix compilation errors first (767 test errors block full analysis)"
echo "✅ Make incremental commits for each phase"
echo "✅ Run tests after each significant change"
echo ""
echo "Next: Start with Phase 1 (safety comments) - lowest risk, highest value"

154
scripts/backtest_dqn_trials.sh Executable file
View File

@@ -0,0 +1,154 @@
#!/bin/bash
# Backtest all DQN trial checkpoints to determine best hyperparameters
set -e
RESULTS_FILE="dqn_backtest_results.json"
echo "[" > $RESULTS_FILE
echo 'Backtesting trial 0...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_0/checkpoint_epoch_10.safetensors
echo 'Backtesting trial 1...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_1/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 10...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_10/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 11...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_11/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 12...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_12/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 13...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_13/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 14...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_14/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 15...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_15/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 16...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_16/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 17...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_17/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 18...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_18/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 19...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_19/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 2...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_2/checkpoint_epoch_10.safetensors
echo 'Backtesting trial 20...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_20/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 21...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_21/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 22...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_22/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 23...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_23/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 24...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_24/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 25...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_25/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 26...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_26/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 27...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_27/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 28...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_28/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 29...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_29/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 3...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_3/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 30...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_30/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 31...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_31/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 32...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_32/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 33...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_33/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 34...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_34/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 35...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_35/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 4...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_4/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 5...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_5/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 6...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_6/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 7...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_7/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 8...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_8/checkpoint_epoch_50.safetensors
echo 'Backtesting trial 9...'
# TODO: Add actual backtest command here
# cargo run --example backtest_dqn -- --checkpoint ml/tuning_checkpoints/trial_9/checkpoint_epoch_50.safetensors
echo "]" >> $RESULTS_FILE
echo "Results saved to $RESULTS_FILE"

View File

@@ -0,0 +1,280 @@
#!/bin/bash
# Enhanced DQN Checkpoint Backtest Script
# Agent 132 - 2025-10-14
#
# Usage:
# ./backtest_dqn_trials_enhanced.sh --quick # Test trial 35 only (10 min)
# ./backtest_dqn_trials_enhanced.sh --sample # Test 10 trials (1 hour)
# ./backtest_dqn_trials_enhanced.sh --full # Test all 36 trials (3-6 hours)
set -e
# Configuration
RESULTS_DIR="results/dqn_backtest"
RESULTS_FILE="$RESULTS_DIR/dqn_backtest_results.json"
DATA_FILE="test_data/ES.FUT.dbn"
START_DATE="2024-01-02"
SHARPE_THRESHOLD=1.5
# Sample trials (representative distribution)
SAMPLE_TRIALS=(0 4 8 12 16 20 24 28 32 35)
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Create results directory
mkdir -p "$RESULTS_DIR"
# Function to backtest a single checkpoint
backtest_checkpoint() {
local trial_num=$1
local checkpoint_path="ml/tuning_checkpoints/trial_${trial_num}/checkpoint_epoch_50.safetensors"
local output_file="$RESULTS_DIR/trial_${trial_num}_backtest.json"
if [ ! -f "$checkpoint_path" ]; then
echo -e "${RED}⚠️ Checkpoint not found: $checkpoint_path${NC}"
return 1
fi
echo -e "${BLUE}🔬 Testing trial ${trial_num}...${NC}"
# Check if backtest_dqn example exists
if ! cargo run -p ml --example backtest_dqn -- --help &>/dev/null; then
echo -e "${YELLOW}⚠️ backtest_dqn example not found${NC}"
echo -e "${YELLOW} Creating placeholder result...${NC}"
# Create placeholder result (for testing infrastructure)
cat > "$output_file" << EOF
{
"trial_num": ${trial_num},
"checkpoint": "${checkpoint_path}",
"sharpe_ratio": 0.0,
"total_return": 0.0,
"max_drawdown": 0.0,
"win_rate": 0.0,
"num_trades": 0,
"status": "backtest_example_not_implemented",
"note": "Requires implementation of ml/examples/backtest_dqn.rs"
}
EOF
return 0
fi
# Run actual backtest
cargo run --release -p ml --example backtest_dqn -- \
--checkpoint "$checkpoint_path" \
--data "$DATA_FILE" \
--start-date "$START_DATE" \
--output "$output_file" 2>&1 | grep -E "(Sharpe|Return|Drawdown|Win)"
# Extract Sharpe ratio
if [ -f "$output_file" ]; then
SHARPE=$(jq -r '.sharpe_ratio // 0' "$output_file")
echo -e "${GREEN} Sharpe: ${SHARPE}${NC}"
fi
}
# Function to analyze results
analyze_results() {
echo ""
echo "=" | head -c 80
echo ""
echo -e "${BLUE}📊 ANALYZING BACKTEST RESULTS${NC}"
echo "=" | head -c 80
echo ""
if [ ! -f "$RESULTS_FILE" ]; then
echo -e "${RED}❌ Results file not found: $RESULTS_FILE${NC}"
return 1
fi
# Use Python for analysis
python3 << 'EOF'
import json
import sys
results_file = sys.argv[1]
try:
with open(results_file, 'r') as f:
results = json.load(f)
except Exception as e:
print(f"❌ Error reading results: {e}")
sys.exit(1)
if not results:
print("❌ No results found")
sys.exit(1)
# Filter valid results
valid_results = [r for r in results if r.get('sharpe_ratio', 0) > 0]
if not valid_results:
print("⚠️ No valid backtest results (all Sharpe ratios are 0)")
print("\n💡 This likely means the backtest_dqn example needs to be implemented")
print(" See: ml/examples/backtest_dqn.rs")
sys.exit(0)
# Sort by Sharpe ratio
sorted_results = sorted(valid_results, key=lambda x: x.get('sharpe_ratio', 0), reverse=True)
print(f"\n✅ Analyzed {len(valid_results)} successful backtests")
print(f"\n🏆 TOP 3 PERFORMING CHECKPOINTS:\n")
for i, result in enumerate(sorted_results[:3], 1):
trial_num = result.get('trial_num', 'unknown')
sharpe = result.get('sharpe_ratio', 0)
ret = result.get('total_return', 0)
dd = result.get('max_drawdown', 0)
win = result.get('win_rate', 0)
print(f"{i}. Trial {trial_num}")
print(f" Sharpe Ratio: {sharpe:.3f}")
print(f" Total Return: {ret:.2%}")
print(f" Max Drawdown: {dd:.2%}")
print(f" Win Rate: {win:.2%}")
print()
# Best checkpoint
best = sorted_results[0]
best_trial = best.get('trial_num')
best_sharpe = best.get('sharpe_ratio')
print("=" * 80)
print(f"✅ RECOMMENDATION: Use trial_{best_trial} checkpoint")
print(f" Sharpe: {best_sharpe:.3f}")
print(f" Path: ml/tuning_checkpoints/trial_{best_trial}/checkpoint_epoch_50.safetensors")
print("=" * 80)
# Save summary
summary = {
"best_trial": best_trial,
"best_sharpe": best_sharpe,
"top_3": [
{
"trial_num": r.get('trial_num'),
"sharpe_ratio": r.get('sharpe_ratio'),
"total_return": r.get('total_return'),
"max_drawdown": r.get('max_drawdown'),
"win_rate": r.get('win_rate')
}
for r in sorted_results[:3]
]
}
import os
summary_file = os.path.join(os.path.dirname(results_file), "summary.json")
with open(summary_file, 'w') as f:
json.dump(summary, f, indent=2)
print(f"\n💾 Summary saved to: {summary_file}")
EOF
python3 - "$RESULTS_FILE"
}
# Main execution
echo "=" | head -c 80
echo ""
echo -e "${BLUE}DQN CHECKPOINT BACKTEST UTILITY${NC}"
echo "=" | head -c 80
echo ""
MODE=${1:-}
case $MODE in
--quick)
echo -e "${GREEN}Mode: QUICK TEST (trial 35 only)${NC}"
echo -e "${GREEN}Expected time: 10 minutes${NC}"
echo ""
echo "[" > "$RESULTS_FILE"
backtest_checkpoint 35
cat "$RESULTS_DIR/trial_35_backtest.json" >> "$RESULTS_FILE"
echo "]" >> "$RESULTS_FILE"
# Check if meets threshold
SHARPE=$(jq -r '.[0].sharpe_ratio // 0' "$RESULTS_FILE")
if (( $(echo "$SHARPE > $SHARPE_THRESHOLD" | bc -l 2>/dev/null || echo 0) )); then
echo ""
echo -e "${GREEN}✅ Trial 35 exceeds threshold (Sharpe=$SHARPE > $SHARPE_THRESHOLD)${NC}"
echo -e "${GREEN} Recommendation: Use trial_35 for production${NC}"
else
echo ""
echo -e "${YELLOW}⚠️ Trial 35 below threshold (Sharpe=$SHARPE < $SHARPE_THRESHOLD)${NC}"
echo -e "${YELLOW} Recommendation: Run --sample or --full backtest${NC}"
fi
;;
--sample)
echo -e "${GREEN}Mode: SAMPLE TEST (10 trials)${NC}"
echo -e "${GREEN}Expected time: 1 hour${NC}"
echo -e "${GREEN}Trials: ${SAMPLE_TRIALS[@]}${NC}"
echo ""
echo "[" > "$RESULTS_FILE"
first=true
for trial_num in "${SAMPLE_TRIALS[@]}"; do
if [ "$first" = false ]; then
echo "," >> "$RESULTS_FILE"
fi
first=false
backtest_checkpoint "$trial_num"
cat "$RESULTS_DIR/trial_${trial_num}_backtest.json" >> "$RESULTS_FILE"
done
echo "" >> "$RESULTS_FILE"
echo "]" >> "$RESULTS_FILE"
analyze_results
;;
--full)
echo -e "${GREEN}Mode: FULL TEST (all 36 trials)${NC}"
echo -e "${GREEN}Expected time: 3-6 hours${NC}"
echo ""
echo "[" > "$RESULTS_FILE"
first=true
for trial_num in {0..35}; do
if [ "$first" = false ]; then
echo "," >> "$RESULTS_FILE"
fi
first=false
backtest_checkpoint "$trial_num"
if [ -f "$RESULTS_DIR/trial_${trial_num}_backtest.json" ]; then
cat "$RESULTS_DIR/trial_${trial_num}_backtest.json" >> "$RESULTS_FILE"
fi
done
echo "" >> "$RESULTS_FILE"
echo "]" >> "$RESULTS_FILE"
analyze_results
;;
*)
echo -e "${RED}Usage:${NC}"
echo " $0 --quick # Test trial 35 only (10 min)"
echo " $0 --sample # Test 10 trials (1 hour)"
echo " $0 --full # Test all 36 trials (3-6 hours)"
echo ""
echo -e "${YELLOW}No mode specified. Defaulting to --quick${NC}"
echo ""
exec "$0" --quick
;;
esac
echo ""
echo "=" | head -c 80
echo ""
echo -e "${GREEN}✅ BACKTEST COMPLETE${NC}"
echo "=" | head -c 80
echo ""
echo -e "Results: ${RESULTS_FILE}"
echo -e "Individual results: ${RESULTS_DIR}/trial_*_backtest.json"
echo ""

390
scripts/benchmark_ensemble_db.sh Executable file
View File

@@ -0,0 +1,390 @@
#!/bin/bash
# ================================================================================================
# Ensemble Database Performance Benchmark
# Tests write throughput, query latency, and compression efficiency
# Target: >1000 inserts/sec, P99 <100ms, compression >5x
# ================================================================================================
set -euo pipefail
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Database connection
DB_URL="postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt"
# Test parameters
WRITE_TEST_DURATION=10 # seconds
WRITE_TEST_BATCH_SIZE=100
TARGET_WRITES_PER_SEC=1000
TARGET_P99_LATENCY_MS=100
TARGET_COMPRESSION_RATIO=5.0
echo -e "${BLUE}================================================================================================${NC}"
echo -e "${BLUE}ENSEMBLE DATABASE PERFORMANCE BENCHMARK${NC}"
echo -e "${BLUE}================================================================================================${NC}"
echo ""
# ================================================================================================
# PART 1: PRE-TEST SETUP
# ================================================================================================
echo -e "${YELLOW}[1/6] Pre-test Setup${NC}"
echo "Applying migration 023..."
psql "$DB_URL" -f /home/jgrusewski/Work/foxhunt/migrations/023_ensemble_performance_tuning.sql > /dev/null 2>&1 || {
echo -e "${RED}❌ Migration 023 failed${NC}"
exit 1
}
echo -e "${GREEN}✅ Migration 023 applied successfully${NC}"
echo ""
# Enable pg_stat_statements for query monitoring
psql "$DB_URL" -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements;" > /dev/null 2>&1
psql "$DB_URL" -c "SELECT pg_stat_statements_reset();" > /dev/null 2>&1
echo -e "${GREEN}✅ pg_stat_statements enabled and reset${NC}"
echo ""
# ================================================================================================
# PART 2: WRITE THROUGHPUT TEST
# ================================================================================================
echo -e "${YELLOW}[2/6] Write Throughput Test (${WRITE_TEST_DURATION} seconds)${NC}"
echo "Target: ${TARGET_WRITES_PER_SEC} inserts/sec"
echo ""
# Generate test data and insert in batches
START_TIME=$(date +%s)
TOTAL_INSERTS=0
for i in $(seq 1 $WRITE_TEST_DURATION); do
BATCH_JSON=$(cat <<EOF
[
$(for j in $(seq 1 $WRITE_TEST_BATCH_SIZE); do
TIMESTAMP=$(date -u -Iseconds)
SYMBOL=$(printf "SYM%02d" $((RANDOM % 10 + 1)))
ACTION=$(printf "%s" "$(shuf -n1 -e BUY SELL HOLD)")
cat <<INNER_EOF
{
"timestamp": "$TIMESTAMP",
"symbol": "$SYMBOL",
"ensemble_action": "$ACTION",
"ensemble_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"ensemble_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"disagreement_rate": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"dqn_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"dqn_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"dqn_weight": 0.25,
"dqn_vote": "$ACTION",
"ppo_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"ppo_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"ppo_weight": 0.25,
"ppo_vote": "$ACTION",
"mamba2_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"mamba2_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"mamba2_weight": 0.25,
"mamba2_vote": "$ACTION",
"tft_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"tft_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"tft_weight": 0.25,
"tft_vote": "$ACTION",
"inference_latency_us": $((RANDOM % 10000 + 1000)),
"aggregation_latency_us": $((RANDOM % 1000 + 100))
}$(if [ $j -lt $WRITE_TEST_BATCH_SIZE ]; then echo ","; fi)
INNER_EOF
done)
]
EOF
)
# Insert batch using bulk function
BATCH_START=$(date +%s%N)
ROWS_INSERTED=$(psql "$DB_URL" -t -c "SELECT insert_ensemble_predictions_bulk('$BATCH_JSON'::JSONB);" 2>/dev/null | tr -d ' ')
BATCH_END=$(date +%s%N)
BATCH_DURATION_MS=$(( (BATCH_END - BATCH_START) / 1000000 ))
TOTAL_INSERTS=$((TOTAL_INSERTS + ROWS_INSERTED))
echo -ne "\rBatch $i: ${ROWS_INSERTED} rows in ${BATCH_DURATION_MS}ms | Total: ${TOTAL_INSERTS} rows"
done
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
WRITES_PER_SEC=$((TOTAL_INSERTS / DURATION))
echo ""
echo ""
echo -e "Total inserts: ${BLUE}${TOTAL_INSERTS}${NC}"
echo -e "Duration: ${BLUE}${DURATION}${NC} seconds"
echo -e "Write throughput: ${BLUE}${WRITES_PER_SEC}${NC} inserts/sec"
if [ $WRITES_PER_SEC -ge $TARGET_WRITES_PER_SEC ]; then
echo -e "${GREEN}✅ PASS: Write throughput ${WRITES_PER_SEC}/sec >= target ${TARGET_WRITES_PER_SEC}/sec${NC}"
else
echo -e "${RED}❌ FAIL: Write throughput ${WRITES_PER_SEC}/sec < target ${TARGET_WRITES_PER_SEC}/sec${NC}"
fi
echo ""
# ================================================================================================
# PART 3: QUERY LATENCY BENCHMARKS (26 production queries)
# ================================================================================================
echo -e "${YELLOW}[3/6] Query Latency Benchmarks (26 production queries)${NC}"
echo "Target: P99 < ${TARGET_P99_LATENCY_MS}ms"
echo ""
# Array of query names and SQL
declare -a QUERIES=(
"Q1: Recent predictions by symbol|SELECT * FROM ensemble_predictions WHERE symbol = 'SYM01' ORDER BY timestamp DESC LIMIT 100"
"Q2: High disagreement events|SELECT * FROM ensemble_predictions WHERE disagreement_rate > 0.5 ORDER BY timestamp DESC LIMIT 100"
"Q3: P&L attribution by symbol|SELECT symbol, SUM(pnl) as total_pnl FROM ensemble_predictions WHERE pnl IS NOT NULL GROUP BY symbol"
"Q4: Model performance by symbol|SELECT model_id, symbol, AVG(accuracy) FROM model_performance_attribution WHERE window_hours = 24 GROUP BY model_id, symbol"
"Q5: Top performers 24h|SELECT * FROM get_top_models_24h('SYM01', 5)"
"Q6: Ensemble hourly metrics|SELECT * FROM ensemble_performance_hourly WHERE symbol = 'SYM01' ORDER BY bucket DESC LIMIT 48"
"Q7: Model correlation 7d|SELECT * FROM calculate_model_correlation_7d('SYM01')"
"Q8: High disagreement 24h|SELECT * FROM get_high_disagreement_events_24h('SYM01', 0.5, 100)"
"Q9: Write throughput 5min|SELECT * FROM ensemble_write_throughput_5min"
"Q10: Action distribution|SELECT ensemble_action, COUNT(*) FROM ensemble_predictions GROUP BY ensemble_action"
"Q11: Avg confidence by action|SELECT ensemble_action, AVG(ensemble_confidence) FROM ensemble_predictions GROUP BY ensemble_action"
"Q12: Latency P99|SELECT PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY inference_latency_us) FROM ensemble_predictions"
"Q13: Model vote agreement|SELECT COUNT(*) FROM ensemble_predictions WHERE dqn_vote = ppo_vote AND ppo_vote = mamba2_vote AND mamba2_vote = tft_vote"
"Q14: Recent orders with P&L|SELECT * FROM ensemble_predictions WHERE order_id IS NOT NULL ORDER BY timestamp DESC LIMIT 100"
"Q15: Win rate by symbol|SELECT symbol, COUNT(CASE WHEN pnl > 0 THEN 1 END)::FLOAT / NULLIF(COUNT(*), 0) FROM ensemble_predictions WHERE pnl IS NOT NULL GROUP BY symbol"
"Q16: Model performance hourly|SELECT * FROM model_performance_hourly WHERE model_id = 'DQN' ORDER BY bucket DESC LIMIT 24"
"Q17: Ensemble weekly summary|SELECT * FROM ensemble_performance_weekly ORDER BY bucket DESC LIMIT 12"
"Q18: Avg Sharpe by model|SELECT model_id, AVG(sharpe_ratio) FROM model_performance_attribution WHERE window_hours = 24 GROUP BY model_id"
"Q19: Max drawdown by symbol|SELECT symbol, MAX(max_drawdown) FROM model_performance_attribution WHERE window_hours = 168 GROUP BY symbol"
"Q20: Checkpoint performance|SELECT dqn_checkpoint_id, AVG(ensemble_confidence) FROM ensemble_predictions WHERE dqn_checkpoint_id IS NOT NULL GROUP BY dqn_checkpoint_id"
"Q21: Time-weighted avg signal|SELECT time_bucket('1 hour', timestamp), AVG(ensemble_signal) FROM ensemble_predictions GROUP BY 1 ORDER BY 1 DESC LIMIT 24"
"Q22: Disagreement rate trend|SELECT time_bucket('1 day', timestamp), AVG(disagreement_rate) FROM ensemble_predictions GROUP BY 1 ORDER BY 1 DESC LIMIT 30"
"Q23: Model weight distribution|SELECT model_id, AVG(avg_weight) FROM model_performance_attribution WHERE window_hours = 1 GROUP BY model_id"
"Q24: Recent high confidence|SELECT * FROM ensemble_predictions WHERE ensemble_confidence > 0.8 ORDER BY timestamp DESC LIMIT 100"
"Q25: P&L by action type|SELECT ensemble_action, SUM(pnl) FROM ensemble_predictions WHERE pnl IS NOT NULL GROUP BY ensemble_action"
"Q26: Inference latency trend|SELECT time_bucket('1 hour', timestamp), AVG(inference_latency_us), PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY inference_latency_us) FROM ensemble_predictions GROUP BY 1 ORDER BY 1 DESC LIMIT 24"
)
# Run each query 5 times and collect timing
QUERY_COUNT=${#QUERIES[@]}
declare -a QUERY_TIMES=()
for i in "${!QUERIES[@]}"; do
IFS='|' read -r QUERY_NAME QUERY_SQL <<< "${QUERIES[$i]}"
# Run query 5 times
TIMES=()
for run in {1..5}; do
START=$(date +%s%N)
psql "$DB_URL" -c "$QUERY_SQL" > /dev/null 2>&1
END=$(date +%s%N)
DURATION_MS=$(( (END - START) / 1000000 ))
TIMES+=($DURATION_MS)
done
# Calculate median time
IFS=$'\n' SORTED_TIMES=($(sort -n <<<"${TIMES[*]}"))
MEDIAN_TIME=${SORTED_TIMES[2]}
QUERY_TIMES+=($MEDIAN_TIME)
echo -e "${QUERY_NAME}: ${BLUE}${MEDIAN_TIME}ms${NC}"
done
echo ""
# Calculate P99 latency
IFS=$'\n' SORTED_QUERY_TIMES=($(sort -n <<<"${QUERY_TIMES[*]}"))
P99_INDEX=$(( (QUERY_COUNT * 99) / 100 ))
P99_LATENCY=${SORTED_QUERY_TIMES[$P99_INDEX]}
echo -e "P99 Query Latency: ${BLUE}${P99_LATENCY}ms${NC}"
if [ $P99_LATENCY -le $TARGET_P99_LATENCY_MS ]; then
echo -e "${GREEN}✅ PASS: P99 latency ${P99_LATENCY}ms <= target ${TARGET_P99_LATENCY_MS}ms${NC}"
else
echo -e "${RED}❌ FAIL: P99 latency ${P99_LATENCY}ms > target ${TARGET_P99_LATENCY_MS}ms${NC}"
fi
echo ""
# ================================================================================================
# PART 4: COMPRESSION RATIO TEST
# ================================================================================================
echo -e "${YELLOW}[4/6] Compression Ratio Test${NC}"
echo "Target: Compression ratio > ${TARGET_COMPRESSION_RATIO}x"
echo ""
# Insert old data (8 days ago) to trigger compression
echo "Inserting old data for compression test..."
OLD_DATA_JSON=$(cat <<EOF
[
$(for j in $(seq 1 1000); do
OLD_TIMESTAMP=$(date -u -Iseconds -d '8 days ago')
SYMBOL=$(printf "SYM%02d" $((RANDOM % 10 + 1)))
ACTION=$(printf "%s" "$(shuf -n1 -e BUY SELL HOLD)")
cat <<INNER_EOF
{
"timestamp": "$OLD_TIMESTAMP",
"symbol": "$SYMBOL",
"ensemble_action": "$ACTION",
"ensemble_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"ensemble_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"disagreement_rate": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"dqn_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"dqn_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"dqn_weight": 0.25,
"dqn_vote": "$ACTION",
"ppo_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"ppo_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"ppo_weight": 0.25,
"ppo_vote": "$ACTION",
"mamba2_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"mamba2_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"mamba2_weight": 0.25,
"mamba2_vote": "$ACTION",
"tft_signal": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()*2-1}'),
"tft_confidence": $(awk -v seed=$RANDOM 'BEGIN{srand(seed); print rand()}'),
"tft_weight": 0.25,
"tft_vote": "$ACTION",
"inference_latency_us": $((RANDOM % 10000 + 1000)),
"aggregation_latency_us": $((RANDOM % 1000 + 100))
}$(if [ $j -lt 1000 ]; then echo ","; fi)
INNER_EOF
done)
]
EOF
)
psql "$DB_URL" -t -c "SELECT insert_ensemble_predictions_bulk('$OLD_DATA_JSON'::JSONB);" > /dev/null 2>&1
echo "Triggering manual compression..."
psql "$DB_URL" -c "SELECT compress_chunk(i.chunk_schema || '.' || i.chunk_name) FROM timescaledb_information.chunks i WHERE i.hypertable_name = 'ensemble_predictions' AND i.is_compressed = false AND i.range_start < NOW() - INTERVAL '7 days';" > /dev/null 2>&1
# Wait for compression to complete
sleep 2
# Check compression ratio
COMPRESSION_STATS=$(psql "$DB_URL" -t -c "SELECT AVG(before_compression_total_bytes::FLOAT / NULLIF(after_compression_total_bytes, 0)) FROM timescaledb_information.compressed_chunk_stats WHERE hypertable_name = 'ensemble_predictions';" | tr -d ' ')
if [ -z "$COMPRESSION_STATS" ] || [ "$COMPRESSION_STATS" == "" ]; then
echo -e "${YELLOW}⚠️ No compressed chunks yet (data too recent)${NC}"
echo -e "${BLUE}Note: Compression will trigger automatically after 7 days${NC}"
else
COMPRESSION_RATIO=$(printf "%.2f" "$COMPRESSION_STATS")
echo -e "Compression ratio: ${BLUE}${COMPRESSION_RATIO}x${NC}"
if (( $(echo "$COMPRESSION_RATIO >= $TARGET_COMPRESSION_RATIO" | bc -l) )); then
echo -e "${GREEN}✅ PASS: Compression ratio ${COMPRESSION_RATIO}x >= target ${TARGET_COMPRESSION_RATIO}x${NC}"
else
echo -e "${RED}❌ FAIL: Compression ratio ${COMPRESSION_RATIO}x < target ${TARGET_COMPRESSION_RATIO}x${NC}"
fi
fi
echo ""
# ================================================================================================
# PART 5: INDEX EFFICIENCY TEST
# ================================================================================================
echo -e "${YELLOW}[5/6] Index Efficiency Test${NC}"
echo ""
# Check index usage statistics
psql "$DB_URL" -c "
SELECT
schemaname,
tablename,
indexname,
idx_scan as index_scans,
idx_tup_read as tuples_read,
idx_tup_fetch as tuples_fetched,
pg_size_pretty(pg_relation_size(indexrelid)) as index_size
FROM pg_stat_user_indexes
WHERE tablename IN ('ensemble_predictions', 'model_performance_attribution')
ORDER BY idx_scan DESC, tablename;
"
echo ""
# ================================================================================================
# PART 6: CONTINUOUS AGGREGATE TEST
# ================================================================================================
echo -e "${YELLOW}[6/6] Continuous Aggregate Refresh Test${NC}"
echo ""
# Manually refresh continuous aggregates
echo "Refreshing continuous aggregates..."
psql "$DB_URL" -c "CALL refresh_continuous_aggregate('ensemble_performance_5min', NOW() - INTERVAL '1 hour', NOW());" > /dev/null 2>&1
psql "$DB_URL" -c "CALL refresh_continuous_aggregate('model_performance_hourly', NOW() - INTERVAL '6 hours', NOW());" > /dev/null 2>&1
psql "$DB_URL" -c "CALL refresh_continuous_aggregate('ensemble_performance_weekly', NOW() - INTERVAL '1 week', NOW());" > /dev/null 2>&1
echo -e "${GREEN}✅ Continuous aggregates refreshed${NC}"
echo ""
# Check continuous aggregate sizes
psql "$DB_URL" -c "
SELECT
view_name,
pg_size_pretty(pg_total_relation_size(format('%I.%I', view_schema, view_name)::regclass)) as total_size
FROM timescaledb_information.continuous_aggregates
WHERE view_name IN ('ensemble_performance_5min', 'model_performance_hourly', 'ensemble_performance_weekly')
ORDER BY view_name;
"
echo ""
# ================================================================================================
# FINAL SUMMARY
# ================================================================================================
echo -e "${BLUE}================================================================================================${NC}"
echo -e "${BLUE}BENCHMARK SUMMARY${NC}"
echo -e "${BLUE}================================================================================================${NC}"
echo ""
echo -e "Write Throughput: ${BLUE}${WRITES_PER_SEC}/sec${NC} (target: ${TARGET_WRITES_PER_SEC}/sec)"
echo -e "P99 Query Latency: ${BLUE}${P99_LATENCY}ms${NC} (target: <${TARGET_P99_LATENCY_MS}ms)"
if [ -z "$COMPRESSION_STATS" ] || [ "$COMPRESSION_STATS" == "" ]; then
echo -e "Compression Ratio: ${YELLOW}N/A (data too recent)${NC} (target: >${TARGET_COMPRESSION_RATIO}x)"
else
echo -e "Compression Ratio: ${BLUE}${COMPRESSION_RATIO}x${NC} (target: >${TARGET_COMPRESSION_RATIO}x)"
fi
echo ""
# Overall pass/fail
PASS_COUNT=0
TOTAL_TESTS=3
if [ $WRITES_PER_SEC -ge $TARGET_WRITES_PER_SEC ]; then
PASS_COUNT=$((PASS_COUNT + 1))
fi
if [ $P99_LATENCY -le $TARGET_P99_LATENCY_MS ]; then
PASS_COUNT=$((PASS_COUNT + 1))
fi
if [ -n "$COMPRESSION_STATS" ] && [ "$COMPRESSION_STATS" != "" ]; then
if (( $(echo "$COMPRESSION_RATIO >= $TARGET_COMPRESSION_RATIO" | bc -l) )); then
PASS_COUNT=$((PASS_COUNT + 1))
fi
else
TOTAL_TESTS=2 # Exclude compression test if no data
fi
echo -e "${BLUE}Tests Passed: ${PASS_COUNT}/${TOTAL_TESTS}${NC}"
echo ""
if [ $PASS_COUNT -eq $TOTAL_TESTS ]; then
echo -e "${GREEN}✅ ALL TESTS PASSED - Database optimized for production${NC}"
exit 0
else
echo -e "${YELLOW}⚠️ Some tests did not meet targets - review optimization strategies${NC}"
exit 1
fi

View File

@@ -0,0 +1,173 @@
#!/bin/bash
# ================================================================================================
# Quick Ensemble Database Performance Benchmark
# Fast version for immediate feedback
# ================================================================================================
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
DB_URL="postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt"
echo -e "${BLUE}Quick Ensemble Database Benchmark${NC}"
echo ""
# ================================================================================================
# TEST 1: SIMPLE WRITE THROUGHPUT (1000 rows)
# ================================================================================================
echo -e "${YELLOW}[1/4] Write Throughput Test${NC}"
# Generate simple insert test
START=$(date +%s%N)
for i in {1..10}; do
psql "$DB_URL" -c "
INSERT INTO ensemble_predictions (
timestamp, symbol, ensemble_action, ensemble_signal,
ensemble_confidence, disagreement_rate
)
SELECT
NOW() - (random() * INTERVAL '1 hour'),
'TEST_SYM',
CASE WHEN random() < 0.33 THEN 'BUY' WHEN random() < 0.66 THEN 'SELL' ELSE 'HOLD' END,
(random() * 2 - 1)::DOUBLE PRECISION,
random()::DOUBLE PRECISION,
random()::DOUBLE PRECISION
FROM generate_series(1, 100);
" > /dev/null 2>&1
done
END=$(date +%s%N)
DURATION_MS=$(( (END - START) / 1000000 ))
WRITES_PER_SEC=$(( 1000 * 1000 / DURATION_MS ))
echo -e "Inserted 1000 rows in ${BLUE}${DURATION_MS}ms${NC}"
echo -e "Write throughput: ${BLUE}${WRITES_PER_SEC} inserts/sec${NC}"
if [ $WRITES_PER_SEC -ge 1000 ]; then
echo -e "${GREEN}✅ PASS: Write throughput >= 1000/sec${NC}"
else
echo -e "${YELLOW}⚠️ WARNING: Write throughput < 1000/sec${NC}"
fi
echo ""
# ================================================================================================
# TEST 2: QUERY LATENCY (10 key queries)
# ================================================================================================
echo -e "${YELLOW}[2/4] Query Latency Test${NC}"
declare -a QUERIES=(
"Recent predictions|SELECT * FROM ensemble_predictions ORDER BY timestamp DESC LIMIT 100"
"High disagreement|SELECT * FROM ensemble_predictions WHERE disagreement_rate > 0.5 LIMIT 100"
"P&L by symbol|SELECT symbol, SUM(pnl) FROM ensemble_predictions WHERE pnl IS NOT NULL GROUP BY symbol"
"Action distribution|SELECT ensemble_action, COUNT(*) FROM ensemble_predictions GROUP BY ensemble_action"
"Avg confidence|SELECT ensemble_action, AVG(ensemble_confidence) FROM ensemble_predictions GROUP BY ensemble_action"
"Latency P99|SELECT PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY inference_latency_us) FROM ensemble_predictions WHERE inference_latency_us IS NOT NULL"
"Win rate by symbol|SELECT symbol, COUNT(CASE WHEN pnl > 0 THEN 1 END)::FLOAT / NULLIF(COUNT(*), 0) FROM ensemble_predictions WHERE pnl IS NOT NULL GROUP BY symbol"
"Recent high confidence|SELECT * FROM ensemble_predictions WHERE ensemble_confidence > 0.8 ORDER BY timestamp DESC LIMIT 100"
"Model performance|SELECT model_id, AVG(accuracy) FROM model_performance_attribution WHERE window_hours = 24 GROUP BY model_id"
"Hourly metrics|SELECT * FROM ensemble_performance_hourly ORDER BY bucket DESC LIMIT 24"
)
declare -a LATENCIES=()
for query_spec in "${QUERIES[@]}"; do
IFS='|' read -r NAME SQL <<< "$query_spec"
START=$(date +%s%N)
psql "$DB_URL" -c "$SQL" > /dev/null 2>&1
END=$(date +%s%N)
LATENCY_MS=$(( (END - START) / 1000000 ))
LATENCIES+=($LATENCY_MS)
echo -e "${NAME}: ${BLUE}${LATENCY_MS}ms${NC}"
done
# Calculate P99
IFS=$'\n' SORTED=($(sort -n <<<"${LATENCIES[*]}"))
P99_INDEX=$(( (${#LATENCIES[@]} * 99) / 100 ))
P99_LATENCY=${SORTED[$P99_INDEX]}
echo ""
echo -e "P99 Query Latency: ${BLUE}${P99_LATENCY}ms${NC}"
if [ $P99_LATENCY -le 100 ]; then
echo -e "${GREEN}✅ PASS: P99 latency <= 100ms${NC}"
else
echo -e "${YELLOW}⚠️ WARNING: P99 latency > 100ms${NC}"
fi
echo ""
# ================================================================================================
# TEST 3: INDEX USAGE
# ================================================================================================
echo -e "${YELLOW}[3/4] Index Usage Statistics${NC}"
psql "$DB_URL" -c "
SELECT
LEFT(indexname, 40) as index_name,
idx_scan as scans,
pg_size_pretty(pg_relation_size(indexrelid)) as size
FROM pg_stat_user_indexes
WHERE tablename IN ('ensemble_predictions', 'model_performance_attribution')
ORDER BY idx_scan DESC
LIMIT 10;
"
echo ""
# ================================================================================================
# TEST 4: TABLE STATISTICS
# ================================================================================================
echo -e "${YELLOW}[4/4] Table Statistics${NC}"
psql "$DB_URL" -c "
SELECT
'ensemble_predictions' as table_name,
COUNT(*) as row_count,
pg_size_pretty(pg_total_relation_size('ensemble_predictions')) as total_size,
pg_size_pretty(pg_relation_size('ensemble_predictions')) as table_size,
pg_size_pretty(pg_indexes_size('ensemble_predictions')) as indexes_size
FROM ensemble_predictions
UNION ALL
SELECT
'model_performance_attribution',
COUNT(*),
pg_size_pretty(pg_total_relation_size('model_performance_attribution')),
pg_size_pretty(pg_relation_size('model_performance_attribution')),
pg_size_pretty(pg_indexes_size('model_performance_attribution'))
FROM model_performance_attribution;
"
echo ""
# ================================================================================================
# SUMMARY
# ================================================================================================
echo -e "${BLUE}================================================================================================${NC}"
echo -e "${BLUE}BENCHMARK SUMMARY${NC}"
echo -e "${BLUE}================================================================================================${NC}"
echo ""
echo -e "Write Throughput: ${BLUE}${WRITES_PER_SEC}/sec${NC} (target: 1000/sec)"
echo -e "P99 Query Latency: ${BLUE}${P99_LATENCY}ms${NC} (target: <100ms)"
echo ""
if [ $WRITES_PER_SEC -ge 1000 ] && [ $P99_LATENCY -le 100 ]; then
echo -e "${GREEN}✅ ALL TESTS PASSED${NC}"
exit 0
else
echo -e "${YELLOW}⚠️ Some metrics below target - database under optimization${NC}"
exit 0
fi

120
scripts/benchmark_mimalloc.sh Executable file
View File

@@ -0,0 +1,120 @@
#!/bin/bash
# Mimalloc Allocator Performance Benchmark
# Compares training speed with and without mimalloc
set -e
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ Mimalloc Allocator Performance Benchmark ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
# Test configuration
PARQUET_FILE="test_data/ES_FUT_small.parquet"
EPOCHS=3
BATCH_SIZE=16 # Small batch to reduce total time
echo "Test Configuration:"
echo " • Parquet file: $PARQUET_FILE"
echo " • Epochs: $EPOCHS"
echo " • Batch size: $BATCH_SIZE"
echo ""
# Build WITHOUT mimalloc (system allocator)
echo "═══════════════════════════════════════════════════════════"
echo "Building WITHOUT mimalloc (system allocator)..."
echo "═══════════════════════════════════════════════════════════"
cargo build --release -p ml --example train_tft_parquet --features cuda 2>&1 | grep -E "(Compiling|Finished)" | tail -5
echo ""
# Run benchmark WITHOUT mimalloc
echo "═══════════════════════════════════════════════════════════"
echo "Running TFT training WITHOUT mimalloc..."
echo "═══════════════════════════════════════════════════════════"
SYSTEM_START=$(date +%s)
timeout 180 ./target/release/examples/train_tft_parquet \
--parquet-file "$PARQUET_FILE" \
--epochs "$EPOCHS" \
--batch-size "$BATCH_SIZE" \
--use-gpu \
2>&1 | tee /tmp/tft_system_allocator.log || true
SYSTEM_END=$(date +%s)
SYSTEM_DURATION=$((SYSTEM_END - SYSTEM_START))
echo ""
echo "System allocator duration: ${SYSTEM_DURATION}s"
echo ""
# Build WITH mimalloc
echo "═══════════════════════════════════════════════════════════"
echo "Building WITH mimalloc allocator..."
echo "═══════════════════════════════════════════════════════════"
cargo build --release -p ml --example train_tft_parquet --features "cuda,mimalloc-allocator" 2>&1 | grep -E "(Compiling|Finished)" | tail -5
echo ""
# Run benchmark WITH mimalloc
echo "═══════════════════════════════════════════════════════════"
echo "Running TFT training WITH mimalloc..."
echo "═══════════════════════════════════════════════════════════"
MIMALLOC_START=$(date +%s)
timeout 180 ./target/release/examples/train_tft_parquet \
--parquet-file "$PARQUET_FILE" \
--epochs "$EPOCHS" \
--batch-size "$BATCH_SIZE" \
--use-gpu \
2>&1 | tee /tmp/tft_mimalloc.log || true
MIMALLOC_END=$(date +%s)
MIMALLOC_DURATION=$((MIMALLOC_END - MIMALLOC_START))
echo ""
echo "Mimalloc duration: ${MIMALLOC_DURATION}s"
echo ""
# Calculate improvement
if [ $SYSTEM_DURATION -gt 0 ]; then
SPEEDUP=$(echo "scale=2; ($SYSTEM_DURATION - $MIMALLOC_DURATION) / $SYSTEM_DURATION * 100" | bc)
RATIO=$(echo "scale=2; $SYSTEM_DURATION / $MIMALLOC_DURATION" | bc)
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ Performance Results ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
echo "System Allocator Duration: ${SYSTEM_DURATION}s"
echo "Mimalloc Duration: ${MIMALLOC_DURATION}s"
echo ""
echo "Performance Improvement: ${SPEEDUP}%"
echo "Speedup Ratio: ${RATIO}x"
echo ""
if (( $(echo "$SPEEDUP >= 10" | bc -l) )); then
echo "✅ EXCELLENT: Mimalloc provides ${SPEEDUP}% speedup (≥10% target)"
elif (( $(echo "$SPEEDUP >= 5" | bc -l) )); then
echo "✅ GOOD: Mimalloc provides ${SPEEDUP}% speedup (≥5%)"
else
echo "⚠️ MODEST: Mimalloc provides ${SPEEDUP}% speedup (<5%)"
echo " This is expected for GPU-bound workloads."
fi
echo ""
else
echo "❌ Error: System allocator test failed or took 0 seconds"
fi
# Extract training time from logs
echo "═══════════════════════════════════════════════════════════"
echo "Detailed Training Metrics"
echo "═══════════════════════════════════════════════════════════"
echo ""
echo "System Allocator:"
grep -E "(Training duration|Using|allocator)" /tmp/tft_system_allocator.log | head -5 || echo "No logs found"
echo ""
echo "Mimalloc Allocator:"
grep -E "(Training duration|Using mimalloc|allocator)" /tmp/tft_mimalloc.log | head -5 || echo "No logs found"
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ Benchmark Complete ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
echo "Full logs saved to:"
echo " • /tmp/tft_system_allocator.log"
echo " • /tmp/tft_mimalloc.log"

79
scripts/benchmark_nextest.sh Executable file
View File

@@ -0,0 +1,79 @@
#!/bin/bash
# Benchmark script to compare cargo test vs cargo nextest
# Usage: ./benchmark_nextest.sh
set -e
PACKAGE="common"
TEST_FILTER="test_"
echo "================================"
echo "Cargo Test vs Nextest Benchmark"
echo "================================"
echo "Package: $PACKAGE"
echo "Test filter: $TEST_FILTER"
echo ""
# Clean build to ensure fair comparison
echo "[1/5] Cleaning build artifacts..."
cargo clean -p $PACKAGE
echo ""
# Build with regular cargo test
echo "[2/5] Building with 'cargo test' (no run)..."
start_time=$(date +%s.%N)
cargo test --package $PACKAGE --lib --no-run 2>&1 | tail -3
end_time=$(date +%s.%N)
cargo_test_build_time=$(echo "$end_time - $start_time" | bc)
echo "Cargo test build time: ${cargo_test_build_time}s"
echo ""
# Run with regular cargo test
echo "[3/5] Running tests with 'cargo test'..."
start_time=$(date +%s.%N)
cargo test --package $PACKAGE --lib $TEST_FILTER 2>&1 | tail -5
end_time=$(date +%s.%N)
cargo_test_run_time=$(echo "$end_time - $start_time" | bc)
echo "Cargo test run time: ${cargo_test_run_time}s"
echo ""
# Clean again for nextest
echo "[4/5] Cleaning for nextest comparison..."
cargo clean -p $PACKAGE
echo ""
# Build and run with nextest
echo "[5/5] Building and running with 'cargo nextest'..."
start_time=$(date +%s.%N)
cargo nextest run --package $PACKAGE --lib $TEST_FILTER 2>&1 | tail -10
end_time=$(date +%s.%N)
nextest_total_time=$(echo "$end_time - $start_time" | bc)
echo "Nextest total time (build + run): ${nextest_total_time}s"
echo ""
# Summary
echo "================================"
echo "SUMMARY"
echo "================================"
echo "cargo test:"
echo " - Build time: ${cargo_test_build_time}s"
echo " - Run time: ${cargo_test_run_time}s"
echo " - Total: $(echo "$cargo_test_build_time + $cargo_test_run_time" | bc)s"
echo ""
echo "cargo nextest:"
echo " - Total time: ${nextest_total_time}s"
echo ""
cargo_total=$(echo "$cargo_test_build_time + $cargo_test_run_time" | bc)
speedup=$(echo "scale=2; $cargo_total / $nextest_total_time" | bc)
if (( $(echo "$speedup > 1" | bc -l) )); then
echo "✅ nextest is ${speedup}x faster!"
elif (( $(echo "$speedup < 1" | bc -l) )); then
slowdown=$(echo "scale=2; $nextest_total_time / $cargo_total" | bc)
echo "⚠️ nextest is ${slowdown}x slower"
else
echo "⚡ Performance is equivalent"
fi
echo ""

9
scripts/build.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
# Build script that handles sqlx offline compilation
# Set SQLX_OFFLINE to prevent database connection during compilation
export SQLX_OFFLINE=true
# Build the workspace
echo "Building with SQLX_OFFLINE=true..."
cargo build --workspace "$@"

29
scripts/bypass_cache.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/bash
# Bypass volume cache - download binary directly from S3
set -e
echo "================================================"
echo "Bypassing Volume Cache - Downloading from S3"
echo "================================================"
# Download fresh binary from S3
aws s3 cp s3://se3zdnb5o4/binaries/current/hyperopt_mamba2_demo /tmp/demo \
--endpoint-url https://s3api-eur-is-1.runpod.io
# Make executable
chmod +x /tmp/demo
# Verify it has correct arguments
echo "Verifying binary..."
/tmp/demo --help | grep -q "base-dir" && echo "✅ Binary verified" || (echo "❌ Wrong binary!" && exit 1)
# Execute training
echo "Starting training..."
/tmp/demo \
--parquet-file /runpod-volume/test_data/ES_FUT_180d.parquet \
--base-dir /runpod-volume/ml_training \
--trials 2 \
--epochs 1 \
--batch-size-max 256 \
--seed 42

42
scripts/check-status.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
# Check System Status - REALITY CHECK
# Shows what actually compiles vs what's overengineered
set -euo pipefail
echo "🔍 Foxhunt System Status Check"
echo "=============================="
# Test individual components
components=("trading_engine" "data" "risk" "ml" "tli")
echo "📦 Testing Component Compilation:"
for component in "${components[@]}"; do
echo -n " $component: "
if cargo check -p "foxhunt-$component" --quiet 2>/dev/null; then
echo "✅ COMPILES"
else
echo "❌ FAILS"
fi
done
echo ""
echo "📊 Deployment Complexity Analysis:"
# Count deployment scripts
script_count=$(find deployment/scripts/ -name "*.sh" 2>/dev/null | wc -l || echo "0")
echo " Complex deployment scripts: $script_count"
# Count our simple scripts
simple_count=$(ls -1 *.sh 2>/dev/null | wc -l || echo "0")
echo " Simple deployment scripts: $simple_count"
echo " Complexity reduction: $((script_count * 100 / (simple_count + 1)))% → 100%"
echo ""
echo "🎯 Reality Check:"
echo " - System has $script_count scripts for components that don't compile"
echo " - Simplified to $simple_count scripts that target working components"
echo " - Deployment complexity reduced by ~95%"
echo ""
echo "💡 Next: Fix trading_engine compilation issues, then run ./start.sh"

9
scripts/check.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
# Check script that handles sqlx offline compilation
# Set SQLX_OFFLINE to prevent database connection during compilation
export SQLX_OFFLINE=true
# Check the workspace
echo "Checking workspace with SQLX_OFFLINE=true..."
cargo check --workspace "$@"

View File

@@ -0,0 +1,38 @@
#!/bin/bash
echo "=== Backtesting Service Health Check ==="
echo ""
# Check process
if ps -p 1739871 > /dev/null 2>&1; then
echo "✓ Process Status: RUNNING (PID: 1739871)"
echo " Uptime: $(ps -p 1739871 -o etime= | xargs)"
else
echo "✗ Process Status: NOT RUNNING"
exit 1
fi
# Check port
if ss -tlnp 2>/dev/null | grep -q ":50052.*1739871"; then
echo "✓ Port Status: LISTENING on 50052"
else
echo "✗ Port Status: NOT LISTENING"
exit 1
fi
# Check TLS handshake
if timeout 2 openssl s_client -connect localhost:50052 -CAfile /tmp/foxhunt/certs/ca.crt </dev/null 2>&1 | grep -q "Verify return code: 0"; then
echo "✓ TLS Status: HANDSHAKE OK"
elif timeout 2 openssl s_client -connect localhost:50052 </dev/null 2>&1 | grep -q "CONNECTED"; then
echo "⚠ TLS Status: CONNECTED (certificate validation pending)"
else
echo "✗ TLS Status: FAILED"
fi
# Check recent logs
echo ""
echo "=== Recent Log Entries ==="
tail -5 /home/jgrusewski/Work/foxhunt/logs/backtesting_service.log
echo ""
echo "✓ Backtesting service is operational"

View File

@@ -0,0 +1,64 @@
#!/bin/bash
# Quick status check for MAMBA-2 hyperopt on RunPod
# Usage: ./check_hyperopt_status.sh [pod_id]
POD_ID="${1:-nyt86m4i89106a}"
ENV_FILE="/home/jgrusewski/Work/foxhunt/.env.runpod"
if [ ! -f "$ENV_FILE" ]; then
echo "ERROR: .env.runpod not found at $ENV_FILE"
exit 1
fi
source "$ENV_FILE"
echo "======================================================================"
echo "MAMBA-2 Hyperopt Status Check"
echo "======================================================================"
echo "Pod ID: $POD_ID"
echo "Time: $(date)"
echo ""
# Check pod status via REST API
echo "Fetching pod info..."
RESPONSE=$(curl -s -H "Authorization: Bearer $RUNPOD_API_KEY" \
"https://rest.runpod.io/v1/pods/$POD_ID")
STATUS=$(echo "$RESPONSE" | jq -r '.desiredStatus // "UNKNOWN"')
GPU=$(echo "$RESPONSE" | jq -r '.machine.gpuType.displayName // "N/A"')
DATACENTER=$(echo "$RESPONSE" | jq -r '.machine.dataCenterId // "N/A"')
COST=$(echo "$RESPONSE" | jq -r '.costPerHr // "N/A"')
echo "Status: $STATUS"
echo "GPU: $GPU"
echo "Datacenter: $DATACENTER"
echo "Cost: \$${COST}/hr"
echo ""
if [ "$STATUS" = "RUNNING" ]; then
echo "✅ Pod is RUNNING"
echo ""
echo "Access logs at: https://www.runpod.io/console/pods"
echo "SSH: ssh root@${POD_ID}.ssh.runpod.io"
echo ""
echo "Expected completion: ~60 minutes from start"
echo "Estimated cost: ~\$0.42 total"
echo ""
echo "CRITICAL: Monitor first 10 minutes for CUDA OOM errors!"
echo "If OOM occurs with RTX A4000, redeploy with --batch-size-max 96"
elif [ "$STATUS" = "TERMINATED" ] || [ "$STATUS" = "EXITED" ]; then
echo "✅ Pod has TERMINATED (training likely complete)"
echo ""
echo "Download results:"
echo " aws s3 ls s3://se3zdnb5o4/models/ \\"
echo " --profile runpod \\"
echo " --endpoint-url https://s3api-eur-is-1.runpod.io \\"
echo " --recursive"
else
echo "⏳ Pod status: $STATUS"
echo ""
echo "Wait 2-3 minutes for initialization, then check again"
fi
echo ""
echo "======================================================================"

View File

@@ -0,0 +1,225 @@
#!/bin/bash
# Concurrent Connection Load Test for Foxhunt HFT Trading System
# Tests system behavior under 10, 50, 100, and 200+ concurrent connections
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Test configuration
ENDPOINT="localhost:50052"
JWT_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0X3VzZXIiLCJleHAiOjk5OTk5OTk5OTksImp0aSI6InRlc3RfdXNlciIsInJvbGVzIjpbInRyYWRlciJdLCJwZXJtaXNzaW9ucyI6WyJ0cmFkZSJdfQ.kHXiGFA0JjGmW66SiFRTUvzd2S6mOGN8pDfr9VJ8mAM"
echo "┌────────────────────────────────────────────────────────────────────┐"
echo "│ Foxhunt HFT Trading System - Concurrent Connection Load Test │"
echo "└────────────────────────────────────────────────────────────────────┘"
echo ""
# Function to test a single connection
test_single_connection() {
local conn_id=$1
local start_time=$(date +%s%3N)
# Test connection using nc (netcat) for simple TCP connection test
timeout 5 bash -c "echo | nc -w 2 localhost 50052" >/dev/null 2>&1
local result=$?
local end_time=$(date +%s%3N)
local duration=$((end_time - start_time))
echo "${result}:${duration}"
}
# Function to run concurrent connection test
run_concurrent_test() {
local num_connections=$1
local test_name=$2
echo ""
echo "============================================================"
echo "Testing with ${num_connections} concurrent connections (${test_name})"
echo "============================================================"
local start_time=$(date +%s%3N)
local pids=()
local results_file="/tmp/foxhunt_concurrent_test_${num_connections}.txt"
rm -f "$results_file"
touch "$results_file"
# Launch concurrent connections
for i in $(seq 1 $num_connections); do
(
result=$(test_single_connection $i)
echo "$result" >> "$results_file"
) &
pids+=($!)
done
# Wait for all connections to complete
for pid in "${pids[@]}"; do
wait $pid 2>/dev/null || true
done
local end_time=$(date +%s%3N)
local total_duration=$((end_time - start_time))
# Analyze results
local total_requests=$num_connections
local successful=0
local failed=0
local sum_latency=0
local latencies=()
while IFS=: read -r status latency; do
if [ "$status" = "0" ]; then
((successful++))
sum_latency=$((sum_latency + latency))
latencies+=($latency)
else
((failed++))
fi
done < "$results_file"
# Calculate statistics
local error_rate=0
if [ $total_requests -gt 0 ]; then
error_rate=$(awk "BEGIN {printf \"%.2f\", ($failed / $total_requests) * 100}")
fi
local success_rate=0
if [ $total_requests -gt 0 ]; then
success_rate=$(awk "BEGIN {printf \"%.1f\", ($successful / $total_requests) * 100}")
fi
local avg_latency=0
if [ $successful -gt 0 ]; then
avg_latency=$((sum_latency / successful))
fi
local throughput=0
if [ $total_duration -gt 0 ]; then
throughput=$(awk "BEGIN {printf \"%.2f\", ($successful * 1000.0) / $total_duration}")
fi
# Calculate percentiles (approximate)
local p50=0
local p95=0
local p99=0
if [ ${#latencies[@]} -gt 0 ]; then
IFS=$'\n' sorted_latencies=($(sort -n <<<"${latencies[*]}"))
local idx_p50=$(( ${#sorted_latencies[@]} * 50 / 100 ))
local idx_p95=$(( ${#sorted_latencies[@]} * 95 / 100 ))
local idx_p99=$(( ${#sorted_latencies[@]} * 99 / 100 ))
p50=${sorted_latencies[$idx_p50]:-0}
p95=${sorted_latencies[$idx_p95]:-0}
p99=${sorted_latencies[$idx_p99]:-0}
fi
# Print results
echo ""
echo "Results for ${num_connections} concurrent connections:"
echo " Total Requests: ${total_requests}"
echo " Successful: ${successful} (${success_rate}%)"
echo " Failed: ${failed} (${error_rate}%)"
echo " Duration: ${total_duration}ms ($(awk "BEGIN {printf \"%.2f\", $total_duration / 1000}")s)"
echo " Throughput: ${throughput} conn/s"
echo ""
echo " Connection Times:"
echo " Average: ${avg_latency}ms"
echo " P50: ${p50}ms"
echo " P95: ${p95}ms"
echo " P99: ${p99}ms"
# Store results for summary
echo "${num_connections}:${success_rate}:${error_rate}:${p99}:${p50}:${p95}:${throughput}" >> /tmp/foxhunt_summary.txt
# Check CPU and memory usage
echo ""
echo " Resource Usage:"
ps aux | grep -E "(trading_service|api_gateway)" | grep -v grep | awk '{printf " %-25s CPU: %5s%% MEM: %5s%%\n", $11, $3, $4}'
rm -f "$results_file"
}
# Initialize summary file
rm -f /tmp/foxhunt_summary.txt
touch /tmp/foxhunt_summary.txt
# Run tests at different concurrency levels
run_concurrent_test 10 "Baseline"
echo ""
echo "Waiting 5 seconds before next test..."
sleep 5
run_concurrent_test 50 "Moderate Load"
echo ""
echo "Waiting 5 seconds before next test..."
sleep 5
run_concurrent_test 100 "High Load"
echo ""
echo "Waiting 5 seconds before next test..."
sleep 5
run_concurrent_test 200 "Stress Test"
# Print summary table
echo ""
echo ""
echo "┌────────────────────────────────────────────────────────────────────────────────────────────────┐"
echo "│ SUMMARY TABLE - ALL TEST LEVELS │"
echo "├────────────────────────────────────────────────────────────────────────────────────────────────┤"
echo "│ Connections │ Success │ Error % │ Conn P99 │ Lat P50 │ Lat P95 │ Throughput │"
echo "├────────────────────────────────────────────────────────────────────────────────────────────────┤"
while IFS=: read -r connections success error p99 p50 p95 throughput; do
printf "│ %-11s │ %7s%% │ %7s%% │ %8sms │ %7sms │ %7sms │ %10s conn/s │\n" \
"$connections" "$success" "$error" "$p99" "$p50" "$p95" "$throughput"
done < /tmp/foxhunt_summary.txt
echo "└────────────────────────────────────────────────────────────────────────────────────────────────┘"
# Determine PASS/FAIL
echo ""
result_100=$(grep "^100:" /tmp/foxhunt_summary.txt || echo "")
if [ -n "$result_100" ]; then
IFS=: read -r connections success error p99 p50 p95 throughput <<< "$result_100"
error_ok=$(awk "BEGIN {print ($error < 1.0) ? 1 : 0}")
latency_ok=$(awk "BEGIN {print ($p99 < 100) ? 1 : 0}")
if [ "$error_ok" = "1" ] && [ "$latency_ok" = "1" ]; then
echo -e "${GREEN}✅ TEST PASSED${NC} - System successfully handled 100+ concurrent connections"
echo " - Error rate < 1%"
echo " - P99 latency < 100ms"
else
echo -e "${RED}❌ TEST FAILED${NC} - System did not meet success criteria"
echo " - Error rate: ${error}% (required: <1%)"
echo " - P99 latency: ${p99}ms (required: <100ms)"
fi
else
echo -e "${YELLOW}⚠️ WARNING${NC} - Could not find 100-connection test results"
fi
# Check for connection leaks
echo ""
echo "Connection Status:"
netstat -an | grep -E "(50051|50052|50053|50054)" | wc -l | awk '{printf " Active connections on service ports: %d\n", $1}'
ss -s | grep TCP | head -1
# Cleanup
rm -f /tmp/foxhunt_summary.txt
echo ""
echo "Test completed at $(date)"

View File

@@ -0,0 +1,345 @@
#!/bin/bash
# Cross-Service Integration Test Script
# Tests actual cross-service communication flows
set -e
echo "================================"
echo "Cross-Service Integration Tests"
echo "================================"
echo ""
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Test results
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
function test_service_health() {
echo "Test 1: Service Health Checks"
echo "=============================="
TOTAL_TESTS=$((TOTAL_TESTS + 4))
# API Gateway
if curl -s -f http://localhost:9091/health > /dev/null 2>&1; then
echo -e "${GREEN}${NC} API Gateway (9091) - Healthy"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} API Gateway (9091) - Unhealthy"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
# Trading Service
if curl -s -f http://localhost:9092/health > /dev/null 2>&1; then
echo -e "${GREEN}${NC} Trading Service (9092) - Healthy"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} Trading Service (9092) - Unhealthy"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
# Backtesting Service
if curl -s -f http://localhost:8083/health > /dev/null 2>&1; then
echo -e "${GREEN}${NC} Backtesting Service (8083) - Healthy"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} Backtesting Service (8083) - Unhealthy"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
# ML Training Service
if curl -s -f http://localhost:8095/health > /dev/null 2>&1; then
echo -e "${GREEN}${NC} ML Training Service (8095) - Healthy"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} ML Training Service (8095) - Unhealthy"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
echo ""
}
function test_database_connection() {
echo "Test 2: PostgreSQL Connectivity"
echo "==============================="
TOTAL_TESTS=$((TOTAL_TESTS + 1))
if psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt -c "SELECT 1" > /dev/null 2>&1; then
echo -e "${GREEN}${NC} PostgreSQL connection successful"
PASSED_TESTS=$((PASSED_TESTS + 1))
# Check key tables
TABLES=$(psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='public'")
echo " Found $TABLES tables in public schema"
else
echo -e "${RED}${NC} PostgreSQL connection failed"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
echo ""
}
function test_redis_connection() {
echo "Test 3: Redis Connectivity"
echo "=========================="
TOTAL_TESTS=$((TOTAL_TESTS + 1))
if redis-cli -h localhost -p 6379 PING 2>/dev/null | grep -q PONG; then
echo -e "${GREEN}${NC} Redis connection successful"
PASSED_TESTS=$((PASSED_TESTS + 1))
# Test set/get
redis-cli -h localhost -p 6379 SET test_key "integration_test" > /dev/null 2>&1
VALUE=$(redis-cli -h localhost -p 6379 GET test_key 2>/dev/null)
if [ "$VALUE" = "integration_test" ]; then
echo " Redis SET/GET working"
fi
redis-cli -h localhost -p 6379 DEL test_key > /dev/null 2>&1
else
echo -e "${RED}${NC} Redis connection failed"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
echo ""
}
function test_grpc_ports() {
echo "Test 4: gRPC Port Availability"
echo "=============================="
TOTAL_TESTS=$((TOTAL_TESTS + 4))
# API Gateway gRPC
if lsof -i :50051 2>/dev/null | grep -q LISTEN; then
echo -e "${GREEN}${NC} API Gateway gRPC (50051) - Listening"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} API Gateway gRPC (50051) - Not listening"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
# Trading Service gRPC
if lsof -i :50052 2>/dev/null | grep -q LISTEN; then
echo -e "${GREEN}${NC} Trading Service gRPC (50052) - Listening"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} Trading Service gRPC (50052) - Not listening"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
# Backtesting Service gRPC
if lsof -i :50053 2>/dev/null | grep -q LISTEN; then
echo -e "${GREEN}${NC} Backtesting Service gRPC (50053) - Listening"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} Backtesting Service gRPC (50053) - Not listening"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
# ML Training Service gRPC
if lsof -i :50054 2>/dev/null | grep -q LISTEN; then
echo -e "${GREEN}${NC} ML Training Service gRPC (50054) - Listening"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} ML Training Service gRPC (50054) - Not listening"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
echo ""
}
function test_metrics_endpoints() {
echo "Test 5: Prometheus Metrics Endpoints"
echo "===================================="
TOTAL_TESTS=$((TOTAL_TESTS + 4))
# API Gateway metrics
if curl -s http://localhost:9091/metrics | grep -q "# TYPE"; then
echo -e "${GREEN}${NC} API Gateway metrics (9091) - Available"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} API Gateway metrics (9091) - Unavailable"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
# Trading Service metrics
if curl -s http://localhost:9092/metrics | grep -q "# TYPE"; then
echo -e "${GREEN}${NC} Trading Service metrics (9092) - Available"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} Trading Service metrics (9092) - Unavailable"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
# Backtesting Service metrics
if curl -s http://localhost:9093/metrics | grep -q "# TYPE"; then
echo -e "${GREEN}${NC} Backtesting Service metrics (9093) - Available"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} Backtesting Service metrics (9093) - Unavailable"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
# ML Training Service metrics
if curl -s http://localhost:9094/metrics | grep -q "# TYPE"; then
echo -e "${GREEN}${NC} ML Training Service metrics (9094) - Available"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} ML Training Service metrics (9094) - Unavailable"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
echo ""
}
function test_prometheus_targets() {
echo "Test 6: Prometheus Service Discovery"
echo "===================================="
TOTAL_TESTS=$((TOTAL_TESTS + 1))
if curl -s http://localhost:9090/api/v1/targets 2>/dev/null | grep -q '"health":"up"'; then
echo -e "${GREEN}${NC} Prometheus has healthy targets"
PASSED_TESTS=$((PASSED_TESTS + 1))
# Count healthy targets
HEALTHY=$(curl -s http://localhost:9090/api/v1/targets 2>/dev/null | grep -o '"health":"up"' | wc -l)
echo " $HEALTHY services reporting to Prometheus"
else
echo -e "${RED}${NC} No healthy Prometheus targets found"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
echo ""
}
function test_parquet_files() {
echo "Test 7: Parquet Test Data Availability"
echo "======================================"
TOTAL_TESTS=$((TOTAL_TESTS + 1))
PARQUET_COUNT=$(find /home/jgrusewski/Work/foxhunt/test_data -name "*.parquet" 2>/dev/null | wc -l)
if [ "$PARQUET_COUNT" -gt 0 ]; then
echo -e "${GREEN}${NC} Found $PARQUET_COUNT Parquet test files"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${YELLOW}${NC} No Parquet test files found"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
echo ""
}
function test_database_orders() {
echo "Test 8: Database Order Persistence"
echo "=================================="
TOTAL_TESTS=$((TOTAL_TESTS + 1))
ORDER_COUNT=$(psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt -t -c "SELECT COUNT(*) FROM orders" 2>/dev/null | tr -d ' ')
if [ $? -eq 0 ]; then
echo -e "${GREEN}${NC} Orders table accessible: $ORDER_COUNT orders"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}${NC} Failed to query orders table"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
echo ""
}
function measure_latency() {
echo "Test 9: Inter-Service Latency Measurement"
echo "========================================="
TOTAL_TESTS=$((TOTAL_TESTS + 4))
# API Gateway
START=$(date +%s%N)
curl -s http://localhost:9091/health > /dev/null 2>&1
END=$(date +%s%N)
LATENCY=$(( (END - START) / 1000000 ))
if [ $LATENCY -lt 100 ]; then
echo -e "${GREEN}${NC} API Gateway health: ${LATENCY}ms"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${YELLOW}${NC} API Gateway health: ${LATENCY}ms (>100ms)"
PASSED_TESTS=$((PASSED_TESTS + 1))
fi
# Trading Service
START=$(date +%s%N)
curl -s http://localhost:9092/health > /dev/null 2>&1
END=$(date +%s%N)
LATENCY=$(( (END - START) / 1000000 ))
if [ $LATENCY -lt 100 ]; then
echo -e "${GREEN}${NC} Trading Service health: ${LATENCY}ms"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${YELLOW}${NC} Trading Service health: ${LATENCY}ms (>100ms)"
PASSED_TESTS=$((PASSED_TESTS + 1))
fi
# Backtesting Service
START=$(date +%s%N)
curl -s http://localhost:8083/health > /dev/null 2>&1
END=$(date +%s%N)
LATENCY=$(( (END - START) / 1000000 ))
if [ $LATENCY -lt 100 ]; then
echo -e "${GREEN}${NC} Backtesting Service health: ${LATENCY}ms"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${YELLOW}${NC} Backtesting Service health: ${LATENCY}ms (>100ms)"
PASSED_TESTS=$((PASSED_TESTS + 1))
fi
# ML Training Service
START=$(date +%s%N)
curl -s http://localhost:8095/health > /dev/null 2>&1
END=$(date +%s%N)
LATENCY=$(( (END - START) / 1000000 ))
if [ $LATENCY -lt 100 ]; then
echo -e "${GREEN}${NC} ML Training Service health: ${LATENCY}ms"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${YELLOW}${NC} ML Training Service health: ${LATENCY}ms (>100ms)"
PASSED_TESTS=$((PASSED_TESTS + 1))
fi
echo ""
}
# Run all tests
test_service_health
test_database_connection
test_redis_connection
test_grpc_ports
test_metrics_endpoints
test_prometheus_targets
test_parquet_files
test_database_orders
measure_latency
# Summary
echo "================================"
echo "Test Summary"
echo "================================"
echo "Total Tests: $TOTAL_TESTS"
echo -e "${GREEN}Passed: $PASSED_TESTS${NC}"
echo -e "${RED}Failed: $FAILED_TESTS${NC}"
echo ""
PASS_RATE=$(awk "BEGIN {printf \"%.1f\", ($PASSED_TESTS / $TOTAL_TESTS) * 100}")
echo "Pass Rate: $PASS_RATE%"
echo ""
if [ $FAILED_TESTS -eq 0 ]; then
echo -e "${GREEN}✓ ALL TESTS PASSED${NC}"
exit 0
else
echo -e "${RED}✗ SOME TESTS FAILED${NC}"
exit 1
fi

363
scripts/database_validation.sh Executable file
View File

@@ -0,0 +1,363 @@
#!/bin/bash
# Database Validation Script for Foxhunt HFT Trading System
# Validates PostgreSQL, Redis, SQLite, and InfluxDB connections and performance
set -e
echo "🚀 Foxhunt Database Layer Validation"
echo "===================================="
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
POSTGRES_URL="${DATABASE_URL:-postgresql://postgres:password@localhost:5432/foxhunt_test}"
REDIS_URL="${REDIS_URL:-localhost:6379}"
INFLUX_URL="${INFLUX_URL:-localhost:8086}"
SQLITE_DB="validation_test.db"
# Counters
TESTS_PASSED=0
TESTS_FAILED=0
TOTAL_TESTS=0
# Helper functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[PASS]${NC} $1"
((TESTS_PASSED++))
((TOTAL_TESTS++))
}
log_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
((TOTAL_TESTS++))
}
log_error() {
echo -e "${RED}[FAIL]${NC} $1"
((TESTS_FAILED++))
((TOTAL_TESTS++))
}
# Test PostgreSQL
test_postgresql() {
echo ""
log_info "🔍 Testing PostgreSQL..."
# Check if PostgreSQL is accessible
if command -v psql >/dev/null 2>&1; then
# Test connection
if psql "$POSTGRES_URL" -c "SELECT 1;" >/dev/null 2>&1; then
log_success "PostgreSQL connection successful"
# Performance test - measure simple query latency
local start_time=$(date +%s%N)
for i in {1..100}; do
psql "$POSTGRES_URL" -t -c "SELECT 1;" >/dev/null 2>&1
done
local end_time=$(date +%s%N)
local total_time=$((end_time - start_time))
local avg_latency_ms=$((total_time / 100000000)) # Convert to ms
log_info "Average query latency: ${avg_latency_ms}ms"
if [ $avg_latency_ms -lt 10 ]; then
log_success "PostgreSQL performance meets requirements (<10ms)"
else
log_warning "PostgreSQL performance suboptimal (${avg_latency_ms}ms > 10ms)"
fi
# Test ACID transaction
psql "$POSTGRES_URL" >/dev/null 2>&1 << EOF
BEGIN;
CREATE TABLE IF NOT EXISTS acid_test_$$
(id SERIAL PRIMARY KEY, value INTEGER);
INSERT INTO acid_test_$$ (value) VALUES (100);
ROLLBACK;
EOF
# Verify rollback worked
local count=$(psql "$POSTGRES_URL" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_name='acid_test_$$';" 2>/dev/null | tr -d ' ' || echo "0")
if [ "$count" = "0" ]; then
log_success "ACID transaction rollback test passed"
else
log_error "ACID transaction rollback test failed"
fi
else
log_error "PostgreSQL connection failed"
fi
else
log_warning "psql not available - skipping PostgreSQL tests"
fi
}
# Test Redis
test_redis() {
echo ""
log_info "🔍 Testing Redis..."
if command -v redis-cli >/dev/null 2>&1; then
# Test connection
if redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" ping >/dev/null 2>&1; then
log_success "Redis connection successful"
# Performance test
local start_time=$(date +%s%N)
for i in {1..100}; do
redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" set "test_key_$i" "test_value_$i" >/dev/null 2>&1
redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" get "test_key_$i" >/dev/null 2>&1
done
local end_time=$(date +%s%N)
local total_time=$((end_time - start_time))
local avg_latency_ms=$((total_time / 100000000))
log_info "Average operation latency: ${avg_latency_ms}ms"
if [ $avg_latency_ms -lt 5 ]; then
log_success "Redis performance meets requirements (<5ms)"
else
log_warning "Redis performance suboptimal (${avg_latency_ms}ms > 5ms)"
fi
# Test TTL functionality
redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" set ttl_test_key ttl_test_value >/dev/null 2>&1
redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" expire ttl_test_key 1 >/dev/null 2>&1
sleep 2
local exists=$(redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" exists ttl_test_key 2>/dev/null)
if [ "$exists" = "0" ]; then
log_success "Redis TTL functionality working"
else
log_error "Redis TTL functionality failed"
fi
# Cleanup test keys
for i in {1..100}; do
redis-cli -h "${REDIS_URL%:*}" -p "${REDIS_URL#*:}" del "test_key_$i" >/dev/null 2>&1
done
else
log_error "Redis connection failed"
fi
else
log_warning "redis-cli not available - skipping Redis tests"
fi
}
# Test SQLite
test_sqlite() {
echo ""
log_info "🔍 Testing SQLite..."
if command -v sqlite3 >/dev/null 2>&1; then
# Remove existing test database
rm -f "$SQLITE_DB"
# Test database creation and operations
if sqlite3 "$SQLITE_DB" "CREATE TABLE config_test (key TEXT PRIMARY KEY, value TEXT, updated_at INTEGER);" >/dev/null 2>&1; then
log_success "SQLite database creation successful"
# Performance test
local start_time=$(date +%s%N)
for i in {1..50}; do
sqlite3 "$SQLITE_DB" "INSERT OR REPLACE INTO config_test (key, value, updated_at) VALUES ('key_$i', 'value_$i', $i);" >/dev/null 2>&1
sqlite3 "$SQLITE_DB" "SELECT value FROM config_test WHERE key='key_$i';" >/dev/null 2>&1
done
local end_time=$(date +%s%N)
local total_time=$((end_time - start_time))
local avg_latency_ms=$((total_time / 50000000))
log_info "Average operation latency: ${avg_latency_ms}ms"
if [ $avg_latency_ms -lt 20 ]; then
log_success "SQLite performance acceptable (<20ms)"
else
log_warning "SQLite performance suboptimal (${avg_latency_ms}ms > 20ms)"
fi
# Test hot-reload simulation
sqlite3 "$SQLITE_DB" "INSERT OR REPLACE INTO config_test (key, value, updated_at) VALUES ('hot_reload_test', 'initial_value', 1);" >/dev/null 2>&1
sqlite3 "$SQLITE_DB" "UPDATE config_test SET value='updated_value', updated_at=2 WHERE key='hot_reload_test';" >/dev/null 2>&1
local updated_value=$(sqlite3 "$SQLITE_DB" "SELECT value FROM config_test WHERE key='hot_reload_test';" 2>/dev/null)
if [ "$updated_value" = "updated_value" ]; then
log_success "SQLite configuration hot-reload simulation successful"
else
log_error "SQLite configuration hot-reload simulation failed"
fi
else
log_error "SQLite database creation failed"
fi
# Cleanup
rm -f "$SQLITE_DB"
else
log_warning "sqlite3 not available - skipping SQLite tests"
fi
}
# Test InfluxDB
test_influxdb() {
echo ""
log_info "🔍 Testing InfluxDB..."
if command -v curl >/dev/null 2>&1; then
# Test health endpoint
if curl -s -o /dev/null -w "%{http_code}" "http://${INFLUX_URL}/health" | grep -q "200"; then
log_success "InfluxDB health check successful"
# Test write operation (simplified)
local timestamp=$(date +%s%N)
local line_protocol="test_measurement,tag1=value1 field1=123 $timestamp"
local write_url="http://${INFLUX_URL}/api/v2/write?org=test&bucket=test"
if curl -s -o /dev/null -w "%{http_code}" -X POST "$write_url" \
-H "Content-Type: text/plain" \
-d "$line_protocol" | grep -q "204\|200"; then
log_success "InfluxDB write test successful (or acceptable without auth)"
else
log_warning "InfluxDB write test failed (may need authentication)"
fi
elif curl -s -o /dev/null -w "%{http_code}" "http://${INFLUX_URL}/ping" | grep -q "204"; then
log_success "InfluxDB ping successful (legacy endpoint)"
else
log_error "InfluxDB connection failed"
fi
else
log_warning "curl not available - skipping InfluxDB tests"
fi
}
# Test backup capabilities
test_backup_capabilities() {
echo ""
log_info "🔍 Testing backup capabilities..."
# Check if backup tools are available
local backup_tools=("pg_dump" "redis-cli" "influxd" "tar")
local available_tools=0
for tool in "${backup_tools[@]}"; do
if command -v "$tool" >/dev/null 2>&1; then
((available_tools++))
log_success "$tool available for backups"
else
log_warning "$tool not available for backups"
fi
done
if [ $available_tools -gt 2 ]; then
log_success "Sufficient backup tools available ($available_tools/4)"
else
log_warning "Limited backup capabilities ($available_tools/4 tools available)"
fi
}
# Test health monitoring
test_health_monitoring() {
echo ""
log_info "🔍 Testing health monitoring capabilities..."
# Check if monitoring tools are available
local monitoring_tools=("systemctl" "ps" "netstat" "ss")
local available_tools=0
for tool in "${monitoring_tools[@]}"; do
if command -v "$tool" >/dev/null 2>&1; then
((available_tools++))
fi
done
if [ $available_tools -gt 2 ]; then
log_success "Health monitoring tools available ($available_tools/4)"
else
log_warning "Limited health monitoring capabilities ($available_tools/4)"
fi
# Test basic system health
local load_avg=$(uptime | awk '{print $(NF-2)}' | sed 's/,//')
if (( $(echo "$load_avg < 2.0" | bc -l 2>/dev/null || echo "1") )); then
log_success "System load acceptable ($load_avg)"
else
log_warning "High system load detected ($load_avg)"
fi
# Test memory usage
local mem_usage=$(free | awk '/Mem:/ { printf("%.1f", $3/$2 * 100.0) }')
if (( $(echo "$mem_usage < 80.0" | bc -l 2>/dev/null || echo "1") )); then
log_success "Memory usage acceptable (${mem_usage}%)"
else
log_warning "High memory usage detected (${mem_usage}%)"
fi
}
# Main execution
main() {
local start_time=$(date +%s)
log_info "Starting database validation at $(date)"
log_info "Configuration:"
log_info " PostgreSQL: $POSTGRES_URL"
log_info " Redis: $REDIS_URL"
log_info " InfluxDB: $INFLUX_URL"
log_info " SQLite: $SQLITE_DB"
# Run all tests
test_postgresql
test_redis
test_sqlite
test_influxdb
test_backup_capabilities
test_health_monitoring
local end_time=$(date +%s)
local total_duration=$((end_time - start_time))
# Generate summary
echo ""
echo "📊 VALIDATION SUMMARY"
echo "===================="
echo "Total Time: ${total_duration}s"
echo "Tests Passed: $TESTS_PASSED"
echo "Tests Failed: $TESTS_FAILED"
echo "Total Tests: $TOTAL_TESTS"
echo ""
if [ $TESTS_FAILED -eq 0 ]; then
log_success "🎉 All database validation tests completed successfully!"
echo ""
echo "✅ Database Layer Status:"
echo " - PostgreSQL: Connection and ACID transactions working"
echo " - Redis: Caching and TTL functionality working"
echo " - SQLite: Configuration storage and hot-reload ready"
echo " - InfluxDB: Metrics storage capability verified"
echo " - Backup/Recovery: Tools available for data protection"
echo " - Health Monitoring: System monitoring capabilities ready"
echo ""
echo "🚀 The database layer is ready for HFT operations!"
exit 0
else
log_error "💥 Database validation completed with $TESTS_FAILED failures"
echo ""
echo "❌ Issues found:"
echo " - $TESTS_FAILED out of $TOTAL_TESTS tests failed"
echo " - Review the logs above for specific failure details"
echo " - Consider addressing failed tests before production deployment"
echo ""
exit 1
fi
}
# Execute main function
main "$@"

266
scripts/db_load_test.sh Executable file
View File

@@ -0,0 +1,266 @@
#!/bin/bash
# PostgreSQL Load Test Script for Foxhunt Trading System
# Tests database performance under increasing concurrent load
# Workload: 40% INSERT, 30% SELECT, 20% UPDATE, 10% Complex queries
set -e
DB_URL="postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt"
TEST_DURATION=60 # seconds per test
RESULTS_FILE="/tmp/db_load_test_results_$(date +%Y%m%d_%H%M%S).txt"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "PostgreSQL Load Test - Foxhunt Trading" | tee -a "$RESULTS_FILE"
echo "Test Duration: $TEST_DURATION seconds per scenario" | tee -a "$RESULTS_FILE"
echo "Start Time: $(date)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
# Function to check database health
check_db_health() {
echo "=== Database Health Check ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT version();" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SHOW max_connections;" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SHOW shared_buffers;" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SHOW synchronous_commit;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Cache Hit Ratio ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT sum(blks_hit)::float / (sum(blks_hit) + sum(blks_read)) * 100 AS cache_hit_ratio FROM pg_stat_database WHERE datname = 'foxhunt';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Active Connections ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT count(*) FROM pg_stat_activity WHERE state = 'active';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to get baseline table counts
get_baseline_counts() {
echo "=== Baseline Table Counts ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT 'orders' AS table_name, COUNT(*) FROM orders UNION ALL SELECT 'executions', COUNT(*) FROM executions UNION ALL SELECT 'fills', COUNT(*) FROM fills UNION ALL SELECT 'positions', COUNT(*) FROM positions;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to run single-threaded baseline test
run_baseline_test() {
echo "========================================" | tee -a "$RESULTS_FILE"
echo "TEST 1: BASELINE (Single-threaded)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
local start_time=$(date +%s)
local end_time=$((start_time + TEST_DURATION))
local insert_count=0
local select_count=0
local update_count=0
local complex_count=0
while [ $(date +%s) -lt $end_time ]; do
# 40% INSERT - orders
for i in {1..4}; do
psql "$DB_URL" -c "INSERT INTO orders (order_id, user_id, symbol, side, order_type, quantity, price, status, created_at) VALUES (gen_random_uuid(), gen_random_uuid(), 'BTC/USD', 'buy', 'limit', 1.0, 50000.0, 'pending', NOW());" > /dev/null 2>&1
((insert_count++))
done
# 30% SELECT - order status
for i in {1..3}; do
psql "$DB_URL" -c "SELECT order_id, status, quantity FROM orders WHERE symbol = 'BTC/USD' ORDER BY created_at DESC LIMIT 10;" > /dev/null 2>&1
((select_count++))
done
# 20% UPDATE - order status
for i in {1..2}; do
psql "$DB_URL" -c "UPDATE orders SET status = 'filled', updated_at = NOW() WHERE order_id = (SELECT order_id FROM orders WHERE status = 'pending' LIMIT 1);" > /dev/null 2>&1
((update_count++))
done
# 10% Complex query - position aggregation
psql "$DB_URL" -c "SELECT symbol, SUM(quantity) as total_quantity, AVG(entry_price) as avg_price FROM positions WHERE user_id IN (SELECT user_id FROM users LIMIT 5) GROUP BY symbol;" > /dev/null 2>&1
((complex_count++))
done
local actual_duration=$(($(date +%s) - start_time))
local total_ops=$((insert_count + select_count + update_count + complex_count))
local tps=$(echo "scale=2; $total_ops / $actual_duration" | bc)
echo "Duration: $actual_duration seconds" | tee -a "$RESULTS_FILE"
echo "Total Operations: $total_ops" | tee -a "$RESULTS_FILE"
echo " - INSERTs: $insert_count" | tee -a "$RESULTS_FILE"
echo " - SELECTs: $select_count" | tee -a "$RESULTS_FILE"
echo " - UPDATEs: $update_count" | tee -a "$RESULTS_FILE"
echo " - Complex: $complex_count" | tee -a "$RESULTS_FILE"
echo "Transactions per Second (TPS): $tps" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to run concurrent load test
run_concurrent_test() {
local num_connections=$1
local test_name=$2
echo "========================================" | tee -a "$RESULTS_FILE"
echo "TEST: $test_name ($num_connections concurrent connections)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
local pids=()
local temp_dir="/tmp/db_load_test_$$"
mkdir -p "$temp_dir"
# Start time
local start_time=$(date +%s.%N)
# Launch concurrent workers
for ((i=1; i<=num_connections; i++)); do
(
local worker_inserts=0
local worker_selects=0
local worker_updates=0
local worker_complex=0
local end_time=$(echo "$start_time + $TEST_DURATION" | bc)
while (( $(echo "$(date +%s.%N) < $end_time" | bc -l) )); do
# 40% INSERT
if (( RANDOM % 10 < 4 )); then
psql "$DB_URL" -c "INSERT INTO orders (order_id, user_id, symbol, side, order_type, quantity, price, status, created_at) VALUES (gen_random_uuid(), gen_random_uuid(), 'BTC/USD', 'buy', 'limit', 1.0, 50000.0, 'pending', NOW());" > /dev/null 2>&1
((worker_inserts++))
# 30% SELECT
elif (( RANDOM % 10 < 7 )); then
psql "$DB_URL" -c "SELECT order_id, status, quantity FROM orders WHERE symbol = 'BTC/USD' ORDER BY created_at DESC LIMIT 10;" > /dev/null 2>&1
((worker_selects++))
# 20% UPDATE
elif (( RANDOM % 10 < 9 )); then
psql "$DB_URL" -c "UPDATE orders SET status = 'filled', updated_at = NOW() WHERE order_id = (SELECT order_id FROM orders WHERE status = 'pending' LIMIT 1);" > /dev/null 2>&1
((worker_updates++))
# 10% Complex
else
psql "$DB_URL" -c "SELECT symbol, COUNT(*) as order_count FROM orders WHERE created_at > NOW() - INTERVAL '1 hour' GROUP BY symbol;" > /dev/null 2>&1
((worker_complex++))
fi
done
# Write worker results
echo "$worker_inserts $worker_selects $worker_updates $worker_complex" > "$temp_dir/worker_$i.txt"
) &
pids+=($!)
done
# Wait for all workers to complete
for pid in "${pids[@]}"; do
wait $pid
done
local end_time=$(date +%s.%N)
local actual_duration=$(echo "$end_time - $start_time" | bc)
# Aggregate results
local total_inserts=0
local total_selects=0
local total_updates=0
local total_complex=0
for ((i=1; i<=num_connections; i++)); do
if [ -f "$temp_dir/worker_$i.txt" ]; then
read inserts selects updates complex < "$temp_dir/worker_$i.txt"
total_inserts=$((total_inserts + inserts))
total_selects=$((total_selects + selects))
total_updates=$((total_updates + updates))
total_complex=$((total_complex + complex))
fi
done
local total_ops=$((total_inserts + total_selects + total_updates + total_complex))
local tps=$(echo "scale=2; $total_ops / $actual_duration" | bc)
echo "Duration: $actual_duration seconds" | tee -a "$RESULTS_FILE"
echo "Concurrent Connections: $num_connections" | tee -a "$RESULTS_FILE"
echo "Total Operations: $total_ops" | tee -a "$RESULTS_FILE"
echo " - INSERTs: $total_inserts" | tee -a "$RESULTS_FILE"
echo " - SELECTs: $total_selects" | tee -a "$RESULTS_FILE"
echo " - UPDATEs: $total_updates" | tee -a "$RESULTS_FILE"
echo " - Complex: $total_complex" | tee -a "$RESULTS_FILE"
echo "Transactions per Second (TPS): $tps" | tee -a "$RESULTS_FILE"
# Check for connection pool exhaustion
echo "" | tee -a "$RESULTS_FILE"
echo "=== Connection Pool Status ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT count(*), state FROM pg_stat_activity GROUP BY state;" | tee -a "$RESULTS_FILE"
# Check for locks and deadlocks
echo "" | tee -a "$RESULTS_FILE"
echo "=== Lock Contention ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT count(*) as lock_count FROM pg_locks WHERE NOT granted;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Deadlock Stats ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT datname, deadlocks FROM pg_stat_database WHERE datname = 'foxhunt';" | tee -a "$RESULTS_FILE"
# Cleanup
rm -rf "$temp_dir"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to check query performance
check_query_performance() {
echo "========================================" | tee -a "$RESULTS_FILE"
echo "QUERY PERFORMANCE ANALYSIS" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "=== Top 10 Slowest Queries ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT query, calls, mean_exec_time, max_exec_time FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 10;" 2>&1 | tee -a "$RESULTS_FILE" || echo "pg_stat_statements extension not available" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Table Statistics ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT relname, seq_scan, seq_tup_read, idx_scan, idx_tup_fetch, n_tup_ins, n_tup_upd, n_tup_del FROM pg_stat_user_tables WHERE schemaname = 'public' AND relname IN ('orders', 'executions', 'fills', 'positions') ORDER BY n_tup_ins DESC;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Index Usage ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch FROM pg_stat_user_indexes WHERE schemaname = 'public' AND tablename IN ('orders', 'executions', 'fills', 'positions') ORDER BY idx_scan DESC LIMIT 10;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to check resource utilization
check_resource_utilization() {
echo "========================================" | tee -a "$RESULTS_FILE"
echo "RESOURCE UTILIZATION" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "=== Database Size ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database WHERE datname = 'foxhunt';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Table Sizes ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT relname, pg_size_pretty(pg_total_relation_size(relid)) AS total_size FROM pg_stat_user_tables WHERE schemaname = 'public' AND relname IN ('orders', 'executions', 'fills', 'positions') ORDER BY pg_total_relation_size(relid) DESC;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Cache Hit Ratio (Final) ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT sum(blks_hit)::float / (sum(blks_hit) + sum(blks_read)) * 100 AS cache_hit_ratio FROM pg_stat_database WHERE datname = 'foxhunt';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Main test execution
main() {
echo "Starting PostgreSQL Load Test..."
# Initial health check
check_db_health
get_baseline_counts
# Run tests with increasing concurrency
run_baseline_test
run_concurrent_test 10 "MODERATE LOAD"
run_concurrent_test 50 "HIGH LOAD"
run_concurrent_test 100 "STRESS TEST"
# Post-test analysis
check_query_performance
check_resource_utilization
echo "========================================" | tee -a "$RESULTS_FILE"
echo "Test Completed: $(date)" | tee -a "$RESULTS_FILE"
echo "Results saved to: $RESULTS_FILE" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
}
# Run main test
main

218
scripts/db_load_test_pgbench.sh Executable file
View File

@@ -0,0 +1,218 @@
#!/bin/bash
# PostgreSQL Load Test using pgbench - Foxhunt Trading System
# Tests database performance under increasing concurrent load
set -e
DB_URL="postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt"
DB_HOST="localhost"
DB_PORT="5432"
DB_NAME="foxhunt"
DB_USER="foxhunt"
DB_PASS="foxhunt_dev_password"
TEST_DURATION=30 # seconds per test
WORKLOAD_FILE="trading_workload.sql"
RESULTS_FILE="DB_LOAD_TEST_RESULTS_$(date +%Y%m%d_%H%M%S).txt"
export PGPASSWORD="$DB_PASS"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "PostgreSQL Load Test - Foxhunt Trading" | tee -a "$RESULTS_FILE"
echo "Using pgbench with custom trading workload" | tee -a "$RESULTS_FILE"
echo "Test Duration: $TEST_DURATION seconds per scenario" | tee -a "$RESULTS_FILE"
echo "Start Time: $(date)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
# Function to check database health
check_db_health() {
echo "=== Database Health Check ===" | tee -a "$RESULTS_FILE"
echo "PostgreSQL Version:" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT version();" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "Configuration:" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SHOW max_connections;" | awk '{print " max_connections: " $1}' | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SHOW shared_buffers;" | awk '{print " shared_buffers: " $1}' | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SHOW synchronous_commit;" | awk '{print " synchronous_commit: " $1}' | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "Cache Hit Ratio:" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT (sum(blks_hit)::float / NULLIF(sum(blks_hit) + sum(blks_read), 0) * 100)::numeric(5,2) || '%' AS cache_hit_ratio FROM pg_stat_database WHERE datname = 'foxhunt';" | awk '{print " " $1}' | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to get baseline table counts
get_baseline_counts() {
echo "=== Baseline Table Counts ===" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 'orders' AS table_name, COUNT(*) FROM orders UNION ALL SELECT 'executions', COUNT(*) FROM executions UNION ALL SELECT 'fills', COUNT(*) FROM fills UNION ALL SELECT 'positions', COUNT(*) FROM positions;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to run pgbench test
run_pgbench_test() {
local clients=$1
local test_name=$2
echo "========================================" | tee -a "$RESULTS_FILE"
echo "TEST: $test_name" | tee -a "$RESULTS_FILE"
echo "Concurrent Clients: $clients" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
# Run pgbench
pgbench -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \
-c "$clients" -j $(( clients > 4 ? 4 : clients )) \
-T "$TEST_DURATION" \
-f "$WORKLOAD_FILE" \
-n 2>&1 | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
# Check connection pool status
echo "=== Connection Pool Status ===" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT state, COUNT(*) FROM pg_stat_activity WHERE datname = 'foxhunt' GROUP BY state ORDER BY COUNT(*) DESC;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
# Check for lock contention
echo "=== Lock Contention ===" | tee -a "$RESULTS_FILE"
local locks_waiting=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM pg_locks WHERE NOT granted;" | tr -d ' ')
echo " Locks waiting: $locks_waiting" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
# Check deadlock count
echo "=== Deadlock Statistics ===" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT datname, deadlocks, conflicts FROM pg_stat_database WHERE datname = 'foxhunt';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to analyze query performance
analyze_query_performance() {
echo "========================================" | tee -a "$RESULTS_FILE"
echo "QUERY PERFORMANCE ANALYSIS" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "=== Table Statistics ===" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
SELECT relname,
n_tup_ins AS inserts,
n_tup_upd AS updates,
n_tup_del AS deletes,
seq_scan,
idx_scan,
CASE WHEN seq_scan + idx_scan > 0
THEN (idx_scan::float / (seq_scan + idx_scan) * 100)::numeric(5,2)
ELSE 0 END AS idx_scan_pct
FROM pg_stat_user_tables
WHERE schemaname = 'public'
AND relname IN ('orders', 'executions', 'fills', 'positions')
ORDER BY n_tup_ins DESC;
" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Index Usage ===" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
SELECT tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
WHERE schemaname = 'public'
AND tablename IN ('orders', 'executions', 'fills', 'positions')
ORDER BY idx_scan DESC
LIMIT 10;
" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to check resource utilization
check_resource_utilization() {
echo "========================================" | tee -a "$RESULTS_FILE"
echo "RESOURCE UTILIZATION" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "=== Database Size ===" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
SELECT datname, pg_size_pretty(pg_database_size(datname)) AS size
FROM pg_database
WHERE datname = 'foxhunt';
" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Table Sizes ===" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
SELECT relname,
pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
pg_size_pretty(pg_relation_size(relid)) AS table_size,
pg_size_pretty(pg_total_relation_size(relid) - pg_relation_size(relid)) AS index_size
FROM pg_stat_user_tables
WHERE schemaname = 'public'
AND relname IN ('orders', 'executions', 'fills', 'positions')
ORDER BY pg_total_relation_size(relid) DESC;
" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Final Cache Hit Ratio ===" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "
SELECT (sum(blks_hit)::float / NULLIF(sum(blks_hit) + sum(blks_read), 0) * 100)::numeric(5,2) || '%' AS cache_hit_ratio
FROM pg_stat_database
WHERE datname = 'foxhunt';
" | awk '{print " " $1}' | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to get final table counts
get_final_counts() {
echo "=== Final Table Counts ===" | tee -a "$RESULTS_FILE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
SELECT 'orders' AS table_name, COUNT(*) FROM orders
UNION ALL SELECT 'executions', COUNT(*) FROM executions
UNION ALL SELECT 'fills', COUNT(*) FROM fills
UNION ALL SELECT 'positions', COUNT(*) FROM positions;
" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Main test execution
main() {
echo "Starting PostgreSQL Load Test with pgbench..."
# Check if workload file exists
if [ ! -f "$WORKLOAD_FILE" ]; then
echo "ERROR: Workload file $WORKLOAD_FILE not found!" | tee -a "$RESULTS_FILE"
exit 1
fi
# Initial health check
check_db_health
get_baseline_counts
# Run tests with increasing concurrency
run_pgbench_test 1 "BASELINE (Single Client)"
run_pgbench_test 10 "MODERATE LOAD (10 Clients)"
run_pgbench_test 50 "HIGH LOAD (50 Clients)"
run_pgbench_test 100 "STRESS TEST (100 Clients)"
# Post-test analysis
analyze_query_performance
check_resource_utilization
get_final_counts
echo "========================================" | tee -a "$RESULTS_FILE"
echo "Test Completed: $(date)" | tee -a "$RESULTS_FILE"
echo "Results saved to: $RESULTS_FILE" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo ""
echo "Test complete! Results saved to: $RESULTS_FILE"
}
# Run main test
main

140
scripts/db_load_test_simple.sh Executable file
View File

@@ -0,0 +1,140 @@
#!/bin/bash
# Simple but effective PostgreSQL Load Test
# Direct SQL execution with timing
set -e
DB_URL="postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt"
TEST_DURATION=20 # seconds per test
RESULTS_FILE="DB_LOAD_TEST_RESULTS_$(date +%Y%m%d_%H%M%S).txt"
echo "========================================" | tee "$RESULTS_FILE"
echo "PostgreSQL Load Test - Foxhunt Trading" | tee -a "$RESULTS_FILE"
echo "Test Duration: $TEST_DURATION seconds per scenario" | tee -a "$RESULTS_FILE"
echo "Start Time: $(date)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
# Health check
echo "=== Database Configuration ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SHOW max_connections;" | awk '{print "Max Connections: " $1}' | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SHOW shared_buffers;" | awk '{print "Shared Buffers: " $1}' | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SHOW synchronous_commit;" | awk '{print "Synchronous Commit: " $1}' | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Baseline Table Counts ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT 'orders' AS table_name, COUNT(*) FROM orders;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
# Function to run load test
run_load_test() {
local clients=$1
local test_name=$2
echo "========================================" | tee -a "$RESULTS_FILE"
echo "TEST: $test_name ($clients clients)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
local temp_dir="/tmp/dbtest_$$_$clients"
mkdir -p "$temp_dir"
local start_time=$(date +%s.%N)
# Launch workers
for ((i=1; i<=clients; i++)); do
(
local count=0
local errors=0
local end_time=$(echo "$start_time + $TEST_DURATION" | bc)
while (( $(echo "$(date +%s.%N) < $end_time" | bc -l) )); do
# Insert order
if psql "$DB_URL" -c "INSERT INTO orders (account_id, symbol, side, order_type, quantity, limit_price, venue, created_at, updated_at) VALUES ('load_test', 'BTC/USD', 'buy', 'limit', 100000000, 5000000000000, 'test', EXTRACT(EPOCH FROM NOW())*1000000000, EXTRACT(EPOCH FROM NOW())*1000000000);" > /dev/null 2>&1; then
((count++))
else
((errors++))
fi
# Periodically run queries
if (( count % 5 == 0 )); then
psql "$DB_URL" -c "SELECT COUNT(*) FROM orders WHERE symbol = 'BTC/USD';" > /dev/null 2>&1 || ((errors++))
fi
done
echo "$count $errors" > "$temp_dir/worker_$i.txt"
) &
done
# Wait for completion
wait
local end_time=$(date +%s.%N)
local duration=$(echo "$end_time - $start_time" | bc)
# Aggregate results
local total_ops=0
local total_errors=0
for ((i=1; i<=clients; i++)); do
if [ -f "$temp_dir/worker_$i.txt" ]; then
read ops errors < "$temp_dir/worker_$i.txt"
total_ops=$((total_ops + ops))
total_errors=$((total_errors + errors))
fi
done
local tps=$(echo "scale=2; $total_ops / $duration" | bc)
echo "Duration: $duration seconds" | tee -a "$RESULTS_FILE"
echo "Total Operations: $total_ops" | tee -a "$RESULTS_FILE"
echo "Errors: $total_errors" | tee -a "$RESULTS_FILE"
echo "Transactions per Second (TPS): $tps" | tee -a "$RESULTS_FILE"
# Connection pool status
echo "" | tee -a "$RESULTS_FILE"
echo "Connection Pool:" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT state, COUNT(*) FROM pg_stat_activity WHERE datname='foxhunt' GROUP BY state;" | tee -a "$RESULTS_FILE"
# Lock stats
echo "" | tee -a "$RESULTS_FILE"
local locks=$(psql "$DB_URL" -t -c "SELECT COUNT(*) FROM pg_locks WHERE NOT granted;" | tr -d ' ')
echo "Locks Waiting: $locks" | tee -a "$RESULTS_FILE"
# Deadlocks
local deadlocks=$(psql "$DB_URL" -t -c "SELECT deadlocks FROM pg_stat_database WHERE datname='foxhunt';" | tr -d ' ')
echo "Deadlocks: $deadlocks" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
rm -rf "$temp_dir"
}
# Run tests
run_load_test 1 "BASELINE"
run_load_test 10 "MODERATE"
run_load_test 50 "HIGH"
run_load_test 100 "STRESS"
# Final analysis
echo "========================================" | tee -a "$RESULTS_FILE"
echo "FINAL ANALYSIS" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "=== Table Statistics ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT relname, n_tup_ins as inserts, n_tup_upd as updates, idx_scan FROM pg_stat_user_tables WHERE relname='orders';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Cache Hit Ratio ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SELECT (sum(blks_hit)::float / NULLIF(sum(blks_hit) + sum(blks_read), 0) * 100)::numeric(5,2) || '%' FROM pg_stat_database WHERE datname='foxhunt';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Final Counts ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT COUNT(*) as total_orders FROM orders;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "Test Completed: $(date)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo ""
echo "Results saved to: $RESULTS_FILE"

266
scripts/db_load_test_v2.sh Executable file
View File

@@ -0,0 +1,266 @@
#!/bin/bash
# PostgreSQL Load Test Script for Foxhunt Trading System (Schema-accurate)
# Tests database performance under increasing concurrent load
# Workload: 40% INSERT, 30% SELECT, 20% UPDATE, 10% Complex queries
set -e
DB_URL="postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt"
TEST_DURATION=30 # seconds per test (reduced for faster execution)
RESULTS_FILE="/tmp/db_load_test_results_$(date +%Y%m%d_%H%M%S).txt"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "PostgreSQL Load Test - Foxhunt Trading" | tee -a "$RESULTS_FILE"
echo "Test Duration: $TEST_DURATION seconds per scenario" | tee -a "$RESULTS_FILE"
echo "Start Time: $(date)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
# Function to check database health
check_db_health() {
echo "=== Database Health Check ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SELECT version();" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SHOW max_connections;" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SHOW shared_buffers;" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SHOW synchronous_commit;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Cache Hit Ratio ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SELECT ROUND(sum(blks_hit)::float / (sum(blks_hit) + sum(blks_read)) * 100, 2) || '%' AS cache_hit_ratio FROM pg_stat_database WHERE datname = 'foxhunt';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Active Connections ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SELECT count(*) FROM pg_stat_activity WHERE state = 'active';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to get baseline table counts
get_baseline_counts() {
echo "=== Baseline Table Counts ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT 'orders' AS table_name, COUNT(*) FROM orders UNION ALL SELECT 'executions', COUNT(*) FROM executions UNION ALL SELECT 'fills', COUNT(*) FROM fills UNION ALL SELECT 'positions', COUNT(*) FROM positions;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to run single-threaded baseline test
run_baseline_test() {
echo "========================================" | tee -a "$RESULTS_FILE"
echo "TEST 1: BASELINE (Single-threaded)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
local start_time=$(date +%s.%N)
local end_time=$(echo "$start_time + $TEST_DURATION" | bc)
local insert_count=0
local select_count=0
local update_count=0
local complex_count=0
local error_count=0
while (( $(echo "$(date +%s.%N) < $end_time" | bc -l) )); do
# 40% INSERT - orders with proper schema
for i in {1..4}; do
psql "$DB_URL" -c "INSERT INTO orders (account_id, symbol, side, order_type, quantity, limit_price, venue, created_at, updated_at) VALUES ('test_account', 'BTC/USD', 'buy', 'limit', 100000000, 5000000000000, 'test_venue', EXTRACT(EPOCH FROM NOW()) * 1000000000, EXTRACT(EPOCH FROM NOW()) * 1000000000);" > /dev/null 2>&1 && ((insert_count++)) || ((error_count++))
done
# 30% SELECT - order status queries
for i in {1..3}; do
psql "$DB_URL" -c "SELECT id, status, quantity FROM orders WHERE symbol = 'BTC/USD' ORDER BY created_at DESC LIMIT 10;" > /dev/null 2>&1 && ((select_count++)) || ((error_count++))
done
# 20% UPDATE - order status changes
for i in {1..2}; do
psql "$DB_URL" -c "UPDATE orders SET status = 'filled', updated_at = EXTRACT(EPOCH FROM NOW()) * 1000000000 WHERE id = (SELECT id FROM orders WHERE status = 'pending' LIMIT 1);" > /dev/null 2>&1 && ((update_count++)) || ((error_count++))
done
# 10% Complex query - order aggregation
psql "$DB_URL" -c "SELECT symbol, COUNT(*) as order_count, SUM(quantity) as total_qty FROM orders WHERE created_at > EXTRACT(EPOCH FROM (NOW() - INTERVAL '1 hour')) * 1000000000 GROUP BY symbol;" > /dev/null 2>&1 && ((complex_count++)) || ((error_count++))
done
local actual_end_time=$(date +%s.%N)
local actual_duration=$(echo "$actual_end_time - $start_time" | bc)
local total_ops=$((insert_count + select_count + update_count + complex_count))
local tps=$(echo "scale=2; $total_ops / $actual_duration" | bc)
echo "Duration: $actual_duration seconds" | tee -a "$RESULTS_FILE"
echo "Total Operations: $total_ops" | tee -a "$RESULTS_FILE"
echo " - INSERTs: $insert_count" | tee -a "$RESULTS_FILE"
echo " - SELECTs: $select_count" | tee -a "$RESULTS_FILE"
echo " - UPDATEs: $update_count" | tee -a "$RESULTS_FILE"
echo " - Complex: $complex_count" | tee -a "$RESULTS_FILE"
echo " - Errors: $error_count" | tee -a "$RESULTS_FILE"
echo "Transactions per Second (TPS): $tps" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to run concurrent load test
run_concurrent_test() {
local num_connections=$1
local test_name=$2
echo "========================================" | tee -a "$RESULTS_FILE"
echo "TEST: $test_name ($num_connections concurrent connections)" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
local pids=()
local temp_dir="/tmp/db_load_test_$$_$num_connections"
mkdir -p "$temp_dir"
# Start time
local start_time=$(date +%s.%N)
# Launch concurrent workers
for ((i=1; i<=num_connections; i++)); do
(
local worker_inserts=0
local worker_selects=0
local worker_updates=0
local worker_complex=0
local worker_errors=0
local end_time=$(echo "$start_time + $TEST_DURATION" | bc)
while (( $(echo "$(date +%s.%N) < $end_time" | bc -l) )); do
local rand=$((RANDOM % 10))
# 40% INSERT
if (( rand < 4 )); then
psql "$DB_URL" -c "INSERT INTO orders (account_id, symbol, side, order_type, quantity, limit_price, venue, created_at, updated_at) VALUES ('test_account', 'BTC/USD', 'buy', 'limit', 100000000, 5000000000000, 'test_venue', EXTRACT(EPOCH FROM NOW()) * 1000000000, EXTRACT(EPOCH FROM NOW()) * 1000000000);" > /dev/null 2>&1 && ((worker_inserts++)) || ((worker_errors++))
# 30% SELECT
elif (( rand < 7 )); then
psql "$DB_URL" -c "SELECT id, status, quantity FROM orders WHERE symbol = 'BTC/USD' ORDER BY created_at DESC LIMIT 10;" > /dev/null 2>&1 && ((worker_selects++)) || ((worker_errors++))
# 20% UPDATE
elif (( rand < 9 )); then
psql "$DB_URL" -c "UPDATE orders SET status = 'partially_filled', updated_at = EXTRACT(EPOCH FROM NOW()) * 1000000000 WHERE id = (SELECT id FROM orders WHERE status = 'pending' LIMIT 1);" > /dev/null 2>&1 && ((worker_updates++)) || ((worker_errors++))
# 10% Complex
else
psql "$DB_URL" -c "SELECT symbol, COUNT(*) as order_count FROM orders WHERE created_at > EXTRACT(EPOCH FROM (NOW() - INTERVAL '1 hour')) * 1000000000 GROUP BY symbol;" > /dev/null 2>&1 && ((worker_complex++)) || ((worker_errors++))
fi
done
# Write worker results
echo "$worker_inserts $worker_selects $worker_updates $worker_complex $worker_errors" > "$temp_dir/worker_$i.txt"
) &
pids+=($!)
done
# Wait for all workers to complete
for pid in "${pids[@]}"; do
wait $pid 2>/dev/null || true
done
local end_time=$(date +%s.%N)
local actual_duration=$(echo "$end_time - $start_time" | bc)
# Aggregate results
local total_inserts=0
local total_selects=0
local total_updates=0
local total_complex=0
local total_errors=0
for ((i=1; i<=num_connections; i++)); do
if [ -f "$temp_dir/worker_$i.txt" ]; then
read inserts selects updates complex errors < "$temp_dir/worker_$i.txt"
total_inserts=$((total_inserts + inserts))
total_selects=$((total_selects + selects))
total_updates=$((total_updates + updates))
total_complex=$((total_complex + complex))
total_errors=$((total_errors + errors))
fi
done
local total_ops=$((total_inserts + total_selects + total_updates + total_complex))
local tps=$(echo "scale=2; $total_ops / $actual_duration" | bc)
echo "Duration: $actual_duration seconds" | tee -a "$RESULTS_FILE"
echo "Concurrent Connections: $num_connections" | tee -a "$RESULTS_FILE"
echo "Total Operations: $total_ops" | tee -a "$RESULTS_FILE"
echo " - INSERTs: $total_inserts" | tee -a "$RESULTS_FILE"
echo " - SELECTs: $total_selects" | tee -a "$RESULTS_FILE"
echo " - UPDATEs: $total_updates" | tee -a "$RESULTS_FILE"
echo " - Complex: $total_complex" | tee -a "$RESULTS_FILE"
echo " - Errors: $total_errors" | tee -a "$RESULTS_FILE"
echo "Transactions per Second (TPS): $tps" | tee -a "$RESULTS_FILE"
# Check for connection pool exhaustion
echo "" | tee -a "$RESULTS_FILE"
echo "=== Connection Pool Status ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT count(*), state FROM pg_stat_activity GROUP BY state;" | tee -a "$RESULTS_FILE"
# Check for locks and deadlocks
echo "" | tee -a "$RESULTS_FILE"
echo "=== Lock Contention ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SELECT count(*) as lock_count FROM pg_locks WHERE NOT granted;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Deadlock Stats ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT datname, deadlocks FROM pg_stat_database WHERE datname = 'foxhunt';" | tee -a "$RESULTS_FILE"
# Cleanup
rm -rf "$temp_dir"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to check query performance
check_query_performance() {
echo "========================================" | tee -a "$RESULTS_FILE"
echo "QUERY PERFORMANCE ANALYSIS" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "=== Table Statistics ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT relname, seq_scan, seq_tup_read, idx_scan, idx_tup_fetch, n_tup_ins, n_tup_upd, n_tup_del FROM pg_stat_user_tables WHERE schemaname = 'public' AND relname IN ('orders', 'executions', 'fills', 'positions') ORDER BY n_tup_ins DESC;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Index Usage ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT tablename, indexname, idx_scan, idx_tup_read FROM pg_stat_user_indexes WHERE schemaname = 'public' AND tablename IN ('orders', 'executions', 'fills', 'positions') ORDER BY idx_scan DESC LIMIT 10;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Function to check resource utilization
check_resource_utilization() {
echo "========================================" | tee -a "$RESULTS_FILE"
echo "RESOURCE UTILIZATION" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo "=== Database Size ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database WHERE datname = 'foxhunt';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Table Sizes ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -c "SELECT relname, pg_size_pretty(pg_total_relation_size(relid)) AS total_size FROM pg_stat_user_tables WHERE schemaname = 'public' AND relname IN ('orders', 'executions', 'fills', 'positions') ORDER BY pg_total_relation_size(relid) DESC;" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
echo "=== Cache Hit Ratio (Final) ===" | tee -a "$RESULTS_FILE"
psql "$DB_URL" -t -c "SELECT ROUND(sum(blks_hit)::float / (sum(blks_hit) + sum(blks_read)) * 100, 2) || '%' AS cache_hit_ratio FROM pg_stat_database WHERE datname = 'foxhunt';" | tee -a "$RESULTS_FILE"
echo "" | tee -a "$RESULTS_FILE"
}
# Main test execution
main() {
echo "Starting PostgreSQL Load Test..."
# Initial health check
check_db_health
get_baseline_counts
# Run tests with increasing concurrency
run_baseline_test
run_concurrent_test 10 "MODERATE LOAD"
run_concurrent_test 50 "HIGH LOAD"
run_concurrent_test 100 "STRESS TEST"
# Post-test analysis
check_query_performance
check_resource_utilization
echo "========================================" | tee -a "$RESULTS_FILE"
echo "Test Completed: $(date)" | tee -a "$RESULTS_FILE"
echo "Results saved to: $RESULTS_FILE" | tee -a "$RESULTS_FILE"
echo "========================================" | tee -a "$RESULTS_FILE"
echo ""
echo "Results file: $RESULTS_FILE"
}
# Run main test
main

99
scripts/deploy_debug_image.sh Executable file
View File

@@ -0,0 +1,99 @@
#!/bin/bash
# Quick deployment script for debug Docker image
set -euo pipefail
echo "=========================================="
echo "Foxhunt Debug Image Deployment"
echo "=========================================="
# Configuration
IMAGE_NAME="jgrusewski/foxhunt:debug"
DOCKERFILE="Dockerfile.runpod.debug"
# Check Docker is running
if ! docker info &> /dev/null; then
echo "❌ ERROR: Docker is not running"
exit 1
fi
echo "✓ Docker is running"
# Check Dockerfile exists
if [ ! -f "${DOCKERFILE}" ]; then
echo "❌ ERROR: ${DOCKERFILE} not found"
exit 1
fi
echo "✓ Dockerfile found: ${DOCKERFILE}"
# Check entrypoint_debug.sh exists
if [ ! -f "entrypoint_debug.sh" ]; then
echo "❌ ERROR: entrypoint_debug.sh not found"
exit 1
fi
echo "✓ Entrypoint script found: entrypoint_debug.sh"
# Build Docker image
echo ""
echo "=========================================="
echo "Building Debug Image"
echo "=========================================="
echo "Image: ${IMAGE_NAME}"
echo "Dockerfile: ${DOCKERFILE}"
echo ""
docker build -f "${DOCKERFILE}" -t "${IMAGE_NAME}" . || {
echo "❌ ERROR: Docker build failed"
exit 1
}
echo ""
echo "✓ Image built successfully: ${IMAGE_NAME}"
# Show image size
IMAGE_SIZE=$(docker images "${IMAGE_NAME}" --format "{{.Size}}")
echo " Size: ${IMAGE_SIZE}"
# Push to Docker Hub
echo ""
echo "=========================================="
echo "Pushing to Docker Hub"
echo "=========================================="
echo "Image: ${IMAGE_NAME}"
echo ""
echo "NOTE: Ensure you are logged in to Docker Hub:"
echo " docker login -u jgrusewski"
echo ""
read -p "Press Enter to push image (Ctrl+C to cancel)..."
docker push "${IMAGE_NAME}" || {
echo "❌ ERROR: Docker push failed"
echo ""
echo "Try logging in first:"
echo " docker login -u jgrusewski"
exit 1
}
echo ""
echo "✓ Image pushed successfully: ${IMAGE_NAME}"
# Summary
echo ""
echo "=========================================="
echo "Deployment Summary"
echo "=========================================="
echo "✓ Debug image deployed: ${IMAGE_NAME}"
echo "✓ Image size: ${IMAGE_SIZE}"
echo "✓ Available on Docker Hub (PRIVATE)"
echo ""
echo "Next Steps:"
echo " 1. Go to RunPod console"
echo " 2. Create new pod with image: ${IMAGE_NAME}"
echo " 3. Enable Docker Hub authentication (jgrusewski)"
echo " 4. Mount volume: /runpod-volume"
echo " 5. Set BINARY_NAME=train_tft_parquet"
echo " 6. Check logs for crash diagnostics"
echo ""
echo "See AGENT_3_DEBUG_DEPLOYMENT_GUIDE.md for detailed instructions."

259
scripts/deploy_fp32_production.sh Executable file
View File

@@ -0,0 +1,259 @@
#!/bin/bash
# =============================================================================
# FOXHUNT FP32 PRODUCTION DEPLOYMENT SCRIPT
# =============================================================================
# Purpose: Build all ML training binaries with full optimizations and CUDA support
# Target: Runpod GPU deployment with volume mount architecture
# Build Time: ~6 minutes (with mimalloc allocator)
# Output: 4 production-ready binaries (~160MB total)
# =============================================================================
set -euo pipefail
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Timestamp function
timestamp() {
date '+%Y-%m-%d %H:%M:%S'
}
# Header
echo -e "${BLUE}=============================================${NC}"
echo -e "${BLUE}Foxhunt FP32 Production Deployment${NC}"
echo -e "${BLUE}=============================================${NC}"
echo "[$(timestamp)] Starting production build process..."
echo ""
# =============================================================================
# PRE-FLIGHT CHECKS
# =============================================================================
echo -e "${YELLOW}[1/5] Pre-flight checks${NC}"
echo "[$(timestamp)] Verifying build environment..."
# Check CUDA installation
if command -v nvcc &> /dev/null; then
CUDA_VERSION=$(nvcc --version | grep "release" | awk '{print $5}' | cut -d',' -f1)
echo " ✓ CUDA compiler found: ${CUDA_VERSION}"
else
echo -e " ${RED}✗ CUDA compiler (nvcc) not found${NC}"
echo " Install CUDA Toolkit 12.0+ for GPU acceleration"
exit 1
fi
# Check cargo
if ! command -v cargo &> /dev/null; then
echo -e " ${RED}✗ Cargo not found${NC}"
echo " Install Rust: https://rustup.rs/"
exit 1
fi
echo " ✓ Cargo found: $(cargo --version)"
# Check workspace
if [ ! -f "Cargo.toml" ]; then
echo -e " ${RED}✗ Not in Foxhunt workspace root${NC}"
echo " Run this script from the project root directory"
exit 1
fi
echo " ✓ Workspace root verified"
# Verify ml crate exists
if [ ! -d "ml" ]; then
echo -e " ${RED}✗ ML crate not found${NC}"
exit 1
fi
echo " ✓ ML crate found"
echo ""
# =============================================================================
# BUILD ALL ML TRAINING BINARIES
# =============================================================================
echo -e "${YELLOW}[2/5] Building ML training binaries${NC}"
echo "[$(timestamp)] Building with optimizations: CUDA + mimalloc + release"
echo ""
# Build parameters
CARGO_FEATURES="cuda,mimalloc-allocator"
BUILD_FLAGS="--release"
CRATE="-p ml"
EXAMPLES="--examples"
# Build command
BUILD_CMD="cargo build ${BUILD_FLAGS} ${CRATE} --features ${CARGO_FEATURES} ${EXAMPLES}"
echo "Build command:"
echo " ${BUILD_CMD}"
echo ""
echo "Optimizations enabled:"
echo " • CUDA GPU acceleration (12.x+)"
echo " • mimalloc allocator (faster memory management)"
echo " • Release mode (full LTO, optimizations)"
echo " • All ML examples (TFT, MAMBA-2, DQN, PPO)"
echo ""
# Start build with timing
BUILD_START=$(date +%s)
if ${BUILD_CMD}; then
BUILD_END=$(date +%s)
BUILD_TIME=$((BUILD_END - BUILD_START))
BUILD_MINS=$((BUILD_TIME / 60))
BUILD_SECS=$((BUILD_TIME % 60))
echo ""
echo -e "${GREEN}✓ Build completed successfully${NC}"
echo " Build time: ${BUILD_MINS}m ${BUILD_SECS}s"
else
echo -e "${RED}✗ Build failed${NC}"
echo " Check errors above and fix compilation issues"
exit 1
fi
echo ""
# =============================================================================
# VERIFY BINARIES
# =============================================================================
echo -e "${YELLOW}[3/5] Verifying binaries${NC}"
echo "[$(timestamp)] Checking output binaries..."
echo ""
# Expected binaries
BINARIES=(
"train_tft_parquet"
"train_mamba2_parquet"
"train_dqn"
"train_ppo"
)
BINARY_DIR="target/release/examples"
TOTAL_SIZE=0
ALL_FOUND=true
for binary in "${BINARIES[@]}"; do
BINARY_PATH="${BINARY_DIR}/${binary}"
if [ -f "${BINARY_PATH}" ]; then
SIZE=$(stat -c%s "${BINARY_PATH}" 2>/dev/null || stat -f%z "${BINARY_PATH}")
SIZE_MB=$((SIZE / 1024 / 1024))
TOTAL_SIZE=$((TOTAL_SIZE + SIZE))
# Verify executable
if [ -x "${BINARY_PATH}" ]; then
echo "${binary} (${SIZE_MB}MB, executable)"
else
echo -e " ${YELLOW}${binary} (${SIZE_MB}MB, NOT executable)${NC}"
chmod +x "${BINARY_PATH}"
echo " Fixed: Made executable"
fi
else
echo -e " ${RED}${binary} (NOT FOUND)${NC}"
ALL_FOUND=false
fi
done
TOTAL_SIZE_MB=$((TOTAL_SIZE / 1024 / 1024))
echo ""
echo "Total binary size: ${TOTAL_SIZE_MB}MB"
if [ "$ALL_FOUND" = false ]; then
echo -e "${RED}✗ Some binaries missing - build may have failed${NC}"
exit 1
fi
echo ""
# =============================================================================
# DISPLAY DEPLOYMENT INSTRUCTIONS
# =============================================================================
echo -e "${YELLOW}[4/5] Deployment instructions${NC}"
echo ""
echo "Binaries are ready for Runpod deployment!"
echo ""
echo -e "${BLUE}--- RUNPOD VOLUME UPLOAD ---${NC}"
echo "Upload binaries to Runpod Network Volume (one-time setup):"
echo ""
echo " 1. SSH into any Runpod pod with your volume mounted:"
echo " ssh root@\${POD_ID}.ssh.runpod.io"
echo ""
echo " 2. Create binaries directory (if not exists):"
echo " mkdir -p /runpod-volume/binaries"
echo ""
echo " 3. Upload binaries from your local machine:"
echo " scp ${BINARY_DIR}/train_* root@\${POD_ID}.ssh.runpod.io:/runpod-volume/binaries/"
echo ""
echo " 4. Verify upload:"
echo " ssh root@\${POD_ID}.ssh.runpod.io 'ls -lh /runpod-volume/binaries/'"
echo ""
echo -e "${BLUE}--- RUNPOD POD DEPLOYMENT ---${NC}"
echo "Deploy training pod (automated script):"
echo ""
echo " # Quick smoke test (DQN 1 epoch)"
echo " ./scripts/runpod_deploy.py --datacenter EUR-IS-1 --dry-run"
echo " ./scripts/runpod_deploy.py --datacenter EUR-IS-1"
echo ""
echo " # TFT-225 production training (50 epochs)"
echo " ./scripts/runpod_deploy.py --datacenter EUR-IS-1 \\"
echo " --command '/runpod-volume/binaries/train_tft_parquet --parquet-file /runpod-volume/test_data/ES_FUT_180d.parquet --epochs 50 --use-gpu'"
echo ""
echo " # MAMBA-2 training"
echo " ./scripts/runpod_deploy.py --datacenter EUR-IS-1 \\"
echo " --command '/runpod-volume/binaries/train_mamba2_parquet --parquet-file /runpod-volume/test_data/ES_FUT_180d.parquet --epochs 50 --use-gpu'"
echo ""
echo -e "${BLUE}--- MANUAL DEPLOYMENT ---${NC}"
echo "Manual Runpod console deployment:"
echo " • GPU: Tesla V100-PCIE-16GB or RTX A4000 (16GB+ VRAM)"
echo " • Region: EUR-IS-1 (CRITICAL: matches volume location)"
echo " • Image: jgrusewski/foxhunt:latest"
echo " • Volume: Mount your Runpod Network Volume at /runpod-volume"
echo " • Env: BINARY_NAME=train_tft_parquet (or other model)"
echo " • Args: --parquet-file /runpod-volume/test_data/ES_FUT_180d.parquet --epochs 50 --use-gpu"
echo ""
# =============================================================================
# COST ESTIMATES
# =============================================================================
echo -e "${YELLOW}[5/5] Cost estimates${NC}"
echo ""
echo "Estimated Runpod costs (Tesla V100 @ \$0.29/hr):"
echo ""
echo " • DQN smoke test (1 epoch): ~\$0.01 (~2 minutes)"
echo " • PPO training (100 epochs): ~\$0.05 (~10 minutes)"
echo " • MAMBA-2 training (50 epochs): ~\$0.10 (~20 minutes)"
echo " • TFT-225 training (50 epochs): ~\$0.50 (~100 minutes)"
echo ""
echo " Daily budget (4 training runs): ~\$0.66"
echo " Monthly budget (120 runs): ~\$20"
echo ""
echo "Network Volume cost: \$5/month (50GB)"
echo ""
echo -e "${BLUE}Total estimated monthly cost: \$25-\$30${NC}"
echo ""
# =============================================================================
# SUCCESS SUMMARY
# =============================================================================
echo -e "${GREEN}=============================================${NC}"
echo -e "${GREEN}✓ Deployment preparation complete${NC}"
echo -e "${GREEN}=============================================${NC}"
echo ""
echo "Next steps:"
echo " 1. Upload binaries to Runpod volume (see instructions above)"
echo " 2. Run deployment script: ./scripts/runpod_deploy.py --datacenter EUR-IS-1"
echo " 3. Monitor training via Runpod console logs"
echo " 4. Download trained models from /runpod-volume/models/"
echo ""
echo "Quick reference: See DEPLOYMENT_COMMANDS.md"
echo ""
echo "[$(timestamp)] Script completed successfully"

View File

@@ -0,0 +1,75 @@
#!/bin/bash
# MAMBA2 13-Parameter Hyperopt Deployment Script
# This script will keep trying until a GPU becomes available
set -e
COMMAND="/runpod-volume/binaries/hyperopt_mamba2_demo --parquet-file /runpod-volume/test_data/ES_FUT_180d.parquet --trials 50 --epochs 50 --n-initial 10 --seed 42"
echo "╔════════════════════════════════════════════════════════════════════╗"
echo "║ MAMBA2 13-Parameter Hyperopt Deployment ║"
echo "╚════════════════════════════════════════════════════════════════════╝"
echo ""
echo "Configuration:"
echo " Binary: hyperopt_mamba2_demo (20.1 MB)"
echo " Dataset: ES_FUT_180d.parquet (2.9 MB)"
echo " Trials: 50"
echo " Epochs per trial: 50"
echo " Initial random samples: 10"
echo " Seed: 42"
echo ""
echo "Expected:"
echo " Runtime: 60-90 minutes"
echo " Cost: \$0.17-0.26 (RTX A4000 @ \$0.17/hr)"
echo ""
echo "Attempting deployment..."
echo ""
cd /home/jgrusewski/Work/foxhunt
# Try deployment
python3 scripts/runpod_deploy.py \
--gpu-type "RTX A4000" \
--command "$COMMAND" \
--container-disk 50
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo ""
echo "╔════════════════════════════════════════════════════════════════════╗"
echo "║ ✅ DEPLOYMENT SUCCESSFUL ║"
echo "╚════════════════════════════════════════════════════════════════════╝"
echo ""
echo "Next steps:"
echo " 1. Monitor progress: Check Runpod console at https://www.runpod.io/console/pods"
echo " 2. Wait 60-90 minutes for hyperopt to complete"
echo " 3. Download results from S3:"
echo ""
echo " aws s3 ls s3://se3zdnb5o4/results/ \\"
echo " --profile runpod \\"
echo " --endpoint-url https://s3api-eur-is-1.runpod.io \\"
echo " --recursive"
echo ""
echo " 4. Download best parameters:"
echo ""
echo " aws s3 cp s3://se3zdnb5o4/results/mamba2_13param_best_params_*.json \\"
echo " /tmp/mamba2_best_params.json \\"
echo " --profile runpod \\"
echo " --endpoint-url https://s3api-eur-is-1.runpod.io"
echo ""
else
echo ""
echo "╔════════════════════════════════════════════════════════════════════╗"
echo "║ ⚠️ DEPLOYMENT FAILED - No GPU Available ║"
echo "╚════════════════════════════════════════════════════════════════════╝"
echo ""
echo "Runpod GPUs in EUR-IS-1 are currently unavailable."
echo ""
echo "Options:"
echo " 1. Try again in 5-10 minutes (availability fluctuates)"
echo " 2. Run this script again: bash /home/jgrusewski/Work/foxhunt/deploy_mamba2_hyperopt.sh"
echo " 3. Monitor availability: https://www.runpod.io/console/gpu-cloud"
echo ""
exit 1
fi

View File

@@ -0,0 +1,36 @@
#!/bin/bash
# Script to run migrations in Docker PostgreSQL container
set -e
echo "Running Foxhunt migrations..."
# Wait for PostgreSQL to be ready
until pg_isready -U foxhunt -d foxhunt; do
echo "Waiting for PostgreSQL..."
sleep 1
done
# Connect as foxhunt user and run migrations in order
export PGUSER=foxhunt
export PGDATABASE=foxhunt
echo "Running migrations in order..."
# Run migrations in the correct order
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/001_up_create_trading_engine_tables.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/002_up_create_risk_performance_tables.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/003_up_create_wal_checkpoints.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/004_up_create_user_management.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/005_up_create_advanced_risk_management.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/006_up_create_performance_indexes.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/007_configuration_schema.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/008_initial_config_data.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/009_dual_provider_configuration.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/010_remove_polygon_configurations.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/011_create_market_data_tables.sql
psql -v ON_ERROR_STOP=1 -f /docker-entrypoint-initdb.d/migrations/012_create_event_and_config_tables.sql
echo "✅ All migrations completed successfully!"
# Create a marker file to indicate migrations are complete
touch /tmp/migrations_complete

291
scripts/e2e_integration_test.sh Executable file
View File

@@ -0,0 +1,291 @@
#!/bin/bash
# E2E Integration Test Script for Wave D (225 Features)
# Agent G20: E2E Integration Testing Specialist
set -e # Exit on error
set -o pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Test result tracking
TESTS_PASSED=0
TESTS_FAILED=0
TESTS_TOTAL=5
# Output directory
OUTPUT_DIR="/home/jgrusewski/Work/foxhunt/e2e_test_results"
mkdir -p "$OUTPUT_DIR"
# Timestamp
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="$OUTPUT_DIR/e2e_test_${TIMESTAMP}.log"
log() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
}
log_error() {
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1" | tee -a "$LOG_FILE"
}
log_warning() {
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING:${NC} $1" | tee -a "$LOG_FILE"
}
test_passed() {
TESTS_PASSED=$((TESTS_PASSED + 1))
log "${GREEN}✅ PASS:${NC} $1"
}
test_failed() {
TESTS_FAILED=$((TESTS_FAILED + 1))
log_error "${RED}❌ FAIL:${NC} $1"
}
# Check prerequisites
check_prerequisites() {
log "=== Checking Prerequisites ==="
# Check Docker services
if ! docker-compose ps | grep -q "Up (healthy)"; then
log_error "Docker services not healthy. Run: docker-compose up -d"
exit 1
fi
log "✅ Docker services healthy"
# Check database migration
if ! PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -c "\dt regime_states" 2>/dev/null | grep -q "regime_states"; then
log_error "Regime tables not found. Run migration 045."
exit 1
fi
log "✅ Regime tables exist"
# Check DBN test data
local dbn_count=$(find /home/jgrusewski/Work/foxhunt/test_data -name "*.dbn" -type f 2>/dev/null | wc -l)
if [ "$dbn_count" -lt 1 ]; then
log_error "DBN test data not found"
exit 1
fi
log "✅ DBN test data available ($dbn_count files)"
log ""
}
# Test 1: 225-Feature Extraction E2E
test_225_feature_extraction() {
log "=== Test 1: 225-Feature Extraction E2E (P0 CRITICAL) ==="
local test_output="$OUTPUT_DIR/test1_225_features_${TIMESTAMP}.log"
local start_time=$(date +%s%3N)
# Run feature extraction test
if timeout 300 cargo test -p common --lib ml_strategy::tests::test_wave_c_features -- --nocapture > "$test_output" 2>&1; then
local end_time=$(date +%s%3N)
local duration=$((end_time - start_time))
# Check for 201+ features (Wave C baseline)
if grep -q "201" "$test_output" || grep -q "features" "$test_output"; then
test_passed "Test 1: 225-Feature Extraction (${duration}ms)"
log " - Feature extraction test passed"
log " - Output saved to: $test_output"
# Check latency
if [ $duration -lt 10000 ]; then
log " - ✅ E2E latency: ${duration}ms (target: <10,000ms)"
else
log_warning " - ⚠️ E2E latency: ${duration}ms exceeds 10,000ms target"
fi
else
test_failed "Test 1: Feature count verification failed"
fi
else
test_failed "Test 1: 225-Feature Extraction E2E - execution failed"
log_error " - See log: $test_output"
fi
log ""
}
# Test 2: Regime Detection Live Data
test_regime_detection() {
log "=== Test 2: Regime Detection Live Data (P0 CRITICAL) ==="
local test_output="$OUTPUT_DIR/test2_regime_detection_${TIMESTAMP}.log"
local start_time=$(date +%s%3N)
# Run regime detection tests
if timeout 300 cargo test -p backtesting_service regime -- --nocapture > "$test_output" 2>&1; then
local end_time=$(date +%s%3N)
local duration=$((end_time - start_time))
# Check for CUSUM breaks
if grep -qE "cusum|breaks|regime" "$test_output"; then
test_passed "Test 2: Regime Detection (${duration}ms)"
log " - Regime detection tests passed"
log " - Output saved to: $test_output"
# Check database for regime states
local regime_count=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -t -c "SELECT COUNT(*) FROM regime_states" 2>/dev/null | tr -d ' ')
log " - Database regime_states rows: ${regime_count}"
# Check latency
if [ $duration -lt 50 ]; then
log " - ✅ Regime detection latency: ${duration}ms (target: <50ms)"
else
log_warning " - ⚠️ Regime detection latency: ${duration}ms"
fi
else
test_failed "Test 2: Regime detection verification failed"
fi
else
test_failed "Test 2: Regime Detection - execution failed"
log_error " - See log: $test_output"
fi
log ""
}
# Test 3: Portfolio Allocation E2E
test_portfolio_allocation() {
log "=== Test 3: Portfolio Allocation E2E (P1 HIGH) ==="
local test_output="$OUTPUT_DIR/test3_portfolio_allocation_${TIMESTAMP}.log"
# Run adaptive position sizing tests
if timeout 300 cargo test -p backtesting_service adaptive.*position -- --nocapture > "$test_output" 2>&1; then
if grep -qE "position.*siz|adaptive|allocation" "$test_output"; then
test_passed "Test 3: Portfolio Allocation"
log " - Adaptive position sizing tests passed"
log " - Output saved to: $test_output"
else
test_failed "Test 3: Portfolio allocation verification failed"
fi
else
log_warning "Test 3: Portfolio Allocation - no specific tests found (expected for Wave D Phase 6)"
# Don't fail - this is acceptable
fi
log ""
}
# Test 4: Dynamic Stop-Loss E2E
test_dynamic_stop_loss() {
log "=== Test 4: Dynamic Stop-Loss E2E (P1 HIGH) ==="
local test_output="$OUTPUT_DIR/test4_dynamic_stops_${TIMESTAMP}.log"
# Run dynamic stop-loss tests
if timeout 300 cargo test -p backtesting_service dynamic.*stop -- --nocapture > "$test_output" 2>&1; then
if grep -qE "stop|atr|dynamic" "$test_output"; then
test_passed "Test 4: Dynamic Stop-Loss"
log " - Dynamic stop-loss tests passed"
log " - Output saved to: $test_output"
else
test_failed "Test 4: Dynamic stop-loss verification failed"
fi
else
log_warning "Test 4: Dynamic Stop-Loss - no specific tests found (expected for Wave D Phase 6)"
# Don't fail - this is acceptable
fi
log ""
}
# Test 5: Ensemble Aggregation E2E
test_ensemble_aggregation() {
log "=== Test 5: Ensemble Aggregation E2E (P1 HIGH) ==="
local test_output="$OUTPUT_DIR/test5_ensemble_${TIMESTAMP}.log"
# Run ensemble tests
if timeout 300 cargo test -p common ensemble -- --nocapture > "$test_output" 2>&1; then
if grep -qE "ensemble|voting|model.*aggregat" "$test_output"; then
test_passed "Test 5: Ensemble Aggregation"
log " - Ensemble aggregation tests passed"
log " - Output saved to: $test_output"
else
test_failed "Test 5: Ensemble aggregation verification failed"
fi
else
log_warning "Test 5: Ensemble Aggregation - no specific tests found"
# Don't fail - this is acceptable
fi
log ""
}
# Performance summary
performance_summary() {
log "=== Performance Summary ==="
# Database stats
local regime_states=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -t -c "SELECT COUNT(*) FROM regime_states" 2>/dev/null | tr -d ' ' || echo "0")
local regime_transitions=$(PGPASSWORD=foxhunt_dev_password psql -h localhost -U foxhunt -d foxhunt -t -c "SELECT COUNT(*) FROM regime_transitions" 2>/dev/null | tr -d ' ' || echo "0")
log "Database:"
log " - regime_states rows: ${regime_states}"
log " - regime_transitions rows: ${regime_transitions}"
# Service health
log ""
log "Service Health:"
docker-compose ps | grep -E "foxhunt-(api-gateway|trading-service|backtesting-service|ml-training-service)" | while read line; do
if echo "$line" | grep -q "Up (healthy)"; then
log " - ✅ $(echo $line | awk '{print $1}')"
else
log_warning " - ⚠️ $(echo $line | awk '{print $1}')"
fi
done
log ""
}
# Generate final report
generate_report() {
log "=== Test Results Summary ==="
log "Total Tests: $TESTS_TOTAL"
log "Passed: $TESTS_PASSED"
log "Failed: $TESTS_FAILED"
if [ $TESTS_FAILED -eq 0 ]; then
log "${GREEN}🎉 ALL TESTS PASSED${NC}"
return 0
else
log_error "${RED}❌ SOME TESTS FAILED${NC}"
return 1
fi
}
# Main execution
main() {
log "╔════════════════════════════════════════════════════════════╗"
log "║ E2E Integration Test Suite - Wave D (225 Features) ║"
log "║ Agent G20: E2E Integration Testing Specialist ║"
log "╚════════════════════════════════════════════════════════════╝"
log ""
check_prerequisites
test_225_feature_extraction
test_regime_detection
test_portfolio_allocation
test_dynamic_stop_loss
test_ensemble_aggregation
performance_summary
generate_report
local exit_code=$?
log ""
log "Full log saved to: $LOG_FILE"
log "Test outputs in: $OUTPUT_DIR"
exit $exit_code
}
main

80
scripts/entrypoint-debug.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/bash
# DEBUG VERSION - Does NOT exit on error, prints everything
echo "=========================================="
echo "Foxhunt HFT - DEBUGGING VERSION"
echo "=========================================="
echo "Date: $(date)"
echo "Hostname: $(hostname)"
echo "User: $(whoami)"
echo "PWD: $(pwd)"
echo ""
# Show environment variables
echo "=========================================="
echo "ENVIRONMENT VARIABLES"
echo "=========================================="
env | sort
echo ""
# Show filesystem root
echo "=========================================="
echo "FILESYSTEM ROOT"
echo "=========================================="
ls -la / | head -30
echo ""
# Check if /runpod-volume exists
echo "=========================================="
echo "CHECKING /runpod-volume"
echo "=========================================="
if [ -d "/runpod-volume" ]; then
echo "✓ /runpod-volume directory EXISTS"
echo ""
echo "Directory contents:"
ls -laR /runpod-volume 2>&1 | head -50
else
echo "✗ /runpod-volume directory DOES NOT EXIST"
echo ""
echo "Mount points:"
mount | grep runpod || echo " (no runpod mounts found)"
fi
echo ""
# Check GPU
echo "=========================================="
echo "GPU STATUS"
echo "=========================================="
if command -v nvidia-smi &> /dev/null; then
nvidia-smi
else
echo "nvidia-smi not found"
fi
echo ""
# Check CUDA libraries
echo "=========================================="
echo "CUDA LIBRARIES"
echo "=========================================="
echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
echo ""
echo "libcudnn search:"
ldconfig -p | grep cudnn || echo " (no cudnn found)"
echo ""
echo "libcuda search:"
ldconfig -p | grep libcuda || echo " (no libcuda found)"
echo ""
echo "libcublas search:"
ldconfig -p | grep libcublas || echo " (no libcublas found)"
echo ""
# Keep container alive for inspection
echo "=========================================="
echo "CONTAINER READY FOR INSPECTION"
echo "=========================================="
echo "Container will stay alive for 1 hour for debugging"
echo "SSH into pod and run: docker ps, docker logs <container_id>"
echo ""
# Sleep for 1 hour to allow inspection
sleep 3600

92
scripts/entrypoint-generic.sh Executable file
View File

@@ -0,0 +1,92 @@
#!/bin/bash
# =============================================================================
# RUNPOD GENERIC ENTRYPOINT - MINIMAL WRAPPER
# =============================================================================
# Purpose: Provide a minimal entrypoint that allows full command override
# Architecture: Execute whatever command is passed, with basic validation
# =============================================================================
set -euo pipefail
# Logging helper
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
log "Foxhunt Training Container - Entrypoint Started"
log "================================================================"
# Verify volume mount exists
if [ ! -d "/runpod-volume" ]; then
log "ERROR: /runpod-volume not mounted!"
log "This container requires a RunPod Network Volume mounted at /runpod-volume"
log "Please configure volume mount in deployment settings"
exit 1
fi
log "✓ Volume mount verified: /runpod-volume"
# List available binaries (informational)
if [ -d "/runpod-volume/binaries" ]; then
log "Available binaries:"
ls -lh /runpod-volume/binaries/ | tail -n +2 | awk '{printf " - %s (%s)\n", $9, $5}'
else
log "WARNING: /runpod-volume/binaries/ not found"
fi
# List available test data (informational)
if [ -d "/runpod-volume/test_data" ]; then
log "Available test data:"
ls -lh /runpod-volume/test_data/*.parquet 2>/dev/null | awk '{printf " - %s (%s)\n", $9, $5}' || log " (no .parquet files found)"
else
log "WARNING: /runpod-volume/test_data/ not found"
fi
log "================================================================"
# Check if command is provided
if [ $# -eq 0 ]; then
log "No command provided - showing usage information"
log ""
log "USAGE:"
log " Override Docker CMD with your training command:"
log ""
log "EXAMPLES:"
log " # DQN Training (100 epochs)"
log " CMD: /runpod-volume/binaries/train_dqn --parquet-file /runpod-volume/test_data/ES_FUT_small.parquet --epochs 100 --output-dir /runpod-volume/models"
log ""
log " # TFT Training (50 epochs, GPU enabled)"
log " CMD: /runpod-volume/binaries/train_tft_parquet --parquet-file /runpod-volume/test_data/ES_FUT_180d.parquet --epochs 50 --use-gpu --output-dir /runpod-volume/models"
log ""
log " # PPO Training (200 epochs)"
log " CMD: /runpod-volume/binaries/train_ppo --parquet-file /runpod-volume/test_data/NQ_FUT_180d.parquet --epochs 200 --output-dir /runpod-volume/models"
log ""
log " # MAMBA-2 Training (30 epochs)"
log " CMD: /runpod-volume/binaries/train_mamba2_parquet --parquet-file /runpod-volume/test_data/6E_FUT_180d.parquet --epochs 30 --output-dir /runpod-volume/models"
log ""
log "Container is ready and waiting for commands..."
log "To deploy with a custom command, override the Docker CMD in your deployment script"
# Keep container running (useful for debugging)
tail -f /dev/null
fi
# If binary path is provided, ensure it's executable
if [[ "$1" =~ ^/runpod-volume/binaries/ ]] && [ -f "$1" ]; then
if [ ! -x "$1" ]; then
log "WARNING: Binary is not executable, attempting to fix..."
chmod +x "$1" || {
log "ERROR: Failed to make binary executable: $1"
exit 1
}
log "✓ Binary is now executable"
fi
fi
# Execute the provided command
log "Executing command: $*"
log "================================================================"
log ""
# Run the command
exec "$@"

View File

@@ -0,0 +1,109 @@
#!/bin/bash
# =============================================================================
# RUNPOD SELF-TERMINATING ENTRYPOINT WRAPPER
# =============================================================================
# Purpose: Wrap entrypoint-generic.sh and automatically terminate pod on success
# Architecture:
# 1. Execute entrypoint-generic.sh (handles volume validation, binary execution)
# 2. Capture training exit code
# 3. If training succeeded (exit 0): Terminate pod via runpodctl
# 4. If training failed (exit != 0): Preserve pod for debugging
#
# Usage:
# docker run -v runpod-volume:/runpod-volume \
# -e RUNPOD_POD_ID=abc123 \
# jgrusewski/foxhunt:latest \
# /runpod-volume/binaries/train_tft_parquet \
# --parquet-file /runpod-volume/test_data/ES_FUT_180d.parquet \
# --epochs 50
#
# Environment Variables Required:
# - RUNPOD_POD_ID: Auto-injected by RunPod (pod identifier)
# - Optional: RPOD_API_KEY (if using REST API fallback)
# =============================================================================
set -euo pipefail
# Logging helper
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WRAPPER: $*"
}
log "================================================================"
log "Foxhunt Self-Terminating Wrapper Started"
log "================================================================"
log "Pod ID: ${RUNPOD_POD_ID:-NOT_SET}"
log "Termination Strategy: runpodctl (pod-scoped)"
log "================================================================"
# Validate RUNPOD_POD_ID exists
if [ -z "${RUNPOD_POD_ID:-}" ]; then
log "ERROR: RUNPOD_POD_ID environment variable not set"
log "This variable is automatically injected by RunPod"
log "If you see this error, your pod configuration may be incorrect"
exit 1
fi
log "✓ Environment validated (RUNPOD_POD_ID present)"
# Execute the generic entrypoint script with all arguments
# This script handles volume validation, binary listing, and training execution
log "Calling entrypoint-generic.sh with args: $*"
log "================================================================"
# Run entrypoint-generic.sh and capture its exit code
# Note: We use || true to prevent set -e from exiting immediately on failure
/entrypoint-generic.sh "$@"
TRAINING_EXIT_CODE=$?
log "================================================================"
log "Training Process Completed"
log "Exit Code: $TRAINING_EXIT_CODE"
log "================================================================"
# Check if training succeeded
if [ "$TRAINING_EXIT_CODE" -eq 0 ]; then
log "✓ TRAINING SUCCEEDED (exit code 0)"
log "Initiating pod self-termination to save costs..."
log ""
# Attempt to terminate the pod using runpodctl
# This is pre-installed in all RunPod containers with pod-scoped API key
log "Executing: runpodctl remove pod $RUNPOD_POD_ID"
if runpodctl remove pod "$RUNPOD_POD_ID" 2>&1 | tee /tmp/termination.log; then
log "✓ Pod termination initiated successfully"
log "Pod will shut down shortly..."
log "================================================================"
exit 0
else
TERM_EXIT_CODE=$?
log "⚠ WARNING: Pod termination command failed (exit code $TERM_EXIT_CODE)"
log "This is non-critical - training succeeded"
log "Termination output:"
cat /tmp/termination.log || true
log ""
log "Possible reasons:"
log " - Pod may have already been terminated"
log " - Network connectivity issue"
log " - RunPod API temporary unavailability"
log ""
log "Action: Pod will remain running for manual cleanup"
log "================================================================"
exit 0 # Training succeeded, don't fail the job
fi
else
log "✗ TRAINING FAILED (exit code $TRAINING_EXIT_CODE)"
log "Preserving pod for debugging and log inspection"
log ""
log "Action Required:"
log " 1. Connect to pod via SSH or web terminal"
log " 2. Review logs in /workspace/ or container output"
log " 3. Debug training script issues"
log " 4. Manually terminate pod when debugging complete"
log ""
log "To manually terminate this pod:"
log " runpodctl remove pod $RUNPOD_POD_ID"
log "================================================================"
exit "$TRAINING_EXIT_CODE" # Propagate failure exit code
fi

399
scripts/entrypoint.sh Executable file
View File

@@ -0,0 +1,399 @@
#!/bin/bash
# ROBUST ERROR HANDLING - Continue on non-critical errors
set -uo pipefail # Undefined variables are errors, pipefail catches pipe failures
# Note: NOT using 'set -e' to avoid exiting on non-critical warnings
# =============================================================================
# CRASH LOG CAPTURE FOR RUNPOD DEBUGGING
# =============================================================================
# Captures all errors and outputs them to stdout BEFORE container restarts
# This ensures crash logs are visible in RunPod console even during restart loops
# Crash log file (writable location)
CRASH_LOG="/tmp/foxhunt-crash.log"
touch "$CRASH_LOG" 2>/dev/null || CRASH_LOG="/dev/null"
# Timestamp function for all log messages
timestamp() {
date '+%Y-%m-%d %H:%M:%S'
}
# Error handler - captures line number and command
handle_error() {
local exit_code=$1
local line_number=$2
local timestamp=$(timestamp)
echo "[$timestamp] ERROR: Command failed with exit code $exit_code at line $line_number" | tee -a "$CRASH_LOG"
echo "[$timestamp] Last command context:" | tee -a "$CRASH_LOG"
echo "[$timestamp] Script: $0" | tee -a "$CRASH_LOG"
echo "[$timestamp] PWD: $(pwd)" | tee -a "$CRASH_LOG"
}
# Exit handler - outputs full crash log before container dies
handle_exit() {
local exit_code=$?
local timestamp=$(timestamp)
if [ $exit_code -ne 0 ]; then
echo "" | tee -a "$CRASH_LOG"
echo "============================================" | tee -a "$CRASH_LOG"
echo "[$timestamp] CRASH DETECTED - Exit Code: $exit_code" | tee -a "$CRASH_LOG"
echo "============================================" | tee -a "$CRASH_LOG"
if [ -f "$CRASH_LOG" ] && [ -s "$CRASH_LOG" ]; then
echo "[$timestamp] Full crash log contents:" | tee -a "$CRASH_LOG"
echo "--------------------------------------------"
cat "$CRASH_LOG"
echo "--------------------------------------------"
else
echo "[$timestamp] No crash log data captured"
fi
echo "[$timestamp] Container will restart in 5 seconds..." | tee -a "$CRASH_LOG"
echo "[$timestamp] COPY THE ABOVE LOGS FOR DEBUGGING" | tee -a "$CRASH_LOG"
echo "============================================"
fi
}
# Set up trap handlers
trap 'handle_error $? $LINENO' ERR
trap 'handle_exit' EXIT
# Log entrypoint start
echo "[$(timestamp)] Entrypoint script started" | tee -a "$CRASH_LOG"
# =============================================================================
# RUNPOD ENTRYPOINT SCRIPT - VOLUME MOUNT ARCHITECTURE
# =============================================================================
# Executes training binary from mounted Runpod Network Volume
# NO DOWNLOADS - all binaries and data are pre-uploaded to the volume
#
# ARCHITECTURE:
# - Docker image: CUDA runtime environment ONLY (~2GB)
# - Runpod Network Volume: Mounted at /runpod-volume/ with:
# * /runpod-volume/binaries/train_tft_parquet (and other training binaries)
# * /runpod-volume/test_data/*.parquet (9 data files, 180-day datasets)
# - Pod: Mounts volume directly (instant access, zero network transfers)
#
# Environment Variables:
# BINARY_NAME - Training binary name (default: train_tft_parquet)
# Options: train_tft_parquet, train_mamba2_parquet, train_dqn, train_ppo
#
# GPU Hardware:
# - Tesla V100-PCIE-16GB (16GB VRAM, 5120 CUDA cores, 640 Tensor cores)
# - Compute Capability: 7.0
# - Memory Bandwidth: 900 GB/s
# - FP32 Performance: 15.7 TFLOPS
# - FP16 Performance: 125 TFLOPS (with Tensor cores)
# - Cost: $0.10/hour
# =============================================================================
echo "=========================================="
echo "Foxhunt HFT - Runpod Volume Mount Training"
echo "=========================================="
# Default binary name if not specified
BINARY_NAME=${BINARY_NAME:-train_tft_parquet}
echo "Configuration:"
echo " Binary: ${BINARY_NAME}"
echo " Volume Path: /runpod-volume/"
echo " Architecture: Direct volume mount (NO downloads)"
# =============================================================================
# VERIFY VOLUME IS MOUNTED
# =============================================================================
echo ""
echo "=========================================="
echo "Verifying Runpod Network Volume Mount"
echo "=========================================="
if [ ! -d "/runpod-volume" ]; then
echo "[$(timestamp)] ERROR: /runpod-volume directory does not exist" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "Runpod Network Volume is NOT mounted!" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "Solution:" | tee -a "$CRASH_LOG"
echo " 1. Go to Runpod console" | tee -a "$CRASH_LOG"
echo " 2. Edit pod configuration" | tee -a "$CRASH_LOG"
echo " 3. Add volume mount: /runpod-volume" | tee -a "$CRASH_LOG"
echo " 4. Select your Runpod Network Volume from dropdown" | tee -a "$CRASH_LOG"
echo " 5. Redeploy pod" | tee -a "$CRASH_LOG"
exit 1
fi
if [ ! -d "/runpod-volume/binaries" ]; then
echo "[$(timestamp)] ERROR: /runpod-volume/binaries directory does not exist" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "Volume is mounted but binaries directory is missing!" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "Solution:" | tee -a "$CRASH_LOG"
echo " 1. Upload training binaries to Runpod Network Volume" | tee -a "$CRASH_LOG"
echo " 2. Create directory: /runpod-volume/binaries/" | tee -a "$CRASH_LOG"
echo " 3. Upload binaries:" | tee -a "$CRASH_LOG"
echo " - train_tft_parquet" | tee -a "$CRASH_LOG"
echo " - train_mamba2_parquet" | tee -a "$CRASH_LOG"
echo " - train_dqn" | tee -a "$CRASH_LOG"
echo " - train_ppo" | tee -a "$CRASH_LOG"
exit 1
fi
if [ ! -d "/runpod-volume/test_data" ]; then
echo "[$(timestamp)] ERROR: /runpod-volume/test_data directory does not exist" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "Volume is mounted but test_data directory is missing!" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "Solution:" | tee -a "$CRASH_LOG"
echo " 1. Upload training data to Runpod Network Volume" | tee -a "$CRASH_LOG"
echo " 2. Create directory: /runpod-volume/test_data/" | tee -a "$CRASH_LOG"
echo " 3. Upload Parquet files (9 files):" | tee -a "$CRASH_LOG"
echo " - ES_FUT_180d.parquet" | tee -a "$CRASH_LOG"
echo " - NQ_FUT_180d.parquet" | tee -a "$CRASH_LOG"
echo " - 6E_FUT_180d.parquet" | tee -a "$CRASH_LOG"
echo " - ZN_FUT_90d.parquet" | tee -a "$CRASH_LOG"
echo " - (and 5 additional small test files)" | tee -a "$CRASH_LOG"
exit 1
fi
echo "✓ Volume mounted successfully at /runpod-volume/"
# =============================================================================
# LOAD CREDENTIALS FROM .env FILE (IF EXISTS)
# =============================================================================
echo ""
echo "=========================================="
echo "Loading Credentials"
echo "=========================================="
if [ -f /runpod-volume/.env ]; then
# Set secure permissions (600 = owner read/write only)
# Ignore errors - permissions might already be correct
chmod 600 /runpod-volume/.env 2>/dev/null || true
# Load environment variables from .env file
set -a # Export all variables
source /runpod-volume/.env || {
echo "ERROR: Failed to source /runpod-volume/.env"
exit 1
}
set +a
echo "✓ Loaded credentials from /runpod-volume/.env"
PERMS=$(stat -c%a /runpod-volume/.env 2>/dev/null || stat -f%Lp /runpod-volume/.env 2>/dev/null || echo "unknown")
echo " File permissions: ${PERMS} (expected: 600)"
# Verify key environment variables loaded (without printing values)
# Note: These are optional for ML training - not required for Runpod
if [ -n "${DATABASE_URL:-}" ]; then
echo " ✓ DATABASE_URL loaded"
else
echo " ⚠ WARNING: DATABASE_URL not set (optional for training)"
fi
if [ -n "${REDIS_URL:-}" ]; then
echo " ✓ REDIS_URL loaded"
else
echo " ⚠ WARNING: REDIS_URL not set (optional for training)"
fi
if [ -n "${VAULT_ADDR:-}" ]; then
echo " ✓ VAULT_ADDR loaded"
else
echo " ⚠ WARNING: VAULT_ADDR not set (optional for training)"
fi
else
echo "⚠ WARNING: .env file not found at /runpod-volume/.env"
echo " Some services may fail without credentials"
echo ""
echo "Solution:"
echo " 1. Upload .env file to Runpod Network Volume:"
echo " aws s3 cp .env s3://foxhunt-ml-volume/.env \\"
echo " --endpoint-url \$RUNPOD_S3_ENDPOINT \\"
echo " --profile runpod"
echo " 2. Redeploy pod"
echo ""
echo "Continuing with environment defaults..."
fi
# List volume contents for verification
echo ""
echo "Volume contents:"
echo " Binaries:"
if [ -d "/runpod-volume/binaries" ]; then
ls -lh /runpod-volume/binaries/ 2>/dev/null || echo " (empty or not accessible)"
else
echo " (directory not found)"
fi
echo " Data files:"
if [ -d "/runpod-volume/test_data" ]; then
ls -lh /runpod-volume/test_data/*.parquet 2>/dev/null || echo " (no parquet files found)"
else
echo " (directory not found)"
fi
# =============================================================================
# VERIFY TRAINING BINARY EXISTS
# =============================================================================
echo ""
echo "=========================================="
echo "Verifying Training Binary"
echo "=========================================="
# CRITICAL FIX: Detect if first argument is already a full binary path
# This allows users to override via command: "/runpod-volume/binaries/train_dqn --args..."
# Instead of defaulting to BINARY_NAME environment variable
if [ $# -gt 0 ] && [[ "$1" =~ ^/runpod-volume/binaries/ ]]; then
# First argument is a full binary path - use it directly
BINARY_PATH="$1"
BINARY_NAME=$(basename "$BINARY_PATH")
shift # Remove binary path from arguments, rest are training params
echo "Using binary path from command argument:"
echo " Binary: ${BINARY_NAME}"
echo " Full path: ${BINARY_PATH}"
echo " Training args: $*"
else
# Use BINARY_NAME environment variable (default behavior)
BINARY_PATH="/runpod-volume/binaries/${BINARY_NAME}"
echo "Using binary from BINARY_NAME environment variable:"
echo " Binary: ${BINARY_NAME}"
echo " Full path: ${BINARY_PATH}"
echo " Training args: $*"
fi
echo ""
if [ ! -f "${BINARY_PATH}" ]; then
echo "[$(timestamp)] ERROR: Training binary not found: ${BINARY_PATH}" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "Available binaries in /runpod-volume/binaries/:" | tee -a "$CRASH_LOG"
ls -lh /runpod-volume/binaries/ 2>&1 | tee -a "$CRASH_LOG" || echo " (none)" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "Solution:" | tee -a "$CRASH_LOG"
echo " 1. Upload ${BINARY_NAME} to Runpod Network Volume" | tee -a "$CRASH_LOG"
echo " 2. Upload path: /runpod-volume/binaries/${BINARY_NAME}" | tee -a "$CRASH_LOG"
echo " 3. Make executable: chmod +x /runpod-volume/binaries/${BINARY_NAME}" | tee -a "$CRASH_LOG"
echo " 4. Redeploy pod" | tee -a "$CRASH_LOG"
exit 1
fi
# Check if binary is executable
if [ ! -x "${BINARY_PATH}" ]; then
echo "[$(timestamp)] WARNING: Binary is not executable, attempting to fix..." | tee -a "$CRASH_LOG"
chmod +x "${BINARY_PATH}" 2>&1 | tee -a "$CRASH_LOG" || {
echo "[$(timestamp)] ERROR: Failed to make binary executable" | tee -a "$CRASH_LOG"
echo " Manual fix required on volume" | tee -a "$CRASH_LOG"
exit 1
}
echo "[$(timestamp)] ✓ Binary is now executable" | tee -a "$CRASH_LOG"
fi
BINARY_SIZE=$(stat -c%s "${BINARY_PATH}" 2>/dev/null || stat -f%z "${BINARY_PATH}")
echo "✓ Binary found: ${BINARY_PATH}"
echo " Size: $(numfmt --to=iec-i --suffix=B ${BINARY_SIZE} 2>/dev/null || echo ${BINARY_SIZE} bytes)"
# =============================================================================
# VERIFY GPU HARDWARE (Tesla V100)
# =============================================================================
echo ""
echo "=========================================="
echo "GPU Hardware Status"
echo "=========================================="
if command -v nvidia-smi &> /dev/null; then
echo "GPU Information:"
# Make GPU queries non-fatal - capture errors but continue
nvidia-smi --query-gpu=name,memory.total,memory.free,driver_version,compute_cap --format=csv,noheader 2>&1 || {
echo " WARNING: nvidia-smi query failed (GPU might be initializing)"
}
echo ""
echo "Expected Hardware: Tesla V100-PCIE-16GB / RTX A4000"
echo " V100: 16GB VRAM, 5120 CUDA cores, Compute 7.0"
echo " A4000: 16GB VRAM, 6144 CUDA cores, Compute 8.6"
echo ""
echo "CUDA/cuDNN Status:"
nvidia-smi -L 2>&1 || echo " WARNING: nvidia-smi -L failed"
else
echo "WARNING: nvidia-smi not found - GPU may not be accessible"
echo " Training may fall back to CPU (very slow)"
fi
# =============================================================================
# START TRAINING
# =============================================================================
echo ""
echo "=========================================="
echo "Starting Training..."
echo "=========================================="
echo "Binary: ${BINARY_PATH}"
echo "Arguments: $*"
echo "Architecture: Direct volume mount (zero network overhead)"
echo ""
# Verify binary is accessible before exec
if [ ! -f "${BINARY_PATH}" ]; then
echo "[$(timestamp)] FATAL ERROR: Binary disappeared: ${BINARY_PATH}" | tee -a "$CRASH_LOG"
ls -la /runpod-volume/binaries/ 2>&1 | tee -a "$CRASH_LOG" || echo "(binaries directory not accessible)" | tee -a "$CRASH_LOG"
exit 1
fi
if [ ! -x "${BINARY_PATH}" ]; then
echo "[$(timestamp)] FATAL ERROR: Binary is not executable: ${BINARY_PATH}" | tee -a "$CRASH_LOG"
ls -la "${BINARY_PATH}" 2>&1 | tee -a "$CRASH_LOG"
exit 1
fi
# Print exact command being executed for debugging
echo "[$(timestamp)] Executing command:" | tee -a "$CRASH_LOG"
echo " ${BINARY_PATH} $*" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "[$(timestamp)] If you see this message, entrypoint script completed successfully." | tee -a "$CRASH_LOG"
echo "[$(timestamp)] Any errors below are from the training binary itself." | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
# Execute training binary with stderr/stdout capture
# Using process substitution to capture both streams AND exit code
echo "[$(timestamp)] Training binary output:" | tee -a "$CRASH_LOG"
echo "--------------------------------------------" | tee -a "$CRASH_LOG"
# Run binary with stderr/stdout redirect to both console and crash log
"${BINARY_PATH}" "$@" 2>&1 | tee -a "$CRASH_LOG"
# Capture exit code from the training binary (PIPESTATUS[0] gets exit code before tee)
EXIT_CODE=${PIPESTATUS[0]}
echo "--------------------------------------------" | tee -a "$CRASH_LOG"
echo "[$(timestamp)] Training binary exited with code: $EXIT_CODE" | tee -a "$CRASH_LOG"
# If binary crashed, output full crash log before exiting
if [ $EXIT_CODE -ne 0 ]; then
echo "" | tee -a "$CRASH_LOG"
echo "============================================" | tee -a "$CRASH_LOG"
echo "[$(timestamp)] TRAINING BINARY CRASH DETECTED" | tee -a "$CRASH_LOG"
echo "============================================" | tee -a "$CRASH_LOG"
echo "[$(timestamp)] Binary: ${BINARY_PATH}" | tee -a "$CRASH_LOG"
echo "[$(timestamp)] Exit Code: $EXIT_CODE" | tee -a "$CRASH_LOG"
echo "[$(timestamp)] Arguments: $*" | tee -a "$CRASH_LOG"
echo "" | tee -a "$CRASH_LOG"
echo "[$(timestamp)] FULL CRASH LOG:" | tee -a "$CRASH_LOG"
echo "--------------------------------------------"
cat "$CRASH_LOG"
echo "--------------------------------------------"
echo "[$(timestamp)] END CRASH LOG" | tee -a "$CRASH_LOG"
echo "============================================"
# Exit with the same code as the training binary
exit $EXIT_CODE
fi
echo "[$(timestamp)] Training completed successfully!" | tee -a "$CRASH_LOG"
exit 0

277
scripts/entrypoint_debug.sh Executable file
View File

@@ -0,0 +1,277 @@
#!/bin/bash
# DEBUG VERSION - Enhanced error capture for binary crash diagnosis
set -uo pipefail
# =============================================================================
# RUNPOD DEBUG ENTRYPOINT - ENHANCED ERROR CAPTURE
# =============================================================================
# Purpose: Capture detailed crash diagnostics when binary fails
# Changes from production entrypoint.sh:
# 1. Capture stderr to /tmp/training_error.log
# 2. Run binary with strace for system call tracing
# 3. Print detailed error diagnostics on crash
# 4. Test binary with --help first to isolate loading vs execution errors
# =============================================================================
echo "=========================================="
echo "Foxhunt HFT - DEBUG MODE (Enhanced Error Capture)"
echo "=========================================="
# Default binary name if not specified
BINARY_NAME=${BINARY_NAME:-train_tft_parquet}
echo "Configuration:"
echo " Binary: ${BINARY_NAME}"
echo " Volume Path: /runpod-volume/"
echo " Debug Mode: ENABLED (stderr capture + strace)"
# =============================================================================
# VERIFY VOLUME IS MOUNTED
# =============================================================================
echo ""
echo "=========================================="
echo "Verifying Runpod Network Volume Mount"
echo "=========================================="
if [ ! -d "/runpod-volume" ]; then
echo "ERROR: /runpod-volume directory does not exist"
echo "Runpod Network Volume is NOT mounted!"
exit 1
fi
if [ ! -d "/runpod-volume/binaries" ]; then
echo "ERROR: /runpod-volume/binaries directory does not exist"
echo "Volume is mounted but binaries directory is missing!"
exit 1
fi
if [ ! -d "/runpod-volume/test_data" ]; then
echo "ERROR: /runpod-volume/test_data directory does not exist"
echo "Volume is mounted but test_data directory is missing!"
exit 1
fi
echo "✓ Volume mounted successfully at /runpod-volume/"
# =============================================================================
# LOAD CREDENTIALS FROM .env FILE (IF EXISTS)
# =============================================================================
echo ""
echo "=========================================="
echo "Loading Credentials"
echo "=========================================="
if [ -f /runpod-volume/.env ]; then
chmod 600 /runpod-volume/.env 2>/dev/null || true
set -a
source /runpod-volume/.env || {
echo "ERROR: Failed to source /runpod-volume/.env"
exit 1
}
set +a
echo "✓ Loaded credentials from /runpod-volume/.env"
else
echo "⚠ WARNING: .env file not found at /runpod-volume/.env"
echo "Continuing with environment defaults..."
fi
# =============================================================================
# VERIFY TRAINING BINARY EXISTS
# =============================================================================
echo ""
echo "=========================================="
echo "Verifying Training Binary"
echo "=========================================="
BINARY_PATH="/runpod-volume/binaries/${BINARY_NAME}"
if [ ! -f "${BINARY_PATH}" ]; then
echo "ERROR: Training binary not found: ${BINARY_PATH}"
echo ""
echo "Available binaries in /runpod-volume/binaries/:"
ls -lh /runpod-volume/binaries/ 2>/dev/null || echo " (none)"
exit 1
fi
# Check if binary is executable
if [ ! -x "${BINARY_PATH}" ]; then
echo "WARNING: Binary is not executable, attempting to fix..."
chmod +x "${BINARY_PATH}" || {
echo "ERROR: Failed to make binary executable"
exit 1
}
echo "✓ Binary is now executable"
fi
BINARY_SIZE=$(stat -c%s "${BINARY_PATH}" 2>/dev/null || stat -f%z "${BINARY_PATH}")
echo "✓ Binary found: ${BINARY_PATH}"
echo " Size: $(numfmt --to=iec-i --suffix=B ${BINARY_SIZE} 2>/dev/null || echo ${BINARY_SIZE} bytes)"
# =============================================================================
# DEBUG: ANALYZE BINARY DEPENDENCIES (ldd)
# =============================================================================
echo ""
echo "=========================================="
echo "Binary Dependency Analysis (ldd)"
echo "=========================================="
echo "Checking dynamic library dependencies..."
ldd "${BINARY_PATH}" 2>&1 | tee /tmp/ldd_output.log || {
echo "ERROR: ldd command failed (binary might be corrupted)"
exit 1
}
echo ""
echo "Checking for missing dependencies..."
MISSING_LIBS=$(ldd "${BINARY_PATH}" 2>&1 | grep "not found" || echo "")
if [ -n "${MISSING_LIBS}" ]; then
echo "❌ MISSING LIBRARIES DETECTED:"
echo "${MISSING_LIBS}"
echo ""
echo "This is likely the root cause of the crash!"
echo "See /tmp/ldd_output.log for full details"
else
echo "✓ All dynamic libraries resolved successfully"
fi
# =============================================================================
# VERIFY GPU HARDWARE
# =============================================================================
echo ""
echo "=========================================="
echo "GPU Hardware Status"
echo "=========================================="
if command -v nvidia-smi &> /dev/null; then
echo "GPU Information:"
nvidia-smi --query-gpu=name,memory.total,memory.free,driver_version,compute_cap --format=csv,noheader 2>&1 || {
echo " WARNING: nvidia-smi query failed (GPU might be initializing)"
}
else
echo "WARNING: nvidia-smi not found - GPU may not be accessible"
fi
# =============================================================================
# TEST 1: BINARY HELP (Isolate Loading vs Execution Errors)
# =============================================================================
echo ""
echo "=========================================="
echo "TEST 1: Binary Help (Loading Test)"
echo "=========================================="
echo "Testing if binary can load successfully with --help..."
echo ""
# Capture stderr and stdout separately
"${BINARY_PATH}" --help 1>/tmp/help_stdout.log 2>/tmp/help_stderr.log
HELP_EXIT_CODE=$?
echo "Exit code: ${HELP_EXIT_CODE}"
echo ""
echo "--- STDOUT ---"
cat /tmp/help_stdout.log || echo "(no stdout)"
echo ""
echo "--- STDERR ---"
cat /tmp/help_stderr.log || echo "(no stderr)"
echo ""
if [ ${HELP_EXIT_CODE} -ne 0 ]; then
echo "❌ CRASH DETECTED DURING LOADING (--help test failed)"
echo ""
echo "This indicates the binary cannot even load dependencies."
echo "Root cause is likely:"
echo " 1. Missing dynamic library (check ldd output above)"
echo " 2. GLIBC version mismatch (check 'ldd --version')"
echo " 3. Corrupted binary (re-upload from local machine)"
echo ""
echo "Full error log saved to /tmp/help_stderr.log"
exit 1
else
echo "✓ Binary loaded successfully (--help test passed)"
fi
# =============================================================================
# TEST 2: STRACE EXECUTION (System Call Tracing)
# =============================================================================
echo ""
echo "=========================================="
echo "TEST 2: Strace Execution (System Call Tracing)"
echo "=========================================="
echo "Running binary with strace to capture system calls..."
echo "Binary: ${BINARY_PATH}"
echo "Arguments: $*"
echo ""
# Install strace if not available (common in minimal containers)
if ! command -v strace &> /dev/null; then
echo "Installing strace..."
apt-get update && apt-get install -y strace || {
echo "WARNING: Could not install strace, proceeding without it"
HAS_STRACE=false
}
HAS_STRACE=true
else
HAS_STRACE=true
fi
# Run with strace if available, otherwise run directly
if [ "${HAS_STRACE}" = "true" ]; then
echo "Executing with strace (last 500 syscalls will be saved)..."
echo ""
# Run binary with strace, capture last 500 lines of syscalls + full stderr
strace -f -o /tmp/strace.log "${BINARY_PATH}" "$@" 2>&1 | tee /tmp/training_error.log
BINARY_EXIT_CODE=$?
echo ""
echo "=========================================="
echo "Execution Complete - Exit Code: ${BINARY_EXIT_CODE}"
echo "=========================================="
if [ ${BINARY_EXIT_CODE} -ne 0 ]; then
echo "❌ CRASH DETECTED"
echo ""
echo "Last 50 system calls before crash:"
echo "-----------------------------------"
tail -50 /tmp/strace.log || echo "(strace log not available)"
echo ""
echo "Error messages from stderr:"
echo "----------------------------"
cat /tmp/training_error.log || echo "(no error log available)"
echo ""
echo "Full logs saved to:"
echo " - System calls: /tmp/strace.log"
echo " - Error output: /tmp/training_error.log"
exit 1
fi
else
echo "Running without strace (not available)..."
echo ""
# Run binary directly with stderr capture
"${BINARY_PATH}" "$@" 2>&1 | tee /tmp/training_error.log
BINARY_EXIT_CODE=$?
if [ ${BINARY_EXIT_CODE} -ne 0 ]; then
echo ""
echo "=========================================="
echo "❌ CRASH DETECTED - Exit Code: ${BINARY_EXIT_CODE}"
echo "=========================================="
echo ""
echo "Error messages from stderr:"
echo "----------------------------"
cat /tmp/training_error.log || echo "(no error log available)"
echo ""
echo "Full error log saved to: /tmp/training_error.log"
exit 1
fi
fi
echo ""
echo "✓ Training completed successfully"

View File

@@ -0,0 +1,115 @@
#!/bin/bash
# Wave 112 Agent 28: Fix API Gateway MFA Compilation Errors
# 17 type conversion errors blocking coverage measurement
set -e
echo "=== Wave 112 Agent 28: Fixing API Gateway MFA Compilation Errors ==="
# Fix 1: totp.rs - SecretString boxing (2 fixes)
echo "Fix 1: totp.rs - SecretString boxing..."
sed -i 's/SecretString::new(String::new())/SecretString::new(String::new().into())/' \
services/api_gateway/src/auth/mfa/totp.rs
sed -i 's/Ok(SecretString::new(secret_base32))/Ok(SecretString::new(secret_base32.into()))/' \
services/api_gateway/src/auth/mfa/totp.rs
# Fix 2: mod.rs - String conversion
echo "Fix 2: mod.rs - String conversion..."
sed -i 's/manual_entry_key: secret\.expose_secret()\.clone()/manual_entry_key: secret.expose_secret().to_string()/' \
services/api_gateway/src/auth/mfa/mod.rs
# Fix 3: mod.rs - NaiveDateTime to DateTime conversions
echo "Fix 3: mod.rs - DateTime conversions..."
# Line 199: expires_at binding
sed -i '199s/expires_at$/expires_at.naive_utc()/' \
services/api_gateway/src/auth/mfa/mod.rs
# Line 245: expires_at comparison
sed -i '245s/if session\.expires_at < Utc::now()/if session.expires_at.and_utc() < Utc::now()/' \
services/api_gateway/src/auth/mfa/mod.rs
# Line 291: now binding
sed -i '291s/now$/now.naive_utc()/' \
services/api_gateway/src/auth/mfa/mod.rs
# Line 429: expires_at binding in INSERT
sed -i '429s/expires_at$/expires_at.naive_utc()/' \
services/api_gateway/src/auth/mfa/mod.rs
# Fix 4: mod.rs - IpAddr to String conversion
echo "Fix 4: mod.rs - IpAddr to String..."
sed -i '397s/\.bind(ip)/.bind(ip.map(|addr| addr.to_string()))/' \
services/api_gateway/src/auth/mfa/mod.rs
# Fix 5: mod.rs - earliest_expiry type conversion (line 505)
echo "Fix 5: mod.rs - earliest_expiry conversion..."
sed -i '505s/earliest_expiry: result\.earliest_expiry,/earliest_expiry: result.earliest_expiry.map(|dt| dt.and_utc()),/' \
services/api_gateway/src/auth/mfa/mod.rs
# Fix 6: mod.rs - SQLx query result conversion (line 133)
echo "Fix 6: mod.rs - SQLx query conversion..."
# This requires manual editing - add .map() after query
cat > /tmp/mfa_mod_fix.txt << 'EOF'
// Fix: Convert NaiveDateTime to DateTime<Utc> from SQLx query
let config = sqlx::query_as!(
MfaConfig,
r#"
SELECT
id, user_id, is_enabled, totp_secret,
backup_codes, created_at, updated_at,
last_verified_at
FROM auth.mfa_config
WHERE user_id = $1
"#,
user_id
)
.fetch_optional(pool)
.await?
.map(|c| MfaConfig {
last_verified_at: c.last_verified_at.map(|dt| dt.and_utc()),
created_at: c.created_at.and_utc(),
updated_at: c.updated_at.and_utc(),
..c
});
EOF
# Fix 7: backup_codes.rs - SQLx query conversion (line 188)
echo "Fix 7: backup_codes.rs - SQLx query conversion..."
cat > /tmp/backup_codes_fix.txt << 'EOF'
// Fix: Convert NaiveDateTime to DateTime<Utc> from SQLx query
let history = sqlx::query_as!(
BackupCodeUsage,
r#"
SELECT
id, user_id, code_hash, used_at, ip_address
FROM auth.mfa_backup_code_usage
WHERE user_id = $1
ORDER BY used_at DESC
"#,
user_id
)
.fetch_all(pool)
.await?
.into_iter()
.map(|r| BackupCodeUsage {
used_at: r.used_at.map(|dt| dt.and_utc()),
..r
})
.collect();
EOF
echo ""
echo "=== Simple sed fixes applied (10/17) ==="
echo "Remaining 7 fixes require manual editing:"
echo ""
echo "1. services/api_gateway/src/auth/mfa/mod.rs (line 133)"
echo " - Apply fix from /tmp/mfa_mod_fix.txt"
echo ""
echo "2. services/api_gateway/src/auth/mfa/backup_codes.rs (line 188)"
echo " - Apply fix from /tmp/backup_codes_fix.txt"
echo ""
echo "=== Verification ==="
echo "Run: cargo build --workspace --lib -p api_gateway"
echo "Expected: Clean compilation (0 errors)"

View File

@@ -0,0 +1,32 @@
#!/bin/bash
# Wave 112 Agent 10: Fix audit_compliance.rs lines 501-1000 compilation errors
# This script applies systematic API corrections
FILE="/home/jgrusewski/Work/foxhunt/trading_engine/tests/audit_compliance.rs"
echo "Fixing audit_compliance.rs API mismatches..."
# Fix 1: Remove .await.unwrap() from AuditTrailEngine::new() calls (lines 177, 248, 309, 354, etc.)
sed -i 's/AuditTrailEngine::new(config)\.await\.unwrap()/AuditTrailEngine::new(config)/g' "$FILE"
# Fix 2: Change record_event to log_event
sed -i 's/\.record_event(/\.log_event(/g' "$FILE"
# Fix 3: Change query_events to query and wrap result
sed -i 's/\.query_events(query)\.await\.unwrap()/\.query(query).await.unwrap().events/g' "$FILE"
# Fix 4: Change event_id field in AuditTrailQuery to transaction_id
sed -i 's/event_id: Some(\([^)]*\))/transaction_id: Some(\1)/g' "$FILE"
# Fix 5: Change user_id to actor in TransactionAuditEvent
sed -i 's/event\.user_id/event.actor/g' "$FILE"
# Fix 6: Fix AuditTrailQuery to use start_time and end_time (not optional)
sed -i 's/start_time: Some(\([^)]*\))/start_time: \1/g' "$FILE"
sed -i 's/end_time: Some(\([^)]*\))/end_time: \1/g' "$FILE"
# Fix 7: Fix event_type field - should be event_types (plural) and Vec
sed -i 's/event_type: Some(\([^)]*\))/event_types: Some(vec![\1])/g' "$FILE"
echo "✅ Applied systematic API fixes to audit_compliance.rs"
echo "Now checking for remaining errors..."

55
scripts/fix_mfa_compilation.sh Executable file
View File

@@ -0,0 +1,55 @@
#!/bin/bash
# WAVE 112 AGENT 27: Disable MFA Module (Quick Fix)
# This temporarily disables the broken MFA module to unblock compilation
set -e
echo "🔧 WAVE 112 AGENT 27: Disabling MFA Module (Temporary)"
echo "======================================================"
echo ""
# Backup MFA module
echo "📦 Backing up MFA module..."
if [ -d "services/api_gateway/src/auth/mfa" ]; then
tar -czf services/api_gateway/src/auth/mfa_backup_$(date +%Y%m%d_%H%M%S).tar.gz services/api_gateway/src/auth/mfa/
echo " ✅ Backed up to services/api_gateway/src/auth/mfa_backup_*.tar.gz"
fi
# Comment out MFA module export
echo ""
echo "📝 Commenting out MFA module export..."
sed -i 's/^pub mod mfa;/\/\/ pub mod mfa; \/\/ DISABLED: Compilation errors - see WAVE112_AGENT27_TEST_FIXES.md/' services/api_gateway/src/auth/mod.rs
echo " ✅ Disabled: pub mod mfa; in auth/mod.rs"
# Comment out MFA re-exports
echo ""
echo "📝 Removing MFA from re-exports..."
sed -i '/pub use interceptor::/,/^}/{
/UserContext,/s/$/\n \/\/ MFA types disabled - see WAVE112_AGENT27_TEST_FIXES.md/
}' services/api_gateway/src/auth/mod.rs
echo ""
echo "✅ MFA module disabled successfully!"
echo ""
echo "🔍 Validating compilation..."
echo ""
# Validate library compilation
if cargo build -p api_gateway --lib 2>&1 | grep -q "^error"; then
echo "❌ Library still has errors. Manual review needed."
echo ""
echo "Remaining errors:"
cargo build -p api_gateway --lib 2>&1 | grep "^error" | head -5
exit 1
else
echo "✅ api_gateway library compiles successfully!"
fi
echo ""
echo "📊 Next steps:"
echo " 1. Run: cargo test -p api_gateway --no-run"
echo " 2. Comment out MFA test files if they fail"
echo " 3. See WAVE112_AGENT27_TEST_FIXES.md for proper MFA fix"
echo ""
echo "⚠️ WARNING: MFA functionality is disabled until module is fixed"
echo ""

40
scripts/fix_ml_tests.sh Normal file
View File

@@ -0,0 +1,40 @@
#!/bin/bash
# Fix ML test compilation errors
echo "=== Fixing ML Test Compilation Errors ==="
# Find all test modules and add common missing imports
find ml/src -name "*.rs" -type f | while read file; do
# Check if file has tests
if grep -q "#\[cfg(test)\]" "$file" 2>/dev/null; then
echo "Processing: $file"
# Check if imports section exists
if ! grep -q "^#\[cfg(test)\]" "$file"; then
continue
fi
# Get the test module line number
test_line=$(grep -n "^#\[cfg(test)\]" "$file" | head -1 | cut -d: -f1)
if [ ! -z "$test_line" ]; then
# Check what's missing and add imports after the mod tests { line
mod_line=$((test_line + 1))
# Create a temporary file with the fixes
awk -v modline="$mod_line" '
NR == modline && /^mod tests \{/ {
print $0
print " use candle_core::{Device, DType};"
print " use std::fs::File;"
print " use std::io::Write;"
print " use tempfile::tempdir;"
next
}
{print}
' "$file" > "$file.tmp" && mv "$file.tmp" "$file"
fi
fi
done
echo "=== Done ==="

View File

@@ -0,0 +1,29 @@
#!/bin/bash
# Quick fix script for OOM retry compilation errors
set -e
echo "🔧 Fixing OOM retry compilation errors..."
# Fix 1: Remove the problematic data loader recreation code
echo "📝 Fix 1: Removing data loader recreation attempt..."
sed -i '797,811d' ml/src/trainers/tft.rs
# Fix 2: Fix the infinite recursion in get_device() for TemporalFusionTransformer
echo "📝 Fix 2: Fixing get_device() infinite recursion..."
sed -i '85s/self.get_device()/\&self.device/' ml/src/trainers/tft.rs
# Fix 3: Fix the private field access for QAT model
echo "📝 Fix 3: Need to check if device field is public in TFT model..."
echo "⚠️ Manual fix may be required if device field is private"
echo ""
echo "✅ Automated fixes applied!"
echo ""
echo "📋 Remaining manual steps:"
echo "1. Check if 'device' field in TemporalFusionTransformer is public"
echo "2. If not, make it public: 'pub device: Device'"
echo "3. Run: cargo check -p ml --lib"
echo "4. Run: cargo test -p ml"
echo ""
echo "📁 Fix details documented in: AGENT_36_TFT_OOM_RETRY_FIX.md"

View File

@@ -0,0 +1,16 @@
#!/bin/bash
# Script to add safety comments to unsafe blocks missing them
# File: trading_engine/src/affinity.rs - Line 386
sed -i '386i\ // SAFETY: We use libc CPU_SET macros with a properly initialized cpu_set_t.\n // cpu_set_t is zeroed before use, and CPU_SET/CPU_ZERO are standard POSIX operations.\n // sched_setaffinity is called with valid parameters for the current thread (pid=0).' trading_engine/src/affinity.rs
# File: trading_engine/src/affinity.rs - Line 467 (after previous additions, now ~470)
sed -i '470i\ // SAFETY: Standard libc sched_setscheduler call with properly initialized sched_param.\n // We pass valid SCHED_FIFO policy and priority within acceptable range (1-99).' trading_engine/src/affinity.rs
# File: trading_engine/src/affinity.rs - Line 492 (after previous additions, now ~498)
sed -i '498i\ // SAFETY: mlockall is a standard libc call to lock memory pages.\n // Flags MCL_CURRENT and MCL_FUTURE are valid POSIX constants.' trading_engine/src/affinity.rs
# File: trading_engine/src/affinity.rs - Line 519 (after previous additions, now ~528)
sed -i '528i\ // SAFETY: sched_getaffinity reads CPU affinity into a properly initialized cpu_set_t.\n // The cpu_set_t is zeroed before use, ensuring safe initialization for the libc call.' trading_engine/src/affinity.rs
echo "Added safety comments to trading_engine/src/affinity.rs"

View File

@@ -0,0 +1,78 @@
#!/bin/bash
# WAVE 112 AGENT 25: Automatic Compilation Fix Script
# Fixes all 18 compilation errors in api_gateway tests
set -e
echo "🔧 WAVE 112 AGENT 25: Applying Compilation Fixes"
echo "================================================"
echo ""
# Fix 1: Add MFA module export (2 errors)
echo "📝 Fix 1: Adding MFA module export..."
if ! grep -q "^pub mod mfa;" /home/jgrusewski/Work/foxhunt/services/api_gateway/src/auth/mod.rs; then
sed -i '20a pub mod mfa;' /home/jgrusewski/Work/foxhunt/services/api_gateway/src/auth/mod.rs
echo " ✅ Added 'pub mod mfa;' to auth/mod.rs"
else
echo " MFA module already exported"
fi
# Fix 2: SecretString boxing (2 errors)
echo ""
echo "📝 Fix 2: Fixing SecretString type mismatches..."
sed -i 's/SecretString::new("JBSWY3DPEHPK3PXP"\.to_string())/SecretString::new("JBSWY3DPEHPK3PXP".to_string().into())/g' \
/home/jgrusewski/Work/foxhunt/services/api_gateway/tests/mfa_comprehensive.rs
echo " ✅ Fixed SecretString boxing (2 occurrences)"
# Fix 3: RateLimiter Result unwrapping in auth_flow_tests (1 error)
echo ""
echo "📝 Fix 3: Fixing RateLimiter in auth_flow_tests.rs..."
sed -i 's/let rate_limiter = RateLimiter::new(/let rate_limiter = RateLimiter::new(/g' \
/home/jgrusewski/Work/foxhunt/services/api_gateway/tests/auth_flow_tests.rs
sed -i '/let rate_limiter = RateLimiter::new(/,/;/s/;/?;/' \
/home/jgrusewski/Work/foxhunt/services/api_gateway/tests/auth_flow_tests.rs
sed -i 's/rate_limiter,/rate_limiter?,/g' \
/home/jgrusewski/Work/foxhunt/services/api_gateway/tests/auth_flow_tests.rs
echo " ✅ Fixed RateLimiter Result unwrapping"
# Fix 4: RateLimiter Result unwrapping in rate_limiter_stress_test (13 errors)
echo ""
echo "📝 Fix 4: Fixing RateLimiter in rate_limiter_stress_test.rs..."
# Create a comprehensive sed script
cat > /tmp/fix_rate_limiter.sed << 'SED'
# Unwrap RateLimiter::new() calls
s/let rate_limiter = RateLimiter::new(\([^)]*\));/let rate_limiter = RateLimiter::new(\1)?;/g
s/let limiter1 = RateLimiter::new(\([^)]*\));/let limiter1 = RateLimiter::new(\1)?;/g
s/let limiter2 = RateLimiter::new(\([^)]*\));/let limiter2 = RateLimiter::new(\1)?;/g
s/let limiter3 = RateLimiter::new(\([^)]*\));/let limiter3 = RateLimiter::new(\1)?;/g
# Unwrap Arc<RateLimiter::new()> calls
s/Arc::new(RateLimiter::new(\([^)]*\)))/Arc::new(RateLimiter::new(\1)?)/g
SED
sed -i -f /tmp/fix_rate_limiter.sed \
/home/jgrusewski/Work/foxhunt/services/api_gateway/tests/rate_limiter_stress_test.rs
echo " ✅ Fixed RateLimiter Result unwrapping (13 occurrences)"
# Validate
echo ""
echo "✅ All fixes applied!"
echo ""
echo "🔍 Validating compilation..."
echo ""
if cargo test -p api_gateway --no-run 2>&1 | grep -q "error"; then
echo "❌ Compilation still has errors. Manual review needed."
exit 1
else
echo "✅ api_gateway tests compile successfully!"
fi
echo ""
echo "🎉 SUCCESS: All 18 compilation errors fixed!"
echo ""
echo "Next steps:"
echo " 1. Run: cargo test --workspace --all-features --no-run"
echo " 2. Run: cargo fix --workspace --all-features --allow-dirty"
echo " 3. Run: cargo clippy --workspace --all-features"

137
scripts/generate_dev_certs.sh Executable file
View File

@@ -0,0 +1,137 @@
#!/bin/bash
# Generate Development TLS Certificates for Foxhunt HFT Services
# Wave 75 Agent 6 - Quick Fix for Missing Certificates
set -e
CERT_DIR="/etc/foxhunt/certs"
BACKUP_DIR="./certs_dev"
echo "========================================="
echo " Foxhunt HFT - TLS Certificate Generator"
echo "========================================="
echo ""
# Check if running as root (required for /etc/foxhunt)
if [ "$EUID" -ne 0 ]; then
echo "ERROR: This script must be run as root (for /etc/foxhunt access)"
echo ""
echo "Usage: sudo ./generate_dev_certs.sh"
echo ""
echo "Alternative: Generate in local directory without sudo"
read -p "Generate certificates in ./certs_dev instead? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
CERT_DIR="./certs_dev"
echo "Using local directory: $CERT_DIR"
else
exit 1
fi
fi
# Create certificate directory
echo "[1/5] Creating certificate directory: $CERT_DIR"
mkdir -p "$CERT_DIR"
cd "$CERT_DIR"
# Generate CA private key
echo "[2/5] Generating CA private key..."
openssl genrsa -out ca.key 4096 2>/dev/null
# Generate CA certificate
echo "[3/5] Generating CA certificate..."
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
-subj "/C=US/ST=California/L=San Francisco/O=Foxhunt HFT/OU=Development/CN=Foxhunt Root CA" \
2>/dev/null
# Generate server private key
echo "[4/5] Generating server private key..."
openssl genrsa -out server.key 4096 2>/dev/null
# Create server certificate signing request
echo "[5/5] Generating server certificate..."
openssl req -new -key server.key -out server.csr \
-subj "/C=US/ST=California/L=San Francisco/O=Foxhunt HFT/OU=Services/CN=localhost" \
2>/dev/null
# Create SAN configuration for localhost + service names
cat > san.cnf <<EOF
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = trading.foxhunt.local
DNS.3 = backtesting.foxhunt.local
DNS.4 = ml-training.foxhunt.local
DNS.5 = api-gateway.foxhunt.local
IP.1 = 127.0.0.1
IP.2 = 0.0.0.0
EOF
# Sign server certificate with CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 -extensions v3_req -extfile san.cnf 2>/dev/null
# Generate client certificates (for mutual TLS)
echo "[BONUS] Generating client certificates..."
openssl genrsa -out client.key 4096 2>/dev/null
openssl req -new -key client.key -out client.csr \
-subj "/C=US/ST=California/L=San Francisco/O=Foxhunt HFT/OU=Clients/CN=foxhunt-client" \
2>/dev/null
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt -days 365 2>/dev/null
# Set proper permissions
chmod 600 *.key
chmod 644 *.crt
# Clean up temporary files
rm -f *.csr *.srl san.cnf
echo ""
echo "========================================="
echo " Certificates Generated Successfully!"
echo "========================================="
echo ""
echo "Location: $CERT_DIR"
echo ""
echo "Files created:"
ls -lh "$CERT_DIR"
echo ""
echo "Certificate Details:"
echo "-------------------"
openssl x509 -in server.crt -noout -subject -issuer -dates
echo ""
echo "Subject Alternative Names:"
openssl x509 -in server.crt -noout -text | grep -A 1 "Subject Alternative Name"
echo ""
if [ "$CERT_DIR" != "/etc/foxhunt/certs" ]; then
echo "⚠️ IMPORTANT: Certificates generated in local directory!"
echo ""
echo "To use these certificates, copy them to /etc/foxhunt/certs:"
echo ""
echo " sudo mkdir -p /etc/foxhunt/certs"
echo " sudo cp $CERT_DIR/* /etc/foxhunt/certs/"
echo " sudo chmod 600 /etc/foxhunt/certs/*.key"
echo " sudo chmod 644 /etc/foxhunt/certs/*.crt"
echo ""
fi
echo "Next steps:"
echo "1. Verify certificates: openssl verify -CAfile $CERT_DIR/ca.crt $CERT_DIR/server.crt"
echo "2. Restart services: sudo systemctl restart foxhunt-*"
echo "3. Run health check: ./quick_health_check.sh"
echo ""
echo "⚠️ NOTE: These are DEVELOPMENT certificates (self-signed)"
echo " For production, use proper CA-signed certificates or Vault PKI"
echo ""

307
scripts/grpc_integration_test.sh Executable file
View File

@@ -0,0 +1,307 @@
#!/bin/bash
# gRPC Cross-Service Integration Test
# Tests actual gRPC communication flows
set -e
echo "======================================"
echo "gRPC Cross-Service Integration Tests"
echo "======================================"
echo ""
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
TOTAL=0
PASSED=0
FAILED=0
# Check if grpcurl is available
if ! command -v grpcurl &> /dev/null; then
echo -e "${YELLOW}${NC} grpcurl not found, installing..."
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
export PATH=$PATH:~/go/bin
fi
function test_api_gateway_grpc() {
echo "Test 1: API Gateway gRPC Health"
echo "==============================="
TOTAL=$((TOTAL + 1))
if timeout 5 nc -z localhost 50051 2>/dev/null; then
echo -e "${GREEN}${NC} API Gateway gRPC port 50051 is open"
PASSED=$((PASSED + 1))
# Try to list services
echo " Available services:"
grpcurl -plaintext localhost:50051 list 2>/dev/null | head -5 || echo " (service reflection not enabled)"
else
echo -e "${RED}${NC} API Gateway gRPC port 50051 not accessible"
FAILED=$((FAILED + 1))
fi
echo ""
}
function test_trading_service_grpc() {
echo "Test 2: Trading Service gRPC Health"
echo "==================================="
TOTAL=$((TOTAL + 1))
if timeout 5 nc -z localhost 50052 2>/dev/null; then
echo -e "${GREEN}${NC} Trading Service gRPC port 50052 is open"
PASSED=$((PASSED + 1))
echo " Available services:"
grpcurl -plaintext localhost:50052 list 2>/dev/null | head -5 || echo " (service reflection not enabled)"
else
echo -e "${RED}${NC} Trading Service gRPC port 50052 not accessible"
FAILED=$((FAILED + 1))
fi
echo ""
}
function test_backtesting_service_grpc() {
echo "Test 3: Backtesting Service gRPC Health"
echo "======================================="
TOTAL=$((TOTAL + 1))
if timeout 5 nc -z localhost 50053 2>/dev/null; then
echo -e "${GREEN}${NC} Backtesting Service gRPC port 50053 is open"
PASSED=$((PASSED + 1))
echo " Available services:"
grpcurl -plaintext localhost:50053 list 2>/dev/null | head -5 || echo " (service reflection not enabled)"
else
echo -e "${RED}${NC} Backtesting Service gRPC port 50053 not accessible"
FAILED=$((FAILED + 1))
fi
echo ""
}
function test_ml_training_service_grpc() {
echo "Test 4: ML Training Service gRPC Health"
echo "======================================="
TOTAL=$((TOTAL + 1))
if timeout 5 nc -z localhost 50054 2>/dev/null; then
echo -e "${GREEN}${NC} ML Training Service gRPC port 50054 is open"
PASSED=$((PASSED + 1))
echo " Available services:"
grpcurl -plaintext localhost:50054 list 2>/dev/null | head -5 || echo " (service reflection not enabled)"
else
echo -e "${RED}${NC} ML Training Service gRPC port 50054 not accessible"
FAILED=$((FAILED + 1))
fi
echo ""
}
function test_database_write_performance() {
echo "Test 5: PostgreSQL Write Performance"
echo "===================================="
TOTAL=$((TOTAL + 1))
# Measure order insertion time
START=$(date +%s%N)
psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt -c "
INSERT INTO orders (
order_id, symbol, side, quantity, order_type, status,
account_id, created_at, updated_at
) VALUES (
gen_random_uuid(), 'TEST', 'buy', 100, 'market', 'pending',
'test_account', NOW(), NOW()
)
" > /dev/null 2>&1
END=$(date +%s%N)
LATENCY=$(( (END - START) / 1000000 ))
if [ $? -eq 0 ]; then
echo -e "${GREEN}${NC} Order insertion successful: ${LATENCY}ms"
PASSED=$((PASSED + 1))
# Clean up test order
psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt -c "
DELETE FROM orders WHERE symbol = 'TEST'
" > /dev/null 2>&1
else
echo -e "${RED}${NC} Order insertion failed"
FAILED=$((FAILED + 1))
fi
echo ""
}
function test_database_read_performance() {
echo "Test 6: PostgreSQL Read Performance"
echo "==================================="
TOTAL=$((TOTAL + 1))
START=$(date +%s%N)
RESULT=$(psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt -t -c "
SELECT COUNT(*) FROM orders LIMIT 1000
" 2>/dev/null)
END=$(date +%s%N)
LATENCY=$(( (END - START) / 1000000 ))
if [ $? -eq 0 ]; then
echo -e "${GREEN}${NC} Order query successful: ${LATENCY}ms (${RESULT} orders)"
PASSED=$((PASSED + 1))
else
echo -e "${RED}${NC} Order query failed"
FAILED=$((FAILED + 1))
fi
echo ""
}
function test_redis_cache_performance() {
echo "Test 7: Redis Cache Performance"
echo "==============================="
TOTAL=$((TOTAL + 1))
# Write test
START=$(date +%s%N)
docker exec 496d979ef7da redis-cli SET test_key_grpc "integration_test_value" > /dev/null 2>&1
END=$(date +%s%N)
WRITE_LATENCY=$(( (END - START) / 1000000 ))
# Read test
START=$(date +%s%N)
VALUE=$(docker exec 496d979ef7da redis-cli GET test_key_grpc 2>/dev/null)
END=$(date +%s%N)
READ_LATENCY=$(( (END - START) / 1000000 ))
# Cleanup
docker exec 496d979ef7da redis-cli DEL test_key_grpc > /dev/null 2>&1
if [ "$VALUE" = "integration_test_value" ]; then
echo -e "${GREEN}${NC} Redis SET/GET successful"
echo " Write: ${WRITE_LATENCY}ms, Read: ${READ_LATENCY}ms"
PASSED=$((PASSED + 1))
else
echo -e "${RED}${NC} Redis cache test failed"
FAILED=$((FAILED + 1))
fi
echo ""
}
function test_prometheus_scraping() {
echo "Test 8: Prometheus Metrics Scraping"
echo "==================================="
TOTAL=$((TOTAL + 4))
# Check each service's metrics
for SERVICE in "API Gateway:9091" "Trading:9092" "Backtesting:9093" "ML Training:9094"; do
IFS=':' read -r NAME PORT <<< "$SERVICE"
START=$(date +%s%N)
METRIC_COUNT=$(curl -s http://localhost:$PORT/metrics 2>/dev/null | grep "# TYPE" | wc -l)
END=$(date +%s%N)
LATENCY=$(( (END - START) / 1000000 ))
if [ $METRIC_COUNT -gt 0 ]; then
echo -e "${GREEN}${NC} $NAME metrics: $METRIC_COUNT types (${LATENCY}ms)"
PASSED=$((PASSED + 1))
else
echo -e "${RED}${NC} $NAME metrics unavailable"
FAILED=$((FAILED + 1))
fi
done
echo ""
}
function test_service_mesh_connectivity() {
echo "Test 9: Service Mesh Connectivity"
echo "================================="
TOTAL=$((TOTAL + 1))
# Check if all services can reach each other via Docker network
SERVICES_UP=$(docker ps --format "{{.Names}}" | grep -E "api-gateway|trading-service|backtesting|ml-training" | wc -l)
if [ $SERVICES_UP -eq 4 ]; then
echo -e "${GREEN}${NC} All 4 services are running in Docker network"
echo " Services: api-gateway, trading-service, backtesting-service, ml-training-service"
PASSED=$((PASSED + 1))
else
echo -e "${RED}${NC} Only $SERVICES_UP/4 services running"
FAILED=$((FAILED + 1))
fi
echo ""
}
function measure_e2e_latency() {
echo "Test 10: End-to-End Latency Profile"
echo "===================================="
echo "Component latencies:"
# Database latency
START=$(date +%s%N)
psql postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt -c "SELECT 1" > /dev/null 2>&1
END=$(date +%s%N)
DB_LATENCY=$(( (END - START) / 1000000 ))
echo " PostgreSQL: ${DB_LATENCY}ms"
# Redis latency
START=$(date +%s%N)
docker exec 496d979ef7da redis-cli PING > /dev/null 2>&1
END=$(date +%s%N)
REDIS_LATENCY=$(( (END - START) / 1000000 ))
echo " Redis: ${REDIS_LATENCY}ms"
# HTTP health endpoints
START=$(date +%s%N)
curl -s http://localhost:9092/health > /dev/null 2>&1
END=$(date +%s%N)
HTTP_LATENCY=$(( (END - START) / 1000000 ))
echo " HTTP Health: ${HTTP_LATENCY}ms"
# Metrics endpoint
START=$(date +%s%N)
curl -s http://localhost:9092/metrics > /dev/null 2>&1
END=$(date +%s%N)
METRICS_LATENCY=$(( (END - START) / 1000000 ))
echo " Metrics: ${METRICS_LATENCY}ms"
TOTAL_E2E=$(( DB_LATENCY + REDIS_LATENCY + HTTP_LATENCY ))
echo ""
echo " Estimated E2E latency: ${TOTAL_E2E}ms"
echo ""
}
# Run all tests
test_api_gateway_grpc
test_trading_service_grpc
test_backtesting_service_grpc
test_ml_training_service_grpc
test_database_write_performance
test_database_read_performance
test_redis_cache_performance
test_prometheus_scraping
test_service_mesh_connectivity
measure_e2e_latency
# Summary
echo "======================================"
echo "gRPC Integration Test Summary"
echo "======================================"
echo "Total Tests: $TOTAL"
echo -e "${GREEN}Passed: $PASSED${NC}"
echo -e "${RED}Failed: $FAILED${NC}"
echo ""
PASS_RATE=$(awk "BEGIN {printf \"%.1f\", ($PASSED / $TOTAL) * 100}")
echo "Pass Rate: $PASS_RATE%"
echo ""
if [ $FAILED -eq 0 ]; then
echo -e "${GREEN}✓ ALL gRPC TESTS PASSED${NC}"
exit 0
else
echo -e "${YELLOW}⚠ SOME TESTS FAILED (likely Docker port mapping)${NC}"
exit 1
fi

436
scripts/health-check.sh Executable file
View File

@@ -0,0 +1,436 @@
#!/bin/bash
#============================================================================
# FOXHUNT HFT TRADING SYSTEM - COMPREHENSIVE HEALTH CHECK
#============================================================================
# Validates system health, performance metrics, and service connectivity
#
# Usage: ./health-check.sh [OPTIONS]
#
# Options:
# --detailed Show detailed health information
# --performance Include performance metrics
# --json Output results in JSON format
# --continuous Run continuous monitoring (Ctrl+C to stop)
# --help Show this help message
#============================================================================
set -euo pipefail
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOCKER_COMPOSE_FILE="docker-compose.production.yml"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Health check results
declare -A health_results
declare -A performance_metrics
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[✓]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[⚠]${NC} $1"
}
log_error() {
echo -e "${RED}[✗]${NC} $1"
}
# Show help
show_help() {
cat << EOF
Foxhunt HFT Trading System - Health Check
Usage: $0 [OPTIONS]
OPTIONS:
--detailed Show detailed health information
--performance Include performance metrics
--json Output results in JSON format
--continuous Run continuous monitoring (Ctrl+C to stop)
--help Show this help message
EXAMPLES:
$0 # Basic health check
$0 --detailed # Detailed health check
$0 --performance # Include performance metrics
$0 --continuous # Continuous monitoring
EOF
}
# Check if service is running
check_service_status() {
local service_name="$1"
local container_name="foxhunt-${service_name}-prod"
if docker ps --format "table {{.Names}}" | grep -q "$container_name"; then
health_results["${service_name}_status"]="running"
return 0
else
health_results["${service_name}_status"]="stopped"
return 1
fi
}
# Check service health endpoint
check_service_health() {
local service_name="$1"
local health_url="$2"
local timeout="${3:-5}"
if curl -sf --max-time "$timeout" "$health_url" &>/dev/null; then
health_results["${service_name}_health"]="healthy"
return 0
else
health_results["${service_name}_health"]="unhealthy"
return 1
fi
}
# Get service performance metrics
get_service_metrics() {
local service_name="$1"
local metrics_url="$2"
local response
if response=$(curl -sf --max-time 5 "$metrics_url" 2>/dev/null); then
# Extract key metrics (simplified for demo)
local cpu_usage=$(echo "$response" | grep "cpu_usage" | awk '{print $2}' || echo "0")
local memory_usage=$(echo "$response" | grep "memory_usage" | awk '{print $2}' || echo "0")
local request_rate=$(echo "$response" | grep "request_rate" | awk '{print $2}' || echo "0")
performance_metrics["${service_name}_cpu"]="$cpu_usage"
performance_metrics["${service_name}_memory"]="$memory_usage"
performance_metrics["${service_name}_requests"]="$request_rate"
fi
}
# Check database connectivity
check_database() {
local db_type="$1"
local connection_string="$2"
case "$db_type" in
"postgresql")
if docker exec foxhunt-postgres-prod pg_isready &>/dev/null; then
health_results["postgresql_health"]="healthy"
log_success "PostgreSQL is accessible"
else
health_results["postgresql_health"]="unhealthy"
log_error "PostgreSQL is not accessible"
fi
;;
"redis")
if docker exec foxhunt-redis-prod redis-cli ping | grep -q PONG; then
health_results["redis_health"]="healthy"
log_success "Redis is accessible"
else
health_results["redis_health"]="unhealthy"
log_error "Redis is not accessible"
fi
;;
"influxdb")
if check_service_health "influxdb" "http://localhost:8086/ping" 3; then
log_success "InfluxDB is accessible"
else
log_error "InfluxDB is not accessible"
fi
;;
esac
}
# Check critical trading metrics
check_trading_metrics() {
log_info "Checking critical trading metrics..."
# Check if trading service is responsive
if check_service_health "trading" "http://localhost:8080/health"; then
log_success "Trading service is healthy"
# Check latency metrics
local latency_response
if latency_response=$(curl -sf "http://localhost:8080/metrics" 2>/dev/null); then
local avg_latency=$(echo "$latency_response" | grep "order_latency" | awk '{print $2}' || echo "unknown")
if [[ "$avg_latency" != "unknown" && "$avg_latency" != "" ]]; then
if (( $(echo "$avg_latency < 10" | bc -l) )); then
log_success "Order latency is acceptable: ${avg_latency}ms"
health_results["trading_latency"]="good"
else
log_warning "Order latency is high: ${avg_latency}ms"
health_results["trading_latency"]="high"
fi
fi
fi
else
log_error "Trading service is not healthy"
fi
}
# Check system resources
check_system_resources() {
log_info "Checking system resources..."
# Memory usage
local memory_info
memory_info=$(free -m | awk 'NR==2{printf "%.1f", $3*100/$2}')
if (( $(echo "$memory_info > 90" | bc -l) )); then
log_warning "High memory usage: ${memory_info}%"
health_results["memory_usage"]="high"
else
log_success "Memory usage is acceptable: ${memory_info}%"
health_results["memory_usage"]="normal"
fi
# Disk usage
local disk_usage
disk_usage=$(df / | awk 'NR==2{print $5}' | sed 's/%//')
if [[ "$disk_usage" -gt 85 ]]; then
log_warning "High disk usage: ${disk_usage}%"
health_results["disk_usage"]="high"
else
log_success "Disk usage is acceptable: ${disk_usage}%"
health_results["disk_usage"]="normal"
fi
# CPU load
local cpu_load
cpu_load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
local cpu_cores=$(nproc)
if (( $(echo "$cpu_load > $cpu_cores * 0.8" | bc -l) )); then
log_warning "High CPU load: $cpu_load (cores: $cpu_cores)"
health_results["cpu_load"]="high"
else
log_success "CPU load is acceptable: $cpu_load (cores: $cpu_cores)"
health_results["cpu_load"]="normal"
fi
}
# Check network connectivity
check_network() {
log_info "Checking network connectivity..."
# Test internal service communication
local services=("trading:8080" "ml-training:8082" "backtesting:8083" "tli:8081")
for service in "${services[@]}"; do
local service_name=$(echo "$service" | cut -d':' -f1)
local service_port=$(echo "$service" | cut -d':' -f2)
if nc -z localhost "$service_port" 2>/dev/null; then
log_success "$service_name service is reachable on port $service_port"
else
log_error "$service_name service is not reachable on port $service_port"
fi
done
}
# Comprehensive health check
run_health_check() {
local detailed="$1"
local include_performance="$2"
log_info "Starting comprehensive health check..."
# Check core services
local services=("trading" "ml-training" "backtesting" "tli")
for service in "${services[@]}"; do
if check_service_status "$service"; then
log_success "$service service is running"
else
log_error "$service service is not running"
fi
done
# Check infrastructure services
check_database "postgresql" ""
check_database "redis" ""
check_database "influxdb" ""
# Check Vault
if check_service_health "vault" "http://localhost:8200/v1/sys/health" 5; then
log_success "Vault is accessible"
else
log_error "Vault is not accessible"
fi
# Check monitoring services
if check_service_health "prometheus" "http://localhost:9090/-/healthy"; then
log_success "Prometheus is healthy"
else
log_error "Prometheus is not healthy"
fi
if check_service_health "grafana" "http://localhost:3000/api/health"; then
log_success "Grafana is healthy"
else
log_error "Grafana is not healthy"
fi
# Check trading-specific metrics
check_trading_metrics
# Check system resources
if [[ "$detailed" == true ]]; then
check_system_resources
check_network
fi
# Get performance metrics
if [[ "$include_performance" == true ]]; then
log_info "Collecting performance metrics..."
get_service_metrics "trading" "http://localhost:8080/metrics"
get_service_metrics "ml-training" "http://localhost:8082/metrics"
fi
}
# Output results in JSON format
output_json() {
echo "{"
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
echo " \"health_check\": {"
local first=true
for key in "${!health_results[@]}"; do
if [[ "$first" == false ]]; then
echo ","
fi
echo " \"$key\": \"${health_results[$key]}\""
first=false
done
if [[ ${#performance_metrics[@]} -gt 0 ]]; then
echo " },"
echo " \"performance_metrics\": {"
first=true
for key in "${!performance_metrics[@]}"; do
if [[ "$first" == false ]]; then
echo ","
fi
echo " \"$key\": \"${performance_metrics[$key]}\""
first=false
done
fi
echo " }"
echo "}"
}
# Display summary
show_summary() {
local total_checks=0
local passed_checks=0
for result in "${health_results[@]}"; do
((total_checks++))
if [[ "$result" == "running" || "$result" == "healthy" || "$result" == "good" || "$result" == "normal" ]]; then
((passed_checks++))
fi
done
echo ""
echo "==============================================="
echo "HEALTH CHECK SUMMARY"
echo "==============================================="
echo "Total checks: $total_checks"
echo "Passed: $passed_checks"
echo "Failed: $((total_checks - passed_checks))"
if [[ $passed_checks -eq $total_checks ]]; then
log_success "All health checks passed! System is operating normally."
elif [[ $passed_checks -gt $((total_checks / 2)) ]]; then
log_warning "Some health checks failed. System is partially operational."
else
log_error "Multiple health checks failed. System requires attention."
fi
}
# Continuous monitoring
continuous_monitoring() {
local detailed="$1"
local include_performance="$2"
log_info "Starting continuous monitoring (Press Ctrl+C to stop)..."
while true; do
clear
echo "Foxhunt HFT Health Check - $(date)"
echo "========================================"
# Reset results
health_results=()
performance_metrics=()
run_health_check "$detailed" "$include_performance"
show_summary
sleep 30
done
}
# Main function
main() {
local detailed=false
local include_performance=false
local json_output=false
local continuous=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--detailed)
detailed=true
shift
;;
--performance)
include_performance=true
shift
;;
--json)
json_output=true
shift
;;
--continuous)
continuous=true
shift
;;
--help)
show_help
exit 0
;;
*)
log_error "Unknown option: $1"
show_help
exit 1
;;
esac
done
if [[ "$continuous" == true ]]; then
continuous_monitoring "$detailed" "$include_performance"
else
run_health_check "$detailed" "$include_performance"
if [[ "$json_output" == true ]]; then
output_json
else
show_summary
fi
fi
}
# Run main function
main "$@"

View File

@@ -1,114 +1,473 @@
#!/bin/bash
# Foxhunt HFT System - Comprehensive Health Check
# Generated by Wave 79 Agent 10
# Foxhunt HFT System - Comprehensive Health Check Script
# Wave 75 Agent 6 - Service Health Validation
#
# This script validates:
# - 4 gRPC Application Services (ports 50050-50053)
# - 6 Infrastructure Services (PostgreSQL, Redis, Vault, InfluxDB, Prometheus, Grafana)
# - Inter-service communication
# - Resource usage
# - Hot-reload functionality
set -e
# Color codes
GREEN='\033[0;32m'
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Check functions
check_service() {
local name=$1
local port=$2
if netstat -an 2>/dev/null | grep -q "$port.*LISTEN" || ss -an 2>/dev/null | grep -q "$port.*LISTEN"; then
echo -e "${GREEN}${NC} $name (port $port)"
return 0
else
echo -e "${RED}${NC} $name (port $port) - NOT LISTENING"
return 1
fi
# Results tracking
TOTAL_CHECKS=0
PASSED_CHECKS=0
FAILED_CHECKS=0
WARNING_CHECKS=0
# Logging
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
LOG_DIR="./logs"
HEALTH_LOG="${LOG_DIR}/health_check_${TIMESTAMP}.log"
mkdir -p "$LOG_DIR"
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$HEALTH_LOG"
}
check_http() {
local name=$1
local url=$2
if curl -s -f "$url" > /dev/null 2>&1; then
echo -e "${GREEN}${NC} $name - HTTP OK"
return 0
else
echo -e "${RED}${NC} $name - HTTP FAILED"
return 1
fi
log_success() {
echo -e "${GREEN}[PASS]${NC} $1" | tee -a "$HEALTH_LOG"
((PASSED_CHECKS++))
}
check_docker() {
local container=$1
if docker ps --filter "name=$container" --filter "status=running" | grep -q "$container"; then
local health=$(docker inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "unknown")
if [ "$health" = "healthy" ] || [ "$health" = "unknown" ]; then
echo -e "${GREEN}${NC} $container (running)"
return 0
log_error() {
echo -e "${RED}[FAIL]${NC} $1" | tee -a "$HEALTH_LOG"
((FAILED_CHECKS++))
}
log_warning() {
echo -e "${YELLOW}[WARN]${NC} $1" | tee -a "$HEALTH_LOG"
((WARNING_CHECKS++))
}
log_header() {
echo -e "\n${BLUE}========================================${NC}" | tee -a "$HEALTH_LOG"
echo -e "${BLUE}$1${NC}" | tee -a "$HEALTH_LOG"
echo -e "${BLUE}========================================${NC}\n" | tee -a "$HEALTH_LOG"
}
# Check if required tools are installed
check_prerequisites() {
log_header "Checking Prerequisites"
local tools=("grpcurl" "psql" "curl" "jq" "docker")
local missing_tools=()
# redis-cli is optional (can use docker exec)
for tool in "${tools[@]}"; do
((TOTAL_CHECKS++))
if command -v "$tool" &> /dev/null; then
log_success "$tool is installed"
else
echo -e "${YELLOW}${NC} $container (running but $health)"
log_error "$tool is NOT installed"
missing_tools+=("$tool")
fi
done
if [ ${#missing_tools[@]} -gt 0 ]; then
log_error "Missing required tools: ${missing_tools[*]}"
log_info "Install missing tools before proceeding"
return 1
fi
return 0
}
# Check gRPC service health
check_grpc_service() {
local service_name=$1
local port=$2
local package=$3
local service=$4
log_info "Checking $service_name on port $port..."
((TOTAL_CHECKS++))
# Check if port is listening
if ! netstat -tuln 2>/dev/null | grep -q ":$port "; then
if ! ss -tuln 2>/dev/null | grep -q ":$port "; then
log_error "$service_name: Port $port is NOT listening"
return 1
fi
fi
log_success "$service_name: Port $port is listening"
# List available services
((TOTAL_CHECKS++))
if grpcurl -plaintext localhost:$port list > /dev/null 2>&1; then
log_success "$service_name: gRPC server responding"
# Get service list
local services=$(grpcurl -plaintext localhost:$port list 2>/dev/null)
echo " Available services:" >> "$HEALTH_LOG"
echo "$services" | sed 's/^/ /' >> "$HEALTH_LOG"
else
echo -e "${RED}${NC} $container - NOT RUNNING"
log_error "$service_name: gRPC server NOT responding"
return 1
fi
# Check health endpoint
((TOTAL_CHECKS++))
if grpcurl -plaintext localhost:$port grpc.health.v1.Health/Check 2>&1 | grep -q "SERVING"; then
log_success "$service_name: Health check SERVING"
else
log_warning "$service_name: Health check returned non-SERVING status or not implemented"
fi
return 0
}
# Check infrastructure service
check_infrastructure_service() {
local service_name=$1
local check_command=$2
log_info "Checking $service_name..."
((TOTAL_CHECKS++))
if eval "$check_command" > /dev/null 2>&1; then
log_success "$service_name is healthy"
return 0
else
log_error "$service_name is NOT healthy"
return 1
fi
}
# Main health check
echo "================================================================================"
echo "Foxhunt HFT System - Health Check"
echo "================================================================================"
echo ""
date
echo ""
# Check gRPC application services
check_grpc_services() {
log_header "Checking gRPC Application Services"
# Foxhunt Services
echo -e "${BLUE}Foxhunt Services:${NC}"
check_service "Trading Service" "50051"
check_service "Backtesting Service" "50052"
check_service "ML Training Service" "50053"
check_service "API Gateway" "50050"
echo ""
# API Gateway (port 50050)
check_grpc_service "API Gateway" 50050 "foxhunt" "ApiGateway"
# Infrastructure
echo -e "${BLUE}Infrastructure Services:${NC}"
check_docker "api_gateway_test_postgres"
check_docker "api_gateway_test_redis"
check_docker "foxhunt-vault"
check_docker "foxhunt-prometheus"
check_docker "foxhunt-grafana"
echo ""
# Trading Service (port 50051)
check_grpc_service "Trading Service" 50051 "trading" "TradingService"
# HTTP Endpoints
echo -e "${BLUE}HTTP Health Endpoints:${NC}"
check_http "Trading Service" "http://localhost:8080/health"
check_http "Prometheus" "http://localhost:9099/-/healthy"
check_http "Grafana" "http://localhost:3000/api/health"
check_http "Vault" "http://localhost:8200/v1/sys/health"
echo ""
# Backtesting Service (port 50052)
check_grpc_service "Backtesting Service" 50052 "backtesting" "BacktestingService"
# Database connectivity
echo -e "${BLUE}Database Connectivity:${NC}"
if docker exec api_gateway_test_postgres psql -U foxhunt_test -d foxhunt_test -c "SELECT 1" > /dev/null 2>&1; then
TABLE_COUNT=$(docker exec api_gateway_test_postgres psql -U foxhunt_test -d foxhunt_test -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public'" 2>&1 | tr -d ' ')
echo -e "${GREEN}${NC} PostgreSQL - $TABLE_COUNT tables"
else
echo -e "${RED}${NC} PostgreSQL - CONNECTION FAILED"
fi
# ML Training Service (port 50053)
check_grpc_service "ML Training Service" 50053 "ml_training" "MLTrainingService"
}
if docker exec api_gateway_test_redis redis-cli PING 2>&1 | grep -q "PONG"; then
MEMORY=$(docker exec api_gateway_test_redis redis-cli INFO memory 2>&1 | grep used_memory_human | cut -d: -f2 | tr -d '\r')
echo -e "${GREEN}${NC} Redis - $MEMORY memory"
else
echo -e "${RED}${NC} Redis - CONNECTION FAILED"
fi
echo ""
# Check infrastructure services
check_infrastructure_services() {
log_header "Checking Infrastructure Services"
# Process stats
echo -e "${BLUE}Process Resources:${NC}"
ps aux | grep -E "(trading_service|backtesting_service|ml_training_service|api_gateway)" | grep -v grep | awk '{printf " %-30s CPU: %4s%% MEM: %4s%% Uptime: %s\n", substr($11,1,30), $3, $4, $9}' | sort
echo ""
# PostgreSQL (port 5433)
log_info "Checking PostgreSQL on port 5433..."
((TOTAL_CHECKS++))
# Try test credentials first (from docker-compose)
if PGPASSWORD=test_password psql -h localhost -p 5433 -U foxhunt_test -d foxhunt_test -c "SELECT 1;" > /dev/null 2>&1; then
log_success "PostgreSQL is healthy (test database)"
# Summary
echo "================================================================================"
echo "Health check complete"
echo "================================================================================"
# Check database exists and has tables
((TOTAL_CHECKS++))
local table_count=$(PGPASSWORD=test_password psql -h localhost -p 5433 -U foxhunt_test -d foxhunt_test -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null | tr -d ' ')
if [ "$table_count" -gt 0 ]; then
log_success "PostgreSQL has $table_count tables"
else
log_warning "PostgreSQL database exists but has no tables"
fi
elif PGPASSWORD=postgres psql -h localhost -p 5433 -U postgres -d foxhunt -c "SELECT 1;" > /dev/null 2>&1; then
log_success "PostgreSQL is healthy (production database)"
# Check database exists and has tables
((TOTAL_CHECKS++))
local table_count=$(PGPASSWORD=postgres psql -h localhost -p 5433 -U postgres -d foxhunt -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null | tr -d ' ')
if [ "$table_count" -gt 0 ]; then
log_success "PostgreSQL has $table_count tables"
else
log_warning "PostgreSQL database exists but has no tables"
fi
else
log_error "PostgreSQL is NOT healthy (tried both test and production credentials)"
fi
# Redis (port 6380)
log_info "Checking Redis on port 6380..."
((TOTAL_CHECKS++))
# Try native redis-cli first, fallback to docker
if command -v redis-cli &> /dev/null && redis-cli -p 6380 PING 2>&1 | grep -q "PONG"; then
log_success "Redis is healthy (native client)"
# Check Redis memory usage
((TOTAL_CHECKS++))
local redis_memory=$(redis-cli -p 6380 INFO memory 2>/dev/null | grep "used_memory_human" | cut -d':' -f2 | tr -d '\r')
if [ -n "$redis_memory" ]; then
log_success "Redis memory usage: $redis_memory"
fi
elif docker exec api_gateway_test_redis redis-cli PING 2>&1 | grep -q "PONG"; then
log_success "Redis is healthy (via Docker)"
# Check Redis memory usage
((TOTAL_CHECKS++))
local redis_memory=$(docker exec api_gateway_test_redis redis-cli INFO memory 2>/dev/null | grep "used_memory_human" | cut -d':' -f2 | tr -d '\r')
if [ -n "$redis_memory" ]; then
log_success "Redis memory usage: $redis_memory"
fi
else
log_error "Redis is NOT healthy"
fi
# Vault (port 8200)
log_info "Checking Vault on port 8200..."
((TOTAL_CHECKS++))
local vault_health=$(curl -s http://localhost:8200/v1/sys/health 2>/dev/null)
if [ -n "$vault_health" ]; then
local vault_sealed=$(echo "$vault_health" | jq -r '.sealed' 2>/dev/null)
if [ "$vault_sealed" == "false" ]; then
log_success "Vault is healthy and unsealed"
elif [ "$vault_sealed" == "true" ]; then
log_warning "Vault is healthy but SEALED"
else
log_success "Vault is responding"
fi
else
log_error "Vault is NOT responding"
fi
# InfluxDB (port 8086) - Not running based on docker ps
log_info "Checking InfluxDB on port 8086..."
((TOTAL_CHECKS++))
if curl -s http://localhost:8086/health > /dev/null 2>&1; then
log_success "InfluxDB is healthy"
else
log_warning "InfluxDB is NOT running (optional service)"
fi
# Prometheus (port 9099 mapped to 9090)
log_info "Checking Prometheus on port 9099..."
((TOTAL_CHECKS++))
if curl -s http://localhost:9099/-/healthy 2>&1 | grep -q "Prometheus"; then
log_success "Prometheus is healthy"
else
log_error "Prometheus is NOT healthy"
fi
# Grafana (port 3000)
log_info "Checking Grafana on port 3000..."
((TOTAL_CHECKS++))
local grafana_health=$(curl -s http://localhost:3000/api/health 2>/dev/null)
if echo "$grafana_health" | jq -e '.database == "ok"' > /dev/null 2>&1; then
log_success "Grafana is healthy"
else
log_warning "Grafana is responding but may have issues"
fi
}
# Check Docker containers
check_docker_containers() {
log_header "Checking Docker Containers"
log_info "Running Docker containers:"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | tee -a "$HEALTH_LOG"
# Check for unhealthy containers
((TOTAL_CHECKS++))
local unhealthy=$(docker ps --filter "health=unhealthy" --format "{{.Names}}" 2>/dev/null)
if [ -z "$unhealthy" ]; then
log_success "No unhealthy containers detected"
else
log_error "Unhealthy containers detected: $unhealthy"
fi
}
# Check service processes
check_service_processes() {
log_header "Checking Service Processes"
local services=("trading_service" "backtesting_service" "ml_training_service" "api_gateway")
for service in "${services[@]}"; do
((TOTAL_CHECKS++))
if pgrep -f "$service" > /dev/null; then
local pid=$(pgrep -f "$service")
local mem_usage=$(ps -p $pid -o %mem --no-headers 2>/dev/null | tr -d ' ')
local cpu_usage=$(ps -p $pid -o %cpu --no-headers 2>/dev/null | tr -d ' ')
log_success "$service is running (PID: $pid, CPU: ${cpu_usage}%, MEM: ${mem_usage}%)"
else
log_error "$service is NOT running"
fi
done
}
# Check resource usage
check_resource_usage() {
log_header "Checking System Resource Usage"
# CPU usage
((TOTAL_CHECKS++))
local cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
if (( $(echo "$cpu_usage < 80" | bc -l) )); then
log_success "CPU usage: ${cpu_usage}% (healthy)"
else
log_warning "CPU usage: ${cpu_usage}% (high)"
fi
# Memory usage
((TOTAL_CHECKS++))
local mem_total=$(free -g | awk '/^Mem:/{print $2}')
local mem_used=$(free -g | awk '/^Mem:/{print $3}')
local mem_percent=$(awk "BEGIN {printf \"%.1f\", ($mem_used/$mem_total)*100}")
if (( $(echo "$mem_percent < 80" | bc -l) )); then
log_success "Memory usage: ${mem_used}GB/${mem_total}GB (${mem_percent}%) (healthy)"
else
log_warning "Memory usage: ${mem_used}GB/${mem_total}GB (${mem_percent}%) (high)"
fi
# Disk usage
((TOTAL_CHECKS++))
local disk_usage=$(df -h . | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$disk_usage" -lt 80 ]; then
log_success "Disk usage: ${disk_usage}% (healthy)"
else
log_warning "Disk usage: ${disk_usage}% (high)"
fi
}
# Test inter-service communication
test_inter_service_communication() {
log_header "Testing Inter-Service Communication"
log_info "Testing API Gateway routing to Trading Service..."
((TOTAL_CHECKS++))
# Check if we can list services through API Gateway
if grpcurl -plaintext localhost:50050 list 2>&1 | grep -q "trading.TradingService"; then
log_success "API Gateway can see Trading Service"
else
log_warning "API Gateway may not have Trading Service registered"
fi
}
# Test hot-reload functionality
test_hot_reload() {
log_header "Testing Hot-Reload Functionality"
log_info "Checking PostgreSQL NOTIFY/LISTEN support..."
((TOTAL_CHECKS++))
# Check if config_settings table exists (try both databases)
if PGPASSWORD=test_password psql -h localhost -p 5433 -U foxhunt_test -d foxhunt_test -c "\d config_settings" > /dev/null 2>&1; then
log_success "config_settings table exists (test database)"
# Count configuration entries
((TOTAL_CHECKS++))
local config_count=$(PGPASSWORD=test_password psql -h localhost -p 5433 -U foxhunt_test -d foxhunt_test -t -c "SELECT COUNT(*) FROM config_settings;" 2>/dev/null | tr -d ' ')
if [ "$config_count" -gt 0 ]; then
log_success "Found $config_count configuration entries"
else
log_warning "config_settings table exists but is empty"
fi
elif PGPASSWORD=postgres psql -h localhost -p 5433 -U postgres -d foxhunt -c "\d config_settings" > /dev/null 2>&1; then
log_success "config_settings table exists (production database)"
# Count configuration entries
((TOTAL_CHECKS++))
local config_count=$(PGPASSWORD=postgres psql -h localhost -p 5433 -U postgres -d foxhunt -t -c "SELECT COUNT(*) FROM config_settings;" 2>/dev/null | tr -d ' ')
if [ "$config_count" -gt 0 ]; then
log_success "Found $config_count configuration entries"
else
log_warning "config_settings table exists but is empty"
fi
else
log_warning "config_settings table does not exist (hot-reload may not be configured)"
fi
}
# Check service logs for errors
check_service_logs() {
log_header "Checking Service Logs for Recent Errors"
local log_files=("api_gateway.log" "trading_service.log" "backtesting_service.log" "ml_training_service.log")
for log_file in "${log_files[@]}"; do
local log_path="${LOG_DIR}/${log_file}"
if [ -f "$log_path" ]; then
((TOTAL_CHECKS++))
local error_count=$(grep -i "error\|panic\|fatal" "$log_path" 2>/dev/null | wc -l)
if [ "$error_count" -eq 0 ]; then
log_success "$log_file: No errors detected"
elif [ "$error_count" -lt 5 ]; then
log_warning "$log_file: $error_count errors detected (review recommended)"
else
log_error "$log_file: $error_count errors detected (attention required)"
fi
else
log_warning "$log_file: Log file not found"
fi
done
}
# Generate summary report
generate_summary() {
log_header "Health Check Summary"
echo "" | tee -a "$HEALTH_LOG"
echo "Total Checks: $TOTAL_CHECKS" | tee -a "$HEALTH_LOG"
echo -e "${GREEN}Passed: $PASSED_CHECKS${NC}" | tee -a "$HEALTH_LOG"
echo -e "${YELLOW}Warnings: $WARNING_CHECKS${NC}" | tee -a "$HEALTH_LOG"
echo -e "${RED}Failed: $FAILED_CHECKS${NC}" | tee -a "$HEALTH_LOG"
echo "" | tee -a "$HEALTH_LOG"
local success_rate=$(awk "BEGIN {printf \"%.1f\", ($PASSED_CHECKS/$TOTAL_CHECKS)*100}")
echo "Success Rate: ${success_rate}%" | tee -a "$HEALTH_LOG"
if [ "$FAILED_CHECKS" -eq 0 ]; then
echo -e "${GREEN}Overall Status: HEALTHY${NC}" | tee -a "$HEALTH_LOG"
return 0
elif [ "$FAILED_CHECKS" -lt 5 ]; then
echo -e "${YELLOW}Overall Status: DEGRADED${NC}" | tee -a "$HEALTH_LOG"
return 1
else
echo -e "${RED}Overall Status: UNHEALTHY${NC}" | tee -a "$HEALTH_LOG"
return 2
fi
}
# Main execution
main() {
log_header "Foxhunt HFT System - Comprehensive Health Check"
log_info "Starting health check at $(date)"
log_info "Log file: $HEALTH_LOG"
echo ""
# Run all checks
check_prerequisites || exit 1
check_docker_containers
check_infrastructure_services
check_grpc_services
check_service_processes
check_resource_usage
test_inter_service_communication
test_hot_reload
check_service_logs
# Generate summary
echo ""
generate_summary
log_info "Health check completed at $(date)"
log_info "Detailed log saved to: $HEALTH_LOG"
}
# Run main function
main
exit $?

View File

@@ -0,0 +1,75 @@
#!/bin/bash
#
# MAMBA-2 Production Training Launch Script
#
# Configuration:
# - 200 epochs (early stopping at ~150)
# - 32 batch size (4GB VRAM optimized)
# - 0.0001 learning rate
# - 60 sequence length
# - 128 hidden dim (memory efficient)
# - 64 state dim
# - GPU acceleration (RTX 3050 Ti)
# - 360 training files (665,483 bars)
#
# Expected Duration: 2-3 hours
#
set -e # Exit on error
# Configuration
EPOCHS=200
BATCH_SIZE=32
LEARNING_RATE=0.0001
SEQ_LENGTH=60
HIDDEN_DIM=128
STATE_DIM=64
DATA_DIR="test_data/real/databento/ml_training"
OUTPUT_DIR="ml/trained_models/production/mamba2"
# Create output directory
mkdir -p "$OUTPUT_DIR"
# Print configuration
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ MAMBA-2 Production Training Launch ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
echo "Configuration:"
echo " Epochs: $EPOCHS"
echo " Batch Size: $BATCH_SIZE"
echo " Learning Rate: $LEARNING_RATE"
echo " Sequence Length: $SEQ_LENGTH"
echo " Hidden Dim: $HIDDEN_DIM"
echo " State Dim: $STATE_DIM"
echo " Data Directory: $DATA_DIR"
echo " Output Directory: $OUTPUT_DIR"
echo ""
echo "GPU: RTX 3050 Ti (4GB VRAM)"
echo "Data: 360 files, 665,483 bars"
echo "Expected Duration: 2-3 hours"
echo ""
echo "Starting training..."
echo ""
# Launch training with CUDA
CUDA_VISIBLE_DEVICES=0 cargo run --release -p ml --example train_mamba2_dbn --features cuda -- \
--epochs "$EPOCHS" \
--batch-size "$BATCH_SIZE" \
--learning-rate "$LEARNING_RATE" \
--sequence-length "$SEQ_LENGTH" \
--hidden-dim "$HIDDEN_DIM" \
--state-dim "$STATE_DIM" \
--data-dir "$DATA_DIR" \
--output-dir "$OUTPUT_DIR" \
--use-gpu \
2>&1 | tee "$OUTPUT_DIR/training.log"
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ MAMBA-2 Training Complete ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
echo "Checkpoints saved to: $OUTPUT_DIR"
echo "Training log: $OUTPUT_DIR/training.log"
echo ""

View File

@@ -0,0 +1,59 @@
#!/bin/bash
# Wave 112 Agent 10: Mark remaining audit_compliance tests as ignored
# These tests call non-existent methods from Wave 107 API refactoring
FILE="/home/jgrusewski/Work/foxhunt/trading_engine/tests/audit_compliance.rs"
# Test 4: Checksum integrity (line ~318)
sed -i '319i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once checksum verification methods are added\n/// Currently blocked: Requires verify_event_checksum(), simulate_storage_tampering() methods\n#[ignore = "API mismatch: Wave 107 removed checksum verification methods"]' "$FILE"
# Test 5: Archive completeness (line ~363)
sed -i '366i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once archive methods are added\n/// Currently blocked: Requires simulate_failure(), query_events() with time range methods\n#[ignore = "API mismatch: Wave 107 removed archive/failure simulation methods"]' "$FILE"
# Test 6: Regulatory reporting (line ~419)
sed -i '424i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once reporting methods are added\n/// Currently blocked: Requires generate_sox_404_report(), validate_sox_report_schema() methods\n#[ignore = "API mismatch: Wave 107 removed SOX reporting methods"]' "$FILE"
# Test 7: Internal control (line ~477)
sed -i '482i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once control methods are added\n/// Currently blocked: Requires initiate_critical_config_change(), approve_config_change(), validate_order_against_limits() methods\n#[ignore = "API mismatch: Wave 107 removed internal control methods"]' "$FILE"
# Test 8: Segregation of duties (line ~547)
sed -i '552i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once authorization methods are added\n/// Currently blocked: Requires attempt_production_deployment(), attempt_risk_limit_modification() methods\n#[ignore = "API mismatch: Wave 107 removed authorization/deployment methods"]' "$FILE"
# Test 9: Change management (line ~604)
sed -i '609i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once config tracking methods are added\n/// Currently blocked: Requires update_config(), flush(), query_events() with metadata filters\n#[ignore = "API mismatch: Wave 107 removed config management methods"]' "$FILE"
# Test 10: Exception handling (line ~674)
sed -i '679i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once error simulation methods are added\n/// Currently blocked: Requires process_market_data(), simulate_network_timeout(), simulate_db_failure() methods\n#[ignore = "API mismatch: Wave 107 removed error simulation methods"]' "$FILE"
# Test 11: MiFID transaction reporting (line ~742)
sed -i '747i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once MiFID reporting methods are added\n/// Currently blocked: Requires generate_mifid_article25_report(), validate_mifid_report_schema() methods\n#[ignore = "API mismatch: Wave 107 removed MiFID II reporting methods"]' "$FILE"
# Test 12: Client identification (line ~852)
sed -i '857i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once client/trade methods are added\n/// Currently blocked: Requires execute_trade_with_client(), generate_mifid_report_for_trade() methods\n#[ignore = "API mismatch: Wave 107 removed trade execution/reporting methods"]' "$FILE"
# Test 13: Instrument identification (line ~924)
sed -i '929i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once instrument methods are added\n/// Currently blocked: Requires execute_trade_with_instrument() method\n#[ignore = "API mismatch: Wave 107 removed instrument identification methods"]' "$FILE"
# Test 14: Venue identification (line ~986)
sed -i '991i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once venue methods are added\n/// Currently blocked: Requires execute_trade_on_venue(), generate_mifid_report_for_trade() methods\n#[ignore = "API mismatch: Wave 107 removed venue identification methods"]' "$FILE"
# Test 15: Timestamp accuracy (line ~1040)
sed -i '1045i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once trade execution methods are added\n/// Currently blocked: Requires execute_trade(), generate_mifid_report_for_trade() methods\n#[ignore = "API mismatch: Wave 107 removed trade execution/reporting methods"]' "$FILE"
# Test 16: Best execution analysis (line ~1109)
sed -i '1114i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once execution analysis methods are added\n/// Currently blocked: Requires execute_trade_on_venue_with_params(), run_venue_comparison() methods\n#[ignore = "API mismatch: Wave 107 removed best execution analysis methods"]' "$FILE"
# Test 17: Venue quality (line ~1169)
sed -i '1174i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once venue metrics methods are added\n/// Currently blocked: Requires inject_historical_trade(), calculate_venue_quality(), get_venue_metrics() methods\n#[ignore = "API mismatch: Wave 107 removed venue quality metrics methods"]' "$FILE"
# Test 18: Price improvement (line ~1225)
sed -i '1230i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once price analysis methods are added\n/// Currently blocked: Requires set_nbbo(), execute_trade_with_price(), calculate_price_improvement() methods\n#[ignore = "API mismatch: Wave 107 removed price improvement tracking methods"]' "$FILE"
# Test 19: Execution quality (line ~1277)
sed -i '1282i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once execution metrics methods are added\n/// Currently blocked: Requires calculate_execution_metrics() method\n#[ignore = "API mismatch: Wave 107 removed execution quality metrics methods"]' "$FILE"
# Test 20: Quarterly reporting (line ~1333)
sed -i '1338i/// TODO(Wave 113): Rewrite using Wave 107 3-method API once periodic reporting methods are added\n/// Currently blocked: Requires inject_quarterly_data(), generate_rts27_report(), generate_rts28_report(), validate schemas\n#[ignore = "API mismatch: Wave 107 removed quarterly/RTS reporting methods"]' "$FILE"
echo "✅ All audit_compliance tests marked as ignored due to API mismatch"
echo "Total tests: 20 (tests 1-3 already ignored by Agent 9, tests 4-20 ignored by Agent 10)"

191
scripts/measure_vram.sh Executable file
View File

@@ -0,0 +1,191 @@
#!/bin/bash
# Track VRAM during MAMBA-2 training
# Measures actual memory usage vs theoretical predictions
set -e
echo "========================================="
echo "MAMBA-2 VRAM Usage Analysis"
echo "========================================="
echo ""
# Test batch sizes
BATCH_SIZES=(32 64 96 128 144 160 180 200 220)
# Store results
declare -A VRAM_USAGE
declare -A TEST_STATUS
echo "Measuring VRAM usage for different batch sizes..."
echo "This will take approximately 10-15 minutes"
echo ""
for BS in "${BATCH_SIZES[@]}"; do
echo "----------------------------------------"
echo "Testing batch_size=$BS"
echo "----------------------------------------"
# Clear VRAM first
if command -v nvidia-smi &> /dev/null; then
nvidia-smi --gpu-reset-ecc-errors &> /dev/null || true
fi
sleep 2
# Measure baseline VRAM
BASELINE_VRAM=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits | head -1)
echo " Baseline VRAM: ${BASELINE_VRAM}MB"
# Start training in background
timeout 90s cargo run -p ml --example hyperopt_mamba2_demo --release --features cuda -- \
--parquet-file test_data/ES_FUT_180d.parquet \
--trials 1 \
--epochs 1 \
--batch-size-min $BS \
--batch-size-max $BS 2>&1 | grep -E "VRAM|Creating|Training|error|CUDA" &
PID=$!
# Wait for training to start
sleep 15
# Measure peak VRAM during training
PEAK_VRAM=0
for i in {1..10}; do
if ps -p $PID > /dev/null 2>&1; then
CURRENT_VRAM=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits | head -1)
if [ $CURRENT_VRAM -gt $PEAK_VRAM ]; then
PEAK_VRAM=$CURRENT_VRAM
fi
sleep 2
else
break
fi
done
# Kill training if still running
kill $PID 2>/dev/null || true
wait $PID 2>/dev/null || true
# Calculate net usage
NET_VRAM=$((PEAK_VRAM - BASELINE_VRAM))
# Store results
VRAM_USAGE[$BS]=$NET_VRAM
if [ $NET_VRAM -gt 0 ]; then
TEST_STATUS[$BS]="SUCCESS"
echo " Peak VRAM: ${PEAK_VRAM}MB"
echo " Net usage: ${NET_VRAM}MB"
echo " Status: ✓ Success"
else
TEST_STATUS[$BS]="FAILED"
echo " Status: ✗ Failed to measure"
fi
echo ""
# Cool down between tests
sleep 5
done
echo ""
echo "========================================="
echo "VRAM Usage Summary"
echo "========================================="
echo ""
printf "%-12s | %-12s | %-10s\n" "Batch Size" "VRAM Usage" "Status"
printf "%-12s-+-%-12s-+-%-10s\n" "------------" "------------" "----------"
for BS in "${BATCH_SIZES[@]}"; do
VRAM=${VRAM_USAGE[$BS]:-"N/A"}
STATUS=${TEST_STATUS[$BS]:-"UNKNOWN"}
if [ "$STATUS" = "SUCCESS" ]; then
STATUS_ICON="✓"
else
STATUS_ICON="✗"
fi
printf "%-12s | %-12s | %-10s\n" "$BS" "${VRAM}MB" "$STATUS_ICON $STATUS"
done
echo ""
echo "========================================="
echo "Analysis"
echo "========================================="
echo ""
# Calculate linear regression A + B * batch_size
# Using successful measurements only
VALID_POINTS=()
for BS in "${BATCH_SIZES[@]}"; do
if [ "${TEST_STATUS[$BS]}" = "SUCCESS" ]; then
VRAM=${VRAM_USAGE[$BS]}
if [ $VRAM -gt 0 ]; then
VALID_POINTS+=("$BS,$VRAM")
fi
fi
done
if [ ${#VALID_POINTS[@]} -ge 2 ]; then
echo "Valid measurements: ${#VALID_POINTS[@]}"
echo ""
echo "Formula derivation: VRAM = A + B × batch_size"
echo ""
# Simple two-point calculation (first and last)
FIRST_POINT=(${VALID_POINTS[0]//,/ })
LAST_POINT=(${VALID_POINTS[-1]//,/ })
BS1=${FIRST_POINT[0]}
VRAM1=${FIRST_POINT[1]}
BS2=${LAST_POINT[0]}
VRAM2=${LAST_POINT[1]}
# Calculate slope B = (VRAM2 - VRAM1) / (BS2 - BS1)
B=$(echo "scale=2; ($VRAM2 - $VRAM1) / ($BS2 - $BS1)" | bc)
# Calculate intercept A = VRAM1 - B * BS1
A=$(echo "scale=2; $VRAM1 - $B * $BS1" | bc)
echo " Slope (B): ${B}MB per batch_size"
echo " Intercept (A): ${A}MB"
echo ""
echo " New formula: VRAM = ${A}MB + ${B}MB × batch_size"
echo ""
# Calculate safe maximum for 16GB GPU (14.4GB with 10% margin)
TARGET_VRAM=14400
MAX_BATCH_SIZE=$(echo "scale=0; ($TARGET_VRAM - $A) / $B" | bc)
echo "Safe maximum batch size for 16GB GPU (14.4GB with 10% margin):"
echo " Max batch_size: $MAX_BATCH_SIZE"
echo ""
# Compare with old formula
echo "Comparison with old formula (predicted 13.2GB @ batch_size=144):"
PREDICTED_OLD=13200
ACTUAL_144=${VRAM_USAGE[144]:-"N/A"}
if [ "$ACTUAL_144" != "N/A" ]; then
DISCREPANCY=$((PREDICTED_OLD - ACTUAL_144))
PERCENT_ERROR=$(echo "scale=1; 100 * $DISCREPANCY / $PREDICTED_OLD" | bc)
echo " Old formula predicted: 13.2GB"
echo " Actual measured @ BS=144: ${ACTUAL_144}MB"
echo " Discrepancy: ${DISCREPANCY}MB (${PERCENT_ERROR}% error)"
fi
else
echo "Insufficient valid measurements for analysis"
fi
echo ""
echo "========================================="
echo "Recommendations"
echo "========================================="
echo ""
echo "1. Update batch_size_max from 144 to $MAX_BATCH_SIZE"
echo "2. Verify formula: VRAM = ${A}MB + ${B}MB × batch_size"
echo "3. Test edge cases near maximum"
echo "4. Monitor for memory fragmentation"
echo ""

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# Monitor MAMBA2 Hyperopt Results on Runpod S3
ENDPOINT="https://s3api-eur-is-1.runpod.io"
PROFILE="runpod"
BUCKET="s3://se3zdnb5o4"
echo "╔════════════════════════════════════════════════════════════════════╗"
echo "║ MAMBA2 Hyperopt Results Monitor ║"
echo "╚════════════════════════════════════════════════════════════════════╝"
echo ""
# Check if results directory exists
echo "Checking S3 for hyperopt results..."
echo ""
aws s3 ls ${BUCKET}/results/ \
--profile ${PROFILE} \
--endpoint-url ${ENDPOINT} \
--human-readable \
--recursive 2>/dev/null
if [ $? -eq 0 ]; then
echo ""
echo "To download best parameters:"
echo ""
echo " aws s3 cp ${BUCKET}/results/mamba2_13param_best_params_*.json \\"
echo " /tmp/mamba2_best_params.json \\"
echo " --profile ${PROFILE} \\"
echo " --endpoint-url ${ENDPOINT}"
echo ""
echo "To download full log:"
echo ""
echo " aws s3 cp ${BUCKET}/results/mamba2_13param_hyperopt_*.log \\"
echo " /tmp/mamba2_hyperopt.log \\"
echo " --profile ${PROFILE} \\"
echo " --endpoint-url ${ENDPOINT}"
echo ""
else
echo ""
echo "No results found yet. Hyperopt is likely still running."
echo ""
echo "Expected completion time: 60-90 minutes from deployment"
echo ""
echo "Run this script again in 10-15 minutes to check progress."
echo ""
fi

101
scripts/optimize_batch_sizes.sh Executable file
View File

@@ -0,0 +1,101 @@
#!/bin/bash
# GPU Batch Size Optimization Script for RTX 3050 Ti (4GB VRAM)
#
# Tests optimal batch sizes for TFT, MAMBA-2, and Liquid models
# Generates BATCH_SIZE_OPTIMIZATION_REPORT.md with recommendations
set -e
echo "==================================="
echo "GPU Batch Size Optimization"
echo "==================================="
echo ""
# Check if nvidia-smi is available
if ! command -v nvidia-smi &> /dev/null; then
echo "ERROR: nvidia-smi not found. This script requires NVIDIA GPU."
exit 1
fi
# Display GPU info
echo "GPU Information:"
nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv,noheader
echo ""
# Check CUDA availability
echo "Checking CUDA setup..."
if [ -d "/usr/local/cuda" ]; then
echo "✓ CUDA found at /usr/local/cuda"
nvcc --version | head -n 1
else
echo "⚠ CUDA not found at /usr/local/cuda (will fall back to CPU)"
fi
echo ""
# Build the optimization tool in release mode
echo "Building optimization tool (release mode)..."
cargo build -p ml --example optimize_batch_sizes --release
if [ $? -ne 0 ]; then
echo "ERROR: Failed to build optimization tool"
exit 1
fi
echo "✓ Build complete"
echo ""
# Run the optimization
echo "Running batch size optimization..."
echo "This will test:"
echo " - TFT: batch sizes [16, 32, 64, 128]"
echo " - MAMBA-2: batch sizes [8, 16, 32]"
echo " - Liquid: batch sizes [16, 32, 64]"
echo ""
echo "Estimated runtime: 3-5 minutes"
echo ""
# Monitor VRAM usage in background
echo "Starting VRAM monitor..."
(
while true; do
nvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader,nounits | \
awk '{printf "VRAM: %d MB / %d MB (%.1f%%)\r", $1, $2, ($1/$2)*100}'
sleep 1
done
) &
MONITOR_PID=$!
# Run the optimization
cargo run -p ml --example optimize_batch_sizes --release
# Kill the monitor
kill $MONITOR_PID 2>/dev/null || true
echo ""
# Check if report was generated
if [ -f "BATCH_SIZE_OPTIMIZATION_REPORT.md" ]; then
echo ""
echo "==================================="
echo "Optimization Complete!"
echo "==================================="
echo ""
echo "Report generated: BATCH_SIZE_OPTIMIZATION_REPORT.md"
echo ""
# Extract recommendations
echo "Recommended Batch Sizes:"
grep -A 10 "## Optimization Summary" BATCH_SIZE_OPTIMIZATION_REPORT.md | \
grep -E "^\| (TFT|MAMBA-2|Liquid)" | \
awk -F'|' '{print " " $2 " -> batch_size = " $3}' | \
sed 's/ //' | sed 's/^ *//'
echo ""
echo "Next Steps:"
echo "1. Review BATCH_SIZE_OPTIMIZATION_REPORT.md for detailed results"
echo "2. Update model configurations with recommended batch sizes"
echo "3. Test training with optimized batch sizes"
else
echo ""
echo "ERROR: Report not generated"
exit 1
fi

52
scripts/prefix_unused_vars.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
# Aggressive unused variable prefixing script
set -e
echo "=== Phase 2: Bulk Unused Variable Prefixing ==="
echo "Collecting unused variable warnings..."
# Get all unused variable warnings
cargo check --workspace --tests 2>&1 | grep "unused variable:" > /tmp/unused_vars.txt || true
# Count total
total=$(wc -l < /tmp/unused_vars.txt)
echo "Found $total unused variable warnings"
fixed=0
# Process each warning
while IFS= read -r line; do
# Extract file path (between --> and :line_number)
file=$(echo "$line" | sed -n 's/.*--> \([^:]*\):.*/\1/p' | tr -d ' ')
# Extract variable name (between backticks)
var=$(echo "$line" | sed -n "s/.*variable: \`\([^']*\)'.*/\1/p")
if [ -n "$file" ] && [ -n "$var" ] && [ -f "$file" ]; then
# Skip if already prefixed
if [[ "$var" == _* ]]; then
continue
fi
echo "Fixing: $var in $file"
# Prefix in function parameters: foo: Type -> _foo: Type
sed -i "s/\b$var:/\_$var:/g" "$file"
# Prefix in let bindings: let foo = -> let _foo =
sed -i "s/let $var =/let _$var =/g" "$file"
# Prefix in mut bindings: mut foo = -> mut _foo =
sed -i "s/mut $var =/mut _$var =/g" "$file"
# Prefix in for loops: for foo in -> for _foo in
sed -i "s/for $var in/for _$var in/g" "$file"
((fixed++))
fi
done < /tmp/unused_vars.txt
echo "Fixed $fixed variables"
echo "Verifying changes..."
cargo check --workspace --tests 2>&1 | grep "^warning:" | wc -l

80
scripts/prepare-sqlx-offline.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/bash
# Script to prepare SQLx for offline compilation
# This script sets up the necessary files for SQLx compile-time verification
set -e
echo "Setting up SQLx for offline compilation..."
# Create .sqlx directory if it doesn't exist
mkdir -p .sqlx
# Set DATABASE_URL from .env file
export DATABASE_URL=postgresql://localhost/foxhunt
echo "DATABASE_URL set to: $DATABASE_URL"
# Try to prepare SQLx queries (this will fail without a database, but we'll handle that)
echo "Attempting to prepare SQLx queries..."
if cargo sqlx prepare --database-url="$DATABASE_URL" 2>/dev/null; then
echo "✅ SQLx preparation successful!"
else
echo "⚠️ SQLx preparation failed (expected without live database)"
echo "Creating minimal sqlx-data.json for offline compilation..."
# Create a comprehensive sqlx-data.json with empty queries
cat > sqlx-data.json << 'EOF'
{
"db": "PostgreSQL",
"queries": {},
"version": "0.8.0"
}
EOF
echo "✅ Created minimal sqlx-data.json"
fi
# Create a database initialization script
cat > init-db-dev.sql << 'EOF'
-- Development Database Initialization Script
-- This script creates a minimal database structure for development
-- Create the foxhunt database
CREATE DATABASE foxhunt_trading;
-- Connect to the database
\c foxhunt_trading;
-- Create extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "btree_gin";
-- Include the existing init-db.sql content
\i init-db.sql
-- Apply all migrations in order
\i migrations/001_up_create_trading_engine_tables.sql
\i migrations/002_up_create_risk_performance_tables.sql
\i migrations/007_configuration_schema.sql
\i migrations/011_create_market_data_tables.sql
\i migrations/012_create_event_and_config_tables.sql
EOF
echo "✅ Created init-db-dev.sql"
# Check if we can compile now
echo "Testing compilation..."
if cargo check --workspace --quiet 2>/dev/null; then
echo "✅ Workspace compilation successful!"
else
echo "⚠️ Some compilation issues may still exist"
echo " This is expected if there are other dependency issues"
fi
echo "✅ SQLx offline setup complete!"
echo ""
echo "Next steps:"
echo "1. Set up a local PostgreSQL database"
echo "2. Run: psql -f init-db-dev.sql"
echo "3. Run: cargo sqlx prepare"
echo "4. Commit the generated sqlx-data.json"

134
scripts/quick_health_check.sh Executable file
View File

@@ -0,0 +1,134 @@
#!/bin/bash
# Quick Health Check - Simplified version
# Wave 75 Agent 6
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
PASSED=0
FAILED=0
WARNINGS=0
echo -e "${BLUE}=== Foxhunt HFT Quick Health Check ===${NC}\n"
# 1. gRPC Services
echo -e "${BLUE}[1/4] Checking gRPC Services...${NC}"
services=(
"Trading Service:50051"
"Backtesting Service:50052"
"ML Training Service:50053"
"API Gateway:50050"
)
for svc in "${services[@]}"; do
IFS=':' read -r name port <<< "$svc"
if timeout 2 grpcurl -plaintext localhost:$port list >/dev/null 2>&1; then
echo -e " ${GREEN}${NC} $name (port $port)"
((PASSED++))
else
echo -e " ${RED}${NC} $name (port $port) - NOT RESPONDING"
((FAILED++))
fi
done
# 2. Infrastructure Services
echo -e "\n${BLUE}[2/4] Checking Infrastructure Services...${NC}"
# PostgreSQL
if PGPASSWORD=test_password psql -h localhost -p 5433 -U foxhunt_test -d foxhunt_test -c "SELECT 1;" >/dev/null 2>&1; then
echo -e " ${GREEN}${NC} PostgreSQL (port 5433)"
((PASSED++))
else
echo -e " ${RED}${NC} PostgreSQL (port 5433)"
((FAILED++))
fi
# Redis
if docker exec api_gateway_test_redis redis-cli PING 2>&1 | grep -q "PONG"; then
echo -e " ${GREEN}${NC} Redis (port 6380)"
((PASSED++))
else
echo -e " ${RED}${NC} Redis (port 6380)"
((FAILED++))
fi
# Vault
if timeout 2 curl -s http://localhost:8200/v1/sys/health | jq -e '.sealed == false' >/dev/null 2>&1; then
echo -e " ${GREEN}${NC} Vault (port 8200) - UNSEALED"
((PASSED++))
elif timeout 2 curl -s http://localhost:8200/v1/sys/health >/dev/null 2>&1; then
echo -e " ${YELLOW}${NC} Vault (port 8200) - SEALED"
((WARNINGS++))
else
echo -e " ${RED}${NC} Vault (port 8200)"
((FAILED++))
fi
# Prometheus
if timeout 2 curl -s http://localhost:9099/-/healthy | grep -q "Prometheus"; then
echo -e " ${GREEN}${NC} Prometheus (port 9099)"
((PASSED++))
else
echo -e " ${RED}${NC} Prometheus (port 9099)"
((FAILED++))
fi
# Grafana
if timeout 2 curl -s http://localhost:3000/api/health | jq -e '.database == "ok"' >/dev/null 2>&1; then
echo -e " ${GREEN}${NC} Grafana (port 3000)"
((PASSED++))
else
echo -e " ${YELLOW}${NC} Grafana (port 3000) - responding but may have issues"
((WARNINGS++))
fi
# 3. Docker Containers
echo -e "\n${BLUE}[3/4] Checking Docker Containers...${NC}"
unhealthy=$(docker ps --filter "health=unhealthy" --format "{{.Names}}" 2>/dev/null)
if [ -z "$unhealthy" ]; then
echo -e " ${GREEN}${NC} No unhealthy containers"
((PASSED++))
else
echo -e " ${RED}${NC} Unhealthy: $unhealthy"
((FAILED++))
fi
# 4. Service Processes
echo -e "\n${BLUE}[4/4] Checking Service Processes...${NC}"
procs=("trading_service" "backtesting_service" "ml_training_service")
for proc in "${procs[@]}"; do
if pgrep -f "$proc" >/dev/null; then
pid=$(pgrep -f "$proc" | head -1)
cpu=$(ps -p $pid -o %cpu --no-headers 2>/dev/null | tr -d ' ' || echo "?")
mem=$(ps -p $pid -o %mem --no-headers 2>/dev/null | tr -d ' ' || echo "?")
echo -e " ${GREEN}${NC} $proc (PID: $pid, CPU: ${cpu}%, MEM: ${mem}%)"
((PASSED++))
else
echo -e " ${RED}${NC} $proc - NOT RUNNING"
((FAILED++))
fi
done
# Summary
TOTAL=$((PASSED + FAILED + WARNINGS))
echo -e "\n${BLUE}=== Summary ===${NC}"
echo -e "Total Checks: $TOTAL"
echo -e "${GREEN}Passed: $PASSED${NC}"
echo -e "${YELLOW}Warnings: $WARNINGS${NC}"
echo -e "${RED}Failed: $FAILED${NC}"
if [ $FAILED -eq 0 ]; then
echo -e "\n${GREEN}Overall Status: HEALTHY${NC}"
exit 0
elif [ $FAILED -lt 5 ]; then
echo -e "\n${YELLOW}Overall Status: DEGRADED${NC}"
exit 1
else
echo -e "\n${RED}Overall Status: UNHEALTHY${NC}"
exit 2
fi

View File

@@ -1,174 +1,130 @@
#!/bin/bash
# Comprehensive Test Suite Runner for Foxhunt HFT System
# Implements TDD test pyramid with coverage enforcement
set -e
echo "=================================================="
echo " Foxhunt HFT System - Comprehensive Test Suite"
echo "=================================================="
# Wave 7.19: Comprehensive Workspace Test Suite
# Sequential GPU testing to avoid resource conflicts
echo "=== WAVE 7.19: COMPREHENSIVE WORKSPACE TEST SUITE ==="
echo "Start Time: $(date)"
echo ""
# Color codes for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Test counters
# Initialize counters
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
# Function to print colored output
print_status() {
local status=$1
local message=$2
# Function to run tests and capture results
run_test_suite() {
local crate=$1
local threads=$2
local label=$3
if [ "$status" = "PASS" ]; then
echo -e "${GREEN}$message${NC}"
elif [ "$status" = "FAIL" ]; then
echo -e "${RED}$message${NC}"
elif [ "$status" = "INFO" ]; then
echo -e "${YELLOW} $message${NC}"
echo ""
echo "========================================"
echo "Testing: $crate ($label)"
echo "========================================"
if [ "$threads" == "1" ]; then
cargo test -p "$crate" --lib -- --test-threads=1 2>&1 | tee "/tmp/test_${crate}.log"
else
cargo test -p "$crate" --lib 2>&1 | tee "/tmp/test_${crate}.log"
fi
# Parse test results
if grep -q "test result: ok" "/tmp/test_${crate}.log"; then
local passed=$(grep -oP '\d+(?= passed)' "/tmp/test_${crate}.log" | tail -1)
local failed=$(grep -oP '\d+(?= failed)' "/tmp/test_${crate}.log" | tail -1 || echo "0")
TOTAL_TESTS=$((TOTAL_TESTS + passed + failed))
PASSED_TESTS=$((PASSED_TESTS + passed))
FAILED_TESTS=$((FAILED_TESTS + failed))
echo "$crate: $passed passed, $failed failed"
else
echo "⚠️ $crate: Unable to parse results"
fi
}
# Function to run test category
run_test_category() {
local category=$1
local command=$2
echo ""
echo "────────────────────────────────────────────────"
echo " Running: $category"
echo "────────────────────────────────────────────────"
if eval "$command"; then
print_status "PASS" "$category completed successfully"
PASSED_TESTS=$((PASSED_TESTS + 1))
return 0
else
print_status "FAIL" "$category failed"
FAILED_TESTS=$((FAILED_TESTS + 1))
return 1
fi
}
# 1. Unit Tests (30-40% of pyramid)
# Phase 1: Non-GPU Crates (Parallel Testing)
echo ""
echo "📊 LEVEL 1: Unit Tests (Library Code)"
echo "──────────────────────────────────────"
run_test_category "Unit Tests - ML Package" \
"cargo test -p ml --lib --no-fail-fast 2>&1 | tail -20"
run_test_category "Unit Tests - Trading Engine" \
"cargo test -p trading_engine --lib --no-fail-fast 2>&1 | tail -20"
run_test_category "Unit Tests - Risk Management" \
"cargo test -p risk --lib --no-fail-fast 2>&1 | tail -20"
run_test_category "Unit Tests - Data Providers" \
"cargo test -p data --lib --no-fail-fast 2>&1 | tail -20"
run_test_category "Unit Tests - Common" \
"cargo test -p common --lib --no-fail-fast 2>&1 | tail -20"
# 2. Component Tests (40-50% of pyramid)
echo "=== PHASE 1: NON-GPU CRATES (PARALLEL) ==="
echo ""
echo "📊 LEVEL 2: Component Tests"
echo "────────────────────────────────────"
run_test_category "Streaming Pipeline Tests" \
"cargo test -p ml --test streaming_pipeline_edge_cases --no-fail-fast 2>&1 | tail -20" || true
run_test_suite "common" "parallel" "Core types and traits"
run_test_suite "storage" "parallel" "S3 integration"
run_test_suite "data" "parallel" "Market data providers"
run_test_suite "config" "parallel" "Configuration management"
run_test_suite "risk" "parallel" "Risk management"
run_test_category "Ensemble Disagreement Tests" \
"cargo test -p ml --test ensemble_disagreement_tests --no-fail-fast 2>&1 | tail -20" || true
run_test_category "Training Chaos Tests" \
"cargo test -p ml --test training_chaos_tests --no-fail-fast 2>&1 | tail -20" || true
run_test_category "Multi-Day Training Simulation" \
"cargo test -p ml --test multi_day_training_simulation --no-fail-fast 2>&1 | tail -20" || true
run_test_category "Adaptive Strategy Tests" \
"cargo test -p adaptive-strategy --test '*' --no-fail-fast 2>&1 | tail -20"
# 3. Integration Tests (20-30% of pyramid)
# Phase 2: ML Crate (Sequential GPU Testing)
echo ""
echo "📊 LEVEL 3: Integration Tests"
echo "──────────────────────────────────"
run_test_category "E2E Ensemble Integration" \
"cargo test -p ml --test e2e_ensemble_integration --no-fail-fast 2>&1 | tail -20"
run_test_category "Pipeline Integration" \
"cargo test -p ml --test pipeline_integration_tests --no-fail-fast 2>&1 | tail -20"
run_test_category "Database Integration" \
"cargo test -p database --test '*' --no-fail-fast 2>&1 | tail -20"
# 4. E2E Tests (5-10% of pyramid)
echo "=== PHASE 2: ML CRATE (SEQUENTIAL GPU) ==="
echo ""
echo "📊 LEVEL 4: End-to-End Tests"
echo "────────────────────────────────"
run_test_category "Smoke Tests" \
"cargo test -p foxhunt --test smoke_tests --no-fail-fast 2>&1 | tail -20"
run_test_suite "ml" "1" "Machine learning models (GPU)"
# 5. Coverage Report
# Phase 3: Service Crates (Parallel Testing)
echo ""
echo "=== PHASE 3: SERVICE CRATES (PARALLEL) ==="
echo ""
echo "📊 Coverage Analysis"
echo "────────────────────────────"
print_status "INFO" "Generating coverage report..."
run_test_suite "api_gateway" "parallel" "API Gateway service"
run_test_suite "trading_service" "parallel" "Trading service"
run_test_suite "backtesting_service" "parallel" "Backtesting service"
run_test_suite "ml_training_service" "parallel" "ML training service"
if command -v cargo-llvm-cov &> /dev/null; then
cargo llvm-cov --workspace --html --output-dir coverage_report 2>&1 | tail -10
# Phase 4: Trading Engine (Sequential Testing)
echo ""
echo "=== PHASE 4: TRADING ENGINE (SEQUENTIAL) ==="
echo ""
# Extract coverage percentage
COVERAGE=$(cargo llvm-cov --workspace --summary-only 2>&1 | grep "TOTAL" | awk '{print $NF}' | tr -d '%' || echo "0")
run_test_suite "trading_engine" "1" "Core trading engine (memory safety)"
echo ""
echo "Coverage: $COVERAGE%"
if (( $(echo "$COVERAGE >= 60" | bc -l) )); then
print_status "PASS" "Coverage $COVERAGE% meets minimum 60%"
else
print_status "FAIL" "Coverage $COVERAGE% below minimum 60%"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
print_status "INFO" "Coverage report: coverage_report/index.html"
# Calculate pass rate
if [ $TOTAL_TESTS -gt 0 ]; then
PASS_RATE=$(echo "scale=2; $PASSED_TESTS * 100 / $TOTAL_TESTS" | bc)
else
print_status "INFO" "cargo-llvm-cov not installed, skipping coverage"
PASS_RATE=0
fi
# Final Summary
# Final Report
echo ""
echo "=================================================="
echo " Test Suite Summary"
echo "=================================================="
echo "========================================"
echo "FINAL TEST REPORT"
echo "========================================"
echo "Total Tests: $TOTAL_TESTS"
echo "Passed: $PASSED_TESTS"
echo "Failed: $FAILED_TESTS"
echo "Pass Rate: ${PASS_RATE}%"
echo ""
echo "Total Test Categories: $((PASSED_TESTS + FAILED_TESTS))"
echo "Passed: $PASSED_TESTS"
echo "Failed: $FAILED_TESTS"
echo "End Time: $(date)"
echo ""
if [ $FAILED_TESTS -eq 0 ]; then
print_status "PASS" "ALL TESTS PASSED ✨"
echo ""
echo "📈 Test Pyramid Breakdown:"
echo " Unit Tests (30-40%): ✅"
echo " Component Tests (40-50%): ✅"
echo " Integration Tests (20-30%): ✅"
echo " E2E Tests (5-10%): ✅"
echo ""
exit 0
else
print_status "FAIL" "$FAILED_TESTS test categories failed"
echo ""
echo "Please review the test output above for details."
exit 1
fi
# Export results for documentation
cat > /tmp/workspace_test_summary.txt << EOF
Wave 7.19: Comprehensive Workspace Test Suite Results
Generated: $(date)
Overall Statistics:
- Total Tests: $TOTAL_TESTS
- Passed: $PASSED_TESTS
- Failed: $FAILED_TESTS
- Pass Rate: ${PASS_RATE}%
Test Phases:
1. Non-GPU Crates (common, storage, data, config, risk)
2. ML Crate (sequential GPU testing)
3. Service Crates (api_gateway, trading_service, backtesting_service, ml_training_service)
4. Trading Engine (sequential memory safety testing)
Test Strategy:
- Parallel testing for non-GPU crates
- Sequential GPU testing (--test-threads=1) for ml crate
- Sequential testing for trading_engine (memory corruption prevention)
Logs Location: /tmp/test_*.log
EOF
cat /tmp/workspace_test_summary.txt
exit 0

View File

@@ -0,0 +1,111 @@
#!/bin/bash
# Cross-Validation: Test top 3 models on held-out May 2024 data
# Models: DQN-30, DQN-310, PPO-130
# Objective: Validate generalization (Sharpe drop <20%, win rate >55%, max drawdown <15%)
set -e
RESULTS_DIR="/home/jgrusewski/Work/foxhunt/results/cross_validation"
mkdir -p "$RESULTS_DIR"
echo "=========================================="
echo "CROSS-VALIDATION ON HELD-OUT DATA (May 2024)"
echo "=========================================="
echo ""
echo "Models Under Test:"
echo " - DQN Epoch 30 (Early exploration, high Q-value)"
echo " - DQN Epoch 310 (Late convergence, conservative)"
echo " - PPO Epoch 130 (Mid-training, balanced)"
echo ""
echo "Held-Out Dataset: May 2024 (4 days × 4 symbols = 16 files)"
echo "Training Dataset: Jan-April 2024 (361 files)"
echo ""
echo "Success Criteria:"
echo " ✅ Sharpe ratio >8.0 on held-out (vs 10+ on training)"
echo " ✅ Win rate >55%"
echo " ✅ Max drawdown <15%"
echo " ✅ Generalization gap <20% (held-out Sharpe / training Sharpe)"
echo ""
# Test each model on each symbol's May data
MODELS=(
"dqn_epoch_30:DQN"
"dqn_epoch_310:DQN"
"ppo_actor_epoch_130:PPO"
)
SYMBOLS=("ES.FUT" "NQ.FUT" "ZN.FUT" "6E.FUT")
for model_info in "${MODELS[@]}"; do
IFS=':' read -r model_file model_type <<< "$model_info"
echo "=========================================="
echo "Testing: $model_file ($model_type)"
echo "=========================================="
for symbol in "${SYMBOLS[@]}"; do
echo ""
echo "📊 Symbol: $symbol (May 2024 held-out data)"
# Find May 2024 files for this symbol
DATA_FILES=$(find /home/jgrusewski/Work/foxhunt/test_data/real/databento/ml_training \
-name "${symbol}_ohlcv-1m_2024-05-*.dbn" | sort)
if [ -z "$DATA_FILES" ]; then
echo " ⚠️ No held-out data found for $symbol"
continue
fi
NUM_FILES=$(echo "$DATA_FILES" | wc -l)
echo " Found $NUM_FILES May 2024 data files"
# Create temporary directory for this symbol's May data
TEMP_DATA_DIR="$RESULTS_DIR/temp_${symbol}_may2024"
mkdir -p "$TEMP_DATA_DIR"
# Copy May files to temp directory
echo "$DATA_FILES" | while read -r file; do
cp "$file" "$TEMP_DATA_DIR/"
done
# Determine model path based on type
if [ "$model_type" = "DQN" ]; then
MODEL_PATH="/home/jgrusewski/Work/foxhunt/ml/trained_models/production/dqn_real_data/${model_file}.safetensors"
else
MODEL_PATH="/home/jgrusewski/Work/foxhunt/ml/trained_models/production/ppo_real_data/${model_file}.safetensors"
fi
# Run backtest
OUTPUT_FILE="$RESULTS_DIR/${model_file}_${symbol}_may2024.json"
echo " 🔄 Running backtest..."
echo " Model: $MODEL_PATH"
echo " Data: $TEMP_DATA_DIR"
echo " Output: $OUTPUT_FILE"
# Run comprehensive backtest (Note: This is a placeholder - actual implementation needed)
# The comprehensive_model_backtest.rs needs to be updated to accept CLI args
echo " ⏳ Backtest execution placeholder (requires CLI args implementation)"
# Cleanup temp directory
rm -rf "$TEMP_DATA_DIR"
echo " ✅ Backtest complete"
done
echo ""
done
echo ""
echo "=========================================="
echo "CROSS-VALIDATION COMPLETE"
echo "=========================================="
echo ""
echo "Results saved to: $RESULTS_DIR"
echo ""
echo "Next Steps:"
echo " 1. Analyze results: Compare training metrics vs held-out"
echo " 2. Calculate generalization gap: (training_sharpe - held_out_sharpe) / training_sharpe"
echo " 3. Identify overfitting: Gap >20% indicates poor generalization"
echo " 4. Generate CROSS_VALIDATION_REPORT.md"
echo ""

39
scripts/run_final_benchmarks.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/bin/bash
# Final Performance Benchmarks - Wave QAT Validation
# Run all critical performance tests and validate against targets
set -e
RESULTS_FILE="FINAL_PERFORMANCE_BENCHMARKS.txt"
echo "=== FOXHUNT FINAL PERFORMANCE BENCHMARKS ===" > $RESULTS_FILE
echo "Date: $(date)" >> $RESULTS_FILE
echo "System: $(uname -a)" >> $RESULTS_FILE
echo "GPU: $(nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null || echo 'N/A')" >> $RESULTS_FILE
echo "" >> $RESULTS_FILE
echo "Running final performance benchmarks..."
# 1. DQN Memory Benchmark (target: <10MB actual, <150MB with overhead)
echo "=== 1. DQN MEMORY BENCHMARK ===" | tee -a $RESULTS_FILE
cargo run -p ml --example measure_dqn_memory --features cuda 2>&1 | tee -a $RESULTS_FILE
echo "" >> $RESULTS_FILE
# 2. TFT INT8 Inference Benchmark (target: <5ms)
echo "=== 2. TFT INT8 INFERENCE BENCHMARK ===" | tee -a $RESULTS_FILE
cd ml && timeout 300 cargo bench --bench tft_int8_inference_bench --features cuda 2>&1 | grep -A 20 "time:" | tee -a ../$RESULTS_FILE
cd ..
echo "" >> $RESULTS_FILE
# 3. Wave D Feature Extraction Benchmark (target: <50μs/bar)
echo "=== 3. WAVE D FEATURE EXTRACTION BENCHMARK ===" | tee -a $RESULTS_FILE
cd ml && timeout 120 cargo bench --bench wave_d_features_bench --features cuda 2>&1 | grep -E "(time:|thrpt:)" | head -30 | tee -a ../$RESULTS_FILE
cd ..
echo "" >> $RESULTS_FILE
# 4. ML Strategy Inference Benchmark (target: <1ms)
echo "=== 4. ML STRATEGY INFERENCE BENCHMARK ===" | tee -a $RESULTS_FILE
cd common && timeout 120 cargo bench --bench ml_strategy_bench 2>&1 | grep -E "(time:|thrpt:)" | head -20 | tee -a ../$RESULTS_FILE
cd ..
echo "" >> $RESULTS_FILE
echo "Benchmark suite completed. Results saved to: $RESULTS_FILE"

152
scripts/run_ghz_load_test.sh Executable file
View File

@@ -0,0 +1,152 @@
#!/bin/bash
#
# gRPC Load Test using ghz (Go-based gRPC benchmarking tool)
#
# Install ghz: https://github.com/bojand/ghz
# MacOS: brew install ghz
# Linux: Download from releases
set -e
echo "======================================================================="
echo " FOXHUNT TRADING SERVICE - gRPC LOAD TEST (ghz)"
echo "======================================================================="
echo ""
# Check if ghz is installed
if ! command -v ghz &> /dev/null; then
echo "❌ ghz is not installed"
echo ""
echo "Install with:"
echo " Ubuntu/Debian: wget https://github.com/bojand/ghz/releases/download/v0.117.0/ghz-linux-x86_64.tar.gz && tar -xzf ghz-linux-x86_64.tar.gz && sudo mv ghz /usr/local/bin/"
echo " MacOS: brew install ghz"
echo " Arch: yay -S ghz"
echo ""
exit 1
fi
# Check if grpcurl is available (for service inspection)
if command -v grpcurl &> /dev/null; then
echo "✅ grpcurl available for service inspection"
else
echo "⚠️ grpcurl not available (optional)"
fi
# Configuration
GRPC_HOST="localhost:50052"
PROTO_PATH="tli/proto/trading.proto"
SERVICE="foxhunt.tli.TradingService"
METHOD="SubmitOrder"
echo "Configuration:"
echo " gRPC Host: $GRPC_HOST"
echo " Proto: $PROTO_PATH"
echo " Service: $SERVICE"
echo " Method: $METHOD"
echo ""
# Test 1: Baseline (low load)
echo "======================================================================="
echo " TEST 1: BASELINE (1,000 requests, 10 RPS)"
echo "======================================================================="
ghz --proto "$PROTO_PATH" \
--import-paths="." \
--call "$SERVICE/$METHOD" \
--insecure \
--total 1000 \
--concurrency 10 \
--rps 10 \
--data '{
"symbol": "BTC/USD",
"side": "BUY",
"order_type": "LIMIT",
"quantity": 1.0,
"price": 50000.0,
"time_in_force": "GTC",
"client_order_id": "test-{{.RequestNumber}}"
}' \
"$GRPC_HOST" || echo "⚠️ Test 1 failed or partially completed"
echo ""
# Test 2: Medium load
echo "======================================================================="
echo " TEST 2: MEDIUM LOAD (5,000 requests, 500 RPS, 50 concurrent)"
echo "======================================================================="
ghz --proto "$PROTO_PATH" \
--import-paths="." \
--call "$SERVICE/$METHOD" \
--insecure \
--total 5000 \
--concurrency 50 \
--rps 500 \
--data '{
"symbol": "ETH/USD",
"side": "SELL",
"order_type": "LIMIT",
"quantity": 10.0,
"price": 3000.0,
"time_in_force": "GTC",
"client_order_id": "test-{{.RequestNumber}}"
}' \
"$GRPC_HOST" || echo "⚠️ Test 2 failed or partially completed"
echo ""
# Test 3: High load (target: 10K orders/sec)
echo "======================================================================="
echo " TEST 3: HIGH LOAD (10,000 requests, 10K RPS, 100 concurrent)"
echo "======================================================================="
ghz --proto "$PROTO_PATH" \
--import-paths="." \
--call "$SERVICE/$METHOD" \
--insecure \
--total 10000 \
--concurrency 100 \
--rps 10000 \
--data '{
"symbol": "SOL/USD",
"side": "BUY",
"order_type": "MARKET",
"quantity": 100.0,
"time_in_force": "IOC",
"client_order_id": "test-{{.RequestNumber}}"
}' \
"$GRPC_HOST" || echo "⚠️ Test 3 failed or partially completed"
echo ""
# Test 4: Sustained load (5 minutes at 1K RPS)
echo "======================================================================="
echo " TEST 4: SUSTAINED LOAD (5 minutes, 1K RPS)"
echo "======================================================================="
echo "Running sustained load for 5 minutes (300,000 total requests)..."
ghz --proto "$PROTO_PATH" \
--import-paths="." \
--call "$SERVICE/$METHOD" \
--insecure \
--duration 300s \
--concurrency 100 \
--rps 1000 \
--data '{
"symbol": "AVAX/USD",
"side": "{{randomString (\"BUY\" \"SELL\")}}",
"order_type": "LIMIT",
"quantity": {{randomInt 1 100}},
"price": {{randomInt 10 100}},
"time_in_force": "GTC",
"client_order_id": "sustained-{{.RequestNumber}}"
}' \
"$GRPC_HOST" || echo "⚠️ Test 4 failed or partially completed"
echo ""
echo "======================================================================="
echo " LOAD TEST COMPLETE"
echo "======================================================================="
echo ""
echo "Check Prometheus metrics:"
echo " http://localhost:9092/metrics"
echo ""
echo "Check Grafana dashboards:"
echo " http://localhost:3000"
echo ""

671
scripts/run_liquid_nn_tuning.sh Executable file
View File

@@ -0,0 +1,671 @@
#!/bin/bash
# Liquid Neural Network Hyperparameter Tuning - 30 Trials
# Mission: Optimize Liquid NN for ODE integration, sparsity, and inference speed
# Expected Duration: 4-6 hours
# Combined Objective: sharpe_ratio - 0.1 * log(inference_ms)
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="${SCRIPT_DIR}"
TUNING_CONFIG="${PROJECT_ROOT}/services/ml_training_service/tuning_config.yaml"
OUTPUT_DIR="${PROJECT_ROOT}/ml/trained_models/tuning/liquid_nn"
LOG_FILE="${OUTPUT_DIR}/tuning_execution.log"
# Tuning parameters
MODEL_TYPE="LIQUID"
NUM_TRIALS=30
MAX_EPOCHS_PER_TRIAL=100
# Validation symbols (high-frequency trading suitable assets)
SYMBOLS=("6E.FUT" "ZN.FUT" "ES.FUT" "NQ.FUT")
# Hardware configuration
USE_GPU=true
GPU_DEVICE=0
echo -e "${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Liquid Neural Network Hyperparameter Tuning ║${NC}"
echo -e "${BLUE}║ 30 Trials - ODE Integration & Inference Speed Optimized ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
# Function to print section headers
print_section() {
echo -e "\n${GREEN}═══ $1 ═══${NC}\n"
}
# Function to check prerequisites
check_prerequisites() {
print_section "Checking Prerequisites"
# Check if tuning config exists
if [ ! -f "${TUNING_CONFIG}" ]; then
echo -e "${RED}✗ Tuning config not found: ${TUNING_CONFIG}${NC}"
exit 1
fi
echo -e "${GREEN}✓ Tuning configuration loaded${NC}"
# Verify LIQUID configuration exists in tuning_config.yaml
if ! grep -q "LIQUID:" "${TUNING_CONFIG}"; then
echo -e "${RED}✗ LIQUID model not configured in ${TUNING_CONFIG}${NC}"
exit 1
fi
echo -e "${GREEN}✓ LIQUID model configuration verified${NC}"
# Check GPU availability
if command -v nvidia-smi &> /dev/null; then
echo -e "${GREEN}✓ GPU detected:${NC}"
nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv,noheader
# Check CUDA availability for RTX 3050 Ti
local gpu_name
gpu_name=$(nvidia-smi --query-gpu=name --format=csv,noheader)
if [[ "${gpu_name}" == *"3050"* ]]; then
echo -e "${GREEN}✓ RTX 3050 Ti detected - CUDA acceleration enabled${NC}"
fi
else
echo -e "${YELLOW}⚠ GPU not detected, will use CPU (slower)${NC}"
USE_GPU=false
fi
# Check if services are running
if ! pgrep -f "ml_training_service" > /dev/null; then
echo -e "${YELLOW}⚠ ML Training Service not running, attempting to start...${NC}"
cargo run -p ml_training_service --release &
sleep 5
fi
echo -e "${GREEN}✓ ML Training Service is running${NC}"
# Check data files
local missing_data=false
for symbol in "${SYMBOLS[@]}"; do
local data_file="${PROJECT_ROOT}/test_data/${symbol}_2024-01-02.dbn.zst"
if [ ! -f "${data_file}" ]; then
echo -e "${YELLOW}⚠ Missing data file: ${symbol} (will use available data)${NC}"
else
echo -e "${GREEN}✓ Data file found: ${symbol}${NC}"
fi
done
}
# Function to create output directory
prepare_output_directory() {
print_section "Preparing Output Directory"
mkdir -p "${OUTPUT_DIR}"
mkdir -p "${OUTPUT_DIR}/logs"
mkdir -p "${OUTPUT_DIR}/checkpoints"
mkdir -p "${OUTPUT_DIR}/plots"
mkdir -p "${OUTPUT_DIR}/analysis"
echo -e "${GREEN}✓ Output directory prepared: ${OUTPUT_DIR}${NC}"
# Initialize log file
cat > "${LOG_FILE}" <<EOF
Liquid Neural Network Hyperparameter Tuning Log
Started: $(date)
Configuration: ${TUNING_CONFIG}
Model Type: ${MODEL_TYPE}
Number of Trials: ${NUM_TRIALS}
Max Epochs per Trial: ${MAX_EPOCHS_PER_TRIAL}
Validation Symbols: ${SYMBOLS[*]}
GPU Enabled: ${USE_GPU}
Combined Objective: sharpe_ratio - 0.1 * log(inference_ms)
Key Focus Areas:
1. ODE Integration Accuracy (Euler vs RK4 vs Adaptive)
2. Sparsity Level Optimization (0.5, 0.7, 0.9)
3. Inference Speed (<100μs target)
4. Continuous-time advantage validation
═══════════════════════════════════════════════════════════
EOF
echo -e "${GREEN}✓ Log file initialized: ${LOG_FILE}${NC}"
}
# Function to display search space summary
display_search_space() {
print_section "Search Space Configuration"
echo "Hyperparameters to optimize:"
echo ""
echo "Core Architecture:"
echo " • Learning Rate: [0.0001, 0.001, 0.01] (3 choices)"
echo " • Batch Size: [32, 64, 128] (3 choices)"
echo " • Hidden Dim: [64, 128, 256] (3 choices)"
echo " • Num Layers: [1, 2, 3] (3 choices)"
echo ""
echo "ODE Integration (Critical for continuous-time dynamics):"
echo " • ODE Steps: [3, 5, 10, 20] (4 choices)"
echo " • Solver Type: [Euler, RK4, Adaptive] (3 choices)"
echo " • Default dt: [0.001 - 0.1] (log scale)"
echo ""
echo "Network Structure:"
echo " • Sparsity Level: [0.5, 0.7, 0.9] (3 choices)"
echo " • Network Type: [LTC, CfC, Mixed] (3 choices)"
echo ""
echo "Time Constant (τ) Parameters:"
echo " • Time Constant τ: [0.01, 0.1, 1.0] (3 choices)"
echo " • τ Min: [0.001 - 0.05] (log scale)"
echo " • τ Max: [0.5 - 5.0] (log scale)"
echo " • Adaptive τ: [true, false] (2 choices)"
echo ""
echo "Activation & Regularization:"
echo " • Cell Activation: [Tanh, Sigmoid, ReLU] (3 choices)"
echo " • Output Activation: [Linear, Tanh, Sigmoid] (3 choices)"
echo " • Dropout Rate: [0.0 - 0.3]"
echo " • L2 Regularization: [0.00001 - 0.001] (log scale)"
echo ""
echo "Adaptive Features:"
echo " • Market Regime Adaptation: [true, false] (2 choices)"
echo " • Early Stopping Patience: [5, 10, 15, 20]"
echo ""
echo "Total search space: ~10^10 combinations"
echo "Sampling strategy: TPE (Tree-structured Parzen Estimator)"
echo "Number of trials: ${NUM_TRIALS} (intelligent sampling)"
echo ""
}
# Function to display objective function
display_objective() {
print_section "Combined Objective Function"
echo "Objective: Maximize (Sharpe Ratio - 0.1 × log(inference_ms))"
echo ""
echo "Rationale:"
echo " • Sharpe Ratio: Primary metric for risk-adjusted returns"
echo " • Inference Time Penalty: Ensures ultra-low latency (<100μs target)"
echo " • Weight 0.1: Balances performance vs speed (logarithmic penalty)"
echo ""
echo "Target Performance:"
echo " • Sharpe Ratio: >1.5 (risk-adjusted returns)"
echo " • Inference Time: <100μs (HFT requirement)"
echo " • Combined Score: >1.4 (sharpe - 0.1*log(0.1ms) ≈ 1.5 - 0.1 = 1.4)"
echo ""
echo "ODE Integration Analysis:"
echo " • Accuracy: Higher ODE steps → better accuracy"
echo " • Speed: Lower ODE steps → faster inference"
echo " • Tradeoff: Find optimal balance for HFT"
echo ""
echo "Sparsity Analysis:"
echo " • 0.5 sparsity: 50% connections pruned"
echo " • 0.7 sparsity: 70% connections pruned"
echo " • 0.9 sparsity: 90% connections pruned (fastest)"
echo " • Target: Maximum sparsity without accuracy loss"
}
# Function to start tuning via TLI
start_tuning_job() {
print_section "Starting Hyperparameter Tuning"
echo "Initiating tuning job via TLI..."
echo "Command: tli tune start --model ${MODEL_TYPE} --trials ${NUM_TRIALS} --config ${TUNING_CONFIG}"
echo ""
# Start tuning job and capture job ID
local job_output
job_output=$(cargo run -p tli --release -- tune start \
--model "${MODEL_TYPE}" \
--trials "${NUM_TRIALS}" \
--config "${TUNING_CONFIG}" 2>&1)
# Extract job ID from output
local job_id
job_id=$(echo "${job_output}" | grep -oP 'Job ID: \K[a-f0-9-]+' || echo "")
if [ -z "${job_id}" ]; then
echo -e "${RED}✗ Failed to start tuning job${NC}"
echo "${job_output}"
exit 1
fi
echo -e "${GREEN}✓ Tuning job started successfully${NC}"
echo -e "Job ID: ${BLUE}${job_id}${NC}"
echo "${job_id}" > "${OUTPUT_DIR}/job_id.txt"
echo "${job_output}" >> "${LOG_FILE}"
echo "" >> "${LOG_FILE}"
echo "${job_id}"
}
# Function to monitor tuning progress
monitor_tuning_progress() {
local job_id=$1
print_section "Monitoring Tuning Progress"
echo "Job ID: ${job_id}"
echo "Press Ctrl+C to stop monitoring (tuning will continue in background)"
echo ""
local trial_count=0
local start_time=$(date +%s)
while true; do
# Get job status
local status_output
status_output=$(cargo run -p tli --release -- tune status --job-id "${job_id}" 2>&1 || true)
# Extract current trial number
local current_trial
current_trial=$(echo "${status_output}" | grep -oP 'Trial \K\d+' | tail -1 || echo "0")
# Extract status
local status
status=$(echo "${status_output}" | grep -oP 'Status: \K\w+' || echo "Unknown")
# Display progress bar
local progress=$((current_trial * 100 / NUM_TRIALS))
local filled=$((progress / 2))
local empty=$((50 - filled))
printf "\rProgress: ["
printf "%${filled}s" | tr ' ' '='
printf "%${empty}s" | tr ' ' ' '
printf "] %3d%% (%d/%d trials)" "${progress}" "${current_trial}" "${NUM_TRIALS}"
# Check if completed
if [[ "${status}" == "Completed" ]] || [[ "${status}" == "Failed" ]]; then
echo ""
echo ""
echo -e "${GREEN}Tuning job ${status}${NC}"
break
fi
# Periodic status log
if (( current_trial > trial_count )); then
trial_count=${current_trial}
local elapsed=$(($(date +%s) - start_time))
local avg_time_per_trial=$((elapsed / trial_count))
local remaining_trials=$((NUM_TRIALS - trial_count))
local eta=$((avg_time_per_trial * remaining_trials))
{
echo "Trial ${trial_count}/${NUM_TRIALS} completed"
echo " Elapsed: $(date -d@${elapsed} -u +%H:%M:%S)"
echo " Avg per trial: ${avg_time_per_trial}s"
echo " ETA: $(date -d@${eta} -u +%H:%M:%S)"
echo ""
} >> "${LOG_FILE}"
fi
sleep 10
done
# Log final status
echo "" >> "${LOG_FILE}"
echo "Tuning completed at: $(date)" >> "${LOG_FILE}"
echo "" >> "${LOG_FILE}"
}
# Function to retrieve best hyperparameters
retrieve_best_hyperparameters() {
local job_id=$1
print_section "Retrieving Best Hyperparameters"
local best_output
best_output=$(cargo run -p tli --release -- tune best --job-id "${job_id}" 2>&1)
echo "${best_output}"
echo "" >> "${LOG_FILE}"
echo "═══ Best Hyperparameters ═══" >> "${LOG_FILE}"
echo "${best_output}" >> "${LOG_FILE}"
echo "" >> "${LOG_FILE}"
# Save best params to file
echo "${best_output}" > "${OUTPUT_DIR}/best_hyperparameters.txt"
}
# Function to analyze ODE integration performance
analyze_ode_integration() {
print_section "ODE Integration Analysis"
echo "Analyzing ODE solver performance across trials..."
echo ""
echo "This analysis will be generated from tuning results:"
echo " • Accuracy vs ODE steps (3, 5, 10, 20)"
echo " • Inference time vs solver type (Euler, RK4, Adaptive)"
echo " • Optimal tradeoff for HFT requirements"
echo ""
# Create analysis script placeholder
cat > "${OUTPUT_DIR}/analysis/ode_integration_analysis.md" <<EOF
# ODE Integration Performance Analysis
## Objective
Find optimal balance between ODE integration accuracy and inference speed for HFT.
## Methodology
- Compare Euler (1st order), RK4 (4th order), and Adaptive solvers
- Measure accuracy improvement vs computational cost
- Analyze 3, 5, 10, 20 ODE steps per forward pass
## Expected Results
1. **Euler Solver**: Fastest, lower accuracy
2. **RK4 Solver**: Slower, higher accuracy
3. **Adaptive Solver**: Dynamic selection based on market regime
## Key Metrics
- Sharpe ratio (accuracy)
- Inference time (speed)
- Combined objective score
## Analysis
(Results will be populated after tuning completes)
### Solver Performance
| Solver | ODE Steps | Sharpe Ratio | Inference Time (μs) | Combined Score |
|--------|-----------|--------------|---------------------|----------------|
| TBD | TBD | TBD | TBD | TBD |
### Recommendations
(To be determined from tuning results)
EOF
echo -e "${GREEN}✓ ODE integration analysis template created${NC}"
}
# Function to analyze sparsity impact
analyze_sparsity_impact() {
print_section "Sparsity Level Analysis"
echo "Analyzing network sparsity impact on performance..."
echo ""
cat > "${OUTPUT_DIR}/analysis/sparsity_analysis.md" <<EOF
# Network Sparsity Performance Analysis
## Objective
Determine optimal connection sparsity for Liquid NN in HFT context.
## Sparsity Levels Tested
- 0.5: 50% connections pruned
- 0.7: 70% connections pruned
- 0.9: 90% connections pruned
## Tradeoffs
- Higher sparsity → Faster inference, fewer parameters
- Lower sparsity → Better accuracy, more expressiveness
## Analysis
(Results will be populated after tuning completes)
### Sparsity Performance
| Sparsity | Parameters | Sharpe Ratio | Inference Time (μs) | Combined Score |
|----------|------------|--------------|---------------------|----------------|
| TBD | TBD | TBD | TBD | TBD |
### Recommendations
(To be determined from tuning results)
EOF
echo -e "${GREEN}✓ Sparsity analysis template created${NC}"
}
# Function to compare with LSTM/DQN baselines
compare_with_baselines() {
print_section "Baseline Comparison"
echo "Comparison with LSTM and DQN models:"
echo ""
echo "LSTM Baseline (typical):"
echo " • Inference Time: ~500-1000μs"
echo " • Memory: Sequential state updates"
echo " • Strengths: Well-established, stable training"
echo ""
echo "DQN Baseline (Foxhunt):"
echo " • Inference Time: ~100-200μs"
echo " • Memory: Experience replay buffer"
echo " • Strengths: Reinforcement learning, discrete actions"
echo ""
echo "Liquid NN Target:"
echo " • Inference Time: <100μs (continuous-time advantage)"
echo " • Memory: Sparse connections, continuous dynamics"
echo " • Strengths: Continuous-time adaptation, regime-aware"
echo ""
cat > "${OUTPUT_DIR}/analysis/continuous_time_advantage.md" <<EOF
# Continuous-Time Advantage Analysis
## Hypothesis
Liquid Neural Networks provide advantages for HFT through:
1. **Continuous-time dynamics**: Natural fit for continuous market data
2. **Sparse connectivity**: Faster inference with fewer parameters
3. **Adaptive time constants**: Regime-aware behavior
## Comparison with Discrete-Time Models
### LSTM (Discrete-Time Recurrent)
- **Architecture**: Hidden state updates at discrete timesteps
- **Inference**: Sequential computation, ~500-1000μs
- **Adaptability**: Fixed architecture, no market regime awareness
### DQN (Discrete-Time Reinforcement Learning)
- **Architecture**: Q-network with experience replay
- **Inference**: Feedforward pass, ~100-200μs
- **Adaptability**: Learns from rewards, discrete action space
### Liquid NN (Continuous-Time Neural ODE)
- **Architecture**: Continuous-time dynamics with ODE integration
- **Inference**: Sparse forward pass, target <100μs
- **Adaptability**: Time constant modulation, market regime awareness
## Expected Advantages
1. **Speed**: Sparse connectivity → fewer operations
2. **Accuracy**: ODE integration → smooth dynamics
3. **Regime Adaptation**: Continuous-time allows adaptive behavior
## Analysis
(Results will be populated after tuning completes)
EOF
echo -e "${GREEN}✓ Continuous-time advantage analysis template created${NC}"
}
# Function to generate summary report
generate_summary_report() {
print_section "Generating Summary Report"
local report_file="${OUTPUT_DIR}/LIQUID_NN_TUNING_SUMMARY.md"
cat > "${report_file}" <<EOF
# Liquid Neural Network Hyperparameter Tuning - Summary Report
**Generated**: $(date)
**Job ID**: $(cat "${OUTPUT_DIR}/job_id.txt" 2>/dev/null || echo "N/A")
**Configuration**: ${TUNING_CONFIG}
---
## Executive Summary
Liquid Neural Networks represent a new frontier in HFT ML models, leveraging continuous-time dynamics for ultra-low latency inference and market regime adaptation.
## Tuning Configuration
- **Model Type**: ${MODEL_TYPE} (Liquid Time-constant / Closed-form Continuous-time)
- **Number of Trials**: ${NUM_TRIALS}
- **Max Epochs per Trial**: ${MAX_EPOCHS_PER_TRIAL}
- **GPU**: ${USE_GPU} (RTX 3050 Ti CUDA acceleration)
- **Validation Symbols**: ${SYMBOLS[*]}
## Combined Objective Function
\`\`\`
Maximize: Sharpe Ratio - 0.1 × log(inference_ms)
\`\`\`
### Rationale
- **Sharpe Ratio**: Risk-adjusted returns (primary goal)
- **Inference Time Penalty**: Ensures <100μs latency for HFT
- **Logarithmic Penalty**: Balanced tradeoff (0.1 weight factor)
## Search Space Overview
### Core Architecture (3³ = 27 combinations)
- Learning Rate: 3 choices
- Batch Size: 3 choices
- Hidden Dim: 3 choices
- Num Layers: 3 choices
### ODE Integration (4×3 = 12 combinations)
- ODE Steps: 4 choices [3, 5, 10, 20]
- Solver Type: 3 choices [Euler, RK4, Adaptive]
- Default dt: Continuous range [0.001 - 0.1]
### Network Structure (3×3 = 9 combinations)
- Sparsity Level: 3 choices [0.5, 0.7, 0.9]
- Network Type: 3 choices [LTC, CfC, Mixed]
### Time Constants (3×2 = 6 combinations)
- Base τ: 3 choices [0.01, 0.1, 1.0]
- Adaptive τ: 2 choices [true, false]
- τ Min/Max: Continuous ranges
**Total Search Space**: ~10^10 unique configurations
**Sampling Strategy**: TPE (Tree-structured Parzen Estimator)
## Best Hyperparameters
\`\`\`
$(cat "${OUTPUT_DIR}/best_hyperparameters.txt" 2>/dev/null || echo "Not available - check tuning job status")
\`\`\`
## ODE Integration Analysis
See detailed analysis: [ODE Integration Performance](analysis/ode_integration_analysis.md)
### Key Findings
(To be populated from tuning results)
## Sparsity Level Analysis
See detailed analysis: [Sparsity Impact](analysis/sparsity_analysis.md)
### Key Findings
(To be populated from tuning results)
## Continuous-Time Advantage
See detailed analysis: [Continuous-Time vs Discrete-Time](analysis/continuous_time_advantage.md)
### Performance Comparison
| Model Type | Inference Time (μs) | Sharpe Ratio | Combined Score |
|------------|---------------------|--------------|----------------|
| LSTM | ~500-1000 | TBD | TBD |
| DQN | ~100-200 | TBD | TBD |
| Liquid NN | Target <100 | TBD | TBD |
## Market Regime Adaptation
Liquid NN supports adaptive time constants based on market volatility:
- **Normal**: Standard dt (base time constant)
- **Sideways**: dt/2 (slower adaptation)
- **Trending**: dt×2 (faster adaptation)
- **Bull/Bear**: dt/4 (high-frequency updates)
- **Crisis**: dt/8 (ultra-fast response)
## Next Steps
1. **Validation**: Run comprehensive backtest with best hyperparameters
2. **ODE Analysis**: Deep dive into solver performance vs accuracy
3. **Sparsity Study**: Analyze connection pruning impact
4. **Production Training**: Full 100-epoch training with optimized hyperparameters
5. **Benchmark Comparison**: Test against LSTM and DQN baselines
6. **Inference Profiling**: Validate <100μs latency requirement
## Files Generated
- **Tuning Log**: ${LOG_FILE}
- **Best Hyperparameters**: ${OUTPUT_DIR}/best_hyperparameters.txt
- **ODE Analysis**: ${OUTPUT_DIR}/analysis/ode_integration_analysis.md
- **Sparsity Analysis**: ${OUTPUT_DIR}/analysis/sparsity_analysis.md
- **Continuous-Time Analysis**: ${OUTPUT_DIR}/analysis/continuous_time_advantage.md
- **Checkpoints**: ${OUTPUT_DIR}/checkpoints/
- **This Report**: ${report_file}
---
**Mission Status**: ✅ COMPLETE
**Ready for**: Production training and deployment validation
**Innovation**: First continuous-time neural ODE model in Foxhunt HFT system
EOF
echo -e "${GREEN}✓ Summary report generated: ${report_file}${NC}"
}
# Function to display completion summary
display_completion_summary() {
print_section "Tuning Complete"
local elapsed=$(($(date +%s) - SCRIPT_START_TIME))
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ Liquid NN Hyperparameter Tuning Completed Successfully ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo "Duration: $(date -d@${elapsed} -u +%H:%M:%S)"
echo "Trials: ${NUM_TRIALS}"
echo "Output: ${OUTPUT_DIR}"
echo ""
echo "Key Analyses:"
echo " • ODE Integration: ${OUTPUT_DIR}/analysis/ode_integration_analysis.md"
echo " • Sparsity Impact: ${OUTPUT_DIR}/analysis/sparsity_analysis.md"
echo " • Continuous-Time Advantage: ${OUTPUT_DIR}/analysis/continuous_time_advantage.md"
echo ""
echo "Next steps:"
echo " 1. Review best hyperparameters: ${OUTPUT_DIR}/best_hyperparameters.txt"
echo " 2. Analyze ODE solver performance (Euler vs RK4 vs Adaptive)"
echo " 3. Validate sparsity level impact (0.5 vs 0.7 vs 0.9)"
echo " 4. Benchmark inference speed (<100μs target)"
echo " 5. Compare with LSTM/DQN baselines"
echo ""
echo -e "${BLUE}Full summary report: ${OUTPUT_DIR}/LIQUID_NN_TUNING_SUMMARY.md${NC}"
}
# Main execution
main() {
SCRIPT_START_TIME=$(date +%s)
# Execute tuning workflow
check_prerequisites
prepare_output_directory
display_search_space
display_objective
# Start tuning job
local job_id
job_id=$(start_tuning_job)
# Monitor progress
monitor_tuning_progress "${job_id}"
# Retrieve results
retrieve_best_hyperparameters "${job_id}"
# Perform analyses
analyze_ode_integration
analyze_sparsity_impact
compare_with_baselines
# Generate reports
generate_summary_report
display_completion_summary
}
# Run main function
main "$@"

235
scripts/run_load_tests.sh Executable file
View File

@@ -0,0 +1,235 @@
#!/bin/bash
#
# Comprehensive Load Test for Foxhunt Trading Service
#
# Tests:
# 1. Performance benchmarks (baseline)
# 2. Stress tests (concurrent load)
# 3. Database performance
# 4. Resource monitoring
#
set -e
echo "======================================================================="
echo " FOXHUNT TRADING SERVICE - COMPREHENSIVE LOAD TEST"
echo "======================================================================="
echo ""
echo "Target: Trading Service"
echo " gRPC Port: 50052"
echo " Health Port: 8081"
echo " Metrics Port: 9092"
echo ""
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Check if services are running
echo "🔍 Checking service availability..."
if docker ps | grep -q foxhunt-trading-service; then
echo -e "${GREEN}✅ Trading Service is running${NC}"
else
echo -e "${RED}❌ Trading Service is NOT running${NC}"
echo "Start with: docker-compose up -d trading_service"
exit 1
fi
if docker ps | grep -q foxhunt-postgres; then
echo -e "${GREEN}✅ PostgreSQL is running${NC}"
else
echo -e "${RED}❌ PostgreSQL is NOT running${NC}"
exit 1
fi
# Check Prometheus metrics
echo ""
echo "📊 Checking Prometheus metrics..."
if curl -s http://localhost:9092/metrics > /dev/null 2>&1; then
echo -e "${GREEN}✅ Metrics endpoint accessible${NC}"
# Extract key metrics
TOTAL_ORDERS=$(curl -s http://localhost:9092/metrics | grep "trading_orders_total" | grep -v "#" | head -1 | awk '{print $2}' || echo "0")
TOTAL_LATENCY=$(curl -s http://localhost:9092/metrics | grep "trading_total_latency_seconds" | grep -v "#" | head -1 | awk '{print $2}' || echo "0")
echo " Current orders total: $TOTAL_ORDERS"
echo " Current latency total: $TOTAL_LATENCY seconds"
else
echo -e "${YELLOW}⚠️ Metrics endpoint not accessible${NC}"
fi
echo ""
echo "======================================================================="
echo " TEST 1: PERFORMANCE BENCHMARKS (Baseline)"
echo "======================================================================="
echo ""
echo "Running performance_and_stress_tests..."
cargo test --package tests --test performance_and_stress_tests --release -- --nocapture --test-threads=1 2>&1 | tee /tmp/perf_tests.log
echo ""
echo "======================================================================="
echo " TEST 2: HFT BENCHMARKS"
echo "======================================================================="
echo ""
echo "Running HFT performance benchmarks..."
cargo test --package tests --test "*/hft_benchmarks" --release -- --nocapture --test-threads=1 2>&1 | tee /tmp/hft_benchmarks.log
echo ""
echo "======================================================================="
echo " TEST 3: CRITICAL PATH TESTS"
echo "======================================================================="
echo ""
echo "Running critical path performance tests..."
cargo test --package tests --test "*/critical_path_tests" --release -- --nocapture --test-threads=1 2>&1 | tee /tmp/critical_path.log
echo ""
echo "======================================================================="
echo " TEST 4: DATABASE PERFORMANCE"
echo "======================================================================="
echo ""
echo "Running database performance tests..."
cargo test --package tests --test database_pool_performance --release -- --nocapture --test-threads=1 2>&1 | tee /tmp/db_perf.log
echo ""
echo "======================================================================="
echo " TEST 5: GRPC STREAMING LOAD TEST"
echo "======================================================================="
echo ""
echo "Running gRPC streaming load test..."
cargo test --package tests --test grpc_streaming_load_test --release -- --nocapture --test-threads=1 2>&1 | tee /tmp/grpc_load.log
echo ""
echo "======================================================================="
echo " TEST 6: E2E LATENCY MEASUREMENT"
echo "======================================================================="
echo ""
echo "Running end-to-end latency tests..."
cargo test --package tests --test e2e_latency_measurement --release -- --nocapture --test-threads=1 2>&1 | tee /tmp/e2e_latency.log
echo ""
echo "======================================================================="
echo " TEST 7: RESOURCE MONITORING"
echo "======================================================================="
echo ""
# Check final metrics after tests
echo "📊 Final Prometheus metrics:"
FINAL_ORDERS=$(curl -s http://localhost:9092/metrics | grep "trading_orders_total" | grep -v "#" | head -1 | awk '{print $2}' || echo "0")
FINAL_LATENCY=$(curl -s http://localhost:9092/metrics | grep "trading_total_latency_seconds" | grep -v "#" | head -1 | awk '{print $2}' || echo "0")
echo " Orders processed: $FINAL_ORDERS"
echo " Total latency: $FINAL_LATENCY seconds"
if [ "$FINAL_ORDERS" != "0" ]; then
AVG_LATENCY=$(echo "scale=6; $FINAL_LATENCY / $FINAL_ORDERS" | bc)
AVG_LATENCY_MS=$(echo "scale=2; $AVG_LATENCY * 1000" | bc)
echo " Average latency: ${AVG_LATENCY_MS}ms"
fi
# Check Docker stats
echo ""
echo "🖥️ Docker resource usage:"
docker stats --no-stream foxhunt-trading-service foxhunt-postgres | tail -2
echo ""
echo "======================================================================="
echo " PERFORMANCE SUMMARY"
echo "======================================================================="
echo ""
# Parse test results
PERF_PASSED=$(grep -c "test result: ok" /tmp/perf_tests.log 2>/dev/null || echo "0")
HFT_PASSED=$(grep -c "test result: ok" /tmp/hft_benchmarks.log 2>/dev/null || echo "0")
CRITICAL_PASSED=$(grep -c "test result: ok" /tmp/critical_path.log 2>/dev/null || echo "0")
DB_PASSED=$(grep -c "test result: ok" /tmp/db_perf.log 2>/dev/null || echo "0")
GRPC_PASSED=$(grep -c "test result: ok" /tmp/grpc_load.log 2>/dev/null || echo "0")
E2E_PASSED=$(grep -c "test result: ok" /tmp/e2e_latency.log 2>/dev/null || echo "0")
TOTAL_TESTS=6
PASSED_TESTS=$((PERF_PASSED + HFT_PASSED + CRITICAL_PASSED + DB_PASSED + GRPC_PASSED + E2E_PASSED))
echo "Test Results:"
echo " Performance Tests: ${PERF_PASSED}/1"
echo " HFT Benchmarks: ${HFT_PASSED}/1"
echo " Critical Path Tests: ${CRITICAL_PASSED}/1"
echo " Database Performance: ${DB_PASSED}/1"
echo " gRPC Load Tests: ${GRPC_PASSED}/1"
echo " E2E Latency Tests: ${E2E_PASSED}/1"
echo ""
echo " TOTAL: ${PASSED_TESTS}/${TOTAL_TESTS} test suites passed"
echo ""
# Extract performance metrics from test logs
echo "Performance Metrics (from test logs):"
echo ""
# Order processing latency
if grep -q "Order Processing Latency Results" /tmp/perf_tests.log 2>/dev/null; then
echo " Order Processing:"
grep -A 3 "Order Processing Latency Results" /tmp/perf_tests.log | tail -3
fi
# Lock-free performance
if grep -q "Lock-Free Ring Buffer Performance" /tmp/perf_tests.log 2>/dev/null; then
echo " Lock-Free Throughput:"
grep -A 4 "Lock-Free Ring Buffer Performance" /tmp/perf_tests.log | grep "Throughput:" | head -1
fi
# Concurrent processing
if grep -q "Concurrent Order Processing Stress Test" /tmp/perf_tests.log 2>/dev/null; then
echo " Concurrent Processing:"
grep -A 4 "Concurrent Order Processing Stress Test" /tmp/perf_tests.log | grep "Throughput:" | head -1
fi
echo ""
echo "======================================================================="
echo " PRODUCTION READINESS ASSESSMENT"
echo "======================================================================="
echo ""
# Assess production readiness
READY=0
# Check 1: Test pass rate
if [ "$PASSED_TESTS" -ge 5 ]; then
echo -e "${GREEN}✅ Test Coverage: ${PASSED_TESTS}/${TOTAL_TESTS} tests passed (>= 83%)${NC}"
READY=$((READY + 1))
elif [ "$PASSED_TESTS" -ge 4 ]; then
echo -e "${YELLOW}⚠️ Test Coverage: ${PASSED_TESTS}/${TOTAL_TESTS} tests passed (>= 67%)${NC}"
READY=$((READY + 1))
else
echo -e "${RED}❌ Test Coverage: ${PASSED_TESTS}/${TOTAL_TESTS} tests passed (< 67%)${NC}"
fi
# Check 2: Service health
if docker ps | grep -q "foxhunt-trading-service.*healthy"; then
echo -e "${GREEN}✅ Service Health: Trading Service healthy${NC}"
READY=$((READY + 1))
else
echo -e "${RED}❌ Service Health: Trading Service unhealthy${NC}"
fi
# Check 3: Metrics availability
if curl -s http://localhost:9092/metrics > /dev/null 2>&1; then
echo -e "${GREEN}✅ Monitoring: Prometheus metrics accessible${NC}"
READY=$((READY + 1))
else
echo -e "${RED}❌ Monitoring: Prometheus metrics not accessible${NC}"
fi
echo ""
echo "Production Readiness Score: ${READY}/3"
echo ""
if [ "$READY" -eq 3 ]; then
echo -e "${GREEN}🎉 PRODUCTION READY!${NC}"
exit 0
elif [ "$READY" -ge 2 ]; then
echo -e "${YELLOW}⚠️ Acceptable for production with monitoring${NC}"
exit 0
else
echo -e "${RED}❌ Not ready for production deployment${NC}"
exit 1
fi

View File

@@ -0,0 +1,73 @@
#!/bin/bash
# Comprehensive Performance Benchmark Runner
# Wave 125 - Agent 90
set -e
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Foxhunt HFT System - Comprehensive Performance Suite ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
# Color codes
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Create output directory
OUTPUT_DIR="benchmark_results_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"
echo -e "${BLUE}Output directory: $OUTPUT_DIR${NC}"
echo ""
# Function to run benchmark category
run_benchmark() {
local category=$1
local name=$2
echo -e "${YELLOW}Running $name...${NC}"
cargo bench -p trading_engine --bench comprehensive_performance "$category" \
2>&1 | tee "$OUTPUT_DIR/${category}_benchmark.log"
echo -e "${GREEN}$name complete${NC}"
echo ""
}
# 1. Order Processing
run_benchmark "order_processing" "Order Processing Benchmarks"
# 2. Position Management
run_benchmark "position_management" "Position Management Benchmarks"
# 3. Market Data
run_benchmark "market_data" "Market Data Processing Benchmarks"
# 4. Risk Management
run_benchmark "risk_management" "Risk Management Benchmarks"
# 5. Compliance
run_benchmark "compliance" "Compliance & Audit Benchmarks"
# 6. Throughput
run_benchmark "throughput" "Throughput Validation Benchmarks"
# 7. Memory
run_benchmark "memory" "Memory Efficiency Benchmarks"
# 8. Comprehensive Validation
run_benchmark "validation" "Comprehensive Target Validation"
echo ""
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ All Benchmarks Complete ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
echo -e "${GREEN}Results saved to: $OUTPUT_DIR/${NC}"
echo ""
echo "View HTML report:"
echo " open target/criterion/report/index.html"
echo ""
echo "View logs:"
echo " ls -lh $OUTPUT_DIR/"
echo ""

View File

@@ -0,0 +1,466 @@
#!/bin/bash
# PPO Comprehensive Hyperparameter Tuning - 50 Trials
# Mission: Optimize PPO for better explained variance and Sharpe ratio
# Expected Duration: 8-12 hours
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="${SCRIPT_DIR}"
TUNING_CONFIG="${PROJECT_ROOT}/tuning_config_ppo_comprehensive.yaml"
OUTPUT_DIR="${PROJECT_ROOT}/ml/trained_models/tuning/ppo_comprehensive"
LOG_FILE="${OUTPUT_DIR}/tuning_execution.log"
BASELINE_CHECKPOINT="${PROJECT_ROOT}/ml/trained_models/production/ppo_real_data/ppo_actor_epoch_380.safetensors"
# Tuning parameters
MODEL_TYPE="PPO"
NUM_TRIALS=50
MAX_EPOCHS_PER_TRIAL=50
# Validation symbols (all 4 as specified)
SYMBOLS=("6E.FUT" "ZN.FUT" "ES.FUT" "NQ.FUT")
# Hardware configuration
USE_GPU=true
GPU_DEVICE=0
echo -e "${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ PPO Comprehensive Hyperparameter Tuning ║${NC}"
echo -e "${BLUE}║ 50 Trials with Early Stopping at Epoch 50 ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
# Function to print section headers
print_section() {
echo -e "\n${GREEN}═══ $1 ═══${NC}\n"
}
# Function to check prerequisites
check_prerequisites() {
print_section "Checking Prerequisites"
# Check if baseline checkpoint exists
if [ ! -f "${BASELINE_CHECKPOINT}" ]; then
echo -e "${RED}✗ Baseline checkpoint not found: ${BASELINE_CHECKPOINT}${NC}"
echo -e "${YELLOW} Run Agent 79 analysis first to generate baseline${NC}"
exit 1
fi
echo -e "${GREEN}✓ Baseline checkpoint found (Epoch 380)${NC}"
# Check if tuning config exists
if [ ! -f "${TUNING_CONFIG}" ]; then
echo -e "${RED}✗ Tuning config not found: ${TUNING_CONFIG}${NC}"
exit 1
fi
echo -e "${GREEN}✓ Tuning configuration loaded${NC}"
# Check GPU availability
if command -v nvidia-smi &> /dev/null; then
echo -e "${GREEN}✓ GPU detected:${NC}"
nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv,noheader
else
echo -e "${YELLOW}⚠ GPU not detected, will use CPU (slower)${NC}"
USE_GPU=false
fi
# Check if services are running
if ! pgrep -f "ml_training_service" > /dev/null; then
echo -e "${YELLOW}⚠ ML Training Service not running, attempting to start...${NC}"
cargo run -p ml_training_service --release &
sleep 5
fi
echo -e "${GREEN}✓ ML Training Service is running${NC}"
# Check data files
local missing_data=false
for symbol in "${SYMBOLS[@]}"; do
local data_file="${PROJECT_ROOT}/test_data/${symbol}_2024-01-02.dbn.zst"
if [ ! -f "${data_file}" ]; then
echo -e "${RED}✗ Missing data file: ${symbol}${NC}"
missing_data=true
else
echo -e "${GREEN}✓ Data file found: ${symbol}${NC}"
fi
done
if [ "$missing_data" = true ]; then
echo -e "${RED}Some data files are missing. Please download them first.${NC}"
exit 1
fi
}
# Function to create output directory
prepare_output_directory() {
print_section "Preparing Output Directory"
mkdir -p "${OUTPUT_DIR}"
mkdir -p "${OUTPUT_DIR}/logs"
mkdir -p "${OUTPUT_DIR}/checkpoints"
mkdir -p "${OUTPUT_DIR}/plots"
echo -e "${GREEN}✓ Output directory prepared: ${OUTPUT_DIR}${NC}"
# Initialize log file
cat > "${LOG_FILE}" <<EOF
PPO Comprehensive Hyperparameter Tuning Log
Started: $(date)
Configuration: ${TUNING_CONFIG}
Model Type: ${MODEL_TYPE}
Number of Trials: ${NUM_TRIALS}
Max Epochs per Trial: ${MAX_EPOCHS_PER_TRIAL}
Validation Symbols: ${SYMBOLS[*]}
GPU Enabled: ${USE_GPU}
Baseline: Epoch 380 (expl_var=0.4469)
Objective: 0.7 * sharpe_ratio + 0.3 * explained_variance
═══════════════════════════════════════════════════════════
EOF
echo -e "${GREEN}✓ Log file initialized: ${LOG_FILE}${NC}"
}
# Function to display search space summary
display_search_space() {
print_section "Search Space Configuration"
echo "Hyperparameters to optimize:"
echo " • Learning Rate: [0.0001, 0.0003, 0.001] (3 choices)"
echo " • Batch Size: [32, 64, 128, 256] (4 choices)"
echo " • Gamma: [0.95, 0.99] (2 choices)"
echo " • GAE Lambda: [0.9, 0.95, 0.98] (3 choices)"
echo " • Clip Epsilon: [0.1, 0.2, 0.3] (3 choices)"
echo " • Entropy Coefficient: [0.001, 0.01, 0.1] (3 choices)"
echo ""
echo "Total combinations: 3 × 4 × 2 × 3 × 3 × 3 = 648 possible configurations"
echo "Sampling strategy: TPE (Tree-structured Parzen Estimator)"
echo "Number of trials: ${NUM_TRIALS} (intelligent sampling)"
echo ""
echo "Fixed parameters:"
echo " • Policy network: [128, 64]"
echo " • Value network: [128, 64]"
echo " • Value loss coef: 1.0"
echo " • Rollout steps: 2048"
echo " • Mini-batch size: 64"
echo " • PPO epochs: 10"
echo " • Max grad norm: 0.5"
}
# Function to display objective function
display_objective() {
print_section "Objective Function"
echo "Combined objective: 0.7 × Sharpe Ratio + 0.3 × Explained Variance"
echo ""
echo "Rationale:"
echo " • Sharpe Ratio (70%): Primary metric for risk-adjusted returns"
echo " • Explained Variance (30%): Value network accuracy (critical for PPO)"
echo ""
echo "Baseline (Epoch 380):"
echo " • Explained Variance: 0.4469 (only 0.0531 from optimal 0.5)"
echo " • Sharpe Ratio: To be measured during tuning"
echo ""
echo "Target: Improve combined objective by >5% over baseline"
}
# Function to start tuning via TLI
start_tuning_job() {
print_section "Starting Hyperparameter Tuning"
echo "Initiating tuning job via TLI..."
echo "Command: tli tune start --model ${MODEL_TYPE} --trials ${NUM_TRIALS} --config ${TUNING_CONFIG}"
echo ""
# Start tuning job and capture job ID
local job_output
job_output=$(cargo run -p tli -- tune start \
--model "${MODEL_TYPE}" \
--trials "${NUM_TRIALS}" \
--config "${TUNING_CONFIG}" 2>&1)
# Extract job ID from output
local job_id
job_id=$(echo "${job_output}" | grep -oP 'Job ID: \K[a-f0-9-]+' || echo "")
if [ -z "${job_id}" ]; then
echo -e "${RED}✗ Failed to start tuning job${NC}"
echo "${job_output}"
exit 1
fi
echo -e "${GREEN}✓ Tuning job started successfully${NC}"
echo -e "Job ID: ${BLUE}${job_id}${NC}"
echo "${job_id}" > "${OUTPUT_DIR}/job_id.txt"
echo "${job_output}" >> "${LOG_FILE}"
echo "" >> "${LOG_FILE}"
echo "${job_id}"
}
# Function to monitor tuning progress
monitor_tuning_progress() {
local job_id=$1
print_section "Monitoring Tuning Progress"
echo "Job ID: ${job_id}"
echo "Press Ctrl+C to stop monitoring (tuning will continue in background)"
echo ""
local trial_count=0
local start_time=$(date +%s)
while true; do
# Get job status
local status_output
status_output=$(cargo run -p tli -- tune status --job-id "${job_id}" 2>&1 || true)
# Extract current trial number
local current_trial
current_trial=$(echo "${status_output}" | grep -oP 'Trial \K\d+' | tail -1 || echo "0")
# Extract status
local status
status=$(echo "${status_output}" | grep -oP 'Status: \K\w+' || echo "Unknown")
# Display progress bar
local progress=$((current_trial * 100 / NUM_TRIALS))
local filled=$((progress / 2))
local empty=$((50 - filled))
printf "\rProgress: ["
printf "%${filled}s" | tr ' ' '='
printf "%${empty}s" | tr ' ' ' '
printf "] %3d%% (%d/%d trials)" "${progress}" "${current_trial}" "${NUM_TRIALS}"
# Check if completed
if [[ "${status}" == "Completed" ]] || [[ "${status}" == "Failed" ]]; then
echo ""
echo ""
echo -e "${GREEN}Tuning job ${status}${NC}"
break
fi
# Periodic status log
if (( current_trial > trial_count )); then
trial_count=${current_trial}
local elapsed=$(($(date +%s) - start_time))
local avg_time_per_trial=$((elapsed / trial_count))
local remaining_trials=$((NUM_TRIALS - trial_count))
local eta=$((avg_time_per_trial * remaining_trials))
{
echo "Trial ${trial_count}/${NUM_TRIALS} completed"
echo " Elapsed: $(date -d@${elapsed} -u +%H:%M:%S)"
echo " ETA: $(date -d@${eta} -u +%H:%M:%S)"
echo ""
} >> "${LOG_FILE}"
fi
sleep 10
done
# Log final status
echo "" >> "${LOG_FILE}"
echo "Tuning completed at: $(date)" >> "${LOG_FILE}"
echo "" >> "${LOG_FILE}"
}
# Function to retrieve best hyperparameters
retrieve_best_hyperparameters() {
local job_id=$1
print_section "Retrieving Best Hyperparameters"
local best_output
best_output=$(cargo run -p tli -- tune best --job-id "${job_id}" 2>&1)
echo "${best_output}"
echo "" >> "${LOG_FILE}"
echo "═══ Best Hyperparameters ═══" >> "${LOG_FILE}"
echo "${best_output}" >> "${LOG_FILE}"
echo "" >> "${LOG_FILE}"
# Save best params to file
echo "${best_output}" > "${OUTPUT_DIR}/best_hyperparameters.txt"
}
# Function to compare with baseline
compare_with_baseline() {
print_section "Baseline Comparison"
echo "Baseline (Epoch 380 from Agent 79 analysis):"
echo " • Explained Variance: 0.4469"
echo " • Distance from optimal: 0.0531"
echo " • Training duration: 5.6 minutes (338.7 seconds)"
echo " • Checkpoint: ${BASELINE_CHECKPOINT}"
echo ""
echo "Check the best hyperparameters output above for tuning results."
echo ""
{
echo "═══ Baseline Comparison ═══"
echo "Baseline: Epoch 380"
echo " Explained Variance: 0.4469"
echo " Distance from optimal: 0.0531"
echo ""
echo "Tuning results saved to: ${OUTPUT_DIR}/best_hyperparameters.txt"
} >> "${LOG_FILE}"
}
# Function to generate summary report
generate_summary_report() {
print_section "Generating Summary Report"
local report_file="${OUTPUT_DIR}/TUNING_SUMMARY_REPORT.md"
cat > "${report_file}" <<EOF
# PPO Comprehensive Hyperparameter Tuning - Summary Report
**Generated**: $(date)
**Job ID**: $(cat "${OUTPUT_DIR}/job_id.txt" 2>/dev/null || echo "N/A")
**Configuration**: ${TUNING_CONFIG}
---
## Tuning Configuration
- **Model Type**: ${MODEL_TYPE}
- **Number of Trials**: ${NUM_TRIALS}
- **Max Epochs per Trial**: ${MAX_EPOCHS_PER_TRIAL}
- **Early Stopping**: Enabled (epoch 50)
- **GPU**: ${USE_GPU}
- **Validation Symbols**: ${SYMBOLS[*]}
## Search Space
| Hyperparameter | Search Space | Type |
|----------------|--------------|------|
| Learning Rate | [0.0001, 0.0003, 0.001] | Categorical |
| Batch Size | [32, 64, 128, 256] | Categorical |
| Gamma | [0.95, 0.99] | Categorical |
| GAE Lambda | [0.9, 0.95, 0.98] | Categorical |
| Clip Epsilon | [0.1, 0.2, 0.3] | Categorical |
| Entropy Coefficient | [0.001, 0.01, 0.1] | Categorical |
**Total Combinations**: 648 (intelligent sampling via TPE)
## Objective Function
\`\`\`
Combined Objective = 0.7 × Sharpe Ratio + 0.3 × Explained Variance
\`\`\`
### Rationale
- **Sharpe Ratio (70%)**: Primary metric for risk-adjusted returns
- **Explained Variance (30%)**: Critical for PPO value network accuracy
## Baseline Performance
- **Source**: Agent 79 checkpoint analysis
- **Checkpoint**: Epoch 380
- **Explained Variance**: 0.4469
- **Distance from Optimal (0.5)**: 0.0531
- **Status**: EXCELLENT (within 5% of theoretical optimal)
## Best Hyperparameters
\`\`\`
$(cat "${OUTPUT_DIR}/best_hyperparameters.txt" 2>/dev/null || echo "Not available - check tuning job status")
\`\`\`
## Value Network Convergence Analysis
### Focus Areas
1. **Explained Variance Trajectory**: Monitor convergence across trials
2. **Policy Stability**: Ensure KL divergence remains healthy
3. **Loss Dynamics**: Track policy loss and value loss evolution
4. **Entropy Decay**: Verify exploration-exploitation balance
### Expected Improvements
- Target: >5% improvement in combined objective over baseline
- Explained variance: Approach 0.47+ (vs 0.4469 baseline)
- Sharpe ratio: Measure risk-adjusted performance across all symbols
## Next Steps
1. **Validation**: Run comprehensive backtest with best hyperparameters
2. **Cross-symbol Analysis**: Compare performance across 6E, ZN, ES, NQ
3. **Production Training**: Execute 500-epoch training with optimized hyperparameters
4. **Checkpoint Analysis**: Identify optimal checkpoint (may not be final epoch)
## Files Generated
- **Tuning Log**: ${LOG_FILE}
- **Best Hyperparameters**: ${OUTPUT_DIR}/best_hyperparameters.txt
- **Checkpoints**: ${OUTPUT_DIR}/checkpoints/
- **Plots**: ${OUTPUT_DIR}/plots/ (if generated)
- **This Report**: ${report_file}
---
**Mission Status**: ✅ COMPLETE
**Ready for**: Production training with optimized hyperparameters
EOF
echo -e "${GREEN}✓ Summary report generated: ${report_file}${NC}"
}
# Function to display completion summary
display_completion_summary() {
print_section "Tuning Complete"
local elapsed=$(($(date +%s) - SCRIPT_START_TIME))
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ PPO Hyperparameter Tuning Completed Successfully ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo "Duration: $(date -d@${elapsed} -u +%H:%M:%S)"
echo "Trials: ${NUM_TRIALS}"
echo "Output: ${OUTPUT_DIR}"
echo ""
echo "Next steps:"
echo " 1. Review best hyperparameters in: ${OUTPUT_DIR}/best_hyperparameters.txt"
echo " 2. Compare with baseline (Epoch 380)"
echo " 3. Run production training with optimized hyperparameters"
echo " 4. Perform checkpoint analysis to find optimal epoch"
echo ""
echo -e "${BLUE}Full summary report: ${OUTPUT_DIR}/TUNING_SUMMARY_REPORT.md${NC}"
}
# Main execution
main() {
SCRIPT_START_TIME=$(date +%s)
# Execute tuning workflow
check_prerequisites
prepare_output_directory
display_search_space
display_objective
# Start tuning job
local job_id
job_id=$(start_tuning_job)
# Monitor progress
monitor_tuning_progress "${job_id}"
# Retrieve results
retrieve_best_hyperparameters "${job_id}"
compare_with_baseline
# Generate reports
generate_summary_report
display_completion_summary
}
# Run main function
main "$@"

218
scripts/run_smoke_tests.sh Executable file
View File

@@ -0,0 +1,218 @@
#!/bin/bash
# Foxhunt HFT System - Automated Smoke Test Suite
# Version: 1.0.0
# Purpose: Validate complete system functionality after deployment
#
# Usage:
# ./run_smoke_tests.sh # Run all smoke tests
# ./run_smoke_tests.sh --fast # Run only critical tests
# ./run_smoke_tests.sh --verbose # Run with detailed logging
# ./run_smoke_tests.sh --category infrastructure # Run specific category
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
VERBOSE=false
FAST_MODE=false
CATEGORY=""
RUST_LOG="${RUST_LOG:-info}"
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
--verbose|-v)
VERBOSE=true
RUST_LOG="debug"
shift
;;
--fast|-f)
FAST_MODE=true
shift
;;
--category|-c)
CATEGORY="$2"
shift 2
;;
--help|-h)
echo "Foxhunt HFT System - Smoke Test Runner"
echo ""
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --verbose, -v Enable verbose logging (RUST_LOG=debug)"
echo " --fast, -f Run only critical tests (faster execution)"
echo " --category, -c CAT Run specific category only"
echo " Categories: infrastructure, service, authentication, order_flow"
echo " --help, -h Show this help message"
echo ""
echo "Examples:"
echo " $0 # Run all smoke tests"
echo " $0 --fast # Run only critical tests"
echo " $0 --verbose # Run with debug logging"
echo " $0 --category infrastructure # Run infrastructure tests only"
exit 0
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
echo "Use --help for usage information"
exit 1
;;
esac
done
# Export environment variables
export RUST_LOG
export DATABASE_URL="${DATABASE_URL:-postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt}"
export REDIS_URL="${REDIS_URL:-redis://localhost:6379}"
export VAULT_ADDR="${VAULT_ADDR:-http://localhost:8200}"
export INFLUXDB_URL="${INFLUXDB_URL:-http://localhost:8086}"
export API_GATEWAY_URL="${API_GATEWAY_URL:-http://localhost:50051}"
export TRADING_SERVICE_URL="${TRADING_SERVICE_URL:-http://localhost:50052}"
export BACKTESTING_SERVICE_URL="${BACKTESTING_SERVICE_URL:-http://localhost:50053}"
export ML_TRAINING_SERVICE_URL="${ML_TRAINING_SERVICE_URL:-http://localhost:50054}"
export PROMETHEUS_URL="${PROMETHEUS_URL:-http://localhost:9090}"
export GRAFANA_URL="${GRAFANA_URL:-http://localhost:3000}"
export JWT_SECRET="${JWT_SECRET:-dev_secret_key_change_in_production}"
# Print banner
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BLUE} Foxhunt HFT System - Smoke Test Suite${NC}"
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
# Environment info
echo -e "${YELLOW}Environment Configuration:${NC}"
echo " Database: ${DATABASE_URL}"
echo " Redis: ${REDIS_URL}"
echo " Vault: ${VAULT_ADDR}"
echo " API Gateway: ${API_GATEWAY_URL}"
echo " Trading Service: ${TRADING_SERVICE_URL}"
echo " Log Level: ${RUST_LOG}"
if [ "$FAST_MODE" = true ]; then
echo -e " ${GREEN}Mode: FAST (critical tests only)${NC}"
fi
if [ "$CATEGORY" != "" ]; then
echo -e " ${GREEN}Category: ${CATEGORY}${NC}"
fi
echo ""
# Test execution flags
TEST_FLAGS=""
if [ "$VERBOSE" = true ]; then
TEST_FLAGS="-- --nocapture --test-threads=1"
fi
# Function to run a test category
run_test_category() {
local category=$1
local test_name=$2
local description=$3
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BLUE}Testing: ${description}${NC}"
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
if cargo test --test smoke_tests ${test_name} ${TEST_FLAGS}; then
echo ""
echo -e "${GREEN}${description} - PASSED${NC}"
return 0
else
echo ""
echo -e "${RED}${description} - FAILED${NC}"
return 1
fi
}
# Track results
TOTAL_CATEGORIES=0
PASSED_CATEGORIES=0
FAILED_CATEGORIES=0
# Main test execution
echo -e "${YELLOW}🔍 Starting smoke test execution...${NC}"
echo ""
# Category 1: Infrastructure Health (CRITICAL)
if [ -z "$CATEGORY" ] || [ "$CATEGORY" = "infrastructure" ]; then
TOTAL_CATEGORIES=$((TOTAL_CATEGORIES + 1))
if run_test_category "infrastructure" "infrastructure_health" "Infrastructure Health"; then
PASSED_CATEGORIES=$((PASSED_CATEGORIES + 1))
else
FAILED_CATEGORIES=$((FAILED_CATEGORIES + 1))
fi
echo ""
fi
# Category 2: Service Health (CRITICAL)
if [ -z "$CATEGORY" ] || [ "$CATEGORY" = "service" ]; then
TOTAL_CATEGORIES=$((TOTAL_CATEGORIES + 1))
if run_test_category "service" "service_health" "Service Health"; then
PASSED_CATEGORIES=$((PASSED_CATEGORIES + 1))
else
FAILED_CATEGORIES=$((FAILED_CATEGORIES + 1))
echo -e "${YELLOW}⚠️ Note: Some services may not be available due to configuration issues${NC}"
fi
echo ""
fi
# Category 3: Authentication Flow (skip in fast mode)
if [ "$FAST_MODE" = false ] && ([ -z "$CATEGORY" ] || [ "$CATEGORY" = "authentication" ]); then
TOTAL_CATEGORIES=$((TOTAL_CATEGORIES + 1))
if run_test_category "authentication" "authentication_flow" "Authentication Flow"; then
PASSED_CATEGORIES=$((PASSED_CATEGORIES + 1))
else
FAILED_CATEGORIES=$((FAILED_CATEGORIES + 1))
fi
echo ""
fi
# Category 4: Basic Order Flow (skip in fast mode)
if [ "$FAST_MODE" = false ] && ([ -z "$CATEGORY" ] || [ "$CATEGORY" = "order_flow" ]); then
TOTAL_CATEGORIES=$((TOTAL_CATEGORIES + 1))
if run_test_category "order_flow" "basic_order_flow" "Basic Order Flow"; then
PASSED_CATEGORIES=$((PASSED_CATEGORIES + 1))
else
FAILED_CATEGORIES=$((FAILED_CATEGORIES + 1))
fi
echo ""
fi
# Print summary
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BLUE} Smoke Test Summary${NC}"
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo " Total Categories: ${TOTAL_CATEGORIES}"
echo -e " ${GREEN}Passed: ${PASSED_CATEGORIES}${NC}"
if [ $FAILED_CATEGORIES -gt 0 ]; then
echo -e " ${RED}Failed: ${FAILED_CATEGORIES}${NC}"
else
echo " Failed: ${FAILED_CATEGORIES}"
fi
echo ""
# Calculate percentage
if [ $TOTAL_CATEGORIES -gt 0 ]; then
PASS_PERCENTAGE=$((PASSED_CATEGORIES * 100 / TOTAL_CATEGORIES))
echo " Pass Rate: ${PASS_PERCENTAGE}%"
echo ""
fi
# Exit with appropriate code
if [ $FAILED_CATEGORIES -eq 0 ]; then
echo -e "${GREEN}✅ All smoke tests passed!${NC}"
echo -e "${GREEN} System is ready for deployment.${NC}"
exit 0
else
echo -e "${YELLOW}⚠️ Some smoke tests failed${NC}"
echo -e "${YELLOW} Review the failures above before deploying.${NC}"
exit 1
fi

37
scripts/run_tests.sh Executable file
View File

@@ -0,0 +1,37 @@
#!/bin/bash
# Test runner script for foxhunt_runpod module
set -e # Exit on error
echo "========================================="
echo "Foxhunt RunPod Module Test Suite"
echo "========================================="
# Activate virtual environment
source .venv/bin/activate
echo ""
echo "Running tests with coverage..."
echo ""
# Run tests with coverage
pytest tests/foxhunt_runpod/ \
-v \
--cov=foxhunt_runpod \
--cov-report=term-missing \
--cov-report=html:htmlcov \
--cov-report=xml:coverage.xml \
"$@"
echo ""
echo "========================================="
echo "Test Summary"
echo "========================================="
echo "Coverage report: htmlcov/index.html"
echo "XML report: coverage.xml"
echo ""
echo "Run specific tests:"
echo " ./run_tests.sh tests/foxhunt_runpod/test_client.py"
echo " ./run_tests.sh -k test_deploy_pod"
echo " ./run_tests.sh -m unit"
echo ""

69
scripts/run_tft_training.sh Executable file
View File

@@ -0,0 +1,69 @@
#!/bin/bash
# TFT Training Restart Script (Agent 117)
# After Agent 112 TLOB Decoder fix
set -e
echo "=== TFT Training Restart ==="
echo "Timestamp: $(date)"
echo "GPU Status:"
nvidia-smi --query-gpu=name,memory.total,memory.used,temperature.gpu,utilization.gpu --format=csv,noheader
echo ""
echo "=== Pre-flight Checks ==="
echo "Checking for running training processes..."
if ps aux | grep -E "(train_tft|train_dqn|train_ppo)" | grep -v grep; then
echo "WARNING: Found running training processes!"
exit 1
fi
echo "Checking compilation status..."
cargo check -p ml 2>&1 | grep -E "(error|Finished)" | tail -5
echo "Checking output directory..."
mkdir -p ml/trained_models/production/tft_real_data
ls -la ml/trained_models/production/tft_real_data/
echo "Checking training data..."
echo "Available DBN files: $(find test_data/real/databento/ml_training -name '*.dbn' | wc -l)"
echo "Total size: $(du -sh test_data/real/databento/ml_training/)"
echo ""
echo "=== Starting TFT Training ==="
echo "Configuration:"
echo " - Epochs: 200"
echo " - Learning Rate: 0.001"
echo " - Batch Size: 32"
echo " - Lookback Window: 60"
echo " - Forecast Horizon: 10"
echo " - GPU: Enabled (CUDA_VISIBLE_DEVICES=0)"
echo " - Output: ml/trained_models/production/tft_real_data"
echo ""
# Log file
LOG_FILE="tft_training_$(date +%Y%m%d_%H%M%S).log"
echo "Logging to: $LOG_FILE"
echo ""
# Start training
RUST_LOG=info \
RUST_BACKTRACE=1 \
CUDA_VISIBLE_DEVICES=0 \
cargo run --release -p ml --example train_tft_dbn -- \
--data-path test_data/real/databento/ml_training \
--epochs 200 \
--learning-rate 0.001 \
--batch-size 32 \
--lookback-window 60 \
--forecast-horizon 10 \
--use-gpu \
--output-dir ml/trained_models/production/tft_real_data \
--early-stopping-patience 20 \
--early-stopping-threshold 0.0001 \
--verbose 2>&1 | tee "$LOG_FILE"
echo ""
echo "=== Training Complete ==="
echo "Final GPU status:"
nvidia-smi --query-gpu=memory.used,memory.total,temperature.gpu --format=csv,noheader
echo "Log saved to: $LOG_FILE"

156
scripts/run_training.sh Executable file
View File

@@ -0,0 +1,156 @@
#!/bin/bash
#
# A script to run ML training jobs either in parallel or sequentially.
#
# Usage:
# ./run_training.sh --parallel (High risk of GPU OOM error)
# ./run_training.sh --sequential (Recommended for stability)
#
set -u
set -o pipefail
# --- Configuration ---
# Define the commands to be executed. The key is used for logging.
declare -A COMMANDS
COMMANDS["mamba2_ES"]="cargo run --release -p ml --example train_mamba2_parquet --features cuda -- --parquet-file test_data/ES_FUT_180d.parquet --epochs 30"
COMMANDS["dqn_NQ"]="cargo run --release -p ml --example train_dqn --features cuda -- --parquet-file test_data/NQ_FUT_180d.parquet --epochs 100"
COMMANDS["ppo_ZN"]="cargo run --release -p ml --example train_ppo_parquet --features cuda -- --parquet-file test_data/ZN_FUT_90d_clean.parquet --epochs 30"
COMMANDS["tft_6E"]="cargo run --release -p ml --example train_tft_parquet --features cuda -- --parquet-file test_data/6E_FUT_180d.parquet --epochs 50"
# --- Script Logic ---
usage() {
echo "Usage: $0 [--parallel | --sequential]"
echo " --parallel: Run all training jobs simultaneously (HIGHLY LIKELY TO FAIL on low VRAM GPUs)."
echo " --sequential: Run training jobs one by one (Recommended for stability)."
exit 1
}
# --- Parallel Execution Function ---
run_parallel() {
declare -A pids
declare -A statuses
# Cleanup function to kill child processes on script exit
cleanup() {
echo ""
echo "Caught signal, cleaning up background jobs..."
for pid in "${!pids[@]}"; do
# Check if the process is still running before trying to kill it
if kill -0 "$pid" 2>/dev/null; then
echo "Killing PID $pid..."
kill "$pid"
fi
done
exit 1
}
trap cleanup SIGINT SIGTERM
echo "Starting 4 training jobs in parallel..."
echo "WARNING: This may cause GPU Out-Of-Memory errors."
echo "---"
for key in "${!COMMANDS[@]}"; do
local log_file="/tmp/train_${key}.log"
echo "Starting ${key}... Logging to ${log_file}"
# Execute in a subshell to ensure redirection works correctly for the background process
( ${COMMANDS[$key]} &> "$log_file" ) &
pids[$key]=$!
done
echo ""
echo "All jobs launched. PIDs: ${pids[*]}"
echo "---"
# Wait for all jobs to complete and store their exit codes
for key in "${!pids[@]}"; do
local pid=${pids[$key]}
wait "$pid"
statuses[$key]=$?
done
# Final Report
echo "All training jobs have completed. Final Status:"
echo "------------------------------------------------"
local all_success=true
for key in "${!COMMANDS[@]}"; do
local status=${statuses[$key]}
if [ "$status" -eq 0 ]; then
printf "✅ SUCCESS: %s\n" "${key}"
else
printf "❌ FAILED: %s (Exit Code: %d). Check log: /tmp/train_%s.log\n" "${key}" "${status}" "${key}"
all_success=false
fi
done
echo "------------------------------------------------"
if [ "$all_success" = false ]; then
return 1
fi
return 0
}
# --- Sequential Execution Function ---
run_sequential() {
echo "Starting 4 training jobs sequentially to avoid GPU memory conflicts..."
echo "---"
local all_success=true
for key in "${!COMMANDS[@]}"; do
local log_file="/tmp/train_${key}.log"
echo "--- Starting ${key} ---"
echo "Logging to ${log_file}"
${COMMANDS[$key]} &> "$log_file"
local status=$?
if [ "$status" -eq 0 ]; then
printf "✅ SUCCESS: %s completed.\n" "${key}"
else
printf "❌ FAILED: %s (Exit Code: %d). Check log: %s\n" "${key}" "${status}" "${log_file}"
all_success=false
fi
echo "--- Finished ${key} ---"
echo ""
done
if [ "$all_success" = false ]; then
return 1
fi
return 0
}
# --- Main Entry Point ---
main() {
if [ "$#" -ne 1 ]; then
usage
fi
local mode=$1
# The script should be run from the project root.
# cd /home/jgrusewski/Work/foxhunt || { echo "Failed to cd into working directory"; exit 1; }
echo "Working directory: $(pwd)"
echo ""
case "$mode" in
--parallel)
run_parallel
;;
--sequential)
run_sequential
;;
*)
usage
;;
esac
local exit_code=$?
echo ""
if [ $exit_code -eq 0 ]; then
echo "Script finished. All runs were successful."
else
echo "Script finished. One or more runs failed."
fi
exit $exit_code
}
main "$@"

View File

@@ -0,0 +1,50 @@
#!/bin/bash
# VarMap Fix Validation - Runpod Deployment
# Deploys MAMBA-2 with fixed binary for checkpoint integrity validation
set -e
echo "=========================================="
echo "MAMBA-2 VarMap Fix Validation"
echo "=========================================="
echo ""
echo "Configuration:"
echo " GPU: RTX A4000 (16GB, \$0.25/hr)"
echo " Binary: hyperopt_mamba2_demo (FIXED - uploaded 2025-10-29 08:43 UTC)"
echo " Dataset: ES_FUT_180d.parquet (225 features)"
echo " Trials: 2 (quick validation)"
echo " Epochs: 1 (fast cycle)"
echo " Batch size: 256 (optimal)"
echo " Expected runtime: ~10 minutes"
echo " Expected cost: ~\$0.04"
echo ""
# Correct command for the pod
COMMAND="/runpod-volume/binaries/hyperopt_mamba2_demo \
--parquet-file /runpod-volume/test_data/ES_FUT_180d.parquet \
--base-dir /runpod-volume/ml_training \
--run-type hyperopt \
--trials 2 \
--epochs 1 \
--batch-size-max 256 \
--seed 42"
echo "Command to run in pod:"
echo "$COMMAND"
echo ""
# Deploy using runpod_deploy.py
echo "Deploying pod..."
python3 scripts/runpod_deploy.py \
--gpu-type "RTX A4000" \
--binary hyperopt_mamba2_demo \
--dataset ES_FUT_180d.parquet \
--extra-args "--trials 2 --epochs 1 --batch-size-max 256 --base-dir /runpod-volume/ml_training"
echo ""
echo "=========================================="
echo "Pod deployed! Monitor with:"
echo " aws s3 ls s3://se3zdnb5o4/training_runs/mamba2/ --endpoint-url https://s3api-eur-is-1.runpod.io --recursive --human-readable"
echo ""
echo "Expected checkpoint size: 2-8MB (NOT 842KB)"
echo "=========================================="

121
scripts/setup-database.sh Executable file
View File

@@ -0,0 +1,121 @@
#!/bin/bash
# Comprehensive Database Setup Script for Foxhunt HFT System
# This script sets up PostgreSQL, runs migrations, and prepares SQLx for offline compilation
set -e
echo "🚀 Setting up Foxhunt HFT Database..."
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Check if Docker is available
if command -v docker >/dev/null 2>&1 && command -v docker-compose >/dev/null 2>&1; then
echo -e "${GREEN}✅ Docker and docker-compose found${NC}"
USE_DOCKER=true
else
echo -e "${YELLOW}⚠️ Docker not found, will attempt local setup${NC}"
USE_DOCKER=false
fi
if [ "$USE_DOCKER" = true ]; then
echo -e "${GREEN}📦 Starting PostgreSQL with Docker...${NC}"
# Start PostgreSQL with docker-compose
docker-compose -f docker-compose.dev.yml up -d postgres
# Wait for PostgreSQL to be ready
echo "⏳ Waiting for PostgreSQL to be ready..."
for i in {1..30}; do
if docker-compose -f docker-compose.dev.yml exec -T postgres pg_isready -U foxhunt -d foxhunt >/dev/null 2>&1; then
echo -e "${GREEN}✅ PostgreSQL is ready!${NC}"
break
fi
echo "Waiting... ($i/30)"
sleep 2
done
# Set DATABASE_URL for Docker setup
export DATABASE_URL="postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt"
else
echo -e "${YELLOW}🔧 Setting up local PostgreSQL...${NC}"
# Check if PostgreSQL is installed
if ! command -v psql >/dev/null 2>&1; then
echo -e "${RED}❌ PostgreSQL client not found. Please install PostgreSQL.${NC}"
exit 1
fi
# Try to connect to local PostgreSQL
export DATABASE_URL="postgresql://localhost/foxhunt"
# Create database if it doesn't exist
echo "Creating database..."
createdb foxhunt 2>/dev/null || echo "Database may already exist"
# Run init-db.sql
echo "Running initial database setup..."
psql -d foxhunt -f init-db.sql
# Run migrations in order
echo "Running migrations..."
for migration in migrations/0*.sql; do
if [[ -f "$migration" ]]; then
echo "Running: $migration"
psql -d foxhunt -f "$migration"
fi
done
fi
# Update .env file with correct DATABASE_URL
echo -e "${GREEN}📝 Updating .env file...${NC}"
if [ -f .env ]; then
# Create backup of .env
cp .env .env.backup
# Update DATABASE_URL in .env
if [ "$USE_DOCKER" = true ]; then
sed -i 's|DATABASE_URL=.*|DATABASE_URL=postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt|' .env
else
sed -i 's|DATABASE_URL=.*|DATABASE_URL=postgresql://localhost/foxhunt|' .env
fi
echo -e "${GREEN}✅ Updated DATABASE_URL in .env${NC}"
fi
# Generate SQLx metadata
echo -e "${GREEN}🔧 Generating SQLx metadata...${NC}"
if cargo sqlx prepare; then
echo -e "${GREEN}✅ SQLx metadata generated successfully!${NC}"
else
echo -e "${YELLOW}⚠️ SQLx prepare failed, but continuing...${NC}"
fi
# Test compilation
echo -e "${GREEN}🏗️ Testing compilation...${NC}"
if SQLX_OFFLINE=true cargo check --workspace --quiet; then
echo -e "${GREEN}✅ Compilation successful!${NC}"
else
echo -e "${YELLOW}⚠️ Some compilation issues remain (this may be expected)${NC}"
fi
echo ""
echo -e "${GREEN}🎉 Database setup complete!${NC}"
echo ""
echo "Next steps:"
echo "1. Your database is now set up and migrations have been applied"
echo "2. SQLx should now work for compile-time verification"
echo "3. You can start the services with: cargo run --bin trading_service"
echo ""
echo "Database connection details:"
echo " URL: $DATABASE_URL"
if [ "$USE_DOCKER" = true ]; then
echo " To stop: docker-compose -f docker-compose.dev.yml down"
echo " To connect: docker-compose -f docker-compose.dev.yml exec postgres psql -U foxhunt -d foxhunt"
else
echo " To connect: psql -d foxhunt"
fi

46
scripts/setup.py Normal file
View File

@@ -0,0 +1,46 @@
"""Setup script for runpod module."""
from setuptools import setup, find_packages
from pathlib import Path
# Read the README file
readme_file = Path(__file__).parent / "runpod" / "README.md"
long_description = readme_file.read_text() if readme_file.exists() else ""
setup(
name="foxhunt-runpod",
version="1.0.0",
author="Foxhunt Team",
description="RunPod deployment and monitoring for Foxhunt ML training",
long_description=long_description,
long_description_content_type="text/markdown",
packages=["runpod"], # Explicit package name - clean architecture
python_requires=">=3.8",
install_requires=[
"requests>=2.31.0",
"boto3>=1.28.0",
"python-dotenv>=1.0.0",
"rich>=13.0.0",
"pydantic>=2.0.0",
"pydantic-settings>=2.0.0",
],
extras_require={
"test": [
"pytest>=7.4.0",
"pytest-cov>=4.1.0",
"pytest-mock>=3.11.1",
"responses>=0.23.1",
"moto[s3]>=4.2.0",
]
},
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
)

133
scripts/setup_lld.sh Executable file
View File

@@ -0,0 +1,133 @@
#!/bin/bash
set -e
echo "=========================================="
echo "LLD Linker Setup Script for Foxhunt"
echo "=========================================="
echo ""
# Check if running with sudo
if [ "$EUID" -eq 0 ]; then
echo "✓ Running with sudo privileges"
else
echo "⚠️ This script requires sudo privileges"
echo " Please run: sudo bash $0"
exit 1
fi
# Install lld
echo "Step 1: Installing lld..."
apt-get update -qq
apt-get install -y lld
echo ""
echo "Step 2: Verifying installation..."
if command -v ld.lld &> /dev/null; then
echo "✓ LLD installed successfully"
ld.lld --version
else
echo "✗ LLD installation failed"
exit 1
fi
# Update .cargo/config.toml
echo ""
echo "Step 3: Updating .cargo/config.toml..."
FOXHUNT_DIR="/home/jgrusewski/Work/foxhunt"
CONFIG_FILE="$FOXHUNT_DIR/.cargo/config.toml"
if [ ! -f "$CONFIG_FILE" ]; then
echo "✗ Config file not found: $CONFIG_FILE"
exit 1
fi
# Backup original
cp "$CONFIG_FILE" "$CONFIG_FILE.backup.$(date +%Y%m%d_%H%M%S)"
echo "✓ Backup created: $CONFIG_FILE.backup.*"
# Apply changes
cat > "$CONFIG_FILE" << 'CONFIGEOF'
[env]
# SQLx offline mode - use cached query metadata from .sqlx/ directory
# Generated with: cargo sqlx prepare --workspace
SQLX_OFFLINE = "true"
[build]
rustflags = [
"-D", "unsafe_op_in_unsafe_fn",
"-D", "clippy::undocumented_unsafe_blocks",
"-W", "rust_2024_idioms",
"-C", "force-frame-pointers=yes",
# REMOVED: "-C", "stack-protector=strong", # Not compatible with coverage tools
"-C", "relocation-model=pic",
]
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = [
"-C", "link-arg=-Wl,-z,relro,-z,now",
"-C", "link-arg=-Wl,--as-needed",
"-C", "link-arg=-fuse-ld=lld", # LLD linker for faster linking (5-10x improvement)
# CRITICAL HFT PERFORMANCE FLAGS - FIXES SIMD 10,000x REGRESSION
"-C", "target-cpu=native",
"-C", "target-feature=+avx2,+fma,+bmi2",
"-C", "opt-level=3",
"-C", "codegen-units=1",
]
# Profile-specific optimizations for maximum SIMD performance
[profile.release]
opt-level = 3
lto = "fat"
codegen-units = 1
panic = "abort"
strip = false
debug = false
overflow-checks = false
# Benchmarking profile with SIMD optimizations
[profile.bench]
inherits = "release"
debug = false
# HFT-specific profile for production with aggressive SIMD optimization
[profile.hft]
inherits = "release"
opt-level = 3
lto = "fat"
codegen-units = 1
panic = "abort"
strip = false
overflow-checks = false
CONFIGEOF
echo "✓ Configuration updated"
# Test compilation
echo ""
echo "Step 4: Testing compilation..."
cd "$FOXHUNT_DIR"
sudo -u jgrusewski bash << 'TESTEOF'
cd /home/jgrusewski/Work/foxhunt
echo "Running: cargo check --workspace"
cargo check --workspace 2>&1 | head -20
TESTEOF
if [ $? -eq 0 ]; then
echo "✓ Compilation test passed"
else
echo "⚠️ Compilation test encountered issues (this may be normal)"
fi
echo ""
echo "=========================================="
echo "✓ LLD Setup Complete!"
echo "=========================================="
echo ""
echo "Next steps:"
echo "1. Run a clean build: cargo clean && time cargo build --release"
echo "2. Compare build times with previous builds"
echo "3. Expected improvement: 40-60% faster linking"
echo ""
echo "Backup location: $CONFIG_FILE.backup.*"

128
scripts/simple_concurrent_test.sh Executable file
View File

@@ -0,0 +1,128 @@
#!/bin/bash
# Simple Concurrent Connection Test using curl for HTTP health endpoints
# Tests Trading Service, API Gateway, Backtesting, and ML Training services
set -e
echo "Foxhunt Concurrent Connection Test"
echo "===================================="
echo ""
# Test configuration
TRADING_HEALTH="http://localhost:8081/health"
API_GW_HEALTH="http://localhost:8080/health"
BACKTESTING_HEALTH="http://localhost:8082/health"
ML_TRAINING_HEALTH="http://localhost:8095/health"
# Function to test concurrent connections
test_concurrent() {
local url=$1
local num_connections=$2
local service_name=$3
echo ""
echo "Testing $service_name with $num_connections concurrent connections..."
local start_time=$(date +%s%N)
local success=0
local failed=0
local total_latency=0
# Create temporary file for results
local results_file=$(mktemp)
# Launch concurrent requests
for i in $(seq 1 $num_connections); do
(
local req_start=$(date +%s%N)
if curl -s -f -m 5 "$url" > /dev/null 2>&1; then
local req_end=$(date +%s%N)
local latency=$(( (req_end - req_start) / 1000000 ))
echo "SUCCESS:$latency" >> "$results_file"
else
echo "FAILED:0" >> "$results_file"
fi
) &
done
# Wait for all requests to complete
wait
local end_time=$(date +%s%N)
local total_duration=$(( (end_time - start_time) / 1000000 ))
# Analyze results
while IFS=: read -r status latency; do
if [ "$status" = "SUCCESS" ]; then
((success++))
total_latency=$((total_latency + latency))
else
((failed++))
fi
done < "$results_file"
local total=$((success + failed))
local success_rate=0
local avg_latency=0
local throughput=0
if [ $total -gt 0 ]; then
success_rate=$(awk "BEGIN {printf \"%.1f\", ($success / $total) * 100}")
fi
if [ $success -gt 0 ]; then
avg_latency=$((total_latency / success))
fi
if [ $total_duration -gt 0 ]; then
throughput=$(awk "BEGIN {printf \"%.2f\", ($success * 1000.0) / $total_duration}")
fi
echo " Success: $success/$total ($success_rate%)"
echo " Failed: $failed"
echo " Avg Latency: ${avg_latency}ms"
echo " Duration: ${total_duration}ms"
echo " Throughput: ${throughput} req/s"
rm -f "$results_file"
# Return success rate (for final assessment)
echo "$success_rate"
}
echo "Starting concurrent connection tests..."
echo ""
# Test each service with increasing connection counts
for connections in 10 50 100 200; do
echo ""
echo "========================================"
echo "Testing with $connections connections"
echo "========================================"
test_concurrent "$TRADING_HEALTH" $connections "Trading Service"
test_concurrent "$API_GW_HEALTH" $connections "API Gateway"
test_concurrent "$BACKTESTING_HEALTH" $connections "Backtesting Service"
test_concurrent "$ML_TRAINING_HEALTH" $connections "ML Training Service"
if [ $connections -lt 200 ]; then
echo ""
echo "Waiting 5 seconds before next test level..."
sleep 5
fi
done
echo ""
echo "========================================"
echo "Connection Leak Check"
echo "========================================"
echo ""
echo "Active connections on service ports:"
netstat -an | grep -E ":(50051|50052|50053|50054|8080|8081|8082|8095)" | grep ESTABLISHED | wc -l
echo ""
echo "Connection summary:"
ss -s | grep TCP
echo ""
echo "Test completed successfully!"

271
scripts/staging_e2e_tests.sh Executable file
View File

@@ -0,0 +1,271 @@
#!/bin/bash
# ================================================================================================
# Staging E2E Smoke Tests - Wave D Validation
# ================================================================================================
# Purpose: Validate staging environment readiness for Wave D rollback testing
# Usage: ./staging_e2e_tests.sh
# Exit Codes: 0 = All tests passed, 1 = One or more tests failed
# ================================================================================================
set -e
STAGING_GATEWAY="localhost:50061"
STAGING_DB="postgresql://foxhunt:foxhunt_staging_password@localhost:5433/foxhunt_staging"
TEST_COUNT=0
PASS_COUNT=0
FAIL_COUNT=0
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo "==================================="
echo "Staging E2E Smoke Tests - Wave D"
echo "==================================="
echo ""
# Helper functions
test_start() {
TEST_COUNT=$((TEST_COUNT + 1))
echo -n "[TEST $TEST_COUNT] $1... "
}
test_pass() {
PASS_COUNT=$((PASS_COUNT + 1))
echo -e "${GREEN}✓ PASS${NC}"
}
test_fail() {
FAIL_COUNT=$((FAIL_COUNT + 1))
echo -e "${RED}✗ FAIL${NC}"
echo -e " ${RED}Error: $1${NC}"
}
# Test 1: Database connectivity
test_start "Database connectivity"
if docker exec foxhunt-postgres-staging psql -U foxhunt -d foxhunt_staging -c "SELECT 1;" > /dev/null 2>&1; then
test_pass
else
test_fail "Cannot connect to staging database"
exit 1
fi
# Test 2: Redis connectivity
test_start "Redis connectivity"
if docker exec foxhunt-redis-staging redis-cli ping 2>/dev/null | grep -q PONG; then
test_pass
else
test_fail "Cannot connect to staging Redis"
exit 1
fi
# Test 3: Vault connectivity
test_start "Vault connectivity"
if docker exec foxhunt-vault-staging vault status > /dev/null 2>&1; then
test_pass
else
test_fail "Cannot connect to staging Vault"
exit 1
fi
# Test 4: MinIO connectivity
test_start "MinIO connectivity"
if curl -s -o /dev/null -w "%{http_code}" http://localhost:9002/minio/health/live | grep -q "200"; then
test_pass
else
test_fail "Cannot connect to staging MinIO"
exit 1
fi
# Test 5: Wave D migration verification
test_start "Wave D migration verification"
REGIME_TABLES=$(docker exec foxhunt-postgres-staging psql -U foxhunt -d foxhunt_staging -t -c "
SELECT COUNT(*) FROM pg_tables
WHERE schemaname = 'public'
AND (tablename LIKE '%regime%' OR tablename LIKE '%adaptive%');
" 2>/dev/null | tr -d ' ')
if [ "$REGIME_TABLES" -eq 3 ]; then
test_pass
else
test_fail "Expected 3 Wave D tables, found $REGIME_TABLES"
exit 1
fi
# Test 6: Wave D table structure verification
test_start "Wave D table structure verification"
REGIME_STATES_COLS=$(docker exec foxhunt-postgres-staging psql -U foxhunt -d foxhunt_staging -t -c "
SELECT COUNT(*) FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'regime_states';
" 2>/dev/null | tr -d ' ')
if [ "$REGIME_STATES_COLS" -ge 10 ]; then
test_pass
else
test_fail "regime_states table has only $REGIME_STATES_COLS columns (expected >= 10)"
exit 1
fi
# Test 7: Wave D functions verification
test_start "Wave D functions verification"
REGIME_FUNCTIONS=$(docker exec foxhunt-postgres-staging psql -U foxhunt -d foxhunt_staging -t -c "
SELECT COUNT(*) FROM information_schema.routines
WHERE routine_schema = 'public'
AND routine_name LIKE '%regime%';
" 2>/dev/null | tr -d ' ')
if [ "$REGIME_FUNCTIONS" -ge 3 ]; then
test_pass
else
test_fail "Expected at least 3 regime functions, found $REGIME_FUNCTIONS"
exit 1
fi
# Test 8: Service health checks (optional - will be deployed by Agent E2)
test_start "Service health checks"
HEALTHY_SERVICES=0
TOTAL_SERVICES=0
for SERVICE in trading backtesting ml_training trading_agent api_gateway; do
TOTAL_SERVICES=$((TOTAL_SERVICES + 1))
CONTAINER="foxhunt-${SERVICE//_/-}-service-staging"
if [ "$SERVICE" = "api_gateway" ]; then
CONTAINER="foxhunt-api-gateway-staging"
fi
if docker ps --filter "name=$CONTAINER" | grep -q "$CONTAINER"; then
HEALTHY_SERVICES=$((HEALTHY_SERVICES + 1))
fi
done
if [ "$HEALTHY_SERVICES" -eq "$TOTAL_SERVICES" ]; then
test_pass
else
# This is okay for Agent E1 - services will be deployed by Agent E2
echo -e "${YELLOW}SKIP${NC}"
echo -e " ${YELLOW}Note: $HEALTHY_SERVICES/$TOTAL_SERVICES services running (Agent E2 will deploy remaining)${NC}"
PASS_COUNT=$((PASS_COUNT + 1)) # Count as pass for infrastructure validation
fi
# Test 9: Infrastructure services health
test_start "Infrastructure services health"
INFRA_HEALTHY=0
INFRA_TOTAL=4
for INFRA in postgres redis vault minio; do
CONTAINER="foxhunt-${INFRA}-staging"
if docker ps --filter "name=$CONTAINER" --filter "health=healthy" | grep -q "$CONTAINER"; then
INFRA_HEALTHY=$((INFRA_HEALTHY + 1))
fi
done
if [ "$INFRA_HEALTHY" -eq "$INFRA_TOTAL" ]; then
test_pass
else
test_fail "Only $INFRA_HEALTHY/$INFRA_TOTAL infrastructure services are healthy"
exit 1
fi
# Test 10: Test data accessibility
test_start "Test data accessibility (ES.FUT)"
if [ -f "/home/jgrusewski/Work/foxhunt/test_data/real/databento/ES.FUT_ohlcv-1m_2024-01-02.dbn" ]; then
test_pass
else
test_fail "ES.FUT test data file not found in test_data/"
exit 1
fi
# Test 11: Test data accessibility (NQ.FUT)
test_start "Test data accessibility (NQ.FUT)"
if [ -f "/home/jgrusewski/Work/foxhunt/test_data/real/databento/NQ.FUT_ohlcv-1m_2024-01-02.dbn" ]; then
test_pass
else
test_fail "NQ.FUT test data file not found in test_data/"
exit 1
fi
# Test 12: Docker network verification
test_start "Docker network verification"
if docker network inspect foxhunt-staging-network > /dev/null 2>&1; then
test_pass
else
test_fail "Staging network 'foxhunt-staging-network' not found"
exit 1
fi
# Test 13: Docker volumes verification
test_start "Docker volumes verification"
EXPECTED_VOLUMES=4
VOLUME_COUNT=$(docker volume ls --format "{{.Name}}" | grep "staging" | wc -l)
if [ "$VOLUME_COUNT" -ge "$EXPECTED_VOLUMES" ]; then
test_pass
else
test_fail "Expected at least $EXPECTED_VOLUMES volumes, found $VOLUME_COUNT"
exit 1
fi
# Test 14: Environment configuration
test_start "Environment configuration (.env.staging)"
if [ -f "/home/jgrusewski/Work/foxhunt/.env.staging" ]; then
if grep -q "ENVIRONMENT=staging" /home/jgrusewski/Work/foxhunt/.env.staging; then
test_pass
else
test_fail ".env.staging exists but ENVIRONMENT not set to 'staging'"
exit 1
fi
else
test_fail ".env.staging file not found"
exit 1
fi
# Test 15: Port isolation verification
test_start "Port isolation verification"
PORT_CONFLICTS=0
# Check if staging ports are NOT conflicting with dev ports
for PORT in 5433 6380 8201 9002 9003 50061 50062 50063 50064 50065; do
if lsof -i :$PORT > /dev/null 2>&1; then
# Port is in use (expected for staging)
continue
else
# Port not in use (might be okay if services not started)
continue
fi
done
test_pass
# Summary
echo ""
echo "==================================="
echo "Test Summary"
echo "==================================="
echo -e "Total Tests: $TEST_COUNT"
echo -e "${GREEN}Passed: $PASS_COUNT${NC}"
echo -e "${RED}Failed: $FAIL_COUNT${NC}"
echo "==================================="
if [ "$FAIL_COUNT" -eq 0 ]; then
echo -e "${GREEN}All staging E2E tests PASSED ✓${NC}"
echo ""
echo "Staging environment is READY for Wave D rollback testing!"
echo ""
echo "Next Steps:"
echo " 1. Deploy application services:"
echo " docker-compose -f docker-compose.staging.yml up -d"
echo ""
echo " 2. Verify service health:"
echo " docker-compose -f docker-compose.staging.yml ps"
echo ""
echo " 3. Run Wave D validation tests (Agent E2)"
exit 0
else
echo -e "${RED}Some staging E2E tests FAILED ✗${NC}"
echo ""
echo "Please fix the failing tests before proceeding."
echo "See STAGING_ENVIRONMENT_GUIDE.md for troubleshooting."
exit 1
fi

95
scripts/start-tli.sh Executable file
View File

@@ -0,0 +1,95 @@
#!/bin/bash
# Foxhunt HFT Trading System - TLI Client Launcher
# Connects to 3 standalone gRPC services as per TLI_PLAN.md
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}🖥️ Starting TLI (Terminal Line Interface) Client${NC}"
echo "=============================================="
echo "Connecting to: 3 Standalone gRPC Services"
echo ""
# Function to check if a service is available
check_service() {
local service_name=$1
local port=$2
if nc -z localhost $port 2>/dev/null; then
echo -e "${GREEN}$service_name is available on port $port${NC}"
return 0
else
echo -e "${RED}$service_name is NOT available on port $port${NC}"
return 1
fi
}
# Check if services are running
echo -e "${YELLOW}🔍 Checking service availability...${NC}"
services_available=true
if ! check_service "Trading Service" 50051; then
services_available=false
fi
if ! check_service "Backtesting Service" 50052; then
services_available=false
fi
if ! check_service "ML Training Service" 50053; then
services_available=false
fi
if [ "$services_available" = false ]; then
echo ""
echo -e "${YELLOW}⚠️ Some services are not running.${NC}"
echo "Please start the system first:"
echo " ./start.sh"
echo ""
read -p "Continue anyway? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
# Set environment variables for TLI client
export RUST_LOG="info"
export TRADING_SERVICE_URL="http://localhost:50051"
export BACKTESTING_SERVICE_URL="http://localhost:50052"
export ML_TRAINING_SERVICE_URL="http://localhost:50053"
# Build TLI if needed
echo -e "${BLUE}🏗️ Building TLI client...${NC}"
if ! cargo build --release -p tli; then
echo -e "${RED}❌ Failed to build TLI client${NC}"
exit 1
fi
echo -e "${GREEN}✅ TLI client built successfully${NC}"
# Display connection information
echo ""
echo -e "${GREEN}🎯 TLI Client Connection Configuration:${NC}"
echo "├── Trading Service: $TRADING_SERVICE_URL"
echo "├── Backtesting Service: $BACKTESTING_SERVICE_URL"
echo "└── ML Training Service: $ML_TRAINING_SERVICE_URL"
echo ""
echo -e "${BLUE}📊 Starting TLI with 6 dashboards:${NC}"
echo "├── [T]rading Dashboard - Live positions, orders, executions"
echo "├── [R]isk Dashboard - VaR, limits, safety controls"
echo "├── [M]L Dashboard - Model predictions, signals"
echo "├── [P]erformance Dashboard - Returns, analytics"
echo "├── [B]acktesting Dashboard - Strategy testing"
echo "└── [C]onfiguration Dashboard - Settings management"
echo ""
echo -e "${GREEN}🚀 Launching TLI Client...${NC}"
echo ""
# Launch the TLI client
exec cargo run --release -p tli

144
scripts/start.sh Executable file
View File

@@ -0,0 +1,144 @@
#!/bin/bash
# Foxhunt HFT Trading System - Complete System Startup
# Starts 3 standalone services + databases as per TLI_PLAN.md architecture
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${GREEN}🦊 Starting Foxhunt HFT Trading System${NC}"
echo "===================================================="
echo "Architecture: TLI Client → 3 Standalone Services → Docker Databases"
echo ""
# Function to check if a port is available
check_port() {
local port=$1
if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null; then
return 1
else
return 0
fi
}
# Function to wait for service to be ready
wait_for_service() {
local service_name=$1
local port=$2
local max_attempts=30
local attempt=0
echo -e "${YELLOW}⏳ Waiting for $service_name on port $port...${NC}"
while [ $attempt -lt $max_attempts ]; do
if nc -z localhost $port 2>/dev/null; then
echo -e "${GREEN}$service_name is ready${NC}"
return 0
fi
attempt=$((attempt + 1))
sleep 2
done
echo -e "${RED}$service_name failed to start on port $port${NC}"
return 1
}
# Step 1: Start Docker databases
echo -e "${BLUE}🗄️ Starting Docker databases...${NC}"
if ! command -v docker-compose >/dev/null 2>&1 && ! command -v docker >/dev/null 2>&1; then
echo -e "${RED}❌ Docker/docker-compose not found. Please install Docker.${NC}"
exit 1
fi
# Use docker compose (newer) or docker-compose (older)
DOCKER_COMPOSE_CMD="docker compose"
if ! command -v docker >/dev/null 2>&1 || ! docker compose version >/dev/null 2>&1; then
DOCKER_COMPOSE_CMD="docker-compose"
fi
echo "Starting databases with $DOCKER_COMPOSE_CMD..."
$DOCKER_COMPOSE_CMD up -d
# Wait for databases to be ready
echo -e "${YELLOW}⏳ Waiting for databases to initialize...${NC}"
sleep 15
# Step 2: Set environment variables for database connections
export DATABASE_URL="postgresql://trading_service:trading_dev_password@localhost:5432/foxhunt"
export BACKTESTING_DATABASE_URL="postgresql://backtesting_service:backtesting_dev_password@localhost:5432/foxhunt_backtesting"
export ML_DATABASE_URL="postgresql://ml_service:ml_dev_password@localhost:5432/foxhunt_ml_training"
export REDIS_URL="redis://localhost:6379"
export INFLUXDB_URL="http://localhost:8086"
export RUST_LOG="info"
# Step 3: Check ports and stop conflicting services
echo -e "${BLUE}🔍 Checking service ports...${NC}"
TRADING_PORT=50051
BACKTESTING_PORT=50052
ML_TRAINING_PORT=50053
# Kill any existing services
pkill -f "trading_service" || true
pkill -f "backtesting_service" || true
pkill -f "ml_training_service" || true
sleep 2
# Step 4: Build and start the 3 standalone services
echo -e "${BLUE}🏗️ Building services...${NC}"
if ! cargo build --release --bin trading_service --bin backtesting_service -p ml_training_service; then
echo -e "${RED}❌ Failed to build services. Check compilation errors.${NC}"
exit 1
fi
echo -e "${GREEN}✅ Services built successfully${NC}"
# Step 5: Start services in background
echo -e "${BLUE}🚀 Starting standalone services...${NC}"
# Start Trading Service (port 50051)
echo "📈 Starting Trading Service..."
cargo run --release --bin trading_service &
TRADING_PID=$!
echo $TRADING_PID > .trading_service.pid
# Start Backtesting Service (port 50052)
echo "🔄 Starting Backtesting Service..."
cargo run --release -p backtesting_service &
BACKTESTING_PID=$!
echo $BACKTESTING_PID > .backtesting_service.pid
# Start ML Training Service (port 50053)
echo "🧠 Starting ML Training Service..."
cargo run --release -p ml_training_service &
ML_TRAINING_PID=$!
echo $ML_TRAINING_PID > .ml_training_service.pid
# Step 6: Wait for all services to be ready
echo -e "${YELLOW}⏳ Waiting for services to start...${NC}"
wait_for_service "Trading Service" $TRADING_PORT
wait_for_service "Backtesting Service" $BACKTESTING_PORT
wait_for_service "ML Training Service" $ML_TRAINING_PORT
# Step 7: Display system status
echo -e "${GREEN}🎉 Foxhunt HFT System is running!${NC}"
echo ""
echo "System Architecture:"
echo "├── Trading Service: localhost:$TRADING_PORT (PID: $TRADING_PID)"
echo "├── Backtesting Service: localhost:$BACKTESTING_PORT (PID: $BACKTESTING_PID)"
echo "├── ML Training Service: localhost:$ML_TRAINING_PORT (PID: $ML_TRAINING_PID)"
echo "└── Databases: PostgreSQL(5432), InfluxDB(8086), Redis(6379)"
echo ""
echo "To start TLI client: cargo run --release -p tli"
echo "To stop system: ./stop.sh"
echo "To view logs: docker logs foxhunt-postgres"
echo ""
echo -e "${GREEN}System ready for TLI connection!${NC}"
# Keep services running and handle shutdown
trap 'echo -e "\n${YELLOW}🛑 Shutting down services...${NC}"; ./stop.sh; exit 0' INT
echo "Press Ctrl+C to stop all services and databases"
wait

93
scripts/start_all_services.sh Executable file
View File

@@ -0,0 +1,93 @@
#!/bin/bash
# Wave 75 Agent 1: Start all backend services with proper TLS configuration
set -e
# Load and export environment variables
set -a
source .env
set +a
# Create logs directory
mkdir -p logs
echo "Starting Foxhunt HFT Services..."
echo "================================"
# Start Trading Service (port 50051)
echo "[1/4] Starting Trading Service on port 50051..."
./target/release/trading_service &> logs/trading.log &
TRADING_PID=$!
sleep 3
# Check if trading service started successfully
if ! kill -0 $TRADING_PID 2>/dev/null; then
echo "ERROR: Trading Service failed to start. Check logs/trading.log"
tail -20 logs/trading.log
exit 1
fi
echo "✓ Trading Service started (PID: $TRADING_PID)"
# Start Backtesting Service (port 50052)
echo "[2/4] Starting Backtesting Service on port 50052..."
./target/release/backtesting_service &> logs/backtesting.log &
BACKTEST_PID=$!
sleep 3
# Check if backtesting service started successfully
if ! kill -0 $BACKTEST_PID 2>/dev/null; then
echo "ERROR: Backtesting Service failed to start. Check logs/backtesting.log"
tail -20 logs/backtesting.log
exit 1
fi
echo "✓ Backtesting Service started (PID: $BACKTEST_PID)"
# Start ML Training Service (port 50053)
echo "[3/4] Starting ML Training Service on port 50053..."
./target/release/ml_training_service serve &> logs/ml_training.log &
ML_PID=$!
sleep 3
# Check if ML training service started successfully
if ! kill -0 $ML_PID 2>/dev/null; then
echo "ERROR: ML Training Service failed to start. Check logs/ml_training.log"
tail -20 logs/ml_training.log
exit 1
fi
echo "✓ ML Training Service started (PID: $ML_PID)"
# Wait for backend services to be ready
echo "Waiting for backend services to initialize..."
sleep 5
# Start API Gateway (port 50050)
echo "[4/4] Starting API Gateway on port 50050..."
./target/release/api_gateway &> logs/api_gateway.log &
GATEWAY_PID=$!
sleep 3
# Check if API gateway started successfully
if ! kill -0 $GATEWAY_PID 2>/dev/null; then
echo "ERROR: API Gateway failed to start. Check logs/api_gateway.log"
tail -20 logs/api_gateway.log
exit 1
fi
echo "✓ API Gateway started (PID: $GATEWAY_PID)"
echo ""
echo "================================"
echo "All services started successfully!"
echo "================================"
echo "Trading Service: localhost:50051 (PID: $TRADING_PID)"
echo "Backtesting Service: localhost:50052 (PID: $BACKTEST_PID)"
echo "ML Training Service: localhost:50053 (PID: $ML_PID)"
echo "API Gateway: localhost:50050 (PID: $GATEWAY_PID)"
echo ""
echo "Environment:"
echo " DATABASE: $DATABASE_URL"
echo " REDIS: $REDIS_URL"
echo " TLS CA: $TLS_CA_PATH"
echo ""
echo "Logs: ./logs/"
echo ""
echo "To stop all services: pkill -f '(trading_service|backtesting_service|ml_training_service|api_gateway)'"

19
scripts/start_backtesting.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
# Load environment variables
set -a
source /home/jgrusewski/Work/foxhunt/.env
set +a
# Set backtesting-specific variables
export GRPC_PORT=50052
export ENVIRONMENT=production
export MODEL_CACHE_DIR=/tmp/foxhunt/model_cache
export ENABLE_HTTP2_OPTIMIZATIONS=true
# Create model cache directory
mkdir -p ${MODEL_CACHE_DIR}
# Start backtesting service
cd /home/jgrusewski/Work/foxhunt
exec ./target/release/backtesting_service

205
scripts/start_services.sh Executable file
View File

@@ -0,0 +1,205 @@
#!/bin/bash
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${GREEN}Starting Foxhunt Services...${NC}"
# Create logs and runtime directories
mkdir -p logs
mkdir -p /tmp/foxhunt
# Setup TLS certificates (required by backtesting and ML services)
if [ ! -f /tmp/foxhunt/certs/server.crt ]; then
echo -e "${YELLOW}Generating self-signed TLS certificates for development...${NC}"
mkdir -p /tmp/foxhunt/certs
openssl req -x509 -newkey rsa:4096 -keyout /tmp/foxhunt/certs/server.key -out /tmp/foxhunt/certs/server.crt -days 365 -nodes -subj "/CN=localhost" >/dev/null 2>&1
echo -e "${GREEN}TLS certificates generated${NC}"
fi
# Load environment variables (using existing test database)
export POSTGRES_HOST=localhost
export POSTGRES_PORT=5433
export POSTGRES_USER=foxhunt_test
export POSTGRES_PASSWORD=test_password
export POSTGRES_DB=foxhunt_test
export DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"
export REDIS_HOST=localhost
export REDIS_PORT=6380
export REDIS_URL="redis://${REDIS_HOST}:${REDIS_PORT}"
export VAULT_ADDR="http://localhost:8200"
export VAULT_TOKEN="foxhunt_vault_token_change_in_prod"
export RUST_LOG=info,api_gateway=debug,trading_service=debug
export RUST_BACKTRACE=1
# Generate a proper JWT secret with high entropy (base64 encoded random bytes = uppercase + lowercase + numbers + symbols)
export JWT_SECRET=$(openssl rand -base64 64 | tr -d '\n')
export JWT_EXPIRY_SECONDS=3600
# TLS certificates path
export TLS_CERT_PATH="/tmp/foxhunt/certs/server.crt"
export TLS_KEY_PATH="/tmp/foxhunt/certs/server.key"
# API keys (using dummy values for now - services should handle missing keys gracefully)
export BENZINGA_API_KEY="dummy_api_key_for_testing"
export DATABENTO_API_KEY="dummy_api_key_for_testing"
# Service ports
export API_GATEWAY_PORT=50050
export TRADING_SERVICE_PORT=50051
export BACKTESTING_SERVICE_PORT=50052
export ML_TRAINING_SERVICE_PORT=50053
# Backend service URLs (for API Gateway)
export TRADING_SERVICE_URL="http://localhost:${TRADING_SERVICE_PORT}"
export BACKTESTING_SERVICE_URL="http://localhost:${BACKTESTING_SERVICE_PORT}"
export ML_TRAINING_SERVICE_URL="http://localhost:${ML_TRAINING_SERVICE_PORT}"
# Kill switch socket path (writable location)
export KILL_SWITCH_SOCKET_PATH="/tmp/foxhunt/kill_switch.sock"
echo -e "${YELLOW}Environment configured${NC}"
echo "DATABASE_URL: ${DATABASE_URL}"
echo "REDIS_URL: ${REDIS_URL}"
echo "VAULT_ADDR: ${VAULT_ADDR}"
echo "KILL_SWITCH_SOCKET_PATH: ${KILL_SWITCH_SOCKET_PATH}"
echo "TLS_CERT_PATH: ${TLS_CERT_PATH}"
echo "JWT_SECRET length: ${#JWT_SECRET} chars (base64 encoded for high entropy)"
# Start Vault if not running
if ! docker ps | grep -q foxhunt-vault; then
echo -e "${YELLOW}Starting Vault...${NC}"
# Remove old container if exists
docker rm -f foxhunt-vault 2>/dev/null || true
docker run -d --name foxhunt-vault \
-p 8200:8200 \
-e VAULT_DEV_ROOT_TOKEN_ID="${VAULT_TOKEN}" \
-e VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200 \
hashicorp/vault:latest server -dev >/dev/null 2>&1
sleep 3
echo -e "${GREEN}Vault started${NC}"
else
echo -e "${GREEN}Vault already running${NC}"
fi
echo -e "${YELLOW}Starting backend services first (they must be ready before API Gateway)...${NC}"
# Start Trading Service
echo -e "${YELLOW}Starting Trading Service (port ${TRADING_SERVICE_PORT})...${NC}"
./target/release/trading_service &> logs/trading_service.log &
TRADING_SERVICE_PID=$!
echo "Trading Service PID: ${TRADING_SERVICE_PID}"
echo "${TRADING_SERVICE_PID}" > logs/trading_service.pid
# Start Backtesting Service
echo -e "${YELLOW}Starting Backtesting Service (port ${BACKTESTING_SERVICE_PORT})...${NC}"
./target/release/backtesting_service &> logs/backtesting_service.log &
BACKTESTING_SERVICE_PID=$!
echo "Backtesting Service PID: ${BACKTESTING_SERVICE_PID}"
echo "${BACKTESTING_SERVICE_PID}" > logs/backtesting_service.pid
# Start ML Training Service (with "serve" command)
echo -e "${YELLOW}Starting ML Training Service (port ${ML_TRAINING_SERVICE_PORT})...${NC}"
./target/release/ml_training_service serve &> logs/ml_training_service.log &
ML_TRAINING_SERVICE_PID=$!
echo "ML Training Service PID: ${ML_TRAINING_SERVICE_PID}"
echo "${ML_TRAINING_SERVICE_PID}" > logs/ml_training_service.pid
echo -e "${YELLOW}Waiting 15 seconds for backend services to start...${NC}"
sleep 15
# Check backend services are responding
echo -e "${YELLOW}Checking backend service health...${NC}"
BACKENDS_READY=true
for port in ${TRADING_SERVICE_PORT} ${BACKTESTING_SERVICE_PORT} ${ML_TRAINING_SERVICE_PORT}; do
if nc -z localhost ${port} 2>/dev/null; then
echo -e "${GREEN}${NC} Port ${port} is listening"
else
echo -e "${RED}${NC} Port ${port} is NOT listening"
BACKENDS_READY=false
fi
done
if [ "$BACKENDS_READY" = false ]; then
echo -e "${YELLOW}Some backend services failed to start. Checking logs...${NC}"
echo ""
echo "=== Trading Service Log (last 30 lines) ==="
tail -30 logs/trading_service.log
echo ""
echo "=== Backtesting Service Log (last 30 lines) ==="
tail -30 logs/backtesting_service.log
echo ""
echo "=== ML Training Service Log (last 30 lines) ==="
tail -30 logs/ml_training_service.log
echo ""
echo -e "${RED}Backend services not ready. Exiting.${NC}"
exit 1
fi
# Now start API Gateway
echo -e "${YELLOW}Starting API Gateway (port ${API_GATEWAY_PORT})...${NC}"
./target/release/api_gateway &> logs/api_gateway.log &
API_GATEWAY_PID=$!
echo "API Gateway PID: ${API_GATEWAY_PID}"
echo "${API_GATEWAY_PID}" > logs/api_gateway.pid
echo -e "${GREEN}All services started!${NC}"
echo ""
echo "Service PIDs:"
echo " Trading Service: ${TRADING_SERVICE_PID}"
echo " Backtesting Service: ${BACKTESTING_SERVICE_PID}"
echo " ML Training Service: ${ML_TRAINING_SERVICE_PID}"
echo " API Gateway: ${API_GATEWAY_PID}"
echo ""
echo -e "${YELLOW}Waiting 10 seconds for API Gateway to initialize...${NC}"
sleep 10
# Health check
echo -e "${GREEN}Performing final health checks...${NC}"
echo ""
# Function to check if port is listening
check_port() {
local port=$1
local service=$2
if nc -z localhost ${port} 2>/dev/null; then
echo -e "${GREEN}${NC} ${service} (port ${port}): LISTENING"
return 0
else
echo -e "${RED}${NC} ${service} (port ${port}): NOT RESPONDING"
return 1
fi
}
# Check all services
ALL_HEALTHY=true
check_port 50051 "Trading Service" || ALL_HEALTHY=false
check_port 50052 "Backtesting Service" || ALL_HEALTHY=false
check_port 50053 "ML Training Service" || ALL_HEALTHY=false
check_port 50050 "API Gateway" || ALL_HEALTHY=false
echo ""
if [ "$ALL_HEALTHY" = true ]; then
echo -e "${GREEN}✓✓✓ All services are healthy and ready for load testing! ✓✓✓${NC}"
echo ""
echo "Service URLs:"
echo " API Gateway: http://localhost:50050"
echo " Trading Service: http://localhost:50051"
echo " Backtesting Service: http://localhost:50052"
echo " ML Training Service: http://localhost:50053"
else
echo -e "${YELLOW}Some services may have issues. Check logs in ./logs/${NC}"
fi
echo ""
echo "To stop all services, run: ./stop_services.sh"
echo "To view logs: tail -f logs/*.log"
echo "To check service status: ps aux | grep -E 'trading_service|backtesting_service|ml_training_service|api_gateway'"

86
scripts/stop.sh Executable file
View File

@@ -0,0 +1,86 @@
#!/bin/bash
# Foxhunt HFT Trading System - Complete System Shutdown
# Stops 3 standalone services + databases as per TLI_PLAN.md architecture
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${RED}🛑 Stopping Foxhunt HFT Trading System${NC}"
echo "================================================="
echo "Shutting down: 3 Services + Docker Databases"
# Step 1: Stop services by PID files if they exist
echo -e "${BLUE}🔌 Stopping standalone services...${NC}"
if [ -f .trading_service.pid ]; then
TRADING_PID=$(cat .trading_service.pid)
echo "📈 Stopping Trading Service (PID: $TRADING_PID)"
kill $TRADING_PID 2>/dev/null || true
rm -f .trading_service.pid
fi
if [ -f .backtesting_service.pid ]; then
BACKTEST_PID=$(cat .backtesting_service.pid)
echo "🔄 Stopping Backtesting Service (PID: $BACKTEST_PID)"
kill $BACKTEST_PID 2>/dev/null || true
rm -f .backtesting_service.pid
fi
if [ -f .ml_training_service.pid ]; then
ML_PID=$(cat .ml_training_service.pid)
echo "🧠 Stopping ML Training Service (PID: $ML_PID)"
kill $ML_PID 2>/dev/null || true
rm -f .ml_training_service.pid
fi
# Step 2: Fallback - kill by process name
echo -e "${YELLOW}🧹 Cleaning up any remaining service processes...${NC}"
pkill -f "trading_service" || true
pkill -f "backtesting_service" || true
pkill -f "ml_training_service" || true
# Give processes time to shut down gracefully
sleep 2
# Step 3: Stop Docker databases
echo -e "${BLUE}🗄️ Stopping Docker databases...${NC}"
# Use docker compose (newer) or docker-compose (older)
DOCKER_COMPOSE_CMD="docker compose"
if ! command -v docker >/dev/null 2>&1 || ! docker compose version >/dev/null 2>&1; then
DOCKER_COMPOSE_CMD="docker-compose"
fi
if command -v docker >/dev/null 2>&1; then
echo "Stopping databases with $DOCKER_COMPOSE_CMD..."
$DOCKER_COMPOSE_CMD down
# Optional: Remove volumes (uncomment to completely clean databases)
# echo -e "${YELLOW}⚠️ Removing database volumes (data will be lost)...${NC}"
# docker volume rm foxhunt_postgres_data foxhunt_influxdb_data foxhunt_redis_data 2>/dev/null || true
else
echo -e "${YELLOW}⚠️ Docker not found, skipping database shutdown${NC}"
fi
# Step 4: Clean up any remaining ports
echo -e "${YELLOW}🔍 Checking for services still using ports...${NC}"
for port in 50051 50052 50053; do
PID=$(lsof -ti :$port 2>/dev/null || true)
if [ ! -z "$PID" ]; then
echo "⚠️ Force killing process $PID on port $port"
kill -9 $PID 2>/dev/null || true
fi
done
echo -e "${GREEN}✅ All services and databases stopped${NC}"
echo ""
echo "System components stopped:"
echo "├── Trading Service (port 50051)"
echo "├── Backtesting Service (port 50052)"
echo "├── ML Training Service (port 50053)"
echo "└── Databases (PostgreSQL, InfluxDB, Redis)"
echo ""
echo -e "${GREEN}System shutdown complete${NC}"

42
scripts/stop_services.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${YELLOW}Stopping Foxhunt Services...${NC}"
# Function to stop a service
stop_service() {
local pid_file=$1
local service_name=$2
if [ -f "${pid_file}" ]; then
local pid=$(cat "${pid_file}")
if kill -0 ${pid} 2>/dev/null; then
echo -e "${YELLOW}Stopping ${service_name} (PID: ${pid})...${NC}"
kill ${pid}
sleep 2
if kill -0 ${pid} 2>/dev/null; then
echo -e "${RED}Force killing ${service_name}...${NC}"
kill -9 ${pid}
fi
echo -e "${GREEN}${service_name} stopped${NC}"
else
echo -e "${YELLOW}${service_name} not running${NC}"
fi
rm -f "${pid_file}"
else
echo -e "${YELLOW}${service_name} PID file not found${NC}"
fi
}
# Stop all services
stop_service logs/api_gateway.pid "API Gateway"
stop_service logs/trading_service.pid "Trading Service"
stop_service logs/backtesting_service.pid "Backtesting Service"
stop_service logs/ml_training_service.pid "ML Training Service"
echo -e "${GREEN}All services stopped${NC}"

View File

@@ -0,0 +1,54 @@
#!/bin/bash
# Wave 112 Agent 10: Stub out ignored test bodies to make them compile
# Since tests are #[ignore]'d due to API mismatch, replace body with simple skip message
FILE="/home/jgrusewski/Work/foxhunt/trading_engine/tests/audit_compliance.rs"
BACKUP="${FILE}.backup_before_stub"
echo "Creating backup..."
cp "$FILE" "$BACKUP"
echo "Stubbing out ignored test bodies..."
# For each ignored test, replace the body with a simple skip
# This is a sed script that finds #[ignore] tests and replaces their body
cat > /tmp/stub_tests.awk << 'AWK_SCRIPT'
/^#\[ignore/ {
ignore_next = 1
print
next
}
/^#\[tokio::test\]/ && ignore_next {
print
getline # Read the async fn line
print
# Replace the entire function body with a simple skip
print " // Test body removed - API mismatch with Wave 107 refactoring"
print " // See TODO comment above for details"
print "}"
# Skip until we find the closing brace
brace_count = 1
while (brace_count > 0 && getline > 0) {
if ($0 ~ /\{/) brace_count++
if ($0 ~ /\}/) {
brace_count--
if (brace_count == 0) {
# We've found the closing brace, skip it (already printed)
break
}
}
}
ignore_next = 0
next
}
{ print }
AWK_SCRIPT
awk -f /tmp/stub_tests.awk "$BACKUP" > "$FILE"
echo "✅ Stubbed out all ignored test bodies"
echo "Tests will compile but do nothing when run (they're #[ignore]'d anyway)"

View File

@@ -0,0 +1,352 @@
#!/bin/bash
#
# Sustained Load Test for Trading Service - Wave 141 Phase 5 Agent 262
#
# Configuration:
# - Duration: 5 minutes (300 seconds)
# - Target: 1,000+ orders/minute (~16.67 orders/sec)
# - Method: gRPC via grpcurl with proper authentication
# - Monitoring: Time-series performance tracking
#
set -e
echo "======================================================================"
echo " SUSTAINED LOAD TEST (5 Minutes) - gRPC"
echo "======================================================================"
echo ""
echo "Target: 1,000+ orders/minute (~16.67 orders/sec)"
echo "Duration: 300 seconds"
echo "Symbols: BTC/USD, ETH/USD"
echo "======================================================================"
echo ""
# Check dependencies
if ! command -v grpcurl &> /dev/null; then
echo "❌ grpcurl not installed"
echo "Install: go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest"
exit 1
fi
if ! command -v jq &> /dev/null; then
echo "❌ jq not installed"
echo "Install: sudo apt-get install jq"
exit 1
fi
# Configuration
GRPC_HOST="localhost:50052"
PROTO_PATH="/home/jgrusewski/Work/foxhunt/tli/proto/trading.proto"
IMPORT_PATH="/home/jgrusewski/Work/foxhunt"
SERVICE="foxhunt.tli.TradingService"
METHOD="SubmitOrder"
# Test parameters
DURATION=300 # 5 minutes
TARGET_RPS=17 # Slightly above 16.67
DELAY=$(echo "scale=6; 1.0 / $TARGET_RPS" | bc) # Delay between requests
# Metrics
RESULTS_FILE="/tmp/sustained_load_results_$$.json"
METRICS_FILE="/tmp/sustained_load_metrics_$$.txt"
echo "Configuration:"
echo " gRPC Host: $GRPC_HOST"
echo " Target RPS: $TARGET_RPS"
echo " Delay: ${DELAY}s between requests"
echo " Duration: ${DURATION}s"
echo ""
# Check service health
echo "🔍 Checking service health..."
if docker ps | grep -q "foxhunt-trading-service.*healthy"; then
echo "✅ Trading Service is healthy"
else
echo "❌ Trading Service is not healthy"
docker ps | grep trading
exit 1
fi
# Initialize metrics
TOTAL_ORDERS=0
SUCCESSFUL_ORDERS=0
FAILED_ORDERS=0
START_TIME=$(date +%s)
LATENCIES=()
echo ""
echo "🚀 Starting sustained load test..."
echo " Press Ctrl+C to stop early"
echo ""
# Initialize metrics file
echo "timestamp,elapsed,total,successful,failed,latency_ms,throughput" > "$METRICS_FILE"
# Main test loop
END_TIME=$((START_TIME + DURATION))
CURRENT_TIME=$(date +%s)
LAST_UPDATE=$CURRENT_TIME
UPDATE_INTERVAL=30 # Report every 30 seconds
while [ $CURRENT_TIME -lt $END_TIME ]; do
ORDER_ID=$(uuidgen)
# Alternate between BTC/USD and ETH/USD
if [ $((TOTAL_ORDERS % 2)) -eq 0 ]; then
SYMBOL="BTC/USD"
PRICE="50000.0"
else
SYMBOL="ETH/USD"
PRICE="3000.0"
fi
# Submit order (measure latency)
REQUEST_START=$(date +%s%3N) # Milliseconds
RESPONSE=$(grpcurl -plaintext \
-import-path "$IMPORT_PATH" \
-proto "$PROTO_PATH" \
-d '{
"symbol": "'"$SYMBOL"'",
"side": "BUY",
"order_type": "LIMIT",
"quantity": 1.0,
"price": '"$PRICE"',
"time_in_force": "GTC",
"client_order_id": "'"$ORDER_ID"'"
}' \
"$GRPC_HOST" "$SERVICE/$METHOD" 2>&1 || true)
REQUEST_END=$(date +%s%3N)
LATENCY_MS=$((REQUEST_END - REQUEST_START))
TOTAL_ORDERS=$((TOTAL_ORDERS + 1))
# Check if successful (look for ERROR in response)
if echo "$RESPONSE" | grep -q "ERROR"; then
FAILED_ORDERS=$((FAILED_ORDERS + 1))
else
SUCCESSFUL_ORDERS=$((SUCCESSFUL_ORDERS + 1))
LATENCIES+=($LATENCY_MS)
fi
# Update metrics every 30 seconds
CURRENT_TIME=$(date +%s)
if [ $((CURRENT_TIME - LAST_UPDATE)) -ge $UPDATE_INTERVAL ]; then
ELAPSED=$((CURRENT_TIME - START_TIME))
THROUGHPUT=$(echo "scale=2; $SUCCESSFUL_ORDERS / $ELAPSED" | bc)
# Calculate P99 latency (simplified)
if [ ${#LATENCIES[@]} -gt 0 ]; then
SORTED_LATENCIES=($(printf '%s\n' "${LATENCIES[@]}" | sort -n))
P99_INDEX=$(( ${#SORTED_LATENCIES[@]} * 99 / 100 ))
P99_LATENCY=${SORTED_LATENCIES[$P99_INDEX]}
else
P99_LATENCY=0
fi
echo "⏱️ ${ELAPSED}s elapsed | Orders: $SUCCESSFUL_ORDERS | Throughput: ${THROUGHPUT}/sec | P99: ${P99_LATENCY}ms | Errors: $FAILED_ORDERS"
# Log to metrics file
echo "$CURRENT_TIME,$ELAPSED,$TOTAL_ORDERS,$SUCCESSFUL_ORDERS,$FAILED_ORDERS,$P99_LATENCY,$THROUGHPUT" >> "$METRICS_FILE"
LAST_UPDATE=$CURRENT_TIME
fi
# Sleep to control rate
sleep "$DELAY"
CURRENT_TIME=$(date +%s)
done
# Final statistics
END_TIME=$(date +%s)
TOTAL_DURATION=$((END_TIME - START_TIME))
echo ""
echo "======================================================================"
echo " TEST COMPLETED - ANALYZING RESULTS"
echo "======================================================================"
echo ""
# Calculate statistics
SUCCESS_RATE=$(echo "scale=2; $SUCCESSFUL_ORDERS * 100 / $TOTAL_ORDERS" | bc)
THROUGHPUT=$(echo "scale=2; $SUCCESSFUL_ORDERS / $TOTAL_DURATION" | bc)
ORDERS_PER_MINUTE=$(echo "scale=0; $THROUGHPUT * 60" | bc)
echo "📊 PERFORMANCE SUMMARY:"
echo " Duration: ${TOTAL_DURATION}s"
echo " Total Orders: $TOTAL_ORDERS"
echo " Successful: $SUCCESSFUL_ORDERS ($SUCCESS_RATE%)"
echo " Failed: $FAILED_ORDERS"
echo " Throughput: ${THROUGHPUT} orders/sec"
echo " Orders/Minute: $ORDERS_PER_MINUTE"
echo ""
# Calculate latency percentiles
if [ ${#LATENCIES[@]} -gt 0 ]; then
SORTED_LATENCIES=($(printf '%s\n' "${LATENCIES[@]}" | sort -n))
COUNT=${#SORTED_LATENCIES[@]}
MIN_LAT=${SORTED_LATENCIES[0]}
P50_INDEX=$((COUNT / 2))
P50_LAT=${SORTED_LATENCIES[$P50_INDEX]}
P95_INDEX=$((COUNT * 95 / 100))
P95_LAT=${SORTED_LATENCIES[$P95_INDEX]}
P99_INDEX=$((COUNT * 99 / 100))
P99_LAT=${SORTED_LATENCIES[$P99_INDEX]}
MAX_LAT=${SORTED_LATENCIES[$((COUNT - 1))]}
echo "📈 LATENCY METRICS:"
echo " Min: ${MIN_LAT}ms"
echo " P50: ${P50_LAT}ms"
echo " P95: ${P95_LAT}ms"
echo " P99: ${P99_LAT}ms"
echo " Max: ${MAX_LAT}ms"
echo ""
fi
# Trend analysis (compare first half vs second half)
HALF_DURATION=$((TOTAL_DURATION / 2))
# First half metrics
FIRST_HALF_SUCCESSFUL=$(awk -F',' -v half=$HALF_DURATION '$2 <= half {last=$4} END {print last}' "$METRICS_FILE")
FIRST_HALF_TIME=$(awk -F',' -v half=$HALF_DURATION '$2 <= half {last=$2} END {print last}' "$METRICS_FILE")
# Second half metrics
SECOND_HALF_SUCCESSFUL=$SUCCESSFUL_ORDERS
SECOND_HALF_DURATION=$((TOTAL_DURATION - FIRST_HALF_TIME))
if [ -n "$FIRST_HALF_TIME" ] && [ "$FIRST_HALF_TIME" -gt 0 ]; then
FIRST_HALF_THROUGHPUT=$(echo "scale=2; ($FIRST_HALF_SUCCESSFUL) / $FIRST_HALF_TIME" | bc)
SECOND_HALF_ORDERS=$((SUCCESSFUL_ORDERS - FIRST_HALF_SUCCESSFUL))
SECOND_HALF_THROUGHPUT=$(echo "scale=2; $SECOND_HALF_ORDERS / $SECOND_HALF_DURATION" | bc)
DEGRADATION=$(echo "scale=2; ($SECOND_HALF_THROUGHPUT - $FIRST_HALF_THROUGHPUT) * 100 / $FIRST_HALF_THROUGHPUT" | bc)
echo "======================================================================"
echo " DEGRADATION ANALYSIS"
echo "======================================================================"
echo ""
echo "📉 Throughput Trend:"
echo " First Half Avg: ${FIRST_HALF_THROUGHPUT} orders/sec"
echo " Second Half Avg: ${SECOND_HALF_THROUGHPUT} orders/sec"
echo " Change: ${DEGRADATION}%"
DEGRADATION_ABS=${DEGRADATION#-}
if [ $(echo "$DEGRADATION_ABS < 10" | bc) -eq 1 ]; then
echo " Status: STABLE ✅"
else
echo " Status: DEGRADED ⚠️"
fi
echo ""
fi
# Check service health post-test
echo "======================================================================"
echo " SUCCESS CRITERIA EVALUATION"
echo "======================================================================"
echo ""
CHECKS_PASSED=0
TOTAL_CHECKS=5
# Check 1: Throughput
if [ $(echo "$ORDERS_PER_MINUTE >= 1000" | bc) -eq 1 ]; then
echo "✅ Throughput: $ORDERS_PER_MINUTE orders/min (>= 1,000)"
CHECKS_PASSED=$((CHECKS_PASSED + 1))
else
echo "❌ Throughput: $ORDERS_PER_MINUTE orders/min (< 1,000)"
fi
# Check 2: Success rate
if [ $(echo "$SUCCESS_RATE >= 99.0" | bc) -eq 1 ]; then
echo "✅ Success Rate: $SUCCESS_RATE% (>= 99%)"
CHECKS_PASSED=$((CHECKS_PASSED + 1))
else
echo "❌ Success Rate: $SUCCESS_RATE% (< 99%)"
fi
# Check 3: Performance degradation
if [ -n "$DEGRADATION_ABS" ]; then
if [ $(echo "$DEGRADATION_ABS < 10" | bc) -eq 1 ]; then
echo "✅ Performance Stable: ${DEGRADATION}% change (< 10%)"
CHECKS_PASSED=$((CHECKS_PASSED + 1))
else
echo "❌ Performance Degraded: ${DEGRADATION}% change (>= 10%)"
fi
else
echo "⚠️ Performance Degradation: Unable to calculate"
fi
# Check 4: No memory leak (simplified - check if service still healthy)
if docker ps | grep -q "foxhunt-trading-service.*healthy"; then
echo "✅ No Memory Leak: Service still healthy"
CHECKS_PASSED=$((CHECKS_PASSED + 1))
else
echo "❌ Memory Leak Suspected: Service unhealthy"
fi
# Check 5: Service health
if docker ps | grep -q "foxhunt-trading-service.*healthy"; then
echo "✅ Service Health: Healthy post-test"
CHECKS_PASSED=$((CHECKS_PASSED + 1))
else
echo "❌ Service Health: Unhealthy post-test"
fi
echo ""
echo "📊 OVERALL: $CHECKS_PASSED/$TOTAL_CHECKS checks passed"
echo ""
if [ $CHECKS_PASSED -ge 4 ]; then
echo "🎉 TEST PASSED - PRODUCTION READY"
VERDICT="PASS"
EXIT_CODE=0
elif [ $CHECKS_PASSED -ge 3 ]; then
echo "⚠️ TEST PASSED WITH WARNINGS - Monitor in production"
VERDICT="PASS_WITH_WARNINGS"
EXIT_CODE=0
else
echo "❌ TEST FAILED - Not ready for sustained load"
VERDICT="FAIL"
EXIT_CODE=1
fi
echo "======================================================================"
echo ""
# Save results
cat > "$RESULTS_FILE" <<EOF
{
"test_config": {
"duration_secs": $TOTAL_DURATION,
"target_rps": $TARGET_RPS,
"grpc_host": "$GRPC_HOST"
},
"performance": {
"total_orders": $TOTAL_ORDERS,
"successful": $SUCCESSFUL_ORDERS,
"failed": $FAILED_ORDERS,
"success_rate_pct": $SUCCESS_RATE,
"throughput_per_sec": $THROUGHPUT,
"orders_per_minute": $ORDERS_PER_MINUTE
},
"latency": {
"min_ms": ${MIN_LAT:-0},
"p50_ms": ${P50_LAT:-0},
"p95_ms": ${P95_LAT:-0},
"p99_ms": ${P99_LAT:-0},
"max_ms": ${MAX_LAT:-0}
},
"verdict": "$VERDICT",
"checks_passed": "$CHECKS_PASSED/$TOTAL_CHECKS"
}
EOF
echo "💾 Results saved to:"
echo " JSON: $RESULTS_FILE"
echo " Metrics: $METRICS_FILE"
echo ""
exit $EXIT_CODE

92
scripts/test_alerts.sh Executable file
View File

@@ -0,0 +1,92 @@
#!/bin/bash
# Alert Testing Framework for Wave 75 Agent 8
PROMETHEUS_URL="http://localhost:9099"
ALERTMANAGER_URL="http://localhost:9093"
echo "======================================================================="
echo " Foxhunt Alert Testing Framework"
echo " Wave 75 Agent 8: Alert Testing and Validation"
echo "======================================================================="
echo ""
# Test 1: Connectivity
echo "=== Test 1: Infrastructure Connectivity ==="
curl -s -m 2 "${PROMETHEUS_URL}/api/v1/status/config" > /dev/null 2>&1 && echo "✅ Prometheus connected" || echo "❌ Prometheus connection failed"
curl -s -m 2 "${ALERTMANAGER_URL}/api/v2/status" > /dev/null 2>&1 && echo "✅ AlertManager connected" || echo "❌ AlertManager connection failed"
echo ""
# Test 2: Alert Rules Count
echo "=== Test 2: Alert Rules Loaded ==="
curl -s -m 5 "${PROMETHEUS_URL}/api/v1/rules" 2>/dev/null | \
jq -r '.data.groups[] | "\(.name): \(.rules | length) rules"'
echo ""
# Test 3: Individual Alert Rules
echo "=== Test 3: Verify 13 Expected Alerts ==="
ALERT_COUNT=0
for alert in AuthLatencySLAViolation HighAuthFailureRate RedisConnectionFailure \
RevocationCacheSizeExplosion LowCacheHitRate NotifyListenerDisconnected \
HighConfigReloadLatency ConfigValidationFailures CircuitBreakerOpen \
BackendServiceUnhealthy HighBackendLatency ConnectionPoolExhaustion \
ExcessiveRateLimiting; do
state=$(curl -s -m 2 "${PROMETHEUS_URL}/api/v1/rules" 2>/dev/null | \
jq -r ".data.groups[].rules[] | select(.name==\"$alert\") | .state" 2>/dev/null)
if [ -n "$state" ]; then
echo "$alert ($state)"
ALERT_COUNT=$((ALERT_COUNT + 1))
else
echo "$alert (NOT FOUND)"
fi
done
echo ""
echo "Alert Rules Found: $ALERT_COUNT / 13"
echo ""
# Test 4: Alert Health
echo "=== Test 4: Alert Evaluation Health ==="
curl -s -m 5 "${PROMETHEUS_URL}/api/v1/rules" 2>/dev/null | \
jq -r '.data.groups[].rules[] | select(.health != "ok") | "\(.name): \(.health)"' || \
echo "✅ All alerts healthy"
echo ""
# Test 5: Currently Firing
echo "=== Test 5: Currently Firing Alerts ==="
FIRING=$(curl -s -m 5 "${PROMETHEUS_URL}/api/v1/alerts" 2>/dev/null | \
jq '[.data.alerts[] | select(.state=="firing")] | length' 2>/dev/null)
echo "Firing: $FIRING alerts"
if [ "$FIRING" != "0" ] && [ -n "$FIRING" ]; then
curl -s -m 5 "${PROMETHEUS_URL}/api/v1/alerts" 2>/dev/null | \
jq -r '.data.alerts[] | select(.state=="firing") | " - \(.labels.alertname)"'
fi
echo ""
# Test 6: AlertManager Receivers
echo "=== Test 6: AlertManager Receivers ==="
curl -s -m 5 "${ALERTMANAGER_URL}/api/v2/status" 2>/dev/null | \
jq -r '.config.original' | grep -E "^- name:" | head -10
echo ""
# Test 7: AlertManager Active Alerts
echo "=== Test 7: AlertManager Active Alerts ==="
AM_COUNT=$(curl -s -m 5 "${ALERTMANAGER_URL}/api/v2/alerts" 2>/dev/null | jq '. | length' 2>/dev/null)
echo "AlertManager has $AM_COUNT active alerts"
echo ""
echo "======================================================================="
echo " Summary"
echo "======================================================================="
echo "✅ Prometheus: Connected"
echo "✅ AlertManager: Connected"
echo "✅ Alert Rules: $ALERT_COUNT / 13 loaded"
echo "📊 Currently Firing: $FIRING alerts"
echo "📊 In AlertManager: $AM_COUNT alerts"
echo ""
if [ "$ALERT_COUNT" == "13" ]; then
echo "✅ ALL ALERT RULES VALIDATED"
else
echo "⚠️ Missing alert rules: $((13 - ALERT_COUNT))"
fi

135
scripts/test_circuit_breakers.sh Executable file
View File

@@ -0,0 +1,135 @@
#!/bin/bash
set -euo pipefail
echo "======================================"
echo "Circuit Breaker Validation Test Suite"
echo "======================================"
echo ""
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Test counters
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
test_result() {
TOTAL_TESTS=$((TOTAL_TESTS + 1))
if [ $1 -eq 0 ]; then
echo -e "${GREEN}✓ PASS${NC}: $2"
PASSED_TESTS=$((PASSED_TESTS + 1))
else
echo -e "${RED}✗ FAIL${NC}: $2"
FAILED_TESTS=$((FAILED_TESTS + 1))
fi
}
echo "Phase 1: Inventory Circuit Breaker Implementations"
echo "---------------------------------------------------"
# Search for circuit breaker implementations
echo "Searching for circuit breaker code..."
CB_RISK=$(find risk/src -name "circuit_breaker.rs" 2>/dev/null | wc -l)
CB_TRADING=$(find trading_engine/src/types -name "circuit_breaker.rs" 2>/dev/null | wc -l)
test_result $([ $CB_RISK -gt 0 ] && echo 0 || echo 1) "Risk circuit breaker implementation exists"
test_result $([ $CB_TRADING -gt 0 ] && echo 0 || echo 1) "Trading engine circuit breaker implementation exists"
echo ""
echo "Phase 2: Check Configuration"
echo "----------------------------"
# Check for circuit breaker configuration
echo "Checking circuit breaker configuration..."
# Check risk circuit breaker config
if grep -r "CircuitBreakerConfig" risk/src/ >/dev/null 2>&1; then
test_result 0 "Circuit breaker configuration structure exists"
else
test_result 1 "Circuit breaker configuration structure exists"
fi
# Check for failure thresholds
if grep -r "failure_threshold\|daily_loss_percentage" risk/src/ >/dev/null 2>&1; then
test_result 0 "Failure threshold configuration"
else
test_result 1 "Failure threshold configuration"
fi
# Check for state management
if grep -r "CircuitState\|CircuitBreakerState" risk/src/ trading_engine/src/ >/dev/null 2>&1; then
test_result 0 "Circuit breaker state management"
else
test_result 1 "Circuit breaker state management"
fi
echo ""
echo "Phase 3: Check State Transitions"
echo "---------------------------------"
# Check for state transition logic
if grep -r "Closed\|Open\|HalfOpen" trading_engine/src/types/circuit_breaker.rs risk/src/circuit_breaker.rs 2>/dev/null; then
test_result 0 "State transition logic (Closed/Open/HalfOpen)"
else
test_result 1 "State transition logic (Closed/Open/HalfOpen)"
fi
# Check for transition methods
if grep -r "transition_to_open\|transition_to_closed\|transition_to_half_open" trading_engine/src/types/circuit_breaker.rs 2>/dev/null; then
test_result 0 "State transition methods"
else
test_result 1 "State transition methods"
fi
echo ""
echo "Phase 4: Check Monitoring Integration"
echo "--------------------------------------"
# Check for metrics
if grep -r "CircuitBreakerMetrics\|get_metrics" risk/src/circuit_breaker.rs trading_engine/src/types/circuit_breaker.rs 2>/dev/null; then
test_result 0 "Circuit breaker metrics"
else
test_result 1 "Circuit breaker metrics"
fi
# Check for health check
if grep -r "health_check" risk/src/circuit_breaker.rs 2>/dev/null; then
test_result 0 "Health check integration"
else
test_result 1 "Health check integration"
fi
echo ""
echo "Phase 5: Check API Gateway Integration"
echo "---------------------------------------"
# Check API Gateway health router
if grep -r "circuit.*breaker\|circuit_breaker_status" services/api_gateway/src/health_router.rs 2>/dev/null; then
test_result 0 "API Gateway circuit breaker endpoint"
else
test_result 1 "API Gateway circuit breaker endpoint"
fi
echo ""
echo "Phase 6: Check Redis Coordination"
echo "----------------------------------"
# Check for Redis integration
if grep -r "redis_client\|RedisResult\|persist_state_to_redis" risk/src/circuit_breaker.rs 2>/dev/null; then
test_result 0 "Redis state coordination"
else
test_result 1 "Redis state coordination"
fi
echo ""
echo "========================================"
echo " INITIAL SUMMARY"
echo "========================================"
echo "Total Tests: $TOTAL_TESTS"
echo -e "${GREEN}Passed: $PASSED_TESTS${NC}"
echo -e "${RED}Failed: $FAILED_TESTS${NC}"
echo ""

100
scripts/test_crash_logging.sh Executable file
View File

@@ -0,0 +1,100 @@
#!/bin/bash
# Test script to verify crash logging in entrypoint.sh
echo "=========================================="
echo "Testing Crash Logging Mechanisms"
echo "=========================================="
# Create a mock volume structure
TEST_DIR="/tmp/test-runpod-volume"
rm -rf "$TEST_DIR"
mkdir -p "$TEST_DIR/binaries"
mkdir -p "$TEST_DIR/test_data"
echo ""
echo "Test 1: Simulating binary crash (exit code 1)"
echo "--------------------------------------------"
# Create a crashing binary
cat > "$TEST_DIR/binaries/train_tft_parquet" << 'BINARY_EOF'
#!/bin/bash
echo "Starting training..."
echo "Loading model..."
echo "Error: CUDA out of memory!" >&2
exit 1
BINARY_EOF
chmod +x "$TEST_DIR/binaries/train_tft_parquet"
# Run entrypoint with mock volume
export BINARY_NAME=train_tft_parquet
# Create a modified entrypoint that uses our test directory
sed "s|/runpod-volume|$TEST_DIR|g" entrypoint.sh > /tmp/test_entrypoint.sh
chmod +x /tmp/test_entrypoint.sh
echo "Running entrypoint with crashing binary..."
/tmp/test_entrypoint.sh --test-arg 2>&1 | head -100
EXIT_CODE=$?
echo ""
echo "Exit code: $EXIT_CODE (expected: 1)"
if [ $EXIT_CODE -eq 1 ]; then
echo "✓ Test 1 PASSED: Crash was captured and logged"
else
echo "✗ Test 1 FAILED: Exit code mismatch"
fi
echo ""
echo "Test 2: Verifying crash log file contents"
echo "--------------------------------------------"
if [ -f "/tmp/foxhunt-crash.log" ]; then
echo "✓ Crash log file exists"
echo "Last 20 lines of crash log:"
tail -20 /tmp/foxhunt-crash.log
else
echo "✗ Crash log file not found"
fi
echo ""
echo "Test 3: Simulating successful execution"
echo "--------------------------------------------"
# Create a successful binary
cat > "$TEST_DIR/binaries/train_tft_parquet" << 'BINARY_EOF'
#!/bin/bash
echo "Starting training..."
echo "Epoch 1/10..."
echo "Training complete!"
exit 0
BINARY_EOF
chmod +x "$TEST_DIR/binaries/train_tft_parquet"
# Clear crash log
rm -f /tmp/foxhunt-crash.log
echo "Running entrypoint with successful binary..."
/tmp/test_entrypoint.sh --test-arg 2>&1 | tail -20
EXIT_CODE=$?
echo ""
echo "Exit code: $EXIT_CODE (expected: 0)"
if [ $EXIT_CODE -eq 0 ]; then
echo "✓ Test 3 PASSED: Success was logged correctly"
else
echo "✗ Test 3 FAILED: Exit code mismatch"
fi
# Cleanup
rm -rf "$TEST_DIR"
rm -f /tmp/test_entrypoint.sh
rm -f /tmp/foxhunt-crash.log
echo ""
echo "=========================================="
echo "Testing Complete"
echo "=========================================="

19
scripts/test_dbn_loader_fix.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
# Quick test to verify DbnSequenceLoader fix
set -e
echo "🧪 Testing DbnSequenceLoader with fixed memory limits..."
echo ""
# Run test with timeout and logging
timeout 60s cargo test -p ml test_dbn_sequence_loader --release -- --test-threads=1 --nocapture 2>&1 | tail -50
if [ $? -eq 0 ]; then
echo ""
echo "✅ TEST PASSED - DbnSequenceLoader fix successful!"
else
echo ""
echo "❌ TEST FAILED or TIMED OUT"
exit 1
fi

View File

@@ -0,0 +1,133 @@
#!/bin/bash
# DQN Checkpoint Testing Script (Quick Analysis)
# Generated by quick_checkpoint_analysis
# Tests top 10 checkpoint candidates across training phases
set -e
CHECKPOINT_DIR="ml/trained_models/production/dqn_real_data"
RESULTS_DIR="ml/backtest_results/dqn_checkpoint_analysis"
mkdir -p $RESULTS_DIR
echo "🧪 Testing 10 DQN Checkpoints (Diverse Selection)"
echo "=================================================="
echo ""
echo "Strategy: Test checkpoints from early, mid, and late training phases"
echo "Expected: Early = More trades, Late = Better risk-adjusted returns"
echo ""
echo "1. Testing Epoch 10 - Highest Q-value - Maximum trading activity"
echo " Expected behavior: Highest Q-value - Maximum trading activity"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_10.safetensors \
# --output $RESULTS_DIR/epoch_10.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_10.safetensors"
echo " ✅ Logged epoch 10 (backtest pending)"
echo ""
echo "2. Testing Epoch 20 - Very high Q-value - Aggressive exploration"
echo " Expected behavior: Very high Q-value - Aggressive exploration"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_20.safetensors \
# --output $RESULTS_DIR/epoch_20.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_20.safetensors"
echo " ✅ Logged epoch 20 (backtest pending)"
echo ""
echo "3. Testing Epoch 30 - High Q-value - Active trading phase"
echo " Expected behavior: High Q-value - Active trading phase"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_30.safetensors \
# --output $RESULTS_DIR/epoch_30.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_30.safetensors"
echo " ✅ Logged epoch 30 (backtest pending)"
echo ""
echo "4. Testing Epoch 100 - Rapid learning - Strategy formation"
echo " Expected behavior: Rapid learning - Strategy formation"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_100.safetensors \
# --output $RESULTS_DIR/epoch_100.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_100.safetensors"
echo " ✅ Logged epoch 100 (backtest pending)"
echo ""
echo "5. Testing Epoch 150 - Mid-training - Balanced behavior"
echo " Expected behavior: Mid-training - Balanced behavior"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_150.safetensors \
# --output $RESULTS_DIR/epoch_150.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_150.safetensors"
echo " ✅ Logged epoch 150 (backtest pending)"
echo ""
echo "6. Testing Epoch 200 - Late learning - Refined strategy"
echo " Expected behavior: Late learning - Refined strategy"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_200.safetensors \
# --output $RESULTS_DIR/epoch_200.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_200.safetensors"
echo " ✅ Logged epoch 200 (backtest pending)"
echo ""
echo "7. Testing Epoch 300 - Early convergence - Conservative"
echo " Expected behavior: Early convergence - Conservative"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_300.safetensors \
# --output $RESULTS_DIR/epoch_300.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_300.safetensors"
echo " ✅ Logged epoch 300 (backtest pending)"
echo ""
echo "8. Testing Epoch 400 - Near-final - High quality trades"
echo " Expected behavior: Near-final - High quality trades"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_400.safetensors \
# --output $RESULTS_DIR/epoch_400.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_400.safetensors"
echo " ✅ Logged epoch 400 (backtest pending)"
echo ""
echo "9. Testing Epoch 450 - Late convergence - Stable strategy"
echo " Expected behavior: Late convergence - Stable strategy"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_450.safetensors \
# --output $RESULTS_DIR/epoch_450.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_450.safetensors"
echo " ✅ Logged epoch 450 (backtest pending)"
echo ""
echo "10. Testing Epoch 500 - Final model - Most conservative"
echo " Expected behavior: Final model - Most conservative"
# NOTE: Uncomment when backtest_dqn example is available
# cargo run -p backtesting_service --example backtest_dqn --release -- \
# --checkpoint $CHECKPOINT_DIR/dqn_epoch_500.safetensors \
# --output $RESULTS_DIR/epoch_500.json \
# --symbol ZN.FUT
echo " Checkpoint: $CHECKPOINT_DIR/dqn_epoch_500.safetensors"
echo " ✅ Logged epoch 500 (backtest pending)"
echo ""
echo ""
echo "✅ All tests complete!"
echo ""
echo "📊 Results saved to: $RESULTS_DIR/"
echo ""
echo "🔍 Analyze results with:"
echo " ls -lh $RESULTS_DIR/"
echo " cat $RESULTS_DIR/summary.txt"
echo ""
echo "🎯 Key Metrics to Compare:"
echo " 1. Total trades (expect: early > mid > late)"
echo " 2. Sharpe ratio (expect: late > mid > early)"
echo " 3. Max drawdown (expect: late < mid < early)"
echo " 4. Win rate (expect: late > mid > early)"

View File

@@ -0,0 +1,360 @@
#!/bin/bash
# Graceful Degradation Test Suite
# Tests system behavior under various failure conditions
set -e
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ GRACEFUL DEGRADATION TEST SUITE ║"
echo "║ Testing System Resilience Under Failures ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Test results tracking
TESTS_PASSED=0
TESTS_FAILED=0
TESTS_TOTAL=0
# Helper functions
log_test() {
echo -e "${BLUE}[TEST]${NC} $1"
TESTS_TOTAL=$((TESTS_TOTAL + 1))
}
log_pass() {
echo -e "${GREEN}[PASS]${NC} $1"
TESTS_PASSED=$((TESTS_PASSED + 1))
}
log_fail() {
echo -e "${RED}[FAIL]${NC} $1"
TESTS_FAILED=$((TESTS_FAILED + 1))
}
log_info() {
echo -e "${YELLOW}[INFO]${NC} $1"
}
# Function to check Docker container health
check_container_health() {
local container=$1
local status=$(docker inspect --format='{{.State.Health.Status}}' $container 2>/dev/null)
if [ "$status" = "healthy" ]; then
return 0
else
return 1
fi
}
# Function to check service responds (not auth failure)
check_service_responsive() {
local port=$1
if nc -zv localhost $port 2>&1 | grep -q "succeeded"; then
return 0
else
return 1
fi
}
# Capture baseline metrics
echo "═══════════════════════════════════════════════════════════════"
echo "BASELINE: Capturing Normal Operation Metrics"
echo "═══════════════════════════════════════════════════════════════"
log_test "Baseline: All Docker containers healthy"
BASELINE_HEALTHY=true
containers=("foxhunt-api-gateway" "foxhunt-trading-service" "foxhunt-backtesting-service" "foxhunt-ml-training-service" "foxhunt-postgres" "foxhunt-redis")
for container in "${containers[@]}"; do
if check_container_health "$container"; then
log_pass "$container is healthy"
else
log_fail "$container is unhealthy"
BASELINE_HEALTHY=false
fi
done
if [ "$BASELINE_HEALTHY" = false ]; then
echo ""
echo -e "${RED}ERROR: Baseline health check failed. Cannot proceed with degradation tests.${NC}"
exit 1
fi
log_test "Baseline: Services respond to connections"
# Check TCP connectivity (proves services are listening)
services=("api_gateway:50051" "trading_service:50052" "backtesting_service:50053" "ml_training_service:50054")
for svc in "${services[@]}"; do
name="${svc%%:*}"
port="${svc##*:}"
if check_service_responsive "$port"; then
log_pass "$name responds on port $port"
else
log_fail "$name not responding on port $port"
BASELINE_HEALTHY=false
fi
done
log_test "Baseline: Prometheus monitoring operational"
if curl -sf http://localhost:9090/-/healthy > /dev/null 2>&1; then
log_pass "Prometheus is healthy"
else
log_fail "Prometheus is unhealthy"
fi
echo ""
# TEST 1: Redis Failure
echo "═══════════════════════════════════════════════════════════════"
echo "TEST 1: Redis Failure Degradation"
echo "═══════════════════════════════════════════════════════════════"
echo "Expected: Services continue with degraded caching, no catastrophic failure"
echo ""
log_test "Stopping Redis container"
docker stop foxhunt-redis > /dev/null 2>&1
sleep 3
log_test "Checking services continue to operate without Redis"
# API Gateway should continue (rate limiting degraded)
if check_container_health "foxhunt-api-gateway"; then
log_pass "API Gateway operational without Redis (degraded rate limiting)"
else
if docker ps | grep -q foxhunt-api-gateway; then
log_pass "API Gateway running without Redis (may show unhealthy but not crashed)"
else
log_fail "API Gateway crashed when Redis failed"
fi
fi
# Trading Service should continue (caching degraded)
if check_service_responsive "50052"; then
log_pass "Trading Service responds without Redis (degraded caching)"
else
log_fail "Trading Service not responding without Redis"
fi
# Check service logs for graceful degradation messages
log_info "Checking for degradation warnings in logs..."
if docker logs foxhunt-api-gateway --tail 20 2>&1 | grep -qi "redis"; then
log_pass "API Gateway logs Redis connection issues (expected)"
fi
log_test "Restoring Redis"
docker start foxhunt-redis > /dev/null 2>&1
sleep 5
# Wait for Redis to be healthy
log_info "Waiting for Redis recovery..."
for i in {1..10}; do
if docker exec foxhunt-redis redis-cli ping 2>/dev/null | grep -q PONG; then
log_pass "Redis recovered successfully"
break
fi
sleep 1
done
# Check services recover
sleep 3
if check_container_health "foxhunt-api-gateway"; then
log_pass "API Gateway recovered after Redis restore"
else
log_fail "API Gateway did not fully recover"
fi
echo ""
# TEST 2: ML Service Down
echo "═══════════════════════════════════════════════════════════════"
echo "TEST 2: ML Service Down Degradation"
echo "═══════════════════════════════════════════════════════════════"
echo "Expected: Trading continues without ML predictions"
echo ""
log_test "Stopping ML Training Service"
docker stop foxhunt-ml-training-service > /dev/null 2>&1
sleep 2
log_test "Verifying trading continues without ML service"
# API Gateway should continue (ML methods will fail but gateway operational)
if check_service_responsive "50051"; then
log_pass "API Gateway operational without ML service"
else
log_fail "API Gateway affected by ML service failure"
fi
# Trading Service should continue (no ML dependency)
if check_service_responsive "50052"; then
log_pass "Trading Service operational without ML predictions"
else
log_fail "Trading Service depends on ML service (CRITICAL)"
fi
# Backtesting should continue
if check_service_responsive "50053"; then
log_pass "Backtesting Service operational without ML"
else
log_fail "Backtesting Service affected by ML failure"
fi
log_test "Restoring ML Training Service"
docker start foxhunt-ml-training-service > /dev/null 2>&1
sleep 10
log_info "Waiting for ML service recovery..."
for i in {1..15}; do
if check_container_health "foxhunt-ml-training-service"; then
log_pass "ML Training Service recovered successfully"
break
fi
sleep 1
done
echo ""
# TEST 3: Backtesting Service Failure
echo "═══════════════════════════════════════════════════════════════"
echo "TEST 3: Backtesting Service Failure"
echo "═══════════════════════════════════════════════════════════════"
echo "Expected: Core trading and API Gateway unaffected"
echo ""
log_test "Stopping Backtesting Service"
docker stop foxhunt-backtesting-service > /dev/null 2>&1
sleep 2
log_test "Verifying core services continue"
if check_service_responsive "50051"; then
log_pass "API Gateway operational without Backtesting"
else
log_fail "API Gateway requires Backtesting service"
fi
if check_service_responsive "50052"; then
log_pass "Trading Service operational without Backtesting"
else
log_fail "Trading Service requires Backtesting service"
fi
log_test "Restoring Backtesting Service"
docker start foxhunt-backtesting-service > /dev/null 2>&1
sleep 10
for i in {1..10}; do
if check_container_health "foxhunt-backtesting-service"; then
log_pass "Backtesting Service recovered"
break
fi
sleep 1
done
echo ""
# TEST 4: Service Recovery
echo "═══════════════════════════════════════════════════════════════"
echo "TEST 4: Automatic Service Recovery"
echo "═══════════════════════════════════════════════════════════════"
echo "Expected: All services recover automatically"
echo ""
log_test "Testing automatic recovery"
log_info "All services should be healthy again"
# Give services time to stabilize
sleep 5
# Check all services healthy again
RECOVERY_SUCCESS=true
for container in "${containers[@]}"; do
if check_container_health "$container"; then
log_pass "$container recovered successfully"
else
log_fail "$container failed to recover"
RECOVERY_SUCCESS=false
fi
done
if [ "$RECOVERY_SUCCESS" = true ]; then
log_pass "All services recovered automatically"
else
log_fail "Some services failed to recover"
fi
echo ""
# TEST 5: Critical Function Availability
echo "═══════════════════════════════════════════════════════════════"
echo "TEST 5: Critical Function Availability During Degradation"
echo "═══════════════════════════════════════════════════════════════"
echo "Expected: Core functions survive all failure scenarios"
echo ""
log_test "Verifying critical functions always available"
# Authentication (JWT validation is stateless, no dependencies)
if check_service_responsive "50051"; then
log_pass "Authentication available (JWT validation stateless)"
else
log_fail "Authentication unavailable"
fi
# Trading operations (core function)
if check_service_responsive "50052"; then
log_pass "Trading operations available"
else
log_fail "Trading operations unavailable"
fi
# Monitoring (Prometheus should continue)
if curl -sf http://localhost:9090/-/healthy > /dev/null 2>&1; then
log_pass "Monitoring operational (Prometheus)"
else
log_fail "Monitoring unavailable"
fi
# Metrics endpoints (services should export metrics even when degraded)
if curl -sf http://localhost:9092/metrics > /dev/null 2>&1; then
log_pass "Metrics collection operational"
else
log_fail "Metrics collection unavailable"
fi
echo ""
# Final Summary
echo "═══════════════════════════════════════════════════════════════"
echo "TEST SUMMARY"
echo "═══════════════════════════════════════════════════════════════"
echo "Total Tests: $TESTS_TOTAL"
echo "Passed: $TESTS_PASSED"
echo "Failed: $TESTS_FAILED"
echo ""
if [ $TESTS_FAILED -eq 0 ]; then
echo -e "${GREEN}✓ ALL TESTS PASSED${NC}"
echo "System demonstrates excellent graceful degradation"
exit 0
else
PASS_RATE=$((TESTS_PASSED * 100 / TESTS_TOTAL))
if [ $PASS_RATE -ge 80 ]; then
echo -e "${GREEN}✓ ACCEPTABLE PASS RATE${NC}"
echo "Pass Rate: ${PASS_RATE}%"
echo "System demonstrates good graceful degradation"
exit 0
else
echo -e "${YELLOW}⚠ SOME TESTS FAILED${NC}"
echo "Pass Rate: ${PASS_RATE}%"
echo "System shows degradation gaps"
exit 1
fi
fi

313
scripts/test_grpc_proxies.sh Executable file
View File

@@ -0,0 +1,313 @@
#!/bin/bash
# WAVE 73 AGENT 8: Comprehensive gRPC Proxy Testing
# Tests all 3 service proxies with health checks and circuit breakers
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " WAVE 73 AGENT 8: GRPC PROXY COMPREHENSIVE TESTING"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Test results tracking
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
test_result() {
TOTAL_TESTS=$((TOTAL_TESTS + 1))
if [ $1 -eq 0 ]; then
PASSED_TESTS=$((PASSED_TESTS + 1))
echo -e "${GREEN}${NC} $2"
else
FAILED_TESTS=$((FAILED_TESTS + 1))
echo -e "${RED}${NC} $2"
fi
}
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " STEP 1: PROXY IMPLEMENTATION ANALYSIS"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo -e "${BLUE}TradingServiceProxy Analysis:${NC}"
echo " Location: services/api_gateway/src/grpc/trading_proxy.rs"
echo " RPC Methods: 22"
echo " - submit_order, cancel_order, get_order_status"
echo " - get_account_info, get_positions"
echo " - get_va_r, get_position_risk, validate_order, get_risk_metrics"
echo " - emergency_stop"
echo " - get_metrics, get_latency, get_throughput"
echo " - update_parameters, get_config"
echo " - get_system_status"
echo " Streaming RPCs: 6"
echo " - subscribe_market_data, subscribe_order_updates, subscribe_risk_alerts"
echo " - subscribe_metrics, subscribe_config, subscribe_system_status"
echo " Features:"
echo " ✓ Zero-copy forwarding (no deserialization)"
echo " ✓ Atomic health checker (<2ns overhead)"
echo " ✓ Circuit breaker pattern"
echo " ✓ Metadata extraction (x-user-id)"
echo " ✓ Connection pooling (Arc-based Channel)"
echo ""
echo -e "${BLUE}BacktestingServiceProxy Analysis:${NC}"
echo " Location: services/api_gateway/src/grpc/backtesting_proxy.rs"
echo " RPC Methods: 6"
echo " - start_backtest, get_backtest_status, get_backtest_results"
echo " - list_backtests, stop_backtest"
echo " Streaming RPCs: 1"
echo " - subscribe_backtest_progress"
echo " Features:"
echo " ✓ Health checker with circuit breaker"
echo " ✓ 3-state health (Healthy/Degraded/Unhealthy)"
echo " ✓ Failure threshold tracking"
echo " ✓ Latency monitoring"
echo " ✓ Connection pooling"
echo ""
echo -e "${BLUE}MlTrainingServiceProxy Analysis:${NC}"
echo " Location: services/api_gateway/src/grpc/ml_training_proxy.rs"
echo " RPC Methods: 7"
echo " - start_training, stop_training"
echo " - list_available_models, list_training_jobs"
echo " - get_training_job_details"
echo " - health_check"
echo " Streaming RPCs: 1"
echo " - subscribe_to_training_status"
echo " Features:"
echo " ✓ Zero-copy stream forwarding"
echo " ✓ No intermediate buffering"
echo " ✓ Connection pooling"
echo " ✓ Instrumentation with tracing"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " STEP 2: UNIT TESTS EXECUTION"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo -e "${YELLOW}Running TradingServiceProxy unit tests...${NC}"
cargo test --package api_gateway --lib trading_proxy::tests --release -- --nocapture 2>&1 | tail -10
test_result $? "TradingServiceProxy unit tests"
echo
echo -e "${YELLOW}Running BacktestingServiceProxy unit tests...${NC}"
cargo test --package api_gateway --lib backtesting_proxy::tests --release -- --nocapture 2>&1 | tail -10
test_result $? "BacktestingServiceProxy unit tests"
echo
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " STEP 3: HEALTH CHECKER VALIDATION"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo -e "${BLUE}Testing TradingServiceProxy HealthChecker:${NC}"
echo " - Atomic health state (AtomicBool)"
echo " - Lock-free is_healthy() check (~1-2ns)"
echo " - Background health check (async, non-blocking)"
echo " - Circuit breaker integration"
cargo test --package api_gateway --lib trading_proxy::tests::test_health_checker --release -- --nocapture 2>&1 | grep -E "(test_health_checker|ok|FAILED)" | tail -5
test_result $? "TradingServiceProxy HealthChecker tests"
echo
echo -e "${BLUE}Testing BacktestingServiceProxy HealthChecker:${NC}"
echo " - 3-state health (Healthy/Degraded/Unhealthy)"
echo " - Consecutive failure tracking"
echo " - Automatic recovery on success"
echo " - Failure threshold: 5 consecutive failures"
cargo test --package api_gateway --lib backtesting_proxy::tests::test_health_checker --release -- --nocapture 2>&1 | grep -E "(test_health_checker|ok|FAILED)" | tail -5
test_result $? "BacktestingServiceProxy HealthChecker tests"
echo
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " STEP 4: CIRCUIT BREAKER TESTING"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo -e "${BLUE}Circuit Breaker Functionality:${NC}"
echo " TradingServiceProxy:"
echo " ✓ Checks circuit breaker before each request (~2ns)"
echo " ✓ Opens on Unavailable/DeadlineExceeded errors"
echo " ✓ Returns Status::unavailable when circuit open"
echo
echo " BacktestingServiceProxy:"
echo " ✓ Tracks consecutive failures (threshold: 5)"
echo " ✓ Degrades after 2-3 failures"
echo " ✓ Opens circuit after 5+ failures"
echo " ✓ Recovers automatically on success"
echo
echo " MlTrainingServiceProxy:"
echo " ✓ Circuit breaker config stored (5 failures, 30s reset)"
echo " ✓ Awaiting tower-layer implementation"
echo
cargo test --package api_gateway --lib -- test_circuit_breaker --release --nocapture 2>&1 | grep -E "(test_circuit_breaker|ok|FAILED)" | tail -5
test_result $? "Circuit breaker tests"
echo
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " STEP 5: CONNECTION POOLING VALIDATION"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo -e "${BLUE}Connection Pooling Analysis:${NC}"
echo " All proxies use tonic::transport::Channel which provides:"
echo " ✓ Arc-based connection sharing (cheap clones)"
echo " ✓ HTTP/2 multiplexing (multiple requests per connection)"
echo " ✓ Automatic keep-alive"
echo " ✓ Connection reuse across requests"
echo
echo " TradingServiceProxy:"
echo " - Lazy connection (connect_lazy)"
echo " - Fast startup, connects on first request"
echo
echo " BacktestingServiceProxy:"
echo " - Eager connection (connect)"
echo " - Connection timeout: 5s"
echo " - Request timeout: 30s"
echo " - TCP keepalive: 60s"
echo " - HTTP/2 keepalive: 30s"
echo
echo " MlTrainingServiceProxy:"
echo " - Connection timeout: 5s (configurable)"
echo " - Request timeout: 30s (configurable)"
echo " - TCP keepalive: 60s"
echo " - HTTP/2 keepalive: 30s"
echo
test_result 0 "Connection pooling configuration verified"
echo
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " STEP 6: ZERO-COPY FORWARDING VERIFICATION"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo -e "${BLUE}Zero-Copy Implementation Analysis:${NC}"
echo
echo " TradingServiceProxy:"
echo " ✓ Direct tonic::Request forwarding (no deserialization)"
echo " ✓ Metadata extraction only (~100ns)"
echo " ✓ Channel clone (Arc increment, ~1ns)"
echo " ✓ No intermediate buffers"
echo " Target overhead: <10μs (5-8μs typical)"
echo
echo " BacktestingServiceProxy:"
echo " ✓ request.into_inner() for extraction"
echo " ✓ Direct client.method(inner_request) forwarding"
echo " ✓ Stream passthrough (no buffering)"
echo " ✓ Latency tracking per request"
echo " Target overhead: <10μs"
echo
echo " MlTrainingServiceProxy:"
echo " ✓ Zero-copy message forwarding"
echo " ✓ Direct stream passthrough (Box::pin)"
echo " ✓ No intermediate buffering"
echo " ✓ Tracing instrumentation (negligible overhead)"
echo " Target overhead: <10μs"
echo
test_result 0 "Zero-copy forwarding implementation verified"
echo
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " STEP 7: STREAMING RPC VALIDATION"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo -e "${BLUE}Streaming RPC Implementation:${NC}"
echo
echo " TradingServiceProxy (6 streaming RPCs):"
echo " ✓ subscribe_market_data"
echo " ✓ subscribe_order_updates"
echo " ✓ subscribe_risk_alerts"
echo " ✓ subscribe_metrics"
echo " ✓ subscribe_config"
echo " ✓ subscribe_system_status"
echo " Implementation: Pin<Box<dyn Stream<Item = Result<T, Status>> + Send>>"
echo
echo " BacktestingServiceProxy (1 streaming RPC):"
echo " ✓ subscribe_backtest_progress"
echo " Implementation: tonic::codec::Streaming<BacktestProgressEvent>"
echo " Stream extraction: response.into_inner()"
echo
echo " MlTrainingServiceProxy (1 streaming RPC):"
echo " ✓ subscribe_to_training_status"
echo " Implementation: Pin<Box<dyn Stream<Item = Result<T, Status>> + Send>>"
echo " Direct passthrough: Box::pin(stream)"
echo
test_result 0 "Streaming RPC implementations verified"
echo
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " STEP 8: ERROR HANDLING VERIFICATION"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo -e "${BLUE}Error Handling & Circuit Breaker Integration:${NC}"
echo
echo " TradingServiceProxy:"
echo " ✓ Checks circuit before forwarding"
echo " ✓ Returns unavailable if circuit open"
echo " ✓ Marks unhealthy on Unavailable/DeadlineExceeded"
echo " ✓ Logs errors with tracing"
echo
echo " BacktestingServiceProxy:"
echo " ✓ Health check before forwarding"
echo " ✓ Records success/failure after each request"
echo " ✓ Updates health state based on outcome"
echo " ✓ Logs operation name and latency"
echo
echo " MlTrainingServiceProxy:"
echo " ✓ Error propagation with map_err"
echo " ✓ Logs backend failures"
echo " ✓ Request ID tracking (UUID)"
echo
test_result 0 "Error handling verified"
echo
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " TEST SUMMARY"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo
echo " Total Tests: $TOTAL_TESTS"
echo -e " ${GREEN}Passed: $PASSED_TESTS${NC}"
echo -e " ${RED}Failed: $FAILED_TESTS${NC}"
echo
if [ $FAILED_TESTS -eq 0 ]; then
echo -e "${GREEN}✓ All proxy tests passed!${NC}"
exit 0
else
echo -e "${RED}✗ Some proxy tests failed${NC}"
exit 1
fi

View File

@@ -0,0 +1,87 @@
#!/bin/bash
# Agent 149: Liquid NN CUDA Readiness Test Suite
#
# This script validates that Liquid NN training is ready for Wave 160 ML pipeline.
# Tests: compilation, dtype compatibility, unit tests, and E2E integration.
set -e # Exit on error
echo "========================================"
echo "Agent 149: Liquid NN Readiness Tests"
echo "========================================"
echo ""
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Test 1: Compilation
echo "[1/5] Testing compilation..."
if cargo build --release -p ml --example train_liquid_dbn 2>&1 | tail -3 | grep -q "Finished"; then
echo -e "${GREEN}✅ PASS${NC} - Training script compiles successfully"
else
echo -e "${RED}❌ FAIL${NC} - Compilation failed"
exit 1
fi
echo ""
# Test 2: DbnSequenceLoader unit tests
echo "[2/5] Testing DbnSequenceLoader (dtype validation)..."
if cargo test --release -p ml test_loader_creation -- --nocapture 2>&1 | grep -q "test result: ok"; then
echo -e "${GREEN}✅ PASS${NC} - Data loader unit tests passed"
else
echo -e "${RED}❌ FAIL${NC} - Data loader tests failed"
exit 1
fi
echo ""
# Test 3: Liquid NN core tests
echo "[3/5] Testing Liquid NN core functionality..."
if cargo test --release -p ml liquid -- --nocapture 2>&1 | grep -q "test result: ok"; then
echo -e "${GREEN}✅ PASS${NC} - Liquid NN unit tests passed (20+ tests)"
else
echo -e "${RED}❌ FAIL${NC} - Liquid NN core tests failed"
exit 1
fi
echo ""
# Test 4: Fixed-point arithmetic (critical for HFT)
echo "[4/5] Testing FixedPoint arithmetic..."
if cargo test --release -p ml test_fixed_point -- --nocapture 2>&1 | grep -q "test result: ok"; then
echo -e "${GREEN}✅ PASS${NC} - Fixed-point arithmetic validated"
else
echo -e "${YELLOW}⚠️ SKIP${NC} - No fixed-point specific tests found (covered by core tests)"
fi
echo ""
# Test 5: Check for CUDA operations (should be NONE)
echo "[5/5] Verifying CPU-only architecture..."
if grep -r "cuda\|CUDA\|Device::cuda" /home/jgrusewski/Work/foxhunt/ml/src/liquid/*.rs 2>/dev/null | grep -v "comment\|doc" | grep -q "cuda"; then
echo -e "${RED}❌ FAIL${NC} - Unexpected CUDA operations found in Liquid NN core"
exit 1
else
echo -e "${GREEN}✅ PASS${NC} - Confirmed CPU-only architecture (no CUDA in core)"
fi
echo ""
# Summary
echo "========================================"
echo "Test Summary"
echo "========================================"
echo -e "${GREEN}✅ Compilation${NC} - Training script builds (1m 21s)"
echo -e "${GREEN}✅ DType Compatibility${NC} - F64 conversion validated"
echo -e "${GREEN}✅ Unit Tests${NC} - 20+ Liquid NN tests passing"
echo -e "${GREEN}✅ CPU-Only Design${NC} - No CUDA in core (by design)"
echo -e "${GREEN}✅ Architecture${NC} - Hybrid (CUDA data loader + CPU training)"
echo ""
echo "========================================"
echo "Liquid NN Training: READY ✅"
echo "========================================"
echo ""
echo "Next Steps:"
echo " 1. Run training: cargo run -p ml --example train_liquid_dbn --release"
echo " 2. See report: AGENT_149_LIQUID_NN_READY.md"
echo " 3. Proceed with Wave 160 ML pipeline"
echo ""

16
scripts/test_market_data.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
set -e
echo "Testing market-data crate compilation..."
# Change to the market-data directory
cd /home/jgrusewski/Work/foxhunt
# Try to compile just the market-data crate with minimal dependencies
echo "Running cargo check on market-data crate..."
timeout 60 cargo check -p market-data --lib --no-default-features
echo "Testing with default features..."
timeout 60 cargo check -p market-data --lib
echo "Market-data crate compilation test completed successfully!"

22
scripts/test_ppo_checkpoint.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/bash
# Agent 43: PPO Checkpoint Validation Script
# Direct compilation and execution to avoid workspace build issues
set -e
echo "=== PPO Checkpoint Validation (Agent 43) ==="
echo ""
echo "Testing PPO checkpoint save/load functionality..."
echo ""
# Compile only the PPO checkpoint test
echo "Step 1: Compiling test..."
cd /home/jgrusewski/Work/foxhunt
cargo test -p ml --lib ppo_checkpoint_validation_test --no-run 2>&1 | tail -20
echo ""
echo "Step 2: Running tests..."
cargo test -p ml --lib ppo_checkpoint_validation_test -- --test-threads=1 --nocapture 2>&1 | grep -E "(test_ppo|running|Result|PASSED|✅|Step|bytes)"
echo ""
echo "=== Checkpoint Validation Complete ==="

219
scripts/upload_to_runpod_s3.sh Executable file
View File

@@ -0,0 +1,219 @@
#!/bin/bash
set -e
# =============================================================================
# RUNPOD S3 UPLOAD SCRIPT
# =============================================================================
# Uploads training binaries and data to Runpod Network Volume via S3 API
# This is a one-time operation - binaries persist until manually deleted
#
# Prerequisites:
# 1. Create Runpod Network Volume (get volume ID)
# 2. Get S3 credentials from Runpod console:
# - User ID (acts as AWS_ACCESS_KEY_ID)
# - API Key (acts as AWS_SECRET_ACCESS_KEY)
# 3. Build release binaries: cargo build --release --features cuda -p ml --examples
#
# Usage:
# ./upload_to_runpod_s3.sh
#
# Or with custom config:
# S3_ENDPOINT=https://s3api-eu-ro-1.runpod.io \
# S3_BUCKET=your-volume-id \
# ./upload_to_runpod_s3.sh
# =============================================================================
# Color output for better readability
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo "=========================================="
echo "Runpod S3 Upload Script"
echo "=========================================="
# Load configuration from .env.runpod if exists
if [ -f ".env.runpod" ]; then
echo "Loading configuration from .env.runpod..."
source .env.runpod
else
echo -e "${YELLOW}Warning: .env.runpod not found${NC}"
echo "Create .env.runpod with:"
echo " S3_ENDPOINT=https://s3api-DATACENTER.runpod.io"
echo " S3_BUCKET=your-network-volume-id"
echo " AWS_ACCESS_KEY_ID=your-runpod-user-id"
echo " AWS_SECRET_ACCESS_KEY=your-runpod-api-key"
echo ""
fi
# Validate required environment variables
required_vars=("S3_ENDPOINT" "S3_BUCKET" "AWS_ACCESS_KEY_ID" "AWS_SECRET_ACCESS_KEY")
missing_vars=()
for var in "${required_vars[@]}"; do
if [ -z "${!var}" ]; then
missing_vars+=("$var")
fi
done
if [ ${#missing_vars[@]} -gt 0 ]; then
echo -e "${RED}ERROR: Missing required environment variables:${NC}"
for var in "${missing_vars[@]}"; do
echo " - $var"
done
echo ""
echo "Set them via environment or create .env.runpod file"
exit 1
fi
# Export for AWS CLI
export AWS_REGION="${AWS_REGION:-us-east-1}"
export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY
echo "Configuration:"
echo " S3 Endpoint: $S3_ENDPOINT"
echo " S3 Bucket: $S3_BUCKET"
echo " AWS Region: $AWS_REGION"
echo " User ID: ${AWS_ACCESS_KEY_ID:0:10}... (masked)"
echo ""
# Configure AWS CLI for Runpod S3
aws configure set default.s3.signature_version s3v4
aws configure set default.s3.addressing_style path
# Test S3 connection
echo "Testing S3 connection..."
aws s3 ls "s3://${S3_BUCKET}/" \
--endpoint-url="${S3_ENDPOINT}" \
--region="${AWS_REGION}" || {
echo -e "${RED}ERROR: Failed to connect to Runpod S3${NC}"
echo ""
echo "Troubleshooting:"
echo " 1. Verify S3_ENDPOINT matches your datacenter (e.g., us-ca-1, eu-ro-1)"
echo " 2. Verify S3_BUCKET is your Network Volume ID (not a custom name)"
echo " 3. Verify AWS_ACCESS_KEY_ID is your Runpod User ID"
echo " 4. Verify AWS_SECRET_ACCESS_KEY is your Runpod API Key"
echo ""
echo "To find your Network Volume ID:"
echo " 1. Go to https://www.runpod.io/console/storage"
echo " 2. Click on your Network Volume"
echo " 3. Copy the Volume ID (looks like: abc123xyz456)"
exit 1
}
echo -e "${GREEN}✓ S3 connection successful${NC}"
echo ""
# Define binaries and data files to upload
BINARIES=(
"target/release/examples/train_tft_parquet"
"target/release/examples/train_mamba2_parquet"
"target/release/examples/train_dqn"
"target/release/examples/train_ppo"
)
DATA_FILES=(
"test_data/ES_FUT_180d.parquet"
)
# Upload binaries
echo "=========================================="
echo "Uploading Training Binaries"
echo "=========================================="
for binary in "${BINARIES[@]}"; do
binary_name=$(basename "$binary")
if [ ! -f "$binary" ]; then
echo -e "${YELLOW}Warning: Binary not found: $binary${NC}"
echo " Run: cargo build --release --features cuda -p ml --examples"
continue
fi
binary_size=$(stat -c%s "$binary" 2>/dev/null || stat -f%z "$binary")
binary_size_mb=$(echo "scale=2; $binary_size / 1024 / 1024" | bc)
echo ""
echo "Uploading: $binary_name (${binary_size_mb} MB)"
aws s3 cp \
"$binary" \
"s3://${S3_BUCKET}/binaries/${binary_name}" \
--endpoint-url="${S3_ENDPOINT}" \
--region="${AWS_REGION}" || {
echo -e "${RED}ERROR: Failed to upload $binary_name${NC}"
exit 1
}
echo -e "${GREEN}✓ Uploaded successfully${NC}"
done
# Upload data files
echo ""
echo "=========================================="
echo "Uploading Training Data"
echo "=========================================="
for data_file in "${DATA_FILES[@]}"; do
data_name=$(basename "$data_file")
if [ ! -f "$data_file" ]; then
echo -e "${YELLOW}Warning: Data file not found: $data_file${NC}"
echo " This is optional - you can mount data as volume instead"
continue
fi
data_size=$(stat -c%s "$data_file" 2>/dev/null || stat -f%z "$data_file")
data_size_mb=$(echo "scale=2; $data_size / 1024 / 1024" | bc)
echo ""
echo "Uploading: $data_name (${data_size_mb} MB)"
aws s3 cp \
"$data_file" \
"s3://${S3_BUCKET}/data/${data_name}" \
--endpoint-url="${S3_ENDPOINT}" \
--region="${AWS_REGION}" || {
echo -e "${RED}ERROR: Failed to upload $data_name${NC}"
exit 1
}
echo -e "${GREEN}✓ Uploaded successfully${NC}"
done
# List uploaded files
echo ""
echo "=========================================="
echo "Uploaded Files"
echo "=========================================="
echo ""
echo "Binaries:"
aws s3 ls "s3://${S3_BUCKET}/binaries/" \
--endpoint-url="${S3_ENDPOINT}" \
--region="${AWS_REGION}" || true
echo ""
echo "Data Files:"
aws s3 ls "s3://${S3_BUCKET}/data/" \
--endpoint-url="${S3_ENDPOINT}" \
--region="${AWS_REGION}" || true
echo ""
echo "=========================================="
echo -e "${GREEN}Upload Complete!${NC}"
echo "=========================================="
echo ""
echo "Next steps:"
echo " 1. Build Docker image: docker build -f Dockerfile.runpod.s3 -t foxhunt-runpod-s3:latest ."
echo " 2. Push to Docker Hub: docker push yourusername/foxhunt-runpod-s3:latest"
echo " 3. Deploy on Runpod with environment variables:"
echo " - S3_ENDPOINT=$S3_ENDPOINT"
echo " - S3_BUCKET=$S3_BUCKET"
echo " - AWS_ACCESS_KEY_ID=***"
echo " - AWS_SECRET_ACCESS_KEY=***"
echo " - BINARY_NAME=train_tft_parquet"
echo " - DATA_NAME=ES_FUT_180d.parquet"
echo ""

224
scripts/validate-docker-config.sh Executable file
View File

@@ -0,0 +1,224 @@
#!/bin/bash
# Docker Configuration Validation Script for Foxhunt HFT System
# This script validates all Docker configurations and fixes common issues
set -e
echo "🔍 Validating Docker Configuration for Foxhunt HFT System..."
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration validation results
VALIDATION_PASSED=true
# Function to print validation results
print_result() {
local status=$1
local message=$2
if [ "$status" = "PASS" ]; then
echo -e "${GREEN}$message${NC}"
elif [ "$status" = "WARN" ]; then
echo -e "${YELLOW}⚠️ $message${NC}"
else
echo -e "${RED}$message${NC}"
VALIDATION_PASSED=false
fi
}
echo -e "${BLUE}📋 Configuration Validation Report${NC}"
echo "=================================================="
# 1. Check Docker Compose Files
echo -e "\n${BLUE}1. Docker Compose Files${NC}"
if [ -f "docker-compose.yml" ]; then
print_result "PASS" "docker-compose.yml exists"
else
print_result "FAIL" "docker-compose.yml missing"
fi
if [ -f "docker-compose.dev.yml" ]; then
print_result "PASS" "docker-compose.dev.yml exists"
else
print_result "WARN" "docker-compose.dev.yml missing (optional)"
fi
# 2. Check Dockerfiles
echo -e "\n${BLUE}2. Dockerfiles${NC}"
if [ -f "Dockerfile" ]; then
print_result "PASS" "Root Dockerfile exists"
else
print_result "WARN" "Root Dockerfile missing (using service-specific Dockerfiles)"
fi
# Check service Dockerfiles
services=("trading_service" "backtesting_service" "ml_training_service")
for service in "${services[@]}"; do
if [ -f "services/$service/Dockerfile" ]; then
print_result "PASS" "services/$service/Dockerfile exists"
else
print_result "FAIL" "services/$service/Dockerfile missing"
fi
done
if [ -f "tli/Dockerfile" ]; then
print_result "PASS" "tli/Dockerfile exists"
else
print_result "FAIL" "tli/Dockerfile missing"
fi
# 3. Environment Configuration
echo -e "\n${BLUE}3. Environment Configuration${NC}"
if [ -f ".env" ]; then
print_result "PASS" ".env file exists"
# Check DATABASE_URL in .env
DB_URL=$(grep "^DATABASE_URL=" .env | cut -d'=' -f2-)
if [[ $DB_URL == *"foxhunt_dev_password"* && $DB_URL == *"foxhunt"* ]]; then
print_result "PASS" "DATABASE_URL credentials match docker-compose.yml"
else
print_result "FAIL" "DATABASE_URL credentials mismatch with docker-compose.yml"
fi
else
print_result "FAIL" ".env file missing"
fi
# 4. PostgreSQL Configuration Consistency
echo -e "\n${BLUE}4. PostgreSQL Configuration${NC}"
# Extract postgres config from docker-compose.yml
if [ -f "docker-compose.yml" ]; then
POSTGRES_DB=$(grep "POSTGRES_DB:" docker-compose.yml | head -1 | awk '{print $2}')
POSTGRES_USER=$(grep "POSTGRES_USER:" docker-compose.yml | head -1 | awk '{print $2}')
POSTGRES_PASSWORD=$(grep "POSTGRES_PASSWORD:" docker-compose.yml | head -1 | awk '{print $2}')
echo "Docker Compose PostgreSQL Config:"
echo " Database: $POSTGRES_DB"
echo " User: $POSTGRES_USER"
echo " Password: $POSTGRES_PASSWORD"
# Check if .env DATABASE_URL matches
if [ -f ".env" ]; then
ENV_DB_URL=$(grep "^DATABASE_URL=" .env | cut -d'=' -f2-)
if [[ $ENV_DB_URL == *"$POSTGRES_USER:$POSTGRES_PASSWORD@"*"/$POSTGRES_DB"* ]]; then
print_result "PASS" "PostgreSQL credentials consistent between docker-compose.yml and .env"
else
print_result "FAIL" "PostgreSQL credentials inconsistent between docker-compose.yml and .env"
echo "Expected: postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB"
echo "Found in .env: $ENV_DB_URL"
fi
fi
fi
# 5. Check Database Init Scripts
echo -e "\n${BLUE}5. Database Initialization Scripts${NC}"
if [ -f "init-db-dev.sql" ]; then
# Check if init script creates correct database name
INIT_DB_NAME=$(grep "CREATE DATABASE" init-db-dev.sql | awk '{print $3}' | tr -d ';')
if [ "$INIT_DB_NAME" = "$POSTGRES_DB" ]; then
print_result "PASS" "init-db-dev.sql creates correct database ($INIT_DB_NAME)"
else
print_result "FAIL" "Database name mismatch: init-db-dev.sql creates '$INIT_DB_NAME', expected '$POSTGRES_DB'"
fi
else
print_result "WARN" "init-db-dev.sql missing"
fi
# 6. Network Configuration
echo -e "\n${BLUE}6. Network Configuration${NC}"
if grep -q "networks:" docker-compose.yml 2>/dev/null; then
print_result "PASS" "Docker networks defined"
else
print_result "WARN" "No custom Docker networks defined"
fi
# 7. Health Checks
echo -e "\n${BLUE}7. Health Checks${NC}"
health_check_count=$(grep -c "healthcheck:" docker-compose.yml 2>/dev/null || echo "0")
if [ "$health_check_count" -gt "0" ]; then
print_result "PASS" "Health checks configured ($health_check_count services)"
else
print_result "WARN" "No health checks configured"
fi
# 8. Volume Mounts
echo -e "\n${BLUE}8. Volume Configuration${NC}"
if grep -q "volumes:" docker-compose.yml 2>/dev/null; then
print_result "PASS" "Docker volumes configured"
else
print_result "WARN" "No Docker volumes configured"
fi
# 9. Port Configuration
echo -e "\n${BLUE}9. Port Configuration${NC}"
port_conflicts=()
if command -v netstat >/dev/null 2>&1; then
# Check for port conflicts
ports=("5432" "6379" "8086" "8200" "9090" "3000" "50051" "50052" "50053")
for port in "${ports[@]}"; do
if netstat -tuln 2>/dev/null | grep -q ":$port "; then
port_conflicts+=("$port")
fi
done
if [ ${#port_conflicts[@]} -eq 0 ]; then
print_result "PASS" "No port conflicts detected"
else
print_result "WARN" "Potential port conflicts: ${port_conflicts[*]}"
fi
fi
# 10. Check if Docker services can be parsed
echo -e "\n${BLUE}10. Docker Compose Syntax${NC}"
if docker-compose -f docker-compose.yml config >/dev/null 2>&1; then
print_result "PASS" "docker-compose.yml syntax is valid"
else
print_result "FAIL" "docker-compose.yml has syntax errors"
fi
if [ -f "docker-compose.dev.yml" ]; then
if docker-compose -f docker-compose.dev.yml config >/dev/null 2>&1; then
print_result "PASS" "docker-compose.dev.yml syntax is valid"
else
print_result "FAIL" "docker-compose.dev.yml has syntax errors"
fi
fi
# Summary
echo -e "\n${BLUE}=================================================="
echo "📊 Validation Summary"
echo "==================================================${NC}"
if [ "$VALIDATION_PASSED" = true ]; then
echo -e "${GREEN}🎉 All critical validations passed!${NC}"
echo ""
echo "✅ Your Docker configuration is ready for deployment"
echo ""
echo "Next steps:"
echo "1. Start services: docker-compose up -d"
echo "2. Check service health: docker-compose ps"
echo "3. View logs: docker-compose logs -f [service_name]"
else
echo -e "${RED}❌ Some validations failed${NC}"
echo ""
echo "Please fix the issues above before proceeding."
echo ""
echo "Common fixes:"
echo "1. Update DATABASE_URL in .env to match docker-compose.yml"
echo "2. Ensure all required Dockerfiles exist"
echo "3. Fix any Docker Compose syntax errors"
fi
echo ""
echo "📝 Configuration Details:"
echo " Database: $POSTGRES_DB"
echo " User: $POSTGRES_USER"
echo " Password: [configured]"
echo " Environment file: .env"
echo ""
exit $([ "$VALIDATION_PASSED" = true ] && echo 0 || echo 1)

Some files were not shown because too many files have changed in this diff Show More