σμ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 ロードマップ›モジュール 2 · 市場データのためのNumPyとpandas›トピック 2.14·~40 分中級

ローリングウィンドウ

ロードマップ上の位置モジュール 2/11 · トピック 14/20
2.14 ローリングウィンドウ
—ラボスコア— / 100合計XP—連続日数—

スライドする窓

今日の価格だけでは意味が乏しく、トレーダーは直近の過去と比べます。ローリングウィンドウは直近 n 件の観測を保持して1歩ずつ進むため、各日付はその直近の履歴から計算された統計量(移動平均、直近のボラティリティ、直近の高値など)を持ちます。pandas では series.rolling(n) が窓を表し、.mean() などの統計量がすべての位置で一度に計算します。

import pandas as pd

prices = pd.Series(
    [100.0, 102, 101, 105, 107, 106, 110],
    index=pd.bdate_range("2026-03-02", periods=7),
    name="close",
)

moving_average = prices.rolling(3).mean()
print(moving_average.round(2).tolist())
# [nan, nan, 101.0, 102.67, 104.33, 106.0, 107.67]

print(prices.rolling(3).max().tolist())   # [nan, nan, 102.0, 105.0, 107.0, 107.0, 110.0]   the 3-day high

系列の最初

最初の n - 1 個の位置にはまだ完全な窓がないため、結果は NaN です。これは正直な扱いで、2つの価格の平均は3日平均ではありません。それでも早く値が欲しいなら、min_periods=1 で使えるデータだけで計算でき、expanding() は固定窓の代わりに開始からのすべてを使います。標準偏差のように複数の点が必要な統計量は、観測が十分に届くまで NaN です。単純リターンのようにすでに NaN で始まる系列では、最初の有効な窓が1つ後ろにずれます。

# min_periods=1: use whatever is available at the start
print(prices.rolling(3, min_periods=1).mean().round(2).tolist())   # [100.0, 101.0, 101.0, 102.67, 104.33, 106.0, 107.67]

# expanding(): everything since the first day, not a fixed window
print(prices.expanding().mean().round(2).tolist())   # [100.0, 101.0, 101.0, 102.0, 103.0, 103.5, 104.43]

# Rolling volatility of the returns: the first return is NaN, so three returns exist only from the 4th day
returns = prices.pct_change()
print(returns.rolling(3).std().round(4).tolist())   # [nan, nan, nan, 0.0249, 0.0248, 0.0246, 0.0237]

窓からシグナルへ

ローリング統計量は比較することで売買シグナルになります。Zスコアは今日の価格が直近の平均から直近の標準偏差の何個分離れているかを表します:(price - rolling mean) / rolling std。ローリングオブジェクトは1回作って(r = prices.rolling(3))2回使いましょう。移動平均のクロスは短期平均と長期平均を比べ、短期が上にある間は直近のトレンドが上向きです。比較は真偽値を返し、astype("int64") で0/1のシグナルにします。NaN との比較は False なので、両方の平均が揃うまでシグナルは0です。

# z-score of each price against its own 3-day window
rolling = prices.rolling(3)
zscore = (prices - rolling.mean()) / rolling.std()
print(zscore.round(2).tolist())   # [nan, nan, 0.0, 1.12, 0.87, 0.0, 1.12]
# Moving-average crossover: 1 while the 2-day average is above the 4-day average
fast = prices.rolling(2).mean()
slow = prices.rolling(4).mean()
signal = (fast > slow).astype("int64")
print(signal.tolist())   # [0, 0, 0, 1, 1, 1, 1]

# Trade on the next day: the signal of today's close cannot be traded before tomorrow
print(signal.shift(1).fillna(0).astype("int64").tolist())   # [0, 0, 0, 0, 1, 1, 1]
未来を覗かないローリングウィンドウは現在の行で終わるので、過去しか使いません。center=True は現在の行を窓の中央に置くため未来の価格を使い、チャートでは見事でも取引はできません。今日の終値から計算したシグナルは明日適用すべきなので、shift(1) を使います。
  • series.rolling(n).mean()(std()・max() なども)は、各位置で直近 n 件の統計量を計算する
  • 最初の n - 1 個は NaN。min_periods と expanding() は意図的にそれを変える
  • Zスコアと移動平均のクロスは窓をシグナルに変える。取引前にシグナルをずらし、center=True は避ける

次は欠損データの扱いです。実際の価格表に必ず含まれる NaN をどうするかを学びます。

ラボ:採点される内容

  • moving_average で価格をならす25点
  • rolling_volatility で直近のリスクを測る25点
  • rolling_zscore で各価格を窓内で標準化する25点
  • ma_crossover で2本の平均線をシグナルにする25点
エクスプローラー · lab-47-1
▾ lab-47-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-47-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

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

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

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

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

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

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