Files
crpto_predictor/train_cross_asset.py
T
crypto_predictorandClaude Sonnet 4.5 9bbdc8d42b Initial commit: BTC 1h prediction model (53.10% accuracy)
🎯 项目成果:
- 准确率: 53.10% (2026年测试集)
- 任务类型: 二分类 (预测涨/跌)
- 特征: OHLCV + RSI + MACD (9个特征)
- 训练数据: 2020-2025年BTC小时数据 (52,351序列)
- 测试数据: 2026年1-29日 (484序列)

📊 性能指标:
- 精确率: 51.79%
- 召回率: 49.36%
- F1分数: 0.5054
- 预测分布: 非常平衡 (偏差仅-11个)

🔬 实验历史:
- 尝试了5种方案 (回归/分类, 不同数据划分)
- 分类任务优于回归任务 (53.10% vs 49.5%)
- 全量训练避免了过拟合问题

📦 主要模型文件:
- models/checkpoints/dlinear_classification_2026/
  - best_model.pt (最佳模型)
  - preprocessor.pkl (预处理器)
  - test_2026_results.json (测试结果)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-29 21:27:15 +08:00

241 lines
9.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""跨资产迁移学习实验 - 用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()