去年の決算発表日、日本製鉄を保有していた。
前日の夜に「業績上方修正の噂」をどこかで読んで、そのまま寝た。翌朝起きたら-8%。噂は噂だった。
その後、「そもそも製造メーカー株の決算って、期待値的にプラスなんだろうか?」という疑問が頭から離れなくなった。Pythonで調べてみた。
分析対象と方法
対象:トヨタ自動車(7203)、日立製作所(6501)、三菱重工(7011)、日本製鉄(5401)の4銘柄。期間:2018〜2024年の全決算発表日。
測定指標は「決算発表翌日の始値〜翌々日の終値」の2日間リターン。
import pandas as pd
import numpy as np
def calc_earnings_return(prices_df, earnings_dates):
"""
決算発表翌営業日の寄りで買い、翌々営業日の引けで売る
2日間のリターンを計算する
"""
returns = []
dates = prices_df.index.tolist()
for ed in earnings_dates:
try:
idx = dates.index(ed)
if idx + 3 >= len(dates):
continue
entry_open = prices_df.iloc[idx + 1]["Open"] # 翌営業日寄り
exit_close = prices_df.iloc[idx + 2]["Close"] # 翌々日引け
ret = exit_close / entry_open - 1
returns.append({"earnings_date": ed, "return": ret})
except (ValueError, IndexError):
continue
return pd.DataFrame(returns)
# 各銘柄で実行
for ticker, dates in earnings_calendar.items():
result = calc_earnings_return(price_data[ticker], dates)
print(f"{ticker}: 平均{result['return'].mean()*100:.2f}% "
f"勝率{(result['return']>0).mean()*100:.1f}% "
f"n={len(result)}")
結果:決算ギャンブルは期待値マイナスだった
4銘柄の平均を取ると、こんな結果になった。
- 平均リターン:-0.4%(手数料・スリッページ込みだと-0.8%程度)
- 勝率:48%(ランダムとほぼ同じ)
- 最大損失:日本製鉄2021年2月 -12.3%
- 最大利益:三菱重工2023年11月 +9.1%
ランダムウォークとほぼ区別がつかない、というのが正直な結果だ。「決算前に噂で買い、発表で売り」という古典的な手法も同様に検証したが、期待値はほぼゼロだった。
じゃあ決算をどう扱うか
逆に有効だったのは決算をリスク回避に使う考え方だ。
def has_earnings_soon(code, date, earnings_calendar, days_ahead=5):
"""
date から days_ahead 営業日以内に決算発表があれば True を返す
(エントリーフィルタとして使用)
"""
upcoming = earnings_calendar.get(code, [])
business_days_ahead = pd.bdate_range(date, periods=days_ahead)
return any(ed in business_days_ahead for ed in upcoming)
# シグナル生成時にフィルタをかける
if entry_signal(row) and not has_earnings_soon(code, today, earnings_cal):
execute_entry(code, today)
決算が近い銘柄へのエントリーを除外するだけで、バックテストのシャープレシオが約0.3改善した。「儲けようとするのではなく、余計なリスクを避ける」という方向で決算情報を使う方が、僕の戦略には合っていた。
まとめ
日本製鉄-8%の教訓は「決算前に感情でポジションを持つな」だった。Pythonで定量化したことで、感情的な判断を減らせるようになった。
次は決算発表後のボラ収縮パターンを利用した戦略を試してみる予定だ(いわゆるガンマスクイーズの株版)。
