- 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
467 lines
15 KiB
Bash
Executable File
467 lines
15 KiB
Bash
Executable File
#!/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 "$@"
|