σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academyロードマップ
Ctrl K
AO
+1.2k 人の学習者
ログイン参加する ↗
ロードマップ
AO
+1.2k 人の学習者
ログイン
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python ロードマップ›モジュール 7 · アルファ研究とリスク›トピック 7.8·~1 時間上級

ARIMAモデル

ロードマップ上の位置モジュール 7/11 · トピック 8/9
7.8 ARIMAモデル
—ラボスコア— / 100合計XP—連続日数—

自分自身を覚えている系列

多くの系列は自分自身の将来についての情報を持っています。金利スプレッド、ボラティリティ、関連する2つの価格の差などは、自由にさまよわず、ある水準へ戻る傾向があります。ARIMAは3つの考え方でそれを捉えます。I:系列を差分して定常にする。AR:自分自身のラグに回帰する。MA:直近の予測誤差を使う。株式リターン自体にはこうした記憶はほとんどなく、ARIMAは持続性や平均回帰のある系列に向いています。

import numpy as np

prices = np.array([100.0, 101.5, 103.2, 104.1, 106.0, 107.2])

print(np.diff(prices))              # first differences: the changes             [1.5 1.7 0.9 1.9 1.2]
print(np.diff(prices, n=2))         # second differences: the change of the changes
print(np.diff(np.log(prices)))      # the differenced log price is the log return

差分と自己相関

価格はさまよい安定した平均を持ちませんが、その変化は持つことが多いです。1階の差分(次数 d = 1)でトレンドが、2階(d = 2)で曲がったトレンドが取り除かれます。自己相関関数(ACF)はその記憶を示します。ラグ k の値は、系列と k ステップ前の自分自身との相関で、sum((x[t] - m) * (x[t+k] - m)) / sum((x[t] - m)**2) です。ゆっくり減衰するACFはARモデルを示唆し、全ラグでゼロ近くなら予測できるものはありません。

# The ACF of a persistent series decays slowly; the ACF of noise is near zero
import numpy as np

def acf(series, lags):
    dev = series - series.mean()
    total = np.sum(dev ** 2)
    return np.array([np.sum(dev[:len(series) - k] * dev[k:]) / total for k in range(1, lags + 1)])

rng = np.random.default_rng(1)
noise = rng.normal(size=500)
persistent = np.empty(500)
persistent[0] = 0.0
for t in range(1, 500):
    persistent[t] = 0.8 * persistent[t - 1] + noise[t]           # an AR(1) with phi = 0.8
print(np.round(acf(persistent, 4), 3))                           # decays slowly: 0.74, 0.58, 0.48, 0.39 in this sample
print(np.round(acf(noise, 4), 3))                                # all near 0
# Differencing a trending series makes its mean stable
import numpy as np

rng = np.random.default_rng(6)
trend = 100 + 0.5 * np.arange(200) + rng.normal(0, 1, size=200).cumsum()          # a trending random walk
changes = np.diff(trend)
print(round(float(trend[:100].mean()), 1), round(float(trend[100:].mean()), 1))     # the level drifts: the halves differ a lot
print(round(float(changes[:100].mean()), 2), round(float(changes[100:].mean()), 2))   # the changes have a similar mean in both halves

AR(1)を当てはめて予測する

AR(1) は x[t] = c + phi * x[t-1] + ノイズ という式です。各値を直前の値に直線で回帰するもので、phi が傾き、c が切片であり、CAPMのトピックのベータと同じ和から求まります。予測は再帰的で、最初のステップは c + phi * last、以降は直前の予測を使います。|phi| < 1 なら予測は長期平均 c / (1 - phi) に向かい、速さは phi で決まる、平均回帰する系列です。

import numpy as np

def fit_ar1(series):
    a, b = series[:-1], series[1:]
    phi = np.sum((a - a.mean()) * (b - b.mean())) / np.sum((a - a.mean()) ** 2)
    return float(b.mean() - phi * a.mean()), float(phi)

def forecast_ar1(last, c, phi, steps):
    out, value = [], last
    for _ in range(steps):
        value = c + phi * value
        out.append(value)
    return np.array(out)

rng = np.random.default_rng(3)
x = np.empty(400)
x[0] = 2.0
for t in range(1, 400):
    x[t] = 0.5 + 0.75 * x[t - 1] + rng.normal(0, 0.3)             # true c = 0.5, phi = 0.75, mean 2.0
c, phi = fit_ar1(x)
print(round(c, 3), round(phi, 3))
print(np.round(forecast_ar1(4.0, c, phi, 5), 3), round(c / (1 - phi), 3))
予測は取引ではないスプレッドで統計的に有意な phi が出ても利益は保証されません。コスト、ノイズに対する値動きの大きさ、推定の不安定さが効きます。いつもの規律を守り、ある期間で当てはめて次の期間を予測し、「変化なし」という素朴な予測と比べましょう。それに勝てないモデルは何も見つけていません。
  • ARIMA=差分(I)+自己回帰(AR)+過去の誤差(MA)。差分でトレンドのある系列を定常にする
  • ラグ k のACFは、系列と k ステップ前の自分との相関。ゆっくりした減衰はARモデルを示唆する
  • AR(1)の当てはめは x[1:] を x[:-1] に回帰すること。予測は互いに引き継がれ、|phi| < 1 なら c / (1 - phi) に収束する。「変化なし」の予測には必ず勝つこと

次はGARCHボラティリティモデルです。リターンの水準ではなく、その動きの激しさを予測します。

ラボ:採点される内容

  • difference でトレンドを取り除く25点
  • acf で系列の記憶を測る25点
  • fit_ar1 でモデルを当てはめる25点
  • forecast_ar1 で先を予測する25点
エクスプローラー · lab-100-1
▾ lab-100-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-100-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

このトピックをリセットしますか?

lab-100-1 の内容はすべてスターターファイルに戻り、ターミナルも消去されます。現在の解答は失われ、元に戻せません。

リセットされるもの
  • main.py → スターターコード
  • ターミナル履歴とテスト出力
  • 未提出の変更
保持されるもの
  • ラボの最高スコア
  • XPと連続日数
  • 講義の進捗とメモ

コードを実行するにはログインしてください。

レクチャーはすべて無料で読めます。コードの実行、テスト、ラボの提出にはアカウントの作成かログインが必要です。

  • ブラウザ内IDEとbashターミナル。インストール不要
  • 即時採点、XP、ロードマップでの現在地
アカウントを作成ログイン
または
GitHubで続ける