1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日経平均の終値を予測する #1

1
Last updated at Posted at 2026-04-17

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 設計の注意点

  1. 対象日 T は JPX 営業日 (大阪取引所の取引日)。8:40 JST 時点で観測可能 = 特徴量、15:30 JST の引けがターゲット。
  2. 特徴量に用いる CME データは必ず 前日 (T − 1 カレンダー) 以前。FX の 8:40 値は Yahoo 日足 Open (≈6:00 JST) を近似として採用し、保守的に扱う。
  3. pandas_market_calendarsJPX スケジュールで祝日休場を除外する。

4.2 モジュール

  • src/fetch_data.py: yfinance → data/raw/*.parquet (4 銘柄)
  • src/build_features.py: 上記生データを JPX 営業日でアライン → data/features.parquet

5. 探索的データ解析

5.1 夜間ギャップと日中変動の分解

当日 15:30 終値を 2 つの遷移に分解する。
image.png

各部分の 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_jstprev_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 に近い値を予測せよ」という同じ結論を異なる係数配分で表現している。
  • 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 結論

断念。以下を満たす安定的なデータソースが個人コスト (月数千円以内) の範囲で存在しない

  1. 日経先物 (OSE または CME) の分足 or ティックJST
  2. 8:30〜8:40 の 10 分をカバー
  3. 2 年以上の履歴(実際に運用するときは現在値をスクレイピングするだけでよいが、過去分析ができない)
  • 加えて、上記で示した日中変動 MAE 下限 281 pts は 8:40 時点情報で圧縮できない性質のもので、仮に夜間ギャップ側で 20〜30 pts 改善しても総合 MAE は 310 台までしか下がらない。
  • コスト対効果が明らかに悪いため、却下。

9. 結論と今後の課題

9.1 主な結論

  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...
1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?