"""跨资产迁移学习实验 - 用BTC训练,在ETH上验证和测试""" import sys import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from data.fetcher import BinanceDataFetcher from data.preprocessor import CryptoPreprocessor, split_data from data.dataset import create_dataloaders from models.dlinear.model import DLinear, DLinearConfig from training.trainer import Trainer from training.config import TrainingConfig import json import numpy as np def main(): print("="*80) print("跨资产迁移学习实验") print("训练:BTC 2020-2025 | 验证+测试:ETH 2020-2025") print("="*80) fetcher = BinanceDataFetcher() # ========== 步骤1: 获取BTC训练数据 ========== print("\n[1/10] 获取BTC数据(用于训练)...") df_btc = fetcher.fetch_ohlcv( symbol='BTC', timeframe='1h', start_date='2020-01-01', end_date='2025-12-31', use_cache=True ) print(f"✓ BTC数据: {len(df_btc)} 行") print(f" 时间: {df_btc['timestamp'].min()} 至 {df_btc['timestamp'].max()}") print(f" 价格: ${df_btc['close'].iloc[0]:,.0f} → ${df_btc['close'].iloc[-1]:,.0f}") btc_return = (df_btc['close'].iloc[-1] - df_btc['close'].iloc[0]) / df_btc['close'].iloc[0] print(f" 收益率: {btc_return*100:+.1f}%") # ========== 步骤2: 获取ETH验证/测试数据 ========== print("\n[2/10] 获取ETH数据(用于验证和测试)...") df_eth = fetcher.fetch_ohlcv( symbol='ETH', timeframe='1h', start_date='2020-01-01', end_date='2025-12-31', use_cache=True ) print(f"✓ ETH数据: {len(df_eth)} 行") print(f" 时间: {df_eth['timestamp'].min()} 至 {df_eth['timestamp'].max()}") print(f" 价格: ${df_eth['close'].iloc[0]:,.2f} → ${df_eth['close'].iloc[-1]:,.2f}") eth_return = (df_eth['close'].iloc[-1] - df_eth['close'].iloc[0]) / df_eth['close'].iloc[0] print(f" 收益率: {eth_return*100:+.1f}%") # ========== 步骤3: 预处理BTC数据 ========== print("\n[3/10] 预处理BTC数据(回归任务)...") preprocessor_btc = CryptoPreprocessor( lookback=168, forecast_horizon=1, price_change_threshold=0.0 ) X_btc, y_btc, processed_btc = preprocessor_btc.preprocess_pipeline( df_btc, task='regression', fit=True ) print(f"✓ BTC序列: X={X_btc.shape}, y={y_btc.shape}") # ========== 步骤4: 预处理ETH数据 ========== print("\n[4/10] 预处理ETH数据(使用BTC的scaler)...") # 重要:复用BTC的preprocessor(已fit的scaler)来处理ETH数据 # 添加技术指标和时间特征 df_eth_processed = preprocessor_btc.add_technical_indicators(df_eth) df_eth_processed = preprocessor_btc.add_time_features(df_eth_processed) df_eth_processed = preprocessor_btc.create_labels(df_eth_processed, task='regression') # 删除NaN行 processed_eth = df_eth_processed.dropna().reset_index(drop=True) # 使用BTC训练的scaler来标准化ETH特征(不重新fit) scaled_features = preprocessor_btc.transform(processed_eth) # 创建序列 X_eth, y_eth = preprocessor_btc.create_sequences( scaled_features, processed_eth['label'].values ) print(f"✓ ETH序列: X={X_eth.shape}, y={y_eth.shape}") # ========== 步骤5: 划分数据集 ========== print("\n[5/10] 划分数据集...") # BTC: 只用前70%作为训练集 n_btc = len(X_btc) train_end = int(n_btc * 0.7) X_train = X_btc[:train_end] y_train = y_btc[:train_end] print(f" 训练集(BTC): {len(X_train)} 样本") print(f" 收益率范围: {y_train.min()*100:.4f}% ~ {y_train.max()*100:.4f}%") # ETH: 70%验证,30%测试 n_eth = len(X_eth) val_end = int(n_eth * 0.7) X_val = X_eth[:val_end] y_val = y_eth[:val_end] X_test = X_eth[val_end:] y_test = y_eth[val_end:] print(f" 验证集(ETH): {len(X_val)} 样本") print(f" 收益率范围: {y_val.min()*100:.4f}% ~ {y_val.max()*100:.4f}%") print(f" 测试集(ETH): {len(X_test)} 样本") print(f" 收益率范围: {y_test.min()*100:.4f}% ~ {y_test.max()*100:.4f}%") # 分析时间范围 lookback = 168 train_df = processed_btc.iloc[lookback:train_end+lookback] val_df = processed_eth.iloc[lookback:val_end+lookback] test_df = processed_eth.iloc[val_end+lookback:] print(f"\n 时间范围分析:") print(f" 训练(BTC): {train_df['timestamp'].min()} 至 {train_df['timestamp'].max()}") print(f" 验证(ETH): {val_df['timestamp'].min()} 至 {val_df['timestamp'].max()}") print(f" 测试(ETH): {test_df['timestamp'].min()} 至 {test_df['timestamp'].max()}") # ========== 步骤6: 创建数据加载器 ========== print("\n[6/10] 创建数据加载器...") train_loader, val_loader, test_loader = create_dataloaders( (X_train, y_train), (X_val, y_val), (X_test, y_test), task='regression', batch_size=64 ) # ========== 步骤7: 创建模型 ========== print("\n[7/10] 创建DLinear回归模型...") model_config = DLinearConfig( input_dim=X_btc.shape[-1], lookback=168, task='regression', hidden_dim=512, dropout=0.1, moving_avg_kernel=25 ) model = DLinear(model_config) print(f"✓ 模型参数: {model.count_parameters():,} 个") # ========== 步骤8: 训练模型 ========== print("\n[8/10] 训练模型(BTC训练,ETH验证)...") train_config = TrainingConfig( batch_size=64, max_epochs=50, learning_rate=0.001, early_stopping_patience=10, lr_scheduler='plateau', save_best=True, checkpoint_dir='./models/checkpoints/cross_asset_btc_to_eth' ) trainer = Trainer(model, train_config, task='regression') history = trainer.fit(train_loader, val_loader) # ========== 步骤9: 在ETH测试集上评估 ========== print("\n[9/10] 在ETH测试集上评估...") metrics_eth = trainer.evaluate(test_loader) results_path = './models/checkpoints/cross_asset_btc_to_eth/test_metrics.json' with open(results_path, 'w') as f: json.dump(metrics_eth, f, indent=2) print(f"✓ 结果保存至: {results_path}") # ========== 步骤10: 对比分析 ========== print("\n[10/10] 性能分析...") print("\n" + "="*80) print("跨资产迁移学习实验结果") print("="*80) print("\n📋 实验设置:") print(f" 训练集: BTC 2020-2024 ({len(X_train):,} 样本)") print(f" 验证集: ETH 2020-2024 ({len(X_val):,} 样本)") print(f" 测试集: ETH 2024-2025 ({len(X_test):,} 样本)") print("\n📊 ETH测试集性能:") print(f" RMSE: {metrics_eth.get('rmse', 0)*100:.4f}%") print(f" MAE: {metrics_eth.get('mae', 0)*100:.4f}%") print(f" 方向准确率: {metrics_eth.get('directional_accuracy', 0)*100:.2f}%") print(f"\n💰 ETH回测结果:") print(f" 总收益率: {metrics_eth.get('backtest_total_return', 0)*100:.2f}%") print(f" 夏普比率: {metrics_eth.get('backtest_sharpe_ratio', 0):.4f}") max_dd = metrics_eth.get('backtest_max_drawdown', 0) if not np.isnan(max_dd): print(f" 最大回撤: {max_dd*100:.2f}%") print(f" 胜率: {metrics_eth.get('backtest_win_rate', 0)*100:.2f}%") print(f" 交易次数: {metrics_eth.get('backtest_num_trades', 0):.0f}") # 对比之前的结果 print("\n" + "="*80) print("📊 性能对比") print("="*80) print("\n实验1:BTC训练 → BTC测试(之前结果)") print(" 方向准确率: 50.67%") print(" RMSE: 0.4881%") print(" 回测收益: -16.71%") print(f"\n实验2:BTC训练 → ETH测试(当前结果)") print(f" 方向准确率: {metrics_eth.get('directional_accuracy', 0)*100:.2f}%") print(f" RMSE: {metrics_eth.get('rmse', 0)*100:.4f}%") print(f" 回测收益: {metrics_eth.get('backtest_total_return', 0)*100:.2f}%") # 性能评估 print("\n🎯 迁移学习效果评估:") dir_acc = metrics_eth.get('directional_accuracy', 0) if dir_acc > 0.52: print(f" ✅ 方向准确率 {dir_acc*100:.1f}% > 52%,跨资产迁移有效") elif dir_acc > 0.50: print(f" ⚠️ 方向准确率 {dir_acc*100:.1f}% 略优于随机") else: print(f" ❌ 方向准确率 {dir_acc*100:.1f}% ≤ 50%,迁移失败") total_return = metrics_eth.get('backtest_total_return', 0) if total_return > 0: print(f" ✅ 回测收益 {total_return*100:.2f}% > 0,策略盈利") else: print(f" ❌ 回测收益 {total_return*100:.2f}% ≤ 0,策略亏损") print("\n💡 结论:") if dir_acc > 0.52 and total_return > 0: print(" ✅ 跨资产迁移学习成功!BTC学到的模式可应用于ETH") elif dir_acc > 0.50: print(" ⚠️ 跨资产迁移部分有效,但收益不佳") else: print(" ❌ 跨资产迁移失败,BTC和ETH市场动态差异太大") print("\n" + "="*80) print("✓ 实验完成!") print("="*80) if __name__ == "__main__": main()