σμ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 ロードマップ›モジュール 11 · 本番システムと最先端モデル›トピック 11.13·~4 時間エキスパート

総仕上げ:エンドツーエンドの価格計算または戦略ライブラリ

ロードマップ上の位置モジュール 11/11 · トピック 13/13
11.13 総仕上げ:エンドツーエンドの価格計算または戦略ライブラリ
—ラボスコア— / 100合計XP—連続日数—

演習からライブラリへ

あなたは100ほどの小さな関数を書いてきました。ライブラリとは、それらの関数を、他の人(半年後の自分を含む)が安心して使えるように整理したものです。明確な公開インターフェース、個別にテストされた各部品、パイプラインとして組み合わされた部品、そして全体がインストールでき、文書化され、自動でチェックされること。この最終プロジェクトはそのパターンの縮図です。戦略ライブラリは練習に最適です。シグナルが価格をポジションに変え、バックテストがポジションをコスト控除後のリターンに変え、指標がリターンを要約し、ランナーがそれらをつなぎます。各段階は素朴な配列を受け取り素朴な配列を返すので、手計算で確認できる数値で個別にテストできます。

# The shape of a small library: a package, its tests, its metadata and its automated checks
tree = """\
quantlib/
├── pyproject.toml            name, version, dependencies (numpy)
├── src/quantlib/
│   ├── __init__.py           the public API: sma_positions, strategy_returns, performance_summary, run_strategy
│   ├── signals.py            prices -> positions
│   ├── backtest.py           positions -> returns after costs
│   └── metrics.py            returns -> total return, volatility, Sharpe, drawdown
├── tests/                    one test file per module, fixed seeds, hand-checked cases
└── .github/workflows/ci.yml  lint, types, tests on every push
"""
print(tree.splitlines()[0])                          # quantlib/
print(sum(1 for line in tree.splitlines() if ".py" in line))     # 4   the four module files

シグナルとバックテスト:先読みなし、コスト込み

ここでのシグナルは移動平均のクロスです。価格の短期平均が長期平均より上ならロング、下ならショート、等しいか長期平均がまだ存在しないなら無ポジションです。バックテストが誠実かどうかを決める2つの規則は、コードに現れます。1つ目は先読みなしです。t 日の引けで決めるポジションは t 日までの価格しか使えず、t + 1 日のリターンを得ます。だからステップ t のリターンは positions[t - 1] を使います。テストで確かめられます。最後の価格を取り除いても、それ以前のポジションが変わってはいけません。2つ目はコストです。ポジションが変わるたびに cost * |変化| を払うので、頻繁に反転する戦略は、コスト前には勝ってもコスト後には負けることがあります。

# The signal and the honest backtest: positions decided at the close are earned on the NEXT step, and trading costs money
import numpy as np

def sma_positions(prices, fast, slow):
    prices = np.asarray(prices, dtype=float)
    positions = np.zeros(len(prices), dtype=int)
    for t in range(slow - 1, len(prices)):
        f = prices[t - fast + 1 : t + 1].mean()
        s = prices[t - slow + 1 : t + 1].mean()
        positions[t] = 1 if f > s else -1 if f < s else 0
    return positions

def strategy_returns(prices, positions, cost):
    returns = []
    for t in range(1, len(prices)):
        before = positions[t - 2] if t >= 2 else 0
        returns.append(positions[t - 1] * (prices[t] / prices[t - 1] - 1) - cost * abs(positions[t - 1] - before))
    return np.array(returns)

prices = np.array([100, 101, 103, 102, 105, 108, 107, 110, 112, 111, 115, 118], dtype=float)
positions = sma_positions(prices, 2, 4)
print(positions)                                     # [0 0 0 1 1 1 1 1 1 1 1 1]   flat until the 4-day average exists, then long
print(np.allclose(sma_positions(prices[:8], 2, 4), positions[:8]))      # True   later prices never change earlier positions
print(np.round(strategy_returns(prices, positions, 0.0).sum() - strategy_returns(prices, positions, 0.001).sum(), 3))    # 0.001   one purchase at 0.1%

パフォーマンス指標とランナー

リターン系列はいくつかの数値で要約します。累積リターンは期間を複利で合成した prod(1 + r) - 1。年率リターンはそれを1年に換算した (1 + total)^(年あたり期間数 / n) - 1。年率ボラティリティは標本標準偏差に sqrt(年あたり期間数) を掛けたもの。シャープレシオは平均リターンをその標準偏差で割って年率化したもので、リスク1単位あたりのリターンを示す代表的な指標です(平坦な系列では除算エラーではなく0)。最大ドローダウンは資産曲線のピークからの最悪の下落で、その戦略がどれだけの痛みを求めるかを示します。ランナー関数がすべてをつなぎます。ポジション、次にリターン、そして要約です。他の関数を組み合わせるだけにして、バグが常に1つの段階に追跡できるようにしましょう。

# Performance statistics of a return series, and the runner that wires the three stages together
import math
import numpy as np

def performance_summary(returns, periods_per_year):
    returns = np.asarray(returns, dtype=float)
    n = len(returns)
    equity = np.concatenate(([1.0], np.cumprod(1 + returns)))
    total = float(equity[-1] - 1)
    deviation = float(np.std(returns, ddof=1))
    peak = np.maximum.accumulate(equity)
    return {
        "total_return": total,
        "annual_return": float((1 + total) ** (periods_per_year / n) - 1),
        "annual_vol": deviation * math.sqrt(periods_per_year),
        "sharpe": float(returns.mean() / deviation * math.sqrt(periods_per_year)) if deviation > 0 else 0.0,
        "max_drawdown": float(np.max((peak - equity) / peak)),
    }

summary = performance_summary([0.10, -0.20, 0.05], 252)
print(round(summary["total_return"], 4), round(summary["max_drawdown"], 4))     # -0.076 0.2   equity 1 -> 1.1 -> 0.88 -> 0.924: a 20% fall from the peak
print(performance_summary([0.0, 0.0, 0.0], 252)["sharpe"])                       # 0.0   no variation: a Sharpe of 0, not an error
# The runner only composes: if a number looks wrong you can test each stage on its own
def run_strategy(prices, fast, slow, cost, periods_per_year=252):
    positions = sma_positions(prices, fast, slow)
    returns = strategy_returns(prices, positions, cost)
    return performance_summary(returns, periods_per_year)

# (sma_positions, strategy_returns and performance_summary are the functions you wrote in this lab)
steps = ["sma_positions", "strategy_returns", "performance_summary"]
print(" -> ".join(steps))                           # sma_positions -> strategy_returns -> performance_summary
print(len(steps), "stages, one result: a dict of five numbers")        # 3 stages, one result: a dict of five numbers

あなたの最終プロジェクト

では自分のものを、自分のリポジトリで作りましょう。次のどちらか1つを選びます。価格評価ライブラリ:Black-Scholes とグリークス、対称変量法を使ったモンテカルロ評価、インプライド・ボラティリティのソルバー、気配の集合へのモデル較正。または戦略ライブラリ:複数のシグナル、コストとポジション制限付きのバックテスト、ウォークフォワード評価、レポート。どちらでも、同じものを納品します。明確な公開 API と型ヒントを備えたパッケージ。固定シードのテストと手計算で確認したケース。インストール方法と例の実行方法を示す pyproject.toml と README。lint・型・テストを走らせる CI ワークフロー。プロファイルしたボトルネックを1つ含むパフォーマンスメモ。前提と、モデルを壊すものについての短い文書。時間配分は、まずインターフェースを設計し、動く最小のパイプラインを作り、それから広げます。

良い結果は再現するのが退屈なほど地味他の人があなたのリポジトリをクローンし、1つのコマンドを実行して、あなたと全く同じ数字を得られるようにしましょう。シードを固定し、バージョンを固定し、データのスナップショットかそれを取得するスクリプトを残し、資産曲線を単純なベンチマークと並べて示します。戦略が稼ぐものだけでなく、ドローダウンと回転率という代償も報告し、どの部分をテストしていないかをはっきり述べます。その誠実さが、クオンツの仕事を信頼できるものにします。
  • ライブラリとは、明確なインターフェースの背後で、テスト済みの小さな関数がパイプラインに組まれたもの。シグナル→ポジション→コスト後リターン→指標を、ランナーがつなぐ
  • 誠実なバックテストは先読みをせず(t のポジションは t までの価格を使い、次のリターンを得る)、ポジションが変わるたびにコストを課す
  • 累積・年率リターン、ボラティリティ、シャープ、最大ドローダウンで要約し、テスト、CI、README、誠実なレポート付きのパッケージを納品する

これでロードマップは完了です。あなたは今、現役のクオンツ開発者が持つ言語、数値ツール、市場データと執行の部品、モデル、エンジニアリングの習慣を手にしています。最終プロジェクトのリポジトリは大切に保管してください。ここで身につけたスキルの最良の証明になります。

ラボ:採点される内容

  • sma_positions でトレンドをポジションにする25点
  • strategy_returns でコスト込みバックテストをする25点
  • performance_summary で結果を評価する25点
  • run_strategy ですべてをつなぐ25点
エクスプローラー · lab-142-1
▾ lab-142-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-142-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

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

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

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

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

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

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