"""详细对比二分类和回归任务在加密货币预测中的差异""" 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()