Files
crpto_predictor/compare_tasks.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

245 lines
9.2 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.
"""详细对比二分类和回归任务在加密货币预测中的差异"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import numpy as np
import pandas as pd
from data.fetcher import BinanceDataFetcher
from data.preprocessor import CryptoPreprocessor
def compare_classification_vs_regression():
print("="*80)
print("二分类 vs 回归任务详细对比")
print("="*80)
# 获取少量数据用于演示
print("\n[1/3] 获取示例数据...")
fetcher = BinanceDataFetcher()
df = fetcher.fetch_ohlcv('BTC', '1h', use_cache=True)
df_sample = df.tail(200).copy() # 只取最近200小时
print(f"✓ 样本数据: {len(df_sample)} 行")
print(f"✓ 时间范围: {df_sample['timestamp'].min()} 至 {df_sample['timestamp'].max()}")
# 对比两种任务
print("\n[2/3] 对比两种任务的标签生成...")
# 二分类任务
print("\n" + "="*80)
print("📊 任务1: 二分类(Binary Classification)")
print("="*80)
preprocessor_cls = CryptoPreprocessor(
lookback=24,
forecast_horizon=1,
price_change_threshold=0.0
)
# 创建标签
df_sample['future_price'] = df_sample['close'].shift(-1)
df_sample['future_return'] = (df_sample['future_price'] - df_sample['close']) / df_sample['close']
df_sample['label_classification'] = (df_sample['future_return'] > 0).astype(int)
print(f"\n目标: 预测价格会上涨(1)还是下跌(0)")
print(f"\n标签生成公式:")
print(f" future_return = (未来价格 - 当前价格) / 当前价格")
print(f" label = 1 if future_return > 0 else 0")
print(f"\n具体例子(前10个样本):")
print(f"{'时间':<20} {'当前价格':<12} {'未来价格':<12} {'收益率':<10} {'标签':<8}")
print("-"*80)
for i in range(10):
row = df_sample.iloc[i]
if pd.notna(row['future_return']):
label = "上涨(1)" if row['label_classification'] == 1 else "下跌(0)"
print(f"{str(row['timestamp']):<20} ${row['close']:<11,.2f} ${row['future_price']:<11,.2f} "
f"{row['future_return']*100:>7.2f}% {label:<8}")
print(f"\n标签统计:")
n_up = df_sample['label_classification'].sum()
n_down = len(df_sample) - n_up - df_sample['label_classification'].isna().sum()
print(f" 上涨(1): {n_up} 个")
print(f" 下跌(0): {n_down} 个")
print(f" 比例: {n_up/(n_up+n_down)*100:.1f}% vs {n_down/(n_up+n_down)*100:.1f}%")
print(f"\n模型输出:")
print(f" 格式: 0-1之间的概率值")
print(f" 例如: 0.73 表示 73% 概率上涨")
print(f" 决策: 如果概率 > 0.5 → 预测上涨")
print(f" 如果概率 < 0.5 → 预测下跌")
print(f"\n评估指标:")
print(f" - 准确率 (Accuracy)")
print(f" - 精确率 (Precision)")
print(f" - 召回率 (Recall)")
print(f" - F1分数")
print(f" - 混淆矩阵")
print(f"\n优点:")
print(f" ✅ 简单直观(涨/跌二选一)")
print(f" ✅ 评估指标清晰")
print(f" ✅ 适合交易决策(做多/做空)")
print(f"\n缺点:")
print(f" ❌ 丢失了涨跌幅度信息")
print(f" ❌ 涨0.1%和涨10%被视为一样")
print(f" ❌ 无法评估风险收益比")
# 回归任务
print("\n" + "="*80)
print("📈 任务2: 回归(Regression)")
print("="*80)
df_sample['label_regression'] = df_sample['future_return']
print(f"\n目标: 预测价格变化的百分比")
print(f"\n标签生成公式:")
print(f" label = (未来价格 - 当前价格) / 当前价格")
print(f" 直接预测收益率(可正可负)")
print(f"\n具体例子(前10个样本):")
print(f"{'时间':<20} {'当前价格':<12} {'未来价格':<12} {'收益率(标签)':<15}")
print("-"*80)
for i in range(10):
row = df_sample.iloc[i]
if pd.notna(row['future_return']):
print(f"{str(row['timestamp']):<20} ${row['close']:<11,.2f} ${row['future_price']:<11,.2f} "
f"{row['label_regression']*100:>12.4f}%")
print(f"\n标签统计:")
valid_returns = df_sample['label_regression'].dropna()
print(f" 最小值: {valid_returns.min()*100:.4f}%")
print(f" 最大值: {valid_returns.max()*100:.4f}%")
print(f" 均值: {valid_returns.mean()*100:.4f}%")
print(f" 标准差: {valid_returns.std()*100:.4f}%")
print(f" 中位数: {valid_returns.median()*100:.4f}%")
print(f"\n模型输出:")
print(f" 格式: 连续的数值(收益率)")
print(f" 例如: 0.0235 表示预测上涨 2.35%")
print(f" -0.0178 表示预测下跌 1.78%")
print(f" 决策: 根据预测值大小决定仓位")
print(f" 预测+5% → 大仓位做多")
print(f" 预测+0.5% → 小仓位做多")
print(f"\n评估指标:")
print(f" - RMSE (均方根误差)")
print(f" - MAE (平均绝对误差)")
print(f" - MAPE (平均绝对百分比误差)")
print(f" - 方向准确率 (预测方向是否正确)")
print(f" - R² (决定系数)")
print(f"\n优点:")
print(f" ✅ 保留了涨跌幅度信息")
print(f" ✅ 可以评估风险收益比")
print(f" ✅ 支持动态仓位管理")
print(f" ✅ 提供更精细的预测")
print(f"\n缺点:")
print(f" ❌ 预测难度更高")
print(f" ❌ 容易过拟合")
print(f" ❌ 对异常值敏感")
# 对比分析
print("\n[3/3] 详细对比分析...")
print("\n" + "="*80)
print("🔍 详细对比")
print("="*80)
comparison = [
["维度", "二分类", "回归"],
["-"*30, "-"*40, "-"*40],
["预测目标", "方向(涨/跌)", "具体涨跌幅度"],
["输出范围", "0-1(概率)", "-∞ to +∞(收益率)"],
["输出示例", "0.73(73%概率上涨)", "+0.0235(预测涨2.35%)"],
["标签类型", "离散(0或1)", "连续(实数)"],
["损失函数", "BCEWithLogitsLoss", "MSELoss / MAELoss"],
["评估指标", "准确率、F1分数", "RMSE、MAE、MAPE"],
["决策方式", "二元(做多/做空)", "连续(仓位大小)"],
["信息量", "少(只有方向)", "多(方向+幅度)"],
["预测难度", "中等", "困难"],
["适用场景", "简单交易策略", "精细化资金管理"],
]
for row in comparison:
print(f"{row[0]:<30} {row[1]:<40} {row[2]:<40}")
# 实际应用对比
print("\n" + "="*80)
print("💰 实际交易应用对比")
print("="*80)
print("\n场景1: 预测未来1小时BTC会上涨")
print("\n二分类模型:")
print(" 输出: 0.68 (68%概率上涨)")
print(" 决策: 概率>0.5,买入BTC")
print(" 行动: 全仓做多(或固定仓位如50%)")
print(" 问题: 不知道预期涨多少,无法评估风险")
print("\n回归模型:")
print(" 输出: +0.0023 (预测上涨0.23%)")
print(" 决策: 预测值>0,买入BTC")
print(" 行动: 根据预测幅度调整仓位(0.23%很小,可能只用10%仓位)")
print(" 优势: 知道预期收益,可以计算风险收益比")
print("\n场景2: 预测未来1小时BTC大涨")
print("\n二分类模型:")
print(" 输出: 0.72 (72%概率上涨)")
print(" 决策: 买入BTC")
print(" 问题: 72%概率可能是涨0.1%,也可能是涨5%,无法区分")
print("\n回归模型:")
print(" 输出: +0.0480 (预测上涨4.8%)")
print(" 决策: 买入BTC")
print(" 行动: 预期涨幅大,可以加大仓位(如80%)")
print(" 优势: 可以根据预期收益调整风险敞口")
# 性能对比
print("\n" + "="*80)
print("📊 当前项目的实际性能对比")
print("="*80)
print("\n二分类任务(当前已实现):")
print(" 准确率: 49.76%(接近随机)")
print(" F1分数: 0.3898")
print(" 召回率: 31.85%")
print(" 问题: 预测能力极弱")
print("\n回归任务(未实现):")
print(" 预期性能: 可能更差")
print(" 原因: 预测具体数值比预测方向更难")
print(" 但优势: 即使方向准确率50%,如果能准确预测幅度,仍可盈利")
# 建议
print("\n" + "="*80)
print("💡 建议")
print("="*80)
print("\n选择二分类的情况:")
print(" ✅ 初学者或概念验证")
print(" ✅ 简单的做多/做空策略")
print(" ✅ 预测周期较长(1天以上)")
print(" ✅ 只关心方向,不关心幅度")
print("\n选择回归的情况:")
print(" ✅ 需要精细化资金管理")
print(" ✅ 需要评估风险收益比")
print(" ✅ 有足够多的训练数据")
print(" ✅ 想要更丰富的预测信息")
print("\n对于1小时BTC预测:")
print(" 当前结论: 两者都很难!")
print(" 二分类: 准确率49.76%(已验证)")
print(" 回归: 预计MAPE会很高(未验证,但大概率也很差)")
print("\n 核心问题: 1小时价格变化接近随机游走")
print(" 建议: 延长预测周期到24小时或更长")
print("\n" + "="*80)
print("✓ 对比分析完成")
print("="*80)
if __name__ == "__main__":
compare_classification_vs_regression()