botter界隈ではおなじみの『ファイナンス機械学習―金融市場分析を変える機械学習アルゴリズムの理論と実践』が枕になってしまっていたので、久々に格闘しながら金融時系列分析の練習をしました。
ファイナンス機械学習―金融市場分析を変える機械学習アルゴリズムの理論と実践
マルコス・ロペス・デ・プラド (著), 長尾 慎太郎 (監修, 翻訳)
↓お世話になったサイト
1. 背景・問い・動機
1.1 今回の背景・問い
個人的な興味で、以下の問いを立て、分析を行った。
JST 8:40 時点で観測可能な公開情報のみから、当日の日経平均 15:30 終値をどの程度の精度(絶対誤差:円)で予測できるか。
そしてその予測を、毎営業日の朝に自動でメール配信し、通知を行うシステムとして運用可能か。
1.2 動機
- 東京市場の現物寄り付きは 9:00 JST。その直前の8:40時点で当日の終値を予測したい。
- 広く知られる「CME 先物 ≒ 翌日の日経」というラフな経験則を正しく定量化し、それを上回れる線形・非線形モデルがあるかを確かめたい。
1.3 予測値の評価の観点・前提
| 指標 | 定義 | 何を意味するか |
|---|---|---|
| MAE | 平均絶対誤差 (pts) | 水準感 (値幅) |
| MAPE | 平均絶対百分率誤差 (%) | 非定常な価格レンジに頑健 |
| 前日比方向的中率 | sign(pred - prev) と sign(actual - prev) の一致率 | シグナルの向き |
| 寄り付き対比方向的中率 | sign(pred - open) と sign(actual - open) の一致率 | 日中の価格の上下 |
| DM (Diebold-Mariano) 検定 | 予測誤差系列の有意差 | ベースラインに勝っているか |
1.4 成功基準を決める
- 最低ライン: MAE ≈ ベースラインを下回ること
- 望ましいライン: MAE を 10% 以上改善、かつ DM 検定で p < 0.05
結論を先に述べると、望ましいラインはもちろん、最低ラインも達成できなかった。
その事実を定量的・定性的に検証する。
2. 制約に関するリサーチ
2.1 日経平均先物市場の構造
日経平均先物は複数の取引所で上場しており、時間帯によって支配的な価格発見者が変わる。
| 取引所 | 銘柄 | 通貨 | 取引時間 (JST) |
|---|---|---|---|
| 大阪取引所 (OSE) | 日経225先物 / 日経225mini future | JPY | 8:45-15:15 / 16:30-翌 6:00 |
| シンガポール (SGX) | SGX Nikkei 225 | JPY / USD | 7:30-翌 5:15 頃 |
| CME Globex (米) | NKD (USD), NIY (JPY) | USD / JPY | 17:00-翌 16:00 CT |
- JST 8:40 時点で既にクローズ済みの銘柄は CME 前日分。
- SGX と OSE 夜間は 8:40 時点でも動いているが、今回は、無料で日足以上の粒度が安定入手できるデータソースとして CME (NKD=F on Yahoo Finance) を採用した。(これらを利用することでパフォーマンスが改善するかどうかは今後の検討課題。)
2.3 2024-11-05 からの引け時刻の延長
- 東京証券取引所の現物セッションは 2024-11-05 から引け時刻が 15:00から15:30 に 30 分延長された。これは予測ターゲットの定義そのものを変える構造変化である。
- これに注意し、今回は、
close_is_1530フラグ特徴量を追加し、モデルが構造変化を学習できるようにした。 - 評価では post-2024-11-05 期間 (
close_is_1530 = True) のサブセットを別途集計して分析を行った。
3. データと特徴量
3.1 生データ
すべて Yahoo Finance (yfinance) から取得。
| ティッカー | 意味 | 期間 | 備考 |
|---|---|---|---|
^N225 |
日経平均現物 | 2023-04-03 〜 2026-04-17 | ターゲット / 前日 Close |
NKD=F |
CME Nikkei USD先物 | 同上 | 主 CME 系列 (流動性高) |
NIY=F |
CME Nikkei JPY先物 | 同上 | Volume=0 が 398/765 日、参考のみ |
JPY=X |
USDJPY | 同上 | 8:40 近似に Open を使用 |
3.2 特徴量テーブル
744 行 × 21 列。JPX 営業日でアラインし、8:40 時点で観測可能な列のみを特徴量化した。
| 列名 | 時点/出典 | 種類 |
|---|---|---|
cme_close_prev_7am_jst |
CME NKD=F 前日 Close (JST 6:00 着) | 特徴量 (主) |
usdjpy_approx_840 |
JPY=X 当日 Open (≈6:00 JST) | 特徴量 |
usdjpy_prev_close_5pmnyc |
JPY=X 前日 Close | 特徴量 |
fx_chg |
usdjpy_approx_840 − usdjpy_prev_close |
派生 |
prev_n225_close_1530 |
^N225 直前 JPX 営業日 Close | 特徴量 |
basis_prev |
prev_n225_close − cme_close_prev |
派生 |
cme_signal |
cme_close_prev − prev_n225_close |
派生 |
close_is_1530 |
≥ 2024-11-05 フラグ | 構造 |
is_sq |
第 2 金曜日 (SQ) | カレンダー |
is_post_holiday |
前営業日との暦日差 ≥ 3 | カレンダー |
dow, month
|
曜日, 月 | カレンダー |
nikkei_close_1530 |
^N225 当日 Close | ターゲット |
n225_open_900 |
^N225 当日 Open | 評価補助 |
4. データパイプライン
4.1 設計の注意点
- 対象日 T は JPX 営業日 (大阪取引所の取引日)。8:40 JST 時点で観測可能 = 特徴量、15:30 JST の引けがターゲット。
- 特徴量に用いる CME データは必ず 前日 (T − 1 カレンダー) 以前。FX の 8:40 値は Yahoo 日足 Open (≈6:00 JST) を近似として採用し、保守的に扱う。
-
pandas_market_calendarsのJPXスケジュールで祝日休場を除外する。
4.2 モジュール
-
src/fetch_data.py: yfinance →data/raw/*.parquet(4 銘柄) -
src/build_features.py: 上記生データを JPX 営業日でアライン →data/features.parquet
5. 探索的データ解析
5.1 夜間ギャップと日中変動の分解
各部分の MAE は以下のようになった。
| レッグ | MAE (pts) | 何を意味するか |
|---|---|---|
| CME → N225 Open (夜間ギャップ) | 161 | CME が既にほぼ織り込み済み |
| N225 Open → Close (日中変動) | 281 | 寄り付き情報があってもこれ以下にはならない |
| CME → N225 Close (合成) | 302 | 両者の和に近い (≠ sqrt(sum of sq)) |
- これが今回の検討の出発点であり、同時にゴールも定めた。
- 8:40 時点特徴量で圧縮可能な余地は理論上 MAE で 20〜30 ptsに過ぎない (302 − 281 = 21)。
5.2 共線性と多重共線性
相関と VIF を算出すると、
-
cme_close_prev_7am_jstとprev_n225_close_1530の相関は 0.999+ -
basis_prev = prev_n225 − cmeの VIF は ∞ (上 2 列の線形結合そのもの) -
cme_signal = cme − prev_n225も同様に冗長
掲)。
5.3 構造変化前後でのベース MAE 比較
baseline_cme の MAE を構造変化 (2024-11-05) で分割すると、
| 期間 | 営業日数 | MAE |
|---|---|---|
| pre (15:00 引け) | 約 400 | 小さめ |
| post (15:30 引け) | 約 344 | 大きめ (価格水準が上昇) |
- 日経平均は日々価格が押し上がっており、価格水準が非定常 なので、MAEも膨張してしまう。(2023: 30k 台 → 2026: 60k 近傍)
- なので、MAPE でも評価する必要がある。
6. モデル構築と評価
6.1 モデル群
Pythonで9モデルを実装した。
| モデル | 損失 | 備考 |
|---|---|---|
baseline_cme |
— | 素朴 (予測 = cme_close_prev_7am_jst) |
quantile_regression |
L1 (q=0.5) | sklearn QuantileRegressor, HIGS ソルバー |
ridge |
L2, α=10 | |
lasso |
L1, α=1 | |
lightgbm_l1 |
L1 | 15 leaves, lr=0.05, 200 rounds |
ensemble_qr_lgbm |
— | QR と LGBM の単純平均 |
qr_delta |
L1 | ターゲットを close − cme_prev に差分化 |
lightgbm_l1_delta |
L1 | 同上 |
ensemble_delta |
— |
qr_delta + lightgbm_l1_delta / 2 |
- 差分予測版 (
_delta) は 6.5 で説明する tree モデルの外挿破綻への対応。
6.2 Walk-forward 交差検証の設計
- 訓練窓: 252 営業日 (約 1 年)
- 検証窓: 63 営業日 (約 3 ヶ月)
- スライド幅: 21 営業日 (約 1 ヶ月)
- 結果: 21 ウィンドウ 生成、うち 14 ウィンドウは val が全期間 post-2024-11-05
- 共通検証日数: 483 日 (2024-04-12 〜 2026-04-06)
6.3 Diebold-Mariano 検定
各モデルの予測誤差系列 $e_{m,t}$ と baseline の誤差系列 $e_{\text{base},t}$ の差
$d_t = |e_{m,t}| − |e_{\text{base},t}|$ を対象に DM 検定をした。
- 自己相関を考慮した HLN 小標本補正を適用
- 帰無仮説 $H_0: \mathbb{E}[d_t] = 0$ (両側検定, 有意水準 5%)
6.4 結果 (定量)
共通 483 日 (post は 344 日) で評価した集計は以下の通り。
| モデル | MAE_all | MAE_post | MAPE_post | hit_prev | win_MAE_std | DM p_post |
|---|---|---|---|---|---|---|
| baseline_cme (採用) | 341.6 | 342.1 | 0.77% | 0.725 | 119.3 | — |
| ridge | 348.2 | 351.7 | 0.80% | 0.725 | 125.5 | 0.148 |
| lasso | 348.9 | 352.6 | 0.80% | 0.729 | 124.9 | 0.120 |
| ensemble_delta | 348.0 | 351.8 | 0.80% | 0.704 | 131.2 | 0.253 |
| lightgbm_l1_delta | 354.9 | 360.1 | 0.81% | 0.681 | 128.5 | 0.025 ★ |
| quantile_regression | 357.1 | 365.2 | 0.83% | 0.718 | 132.3 | 0.028 ★ |
| qr_delta | 357.1 | 365.2 | 0.83% | 0.718 | 132.3 | 0.028 ★ |
| lightgbm_l1 (level) | 1779.6 | 2268.2 | 4.70% | 0.555 | 1881.5 | 0.000 × |
| ensemble_qr_lgbm (level) | 994.6 | 1228.7 | 2.59% | 0.598 | 907.8 | 0.000 × |
★ = baseline に対し 有意に負けている (p < 0.05)
× = tree モデルのレベル外挿破綻 (6.5 節)
- baseline を上回ったモデルは 0 個。Ridge / Lasso / Ensemble_delta は 6-10 pts 劣化するが、DM 有意差なしで実用上は同等だが僅かに悪い。
- QR と LightGBM_delta は有意に baseline に負けた。
6.5 Tree モデルの外挿破綻と差分予測化
-
lightgbm_l1(レベル予測) の MAE_post は 2268 pts と壊滅的だった。 -
原因?:
- 学習期間 (2023-2025) の日経価格レンジ: 27,000 〜 42,000
- 検証期間後半 (2026) の日経価格レンジ: 52,000 〜 60,000 (完全に学習範囲外)
- 決定木は学習データ外の入力に外挿できない → 近傍のリーフ値を返し続ける
-
対応として目的変数を
close − cme_close_prev(差分) に変換したlightgbm_l1_deltaを追加。 -
差分は定常に近い分布 (中央値 ≈ 0, ±500 pts) なので、外挿問題を回避できる。MAE は2268 → 360に改善し正常な範囲に戻ったが、それでも baseline を超えることはなかった。
-
「非定常な価格系列に対して tree モデルをレベル予測で使ってはならない」という教科書的な教訓の実例といえる。
6.6 線形モデルの係数解釈
全期間学習での係数は以下の通り。
| 特徴量 | QR | Ridge | Lasso |
|---|---|---|---|
cme_close_prev_7am_jst |
0.000 | 0.587 | 0.995 |
prev_n225_close_1530 |
0.993 | 0.409 | 0.000 |
cme_signal |
0.864 | 0.178 | -0.000 |
basis_prev |
0.000 | -0.178 | 0.051 |
usdjpy_approx_840 |
0.936 | -0.233 | -0.141 |
fx_chg |
13.21 | 26.21 | 25.57 |
close_is_1530 |
10.09 | -1.87 | 0.000 |
is_sq |
-18.39 | -30.16 | -16.45 |
is_post_holiday |
+55.12 | -10.21 | -3.62 |
dow |
16.13 | 8.92 | 9.16 |
month |
-1.90 | -0.52 | -0.42 |
読み取れることは...
- CME と prev_N225 は多重共線
- QR は
prev_N225×0.993 + cme_signal×0.864で CME を間接表現。 - Lasso は逆に
CME×0.995 + prev_N225×0を選択。どちらも「CME に近い値を予測せよ」という同じ結論を異なる係数配分で表現している。
- QR は
- FX 変化の係数が大きい (13-26)
- 8:40 時点の USDJPY 変化 1 円 = 日経 +13〜26 pts 期待。
- SQ 係数が負 (−18 〜 −30)
- SQ 日はわずかに下振れ傾向。
- 祝日明け係数が QR で +55
- 祝日明けは上振れ傾向 (QR のみ強く検出)。
- basis_prev はほぼ 0
- 予測力なし。VIF=∞ を踏まえると納得の結果。
6.7 失敗ケース (worst-10) の定性分析
baseline の worst-10 は全て市場ショック由来?
| 日付 | 実績 | 予測 | 誤差 | イベント |
|---|---|---|---|---|
| 2024-08-05 | 31458 | 35020 | -3562 | 令和ブラックマンデー |
| 2025-10-06 | 47945 | 46100 | +1845 | 祝日明け急騰 |
| 2026-04-02 | 52463 | 54250 | -1787 | 関税ショック |
| 2025-07-23 | 41171 | 39655 | +1516 | — |
| 2026-03-03 | 56279 | 57710 | -1431 | — |
| 2024-08-07 | 35090 | 33720 | +1370 | 8/5 暴落後反発 |
| 2024-08-06 | 34676 | 33320 | +1356 | 同上 |
| 2025-04-03 | 34736 | 36085 | -1349 | 関税ショック (春) |
| 2026-03-25 | 53750 | 52455 | +1295 | — |
| 2026-03-09 | 52729 | 54020 | -1291 | 祝日明け (月曜) |
- これらは他のどのモデルでも同じように外れる。機械学習は過去に似たパターンがないと学習できない。
- 8:40 時点の公開情報に「今日の暴落」を予告する情報は含まれていない (含まれていたら裁定で消える)。ので、予測自体が無意味で諦めるしか無い。
7. 高頻度データ取得計画の断念
上記の結果を受け、「夜間ギャップのノイズ層を減らせれば MAE は押し下がるのでは」という仮説から、分足データの導入を検討した。
7.1 期待していた情報源と実態
| 候補 | 期待 | 実態 |
|---|---|---|
| yfinance 5 分足 | 過去 60 日だけでも使える | 先物 (NKD=F) に対して空が返る日が多い |
| J-Quants 有料 | OSE 先物の分足 | 先物商品は別途契約、月額が個人コストを超える |
| SGX 公式 | 夜間 SGX Nikkei | API 非公開、データは再販契約経由 |
| Bloomberg / Reuters | 全て入手可 | 個人契約不可 |
7.2 結論
断念。以下を満たす安定的なデータソースが個人コスト (月数千円以内) の範囲で存在しない
- 日経先物 (OSE または CME) の分足 or ティックJST
- 8:30〜8:40 の 10 分をカバー
- 2 年以上の履歴(実際に運用するときは現在値をスクレイピングするだけでよいが、過去分析ができない)
- 加えて、上記で示した日中変動 MAE 下限 281 pts は 8:40 時点情報で圧縮できない性質のもので、仮に夜間ギャップ側で 20〜30 pts 改善しても総合 MAE は 310 台までしか下がらない。
- コスト対効果が明らかに悪いため、却下。
9. 結論と今後の課題
9.1 主な結論
- 「予測 = CME NKD=F 前日 Close」いう素朴ベースラインは、8:40 時点の公開情報ベースでは有意に改善できない。つまり、CMEの6:00 Closeの値をそのまま予測値にするのがベストというなんともつまらない結果に。
→営業日483日の平均絶対誤差は約342円。
2. この不可能性は恣意的な制約ではなく、EDA で分解した日中変動 MAE 下限 (281 pts) に由来する構造的な予測限界である。8:40 時点情報で改善余地がある層 (夜間ギャップ) はせいぜい 20 pts で、学習ノイズに埋もれる。
3. Tree モデルをレベル予測で非定常価格に使ってはならないという教科書的教訓を、MAE 2268 pts という具体数値で再確認した。差分化で 360 pts まで回復するが、それでも baseline を超えない。
9.2 考察
朝 8:40 時点で当日 15:30 終値を予測するタスクでは、CME NKD=F の 6:00 close をそのまま使うのが理論的にも経験的にもほぼ最適。
- ニュース・米株・為替を追加特徴量にしてもほとんど意味がない。
- CME の日経 225 先物 (NKD=F) は 24h 近く取引されていて、6:00 JST の close 価格は、プロの先物トレーダーの取引によって、そこまでに公表されている全情報を織り込んでいる。
- つまり、「米株・為替・ニュースから日経を予測したい」と思ったとき、後から同じ情報を別ルートで足しても、ダブルカウントか相関ノイズにしかならない。
MAE 342 pts はどこから来ている?
予測誤差 ≈ 342 pts (post-2024-11-05)
├─ CMEと現物開の小さな乖離 (~50-80 pts): 6:00→9:00 の情報更新
└─ 寄り→引けの純粋な日中変動 (~281 pts): 8:40 時点で原理的に不可知
- 281 pts は8:40 時点でどんな情報を全部使っても下げられない下限。昼休みの流れ・外人買い・午後のフラッシュニュース・15:30 直前の注文流入etc...これらは 8:40 には存在しないため予測不能。
- 342 − 281 = 61 ptsが、8:40 時点の観測情報で原理的に攻められる最大値。上記で検証した全モデルがここに食い込めなかった。この 61 pts は、サンプル数 (数年分) と特徴量の S/N 比では統計的に抽出不可能なほど小さい、ということ。
でも為替とかの指標や一部の日経先物が 6:00 から 8:40 で動くのでは?
動くが...
- 為替変動自体も CME 先物トレーダが見ていて、6:00 以降の先物価格ムーブ (GLOBEX で続いてる) に織り込まれる
- 為替 → 日経の感応度は確かに存在するが、日中ノイズに比べて小さすぎて係数推定が不安定
「ニュースから上下を予測」は意味ない?
程度問題。
- 定性的に大きい材料 (BoJ 決定会合・米雇用統計ショック等) はすでに CME が織り込む。
- 定性的に拾える小さい材料 (個別銘柄決算の地合い波及等) は CME にまだ入り切ってないかもだが、堅牢な予測ロジックを定量的に検討するのはあまりにも困難な上、理論的にも20pts程度しか改善余地がないと思われる。
- そもそも「方向的中率 72.5%」はすでにかなり高く、baselineだけで十分意義がある。
- 8:40 時点で終値の絶対誤差を最小化したいなら、CME 6:00 close をそのまま答えるのが正解と思われる。
- これは「機械学習を頑張ってない」のではなく、プロの先物トレーダ市場が既に機械学習より賢く最適化した答えを 6:00 に提出しているので、それを借用するのが合理的という話。
さらなる精度改善の仮説
- 先物固有の性質を考慮して、年 4 日のロールオーバーと年 2 日の配当落ち直後だけ、補正する価値が一応ある。が、堅牢な予測になるかどうか、労力対効果が合うかは疑問。
- 他の先物との比較や平均を取るようなアプローチは検討の余地が一定ある。が、流動性が低かったり、安定的なアクセスが可能かどうかの懸念があり、CMEより優先的に利用するべきかどうかは疑問。
- Hyperliquid JP225
- SGX
- etc...
