mcpField
S
signal-classification

signal-classification

github.com/agiprolabs数据与数据库456523 次安装8 周前更新
代码仓库

关于 signal-classification

用于训练监督式分类器,预测资产在未来周期内的价格方向。内容涵盖标签生成、按时间顺序验证、模型解释和面向交易的阈值选择。

主要功能

  1. 01二分类与多分类标签
  2. 02Walk-forward 验证
  3. 03XGBoost 和 LightGBM 训练
  4. 04SHAP 特征分析
  5. 05按盈利因子优化阈值

适用场景

  1. 01避免随机打乱数据造成泄漏,检验方向信号
  2. 02分析哪些特征影响预测
  3. 03为交易信号选择概率阈值

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agiprolabs/claude-trading-skills --skill signal-classification

安装后在 Claude Code 中输入/signal-classification确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
model_guide.md
validation_methods.md
scripts/
train_classifier.py
walk_forward_backtest.py

详细介绍

信号分类

使用有监督机器学习分类器,预测资产价格在未来一段时间内将上涨还是下跌。本技能涵盖完整流程:标签创建、模型训练、走步验证、特征重要性分析,以及针对交易应用的阈值优化。

基于树的模型为何在交易机器学习中占主导地位

XGBoost 和 LightGBM 是量化交易机器学习的主力模型,原因如下:

  • 非线性关系:金融特征之间会以复杂的非线性方式相互作用,树模型能够自然地捕捉这些关系
  • 不受特征尺度影响:无需对输入进行归一化或标准化——树按排序进行分割
  • 内置特征重要性:无需单独分析,即可了解哪些特征驱动了预测
  • 训练和推理速度快:数秒内即可使用数千个样本进行训练,微秒内即可完成预测
  • 处理缺失值:原生支持 NaN,无需采用填补技巧
  • 内置正则化:max_depth、min_child_weight、subsample 均可防止过拟合

线性模型和深度学习也各有用武之地,但对于样本少于 100k 的表格型交易特征,梯度提升树始终优于其他方法。

分类类型

二元分类

最简单、最常见的设置。预测未来收益是否超过某个阈值:

  • 上涨信号:未来收益 > +1%
  • 下跌信号:未来收益 < -1%
  • 中性(排除):-1% 至 +1%——从训练数据中剔除这些样本,以生成更清晰的标签
import numpy as np

def create_binary_labels(
    prices: np.ndarray, horizon: int = 24, threshold: float = 0.01
) -> np.ndarray:
    """Create binary labels from forward returns.

    Args:
        prices: Array of prices.
        horizon: Forward return lookback in bars.
        threshold: Minimum return magnitude for a label.

    Returns:
        Array of labels: 1 (up), 0 (down), NaN (neutral).
    """
    fwd_returns = np.roll(prices, -horizon) / prices - 1
    fwd_returns[-horizon:] = np.nan
    labels = np.where(fwd_returns > threshold, 1,
             np.where(fwd_returns < -threshold, 0, np.nan))
    return labels
多分类

使用三个类别,实现更精细的信号粒度:

类别条件典型阈值
强势上涨fwd_return > +2%高置信度做多
温和上涨+0.5% 至 +2%中等置信度
下跌fwd_return < -0.5%回避/做空

多分类会减少每个类别的样本数量。仅在数据集足够大(每个类别 1000+ 个样本)时使用。

概率校准

XGBoost/LightGBM 输出的原始模型概率校准效果不佳。预测概率为 0.7,并不意味着有 70% 的正确概率。使用校准来改善这一点:

from sklearn.calibration import CalibratedClassifierCV

calibrated = CalibratedClassifierCV(base_model, cv=5, method="isotonic")
calibrated.fit(X_train, y_train)
probs = calibrated.predict_proba(X_test)[:, 1]

对于树模型,等距回归校准的效果优于 Platt 缩放。

走步验证

这是交易机器学习中最重要的概念。 标准交叉验证会随机打乱数据,从而造成前视偏差。走步验证则遵循时间顺序。

工作原理
Window 1: [===TRAIN===][GAP][=TEST=]
Window 2:    [===TRAIN===][GAP][=TEST=]
Window 3:       [===TRAIN===][GAP][=TEST=]
Window 4:          [===TRAIN===][GAP][=TEST=]

每个窗口:

  1. 使用过去 N 根 K 线进行训练
  2. 跳过一段间隔(禁运期),其长度等于未来收益的时间跨度
  3. 对接下来的 M 根 K 线进行预测
  4. 记录样本外预测结果
  5. 向前滑动并重复
典型参数
参数值原因
训练窗口30 天(720 根小时 K 线)数据量足以学习,且足够新,仍具参考价值
测试窗口7 天(168 根小时 K 线)预测数量足以满足统计显著性要求
步长1 天(24 根 K 线)重叠测试窗口以获取更多数据点
间隔(禁运期)与未来收益的时间跨度相同防止标签泄漏
走步验证实现
from typing import Iterator

def walk_forward_splits(
    n_samples: int,
    train_size: int = 720,
    test_size: int = 168,
    step_size: int = 24,
    gap: int = 24,
) -> Iterator[tuple[np.ndarray, np.ndarray]]:
    """Generate walk-forward train/test index splits.

    Args:
        n_samples: Total number of samples.
        train_size: Number of training samples per window.
        test_size: Number of test samples per window.
        step_size: Step between successive windows.
        gap: Gap between train end and test start.

    Yields:
        Tuples of (train_indices, test_indices).
    """
    start = 0
    while start + train_size + gap + test_size <= n_samples:
        train_idx = np.arange(start, start + train_size)
        test_start = start + train_size + gap
        test_idx = np.arange(test_start, test_start + test_size)
        yield train_idx, test_idx
        start += step_size

参见 references/validation_methods.md,了解净化交叉验证(purged CV)、CPCV 和评估指标。

模型训练流程

完整流程概览
  1. 特征工程——计算技术指标、链上指标和成交量特征(参见 feature-engineering 技能)
  2. 标签创建——根据阈值计算未来收益,并剔除中性区间
  3. 走步划分——按时间顺序划分训练/测试窗口并设置间隔
  4. 训练模型——在每个训练窗口上使用 XGBoost 或 LightGBM
  5. 在测试集上预测——生成样本外概率预测
  6. 汇总预测结果——拼接所有样本外结果
  7. 评估——准确率、精确率、召回率、F1、AUC、利润因子
快速训练示例
from xgboost import XGBClassifier

model = XGBClassifier(
    n_estimators=200,
    max_depth=4,
    learning_rate=0.05,
    subsample=0.8,
    colsample_bytree=0.8,
    eval_metric="logloss",
    use_label_encoder=False,
    random_state=42,
)

model.fit(
    X_train, y_train,
    eval_set=[(X_val, y_val)],
    verbose=False,
)

probabilities = model.predict_proba(X_test)[:, 1]

参见 references/model_guide.md,了解参数建议和调优方法。

SHAP 特征重要性

SHAP(SHapley Additive exPlanations)为理解模型预测提供了黄金标准。

全局特征重要性

哪些特征对所有预测最重要:

import shap

explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)

# Summary plot (top 15 features)
shap.summary_plot(shap_values, X_test, max_display=15)
局部解释

为什么会做出某个特定预测:

# Explain a single prediction
shap.force_plot(explainer.expected_value, shap_values[0], X_test.iloc[0])
时间特征重要性

跟踪特征重要性在滚动前向窗口中的变化。如果某个特征的重要性显著下降,市场状态可能已经发生变化。

阈值优化

默认的 0.5 概率阈值几乎从来都不是交易的最佳选择。

为什么不用 0.5?
  • 类别不平衡:如果 60% 的标签为“上涨”,0.5 的阈值就过于激进
  • 交易成本:边际信号(概率为 0.51)很少能覆盖交易成本
  • 收益不对称:交易中精确率比召回率更重要
针对盈利因子进行优化
def optimize_threshold(
    probabilities: np.ndarray,
    returns: np.ndarray,
    thresholds: np.ndarray | None = None,
) -> tuple[float, float]:
    """Find threshold that maximizes profit factor.

    Args:
        probabilities: Model predicted probabilities.
        returns: Actual forward returns.
        thresholds: Thresholds to search over.

    Returns:
        Tuple of (best_threshold, best_profit_factor).
    """
    if thresholds is None:
        thresholds = np.arange(0.50, 0.85, 0.01)
    best_threshold, best_pf = 0.5, 0.0
    for t in thresholds:
        signals = probabilities >= t
        if signals.sum() < 10:
            continue
        signal_returns = returns[signals]
        wins = signal_returns[signal_returns > 0].sum()
        losses = abs(signal_returns[signal_returns < 0].sum())
        pf = wins / losses if losses > 0 else 0.0
        if pf > best_pf:
            best_pf = pf
            best_threshold = t
    return best_threshold, best_pf

典型发现:加密货币交易信号的最佳阈值为 0.60-0.75。

加密货币特定注意事项

较短的训练窗口

加密货币市场状态变化迅速。使用 6 个月数据训练的模型,表现可能不如使用 30 天数据训练的模型。应使用较短的训练窗口并频繁重新训练。

类别不平衡

大多数时间段都处于“横盘”状态(收益在中性区间内)。以下是应对策略:

  • 舍弃中性区间:仅使用明确的上涨/下跌标签进行训练
  • 对多数类欠采样:在 XGBoost 中使用 scale_pos_weight
  • SMOTE:合成少数类过采样(谨慎使用——可能引入前视偏差)
  • 调整阈值:提高概率阈值以进行补偿
交易成本

准确率为 55% 的模型听起来不错,但扣除 0.5% 的往返交易成本(滑点 + 费用)后,许多信号都会变得无利可图。始终评估扣除成本后的信号:

net_return = gross_return - 0.005  # 50 bps round-trip
特征衰减

随着更多参与者发现并据此交易,特征会逐渐失去预测能力。监控滚动表现,并在指标退化时重新训练。

与其他技能集成

技能集成方式
feature-engineering计算分类器的输入特征
vectorbt根据 ML 信号回测交易策略
regime-detection为每种市场状态分别训练模型,或将市场状态作为特征
position-sizing根据分类器的置信度确定仓位规模
risk-management对 ML 生成的信号应用投资组合级风险限制

文件

参考资料
  • references/model_guide.md — XGBoost 和 LightGBM 参数指南、调优和集成
  • references/validation_methods.md — 滚动前向验证、净化交叉验证、CPCV 和评估指标
脚本
  • scripts/train_classifier.py — 使用滚动前向验证和特征重要性训练信号分类器
  • scripts/walk_forward_backtest.py — 使用滚动前向验证,对比回测 ML 信号与买入并持有策略

依赖项

# Core (required)
uv pip install pandas numpy scikit-learn

# Optional (recommended)
uv pip install xgboost lightgbm shap

要点总结

  1. 滚动前向验证不可或缺——随机交叉验证会严重夸大结果
  2. 针对盈利因子而非准确率优化阈值——高精确率、低召回率的模型优于高准确率模型
  3. 加密货币应使用较短的训练窗口——在大多数市场状态下,30 天优于 6 个月
  4. 监控特征衰减——滚动指标低于基准时重新训练
  5. 始终评估扣除成本后的表现——准确率为 55% 的模型扣除费用后可能无利可图
  6. 优先使用 SHAP,而非原始特征重要性——SHAP 提供一致且有理论依据的解释

评论

支持 Markdown