0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【株価推定】HPフィルタ+ハイブリッド推定による株価モンテカルロシミュレーション

Last updated at Posted at 2025-08-31

研究ノート: HPフィルタ+ハイブリッド推定による株価モンテカルロシミュレーション

1. 研究目的

株価の将来予測においては、ノイズを含む生データをそのまま使うのではなく、トレンド成分とサイクル成分を分離して解析することで、より滑らかな推定が可能となる。本研究では、HPフィルタ (Hodrick–Prescott Filter) を用いて株価の分解を行い、そのうえでハイブリッド推定によるパラメータ (μ, σ) を算出し、モンテカルロシミュレーションにより将来の価格分布を推定する。

2. データ処理

2.1 株価データの取得

Yahoo Finance から任意の銘柄 (例: JMIA) の株価終値を取得する。

getdata.py
ticker = "JMIA"
start = "2024-01-01"
end   = "2025-09-01"
data = yf.download(ticker, start=start, end=end)
prices_ = data["Close"]

2.2 HPフィルタによる分解

HPフィルタを適用し、株価をトレンド (prices) と循環成分 (cycle) に分解する。
これにより、短期的なノイズを除去し、長期的な動きをより明確に捉えることができる。

decompose.py
cycle, prices = sm.tsa.filters.hpfilter(prices_, 10)

2.3 リターン計算

対数リターンを計算する。

returns: HPフィルタ後の価格に基づくリターン

returns_c: サイクル成分に基づくリターン

return.py
returns = np.log(prices / prices.shift(1))
# returns_c = np.log(cycle / cycle.shift(1))

3. ハイブリッド推定 (μ, σ)

株価シミュレーションにはリターンの平均と分散 (μ, σ) が必要である。
本研究では、異なる期間を用いて平均とボラティリティを推定する「ハイブリッド推定」を採用する。

hybrid_params.py
def hybrid_params(returns, vol_window=21, mean_window=126):
    vol = returns[-vol_window:].std()   # 短期ボラティリティ
    mu  = returns[-mean_window:].mean() # 中期リターン
    return mu, vol


vol_window (: 21)  直近のボラティリティ (1か月相当)

mean_window (: 63)  より長期の平均リターン (四半期相当)

4. モンテカルロシミュレーション

モンテカルロ法を用いて、株価の将来分布を生成する。
予測期間 horizon を変えることで、翌日〜数か月先の分布を評価可能。

montecarlo.py
def monte_carlo(prices, mu, vol, horizon=1, n_sims=10000):
    S0 = prices.iloc[-1]
    sims = np.zeros(n_sims)
    
    for i in range(n_sims):
        rand_returns = np.random.normal(mu, vol, horizon)
        sims[i] = S0 * np.prod(1 + rand_returns)
        
    return sims

入力: 現在価格、推定された μ と σ

出力: 将来の株価シミュレーション結果 (多数のサンプル)

5. 実行と結果

5.1 シナリオ設定

以下の複数の予測期間を設定する。

senarios.py
scenarios = {
    "1d": 1,
    "1w": 5,
    "1m": 21,
    "2m": 42,
    "3m": 63,
    "4m": 84,
}

5.2 結果の描画

ヒストグラム → 価格分布を可視化

赤線 → 現在価格

青線 → 各シナリオの中央値

plot.py
plt.axvline(prices_.iloc[-1].squeeze(), color="red", linestyle="--", label="現在価格")
plt.legend()
plt.xlim(0,50)
plt.title(f"{ticker} Monte Carloシミュレーション")

5.3 出力例

現在価格 : 15.20

--- 1d --- 15.25
--- 1w --- 15.60
--- 1m --- 16.80
--- 3m --- 20.50

6. 考察

本コードは「HPフィルタによるトレンド抽出 × ハイブリッド推定 × モンテカルロ法」を組み合わせた実験的アプローチです。
投資家にとっては、複数シナリオ下での将来株価分布を確率的に理解するためのツールとして活用できます。

HPフィルタを導入した意義

短期的なノイズを抑えつつ、トレンドに基づいた安定的な推定が可能。

ハイブリッド推定の効果

ボラティリティは直近の変動を反映、平均リターンはより長期の傾向を反映 → 市場環境の変化を早期に捕捉できる。

モンテカルロの結果

将来の株価は確率分布として提示され、投資判断の不確実性を定量的に把握できる。

7. 今後の展開

μ, σ の時系列推移をリアルタイムで可視化
サイクル成分に基づくリスク調整モデルの導入
シナリオ分析 (金利上昇局面、ボラティリティ急増局面)

具体例

$JMIA 大

JMIA
JMIA.
現在価格    : 8.60
--- 1d --- 8.74
--- 1w --- 9.31
--- 1m --- 12.04
--- 2m --- 16.77
--- 3m --- 23.43
--- 4m --- 32.85

jmia_1d-4m.png

$SOFI 大

SOFI
SOFI.
現在価格    : 25.54
--- 1d --- 25.81
--- 1w --- 26.91
--- 1m --- 31.80
--- 2m --- 39.59
--- 3m --- 49.28
--- 4m --- 61.36

sofi_1d-4m.png

$HIMS 低

HIMS
HIMS.
現在価格    : 42.35
--- 1d --- 42.20
--- 1w --- 41.59
--- 1m --- 39.26
--- 2m --- 36.44
--- 3m --- 33.70
--- 4m --- 31.18

hims_1d-4m.png

$APP 小

APP
APP.
現在価格    : 478.59
--- 1d --- 480.23
--- 1w --- 486.46
--- 1m --- 512.86
--- 2m --- 548.80
--- 3m --- 586.80
--- 4m --- 628.81

app_1d-4m.png

$OPEN 大

OPEN
現在価格    : 4.45
--- 1d --- 4.59
--- 1w --- 5.17
--- 1m --- 8.35
--- 2m --- 15.72
--- 3m --- 29.40
--- 4m --- 55.51

open_1d-4m.png

$IREN 大

IREN
IREN.
現在価格    : 26.48
--- 1d --- 26.92
--- 1w --- 28.77
--- 1m --- 37.53
--- 2m --- 53.21
--- 3m --- 75.64
--- 4m --- 106.99

iren_1d-4m.png

$RKLB 大

RKLB
RKLB.
現在価格    : 48.60
--- 1d --- 49.05
--- 1w --- 50.88
--- 1m --- 58.93
--- 2m --- 71.43
--- 3m --- 86.47
--- 4m --- 105.13

rklb_1d-4m.png

$AFRM 大

AFRM
AFRM.
現在価格    : 88.46
--- 1d --- 89.14
--- 1w --- 91.90
--- 1m --- 103.83
--- 2m --- 121.83
--- 3m --- 142.79
--- 4m --- 168.01

afrm_1d-4m.png

$OKLO 小

OKLO
OKLO.
現在価格    : 73.64
--- 1d --- 74.08
--- 1w --- 75.87
--- 1m --- 83.45
--- 2m --- 94.52
--- 3m --- 106.87
--- 4m --- 121.55

oklo_1d-4m.png

$NBIS 小

NBIS
NBIS.
現在価格    : 68.32
--- 1d --- 68.99
--- 1w --- 71.73
--- 1m --- 83.80
--- 2m --- 102.71
--- 3m --- 125.61
--- 4m --- 154.80

nbis_1d-4m.png

$TEM 小

TEM
TEM.
現在価格    : 75.86
--- 1d --- 76.15
--- 1w --- 77.36
--- 1m --- 82.33
--- 2m --- 89.30
--- 3m --- 96.68
--- 4m --- 105.35

tem_1d-4m.png

コード全体

サンプルコード
whole.py
import numpy as np
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
import japanize_matplotlib  # 日本語表示用
import statsmodels.api as sm

# ==============================
# 設定
# ==============================
ticker = "IREN"       # 銘柄コード JMIA SOFI OPEN IREN HIMS APP
start = "2024-01-01"  # データ取得開始日
end   = "2025-09-01"  # データ取得終了日
n_sims = 10000        # シミュレーション回数

# データ取得
data = yf.download(ticker, start=start, end=end)
prices_ = data["Close"]

cycle, prices = sm.tsa.filters.hpfilter(prices_, 10)
# 日次リターン
#returns = prices.pct_change().dropna()
returns = np.log(prices / prices.shift(1))
returns_c = np.log(cycle / cycle.shift(1))
print(cycle)
# ==============================
# ハイブリッド推定関数
# ==============================
def hybrid_params(returns, vol_window=21, mean_window=126):
    """
    vol_window : ボラティリティを計算する日数 (例: 21営業日 ≒ 1か月)
    mean_window: 平均リターンを計算する日数 (例: 252営業日 ≒ 1年)
    """
    #vol = returns_c[-vol_window:].std()
    vol = returns[-vol_window:].std()
    mu  = returns[-mean_window:].mean()
#    mu = returns.mean() * 252  # 年率換算 (252営業日)
#    vol = returns.std() * np.sqrt(252)  # 年率換算
    return mu, vol

# ==============================
# Monte Carloシミュレーション関数
# ==============================
def monte_carlo(prices, mu, vol, horizon=1, n_sims=10000):
    """
    horizon : 予測する営業日数
              1 = 翌日
              5 = 翌週
              21= 翌月
    """
    S0 = prices.iloc[-1] #[-1]
    sims = np.zeros(n_sims)
    
    for i in range(n_sims):
        rand_returns = np.random.normal(mu, vol, horizon)
        sims[i] = S0 * np.prod(1 + rand_returns)
        
    return sims

# ==============================
# 実行
# ==============================
mu, vol = hybrid_params(returns, vol_window=21, mean_window=63) #18 21 #252 126 504 63

scenarios = {
    "1d": 1,
    "1w": 5,
    "1m": 21,
    "2m": 42,
    "3m": 63,
    "4m": 84,
}

results = {}
for label, horizon in scenarios.items():
    sims = monte_carlo(prices_, mu, vol, horizon, n_sims=n_sims)
    results[label] = sims
    
    # 分布表示
    plt.hist(sims, bins=100, alpha=0.6, label=label)

plt.axvline(prices_.iloc[-1].squeeze(), color="red", linestyle="--", label="現在価格")
plt.legend()
#plt.xlim(0,75)
plt.title(f"{ticker} Monte Carloシミュレーション")
#plt.show()

# 結果例: 平均・中央値・下位5%信頼区間
print(f"現在価格    : {prices_.iloc[-1].squeeze():.2f}")
for label, sims in results.items():
    plt.axvline(np.median(sims), color="blue", linestyle="--", label="中央値")
    print(f"\n--- {label} --- {np.mean(sims):.2f}")
    #print(f"平均価格    : {np.mean(sims):.2f}")
    #print(f"中央値      : {np.median(sims):.2f}")
    #print(f"下位25%水準  : {np.percentile(sims, 25):.2f}")
    #print(f"上位75%水準 : {np.percentile(sims, 75):.2f}")
plt.show()
0
1
0

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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?