signal-classification について
将来の期間における資産価格の方向を予測する、教師あり分類器の構築スキルです。ラベル作成、時系列検証、モデル解釈、取引向けの閾値調整を扱います。
主な機能
- 01二値・多クラスのラベル作成
- 02ウォークフォワード検証
- 03XGBoost・LightGBMの学習
- 04SHAPによる特徴分析
- 05プロフィットファクターに基づく閾値調整
活用シーン
- 01データ漏洩を避けて価格方向シグナルを検証
- 02予測に影響する特徴量を調査
- 03取引シグナルの確率閾値を選定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ agiprolabs/ claude-trading-skills --skill signal-classificationインストール後、Claude Code で/signal-classificationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/model_guide.mdvalidation_methods.mdscripts/train_classifier.pywalk_forward_backtest.py詳細
シグナル分類
教師あり機械学習分類器を使って、先行期間における資産価格の上昇または下落を予測します。このスキルでは、ラベル作成、モデルのトレーニング、ウォークフォワード検証、特徴量重要度の分析、取引アプリケーション向けの閾値最適化まで、パイプライン全体を扱います。
ツリーベースモデルが取引MLで主流である理由
XGBoostとLightGBMが定量取引MLの主力であるのには、十分な理由があります。
- 非線形の関係:金融特徴量は複雑に相互作用します。ツリーはこうした非線形の関係を自然に捉えます
- 特徴量のスケールに頑健:入力の正規化や標準化は不要です。ツリーは順位に基づいて分割します
- 特徴量重要度を内蔵:別途分析しなくても、どの特徴量が予測を左右するかを把握できます
- 高速なトレーニングと推論:数千サンプルを数秒でトレーニングし、数マイクロ秒で予測できます
- 欠損値に対応:補完のための小細工なしで、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
多クラス分類
シグナルをより細かくするための3クラス分類です。
| クラス | 条件 | 一般的な閾値 |
|---|---|---|
| 強い上昇 | 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スケーリングよりアイソトニック・キャリブレーションのほうが適しています。
ウォークフォワード検証
**これは取引MLにおいて、最も重要な概念です。**標準的な交差検証ではデータをランダムにシャッフルするため、先読みバイアスが生じます。ウォークフォワード検証では、時間順序を維持します。
仕組み
Window 1: [===TRAIN===][GAP][=TEST=]
Window 2: [===TRAIN===][GAP][=TEST=]
Window 3: [===TRAIN===][GAP][=TEST=]
Window 4: [===TRAIN===][GAP][=TEST=]
各ウィンドウで、以下を行います。
- 過去のN本のバーでトレーニングします
- 先行リターンの期間と同じ長さのギャップ(エンバーゴ)を空けます
- 次のM本のバーを予測します
- アウトオブサンプル予測を記録します
- 期間を先に進めて繰り返します
一般的なパラメーター
| パラメーター | 値 | 理由 |
|---|---|---|
| トレーニングウィンドウ | 30日(720時間足バー) | 学習に十分なデータ量があり、関連性を保てるほど最近のデータです |
| テストウィンドウ | 7日(168時間足バー) | 統計的有意性を得るのに十分な予測数です |
| ステップ幅 | 1日(24本のバー) | テストウィンドウを重ねて、より多くのデータポイントを得ます |
| ギャップ(エンバーゴ) | 先行期間と同じ | ラベルリークを防ぎます |
ウォークフォワードの実装
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
パージ付きCV、CPCV、評価指標については、references/validation_methods.mdを参照してください。
モデルのトレーニングパイプライン
パイプライン全体の概要
- 特徴量エンジニアリング — テクニカル指標、オンチェーン指標、出来高特徴量を計算します(
feature-engineeringスキルを参照) - ラベル作成 — 閾値を用いて先行リターンを計算し、中立ゾーンを除外します
- ウォークフォワード分割 — 時間順に並べたギャップ付きのトレーニング/テストウィンドウを作成します
- モデルのトレーニング — 各トレーニングウィンドウでXGBoostまたはLightGBMを使用します
- テストデータの予測 — アウトオブサンプルの確率予測を生成します
- 予測の集約 — すべてのアウトオブサンプル結果を連結します
- 評価 — 正解率、適合率、再現率、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— ウォークフォワード、パージド CV、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
主なポイント
- ウォークフォワード検証は必須です — ランダム CV では結果が大幅に過大評価されます
- 精度ではなく、プロフィットファクターを基準に閾値を最適化します — 適合率が高く再現率が低いモデルは、精度が高いモデルより優れています
- 暗号資産では学習期間を短くします — ほとんどのレジームで、6 か月より 30 日のほうが有効です
- 特徴量の劣化を監視します — ローリング指標がベースラインを下回ったら再学習します
- 必ずコスト控除後で評価します — 精度 55% のモデルでも、手数料を差し引くと採算割れする可能性があります
- 生の特徴量重要度より SHAP を使います — SHAP は一貫性があり、理論的根拠に基づいた説明を提供します