|
| 1 | +import os |
| 2 | +import sys |
| 3 | +import random |
| 4 | +import numpy as np |
| 5 | +from datetime import datetime |
| 6 | + |
| 7 | +# Add project root to sys.path |
| 8 | +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| 9 | + |
| 10 | +from src.config import ( |
| 11 | + ASSET_NAMES, |
| 12 | + DATA_FOLDER, |
| 13 | + OUTPUT_FOLDER, |
| 14 | + TRAINING_ITERATIONS, |
| 15 | + NUM_MIXTURES, |
| 16 | +) |
| 17 | +from src.data_handler import load_data |
| 18 | +from src.predictors import ExactGPPredictor |
| 19 | +from src.portfolio import ( |
| 20 | + calculate_expected_returns_and_cov, |
| 21 | + MOEADOptimizer, |
| 22 | +) |
| 23 | +from src.visualization import plot_population_evolution |
| 24 | + |
| 25 | + |
| 26 | +def seed_everything(seed=42): |
| 27 | + random.seed(seed) |
| 28 | + np.random.seed(seed) |
| 29 | + try: |
| 30 | + import torch |
| 31 | + |
| 32 | + torch.manual_seed(seed) |
| 33 | + except ImportError: |
| 34 | + pass |
| 35 | + |
| 36 | + |
| 37 | +def run_evolution_demo(): |
| 38 | + seed_everything(42) |
| 39 | + |
| 40 | + # Setup folders |
| 41 | + run_id = datetime.now().strftime("%Y%m%d_%H%M%S_moead_evolution") |
| 42 | + run_folder = os.path.join(OUTPUT_FOLDER, run_id) |
| 43 | + os.makedirs(run_folder, exist_ok=True) |
| 44 | + |
| 45 | + print(f"Starting MOEA/D Evolution Demo. Result will be saved to {run_folder}") |
| 46 | + |
| 47 | + # 1. Load data and calculate expected returns/cov |
| 48 | + # (Simplified data hash for speed in this demo) |
| 49 | + raw_data_dict = load_data(DATA_FOLDER, ASSET_NAMES, verbose=False) |
| 50 | + predictor = ExactGPPredictor( |
| 51 | + training_iterations=TRAINING_ITERATIONS, |
| 52 | + num_mixtures=NUM_MIXTURES, |
| 53 | + verbose=False, |
| 54 | + ) |
| 55 | + |
| 56 | + sample_timestamps = raw_data_dict[ASSET_NAMES[0]]["timestamps"] |
| 57 | + target_timestamp = sample_timestamps[-1] + 100.0 |
| 58 | + |
| 59 | + expected_returns, cov_matrix = calculate_expected_returns_and_cov( |
| 60 | + raw_data_dict, predictor, target_timestamp, ASSET_NAMES, verbose=False |
| 61 | + ) |
| 62 | + |
| 63 | + data_kwargs = {"expected_returns": expected_returns, "cov_matrix": cov_matrix} |
| 64 | + |
| 65 | + # 2. Run MOEA/D with history recording |
| 66 | + print("Running MOEA/D with history recording (interval=10)...") |
| 67 | + moead = MOEADOptimizer() |
| 68 | + history_interval = 10 |
| 69 | + generations = 200 |
| 70 | + |
| 71 | + # generate_pareto_front returns: metrics, population, weight_vectors, history (if record_history=True) |
| 72 | + results = moead.generate_pareto_front( |
| 73 | + num_points=100, |
| 74 | + generations=generations, |
| 75 | + verbose=True, |
| 76 | + record_history=True, |
| 77 | + history_interval=history_interval, |
| 78 | + **data_kwargs, |
| 79 | + ) |
| 80 | + |
| 81 | + # unpack results |
| 82 | + moead_metrics, _, _, history = results |
| 83 | + |
| 84 | + # 3. Plot Population Evolution |
| 85 | + print("Generating Population Evolution Plot...") |
| 86 | + obj_names = ["Expected Return", "Expected Risk"] |
| 87 | + save_path = os.path.join(run_folder, "population_evolution.png") |
| 88 | + |
| 89 | + plot_population_evolution( |
| 90 | + history, obj_names, history_interval=history_interval, save_path=save_path |
| 91 | + ) |
| 92 | + |
| 93 | + print(f"Success! Plot saved to {save_path}") |
| 94 | + |
| 95 | + |
| 96 | +if __name__ == "__main__": |
| 97 | + run_evolution_demo() |
0 commit comments