σμ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.5·~1 時間エキスパート

VWAP執行

ロードマップ上の位置モジュール 11/11 · トピック 5/13
11.5 VWAP執行
—ラボスコア— / 100合計XP—連続日数—

市場が取引するときに取引する

出来高加重平均価格は、取引されたすべてのものの平均価格で、各約定をその大きさで重み付けします(sum(price * volume) / sum(volume))。その日の平均的な参加者が支払った価格なので、機関投資家の取引で最もよく使われるベンチマークです。VWAP アルゴリズムは、*市場の出来高に比例して*取引することでこれに並ぶか上回ろうとします。市場が活発なとき(寄り付き、引け)は多く、静かなとき(昼時)は少なくします。TWAP が時計に従うのに対し、VWAP は群衆に従うので、各注文は他の参加者の取引に対して同程度の割合となり、価格を動かしにくくなります。

# The benchmark: each price counts as much as the volume that traded at it
def vwap(prices, volumes):
    return sum(p * v for p, v in zip(prices, volumes)) / sum(volumes)

prices = [100.0, 101.0, 102.0]
volumes = [100, 300, 600]
print(round(vwap(prices, volumes), 4))               # 101.5     most volume traded near 102, so the VWAP leans that way
print(sum(prices) / len(prices))                     # 101.0     the plain average ignores how much traded at each price

出来高プロファイルとそれに従うスケジュール

その日の出来高は事前には分からないため、VWAP アルゴリズムは過去のデータから推定した出来高プロファイルを使います。たとえば直近20営業日で、各区間に取引された1日の出来高の平均的な割合です。日中の出来高は通常 U 字型で、寄り付きと引けで多くなります。スケジュールは各区間に total * 割合 株を割り当てます。これはめったに整数にならず、それぞれを四捨五入すると株数が増減しかねません。最大剰余法がこれを解決します。各区間に切り捨てた値を与え、残りの株を、小数部が最も大きい区間に1株ずつ配ることで、スケジュールの合計は常に注文数量と一致します。

# From volumes to a profile, then to whole shares by the largest remainder method
import math

def volume_profile(volumes):
    total = sum(volumes)
    return [v / total for v in volumes]

def vwap_schedule(total, profile):
    exact = [total * share for share in profile]
    shares = [math.floor(value + 1e-9) for value in exact]
    leftover = total - sum(shares)
    for index in sorted(range(len(profile)), key=lambda i: (-(exact[i] - shares[i]), i))[:leftover]:
        shares[index] += 1
    return shares

profile = volume_profile([300, 100, 100, 200, 500, 800])       # a U-shape: busy at the open and the close
print([round(p, 3) for p in profile])                # [0.15, 0.05, 0.05, 0.1, 0.25, 0.4]
print(vwap_schedule(1003, profile))                  # [151, 50, 50, 100, 251, 401]   adds up to 1003
print(sum(vwap_schedule(1003, profile)))             # 1003

参加率の上限とベンチマークの追跡

スケジュールは計画であり、市場はプロファイルの予測より静かかもしれません。参加率の上限は、各区間での取引を、その区間の実際の市場出来高の一定割合(たとえば10%)に制限し、フローの大半を自分が占めないようにします。取引できなかった株は後の区間に繰り越され、最後に未執行が残ることもあります。そのときは、リスクを増やすか、時間枠を延ばすか、中止するかを決めます。1日の終わりに、平均価格を市場の VWAP と比べます。その差(ベーシスポイント)がアルゴリズムのトラッキングエラーです。上昇相場で遅く取引して VWAP に勝っても実力ではありません。アルゴリズムは、多数の日にわたるスリッページで評価しましょう。

# A participation cap: never more than a fraction of the market's volume, carrying the rest forward
import math

def cap_participation(schedule, market_volumes, rate):
    trades, carry = [], 0
    for scheduled, volume in zip(schedule, market_volumes):
        wanted = scheduled + carry
        done = min(wanted, math.floor(rate * volume + 1e-9))
        trades.append(done)
        carry = wanted - done
    return trades, carry

print(cap_participation([100, 100, 100], [500, 1000, 1000], 0.1))      # ([50, 100, 100], 50)
print(cap_participation([100, 0, 0, 0], [500, 1000, 400, 800], 0.1))   # ([50, 50, 0, 0], 0)   the carry is traded when the market allows it
# Following the clock (TWAP) and following the volume (VWAP) give different average prices on the same day
prices = [100.0, 100.2, 100.1, 100.4, 100.3, 100.5]
volumes = [300, 100, 100, 200, 500, 800]               # busy at the open and the close

market_vwap = sum(p * v for p, v in zip(prices, volumes)) / sum(volumes)
twap_average = sum(prices) / len(prices)                # equal pieces at every time
print(round(market_vwap, 4), round(twap_average, 4))    # 100.33 100.25
print(round((twap_average - market_vwap) / market_vwap * 10000, 1))      # -8.0   a TWAP buy beat the VWAP here, by trading light when volume was heavy
VWAP はベンチマークであって目標ではないVWAP に並ぶということは、平均的な参加者と同じように取引したということです。自分の注文が価格を押し上げた場合には悪い結果かもしれません(あなたの約定も比較対象の VWAP の一部です)。アルゴリズムは到着価格に対しても確認し、プロファイルを推定に使っていない日でテストし、ニュースのある日、半日取引、指数のリバランスの日にはプロファイルが外れることを想定しましょう。後の分析のため、すべての子注文の読みやすいログを残します。
  • VWAP は sum(price * volume) / sum(volume)。一般的なベンチマークで、VWAP アルゴリズムは市場の出来高に比例して取引する
  • 過去から出来高プロファイルを推定し、最大剰余法で注文を分割して、整数株の合計をちょうど合わせる
  • 各区間の参加率に上限を設けて残りを繰り越し、多数の日にわたるトラッキングエラーとスリッページでアルゴリズムを評価する

次はマーケットメイクです。両サイドに気配を出し、その結果生じる在庫を管理します。

ラボ:採点される内容

  • vwap でベンチマークを計算する25点
  • volume_profile で1日の形を捉える25点
  • vwap_schedule で注文を分割する25点
  • cap_participation で市場への影響を抑える25点
エクスプローラー · lab-134-1
▾ lab-134-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-134-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

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

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

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

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

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

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