σμ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 ロードマップ›モジュール 9 · マーケットデータとマイクロストラクチャー›トピック 9.5·~1 時間上級

FIXプロトコル

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

ブローカーと取引所が話す言語

取引システムがブローカーや取引所に注文を送るとき、非常に多くの場合 FIX(Financial Information eXchange プロトコル)を使います。1990年代初めから使われています。FIX メッセージはプレーンテキストで、タグ=値のフィールドが並び、各フィールドは目に見えない区切り文字 chr(1)(SOH)で終わります。各タグは意味の決まった番号で、35 はメッセージ種別、55 は銘柄、54 は売買、38 は数量、44 は価格です。古くて地味な形式ですが、業界全体が理解しています。

# A FIX message is tag=value fields each ended by a separator (shown here as |)
message = "8=FIX.4.2|9=60|35=D|11=ord-1|55=AAPL|54=1|38=100|40=2|44=184.50|10=123|"

fields = {}
for part in message.split("|"):
    if part:                                       # the last separator leaves an empty piece
        tag, value = part.split("=", 1)            # split at the FIRST = only
        fields[int(tag)] = value

print(fields[35], fields[55], fields[38], fields[44])    # D AAPL 100 184.50
print(sorted(fields))                                    # [8, 9, 10, 11, 35, 38, 40, 44, 54, 55]

メッセージの構造

メッセージは3つの部分からなります。ヘッダーは 8=FIX.4.2(バージョン)で始まり、次に 9= の本文の長さ、続いてメッセージ種別 35= です。本文が内容を運びます。New Order Single(35=D)なら、クライアント注文ID、銘柄、売買(1 買い、2 売り)、数量、注文タイプ(40=2 指値)、価格です。トレーラーは 10= のチェックサムで、それより前のすべての文字コードを足し、256で割った余りを3桁で書きます。受信側は再計算して破損を検出し、本文の長さも確認します。セッションにはさらに、ログオン(35=A)、ハートビート(35=0)、前回追ったような連番が加わります。

# The checksum: add up the character codes, keep the remainder modulo 256, three digits
def checksum(text):
    return f"{sum(ord(c) for c in text) % 256:03d}"

print(checksum("A"))                      # 065  the code of "A" is 65
print(checksum("aaa"))                    # 035  3 * 97 = 291 and 291 - 256 = 35
print(checksum("8=FIX.4.2|35=0|"))        # a heartbeat header
# Writing fields: tag=value and a separator after each one
def build_fix(fields, sep="|"):
    return "".join(f"{tag}={value}{sep}" for tag, value in fields)

body = build_fix([(35, "D"), (11, "ord-1"), (55, "AAPL"), (54, 1), (38, 100)])
print(body)                               # 35=D|11=ord-1|55=AAPL|54=1|38=100|
print(len(body))                          # 34  tag 9 holds this length
# A complete order: header with the body length, the body, then the checksum trailer
def checksum(text):
    return f"{sum(ord(c) for c in text) % 256:03d}"

def build_fix(fields, sep="|"):
    return "".join(f"{tag}={value}{sep}" for tag, value in fields)

def new_order_message(cl_ord_id, symbol, side, quantity, price, sep="|"):
    code = "1" if side == "buy" else "2"
    body = build_fix([(35, "D"), (11, cl_ord_id), (55, symbol), (54, code), (38, quantity), (40, 2), (44, f"{price:.2f}")], sep)
    head = build_fix([(8, "FIX.4.2"), (9, len(body))], sep) + body
    return head + build_fix([(10, checksum(head))], sep)

message = new_order_message("ord-1", "AAPL", "buy", 100, 184.5)
print(message)                            # 8=FIX.4.2|9=...|35=D|11=ord-1|...|44=184.50|10=...|
print(message.split("|")[-2])             # the checksum field
本番のエンジンを自作しないメッセージの解析と組み立ては FIX を理解するのに良い方法ですが、実際の接続にはセッションのロジックが必要です。ログオン、ハートビート、シーケンスのリセット、再送要求、市場ごとの方言などです。本番では QuickFIX のような実績あるエンジンを使い、自分のコードは注文ロジックに絞ります。不正な注文や重複した注文は実際のお金を失わせるので、送受信したすべてのメッセージを記録してください。
  • FIX メッセージは タグ=値 のフィールドが並び、各々が区切り文字(実際は chr(1))で終わる。各フィールドは最初の = で分ける
  • ヘッダーは 8(バージョン)と 9(本文の長さ)、本文は 35(種別)から、トレーラーは 10(チェックサム)
  • チェックサムは文字コードの合計を256で割った余りを3桁にしたもの。本番では実績あるエンジンを使い、すべてのメッセージを記録する

次はクリーンなコードです。命名、小さな関数、トレーディングのコードベースを読みやすく保つ習慣を学びます。

ラボ:採点される内容

  • parse_fix でメッセージを読む25点
  • checksum でメッセージに封をする25点
  • build_fix でフィールドを書く25点
  • new_order_message で注文を送る25点
エクスプローラー · lab-116-1
▾ lab-116-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-116-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

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

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

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

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

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

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