σμ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 AcademySkills
Ctrl K
AO
+1,2 Tsd. Lernende
AnmeldenBeitreten ↗
Skills
AO
+1,2 Tsd. Lernende
Anmelden
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python-Skill›Modul 9 · Marktdaten und Mikrostruktur›Thema 9.5·~1 Std.Fortgeschritten

Das FIX-Protokoll

Position in der SkillModul 9 von 11 · Thema 5 von 5
9.5 Das FIX-Protokoll
—Lab-Punkte— / 100XP gesamt—Serie—

Die Sprache von Brokern und Börsen

Wenn ein Handelssystem eine Order an einen Broker oder eine Börse sendet, geschieht das sehr oft in FIX, dem Financial Information eXchange Protocol, das seit den frühen 1990er-Jahren verwendet wird. Eine FIX-Nachricht ist Klartext: eine Liste von Tag=Wert-Feldern, jedes durch ein unsichtbares Trennzeichen, chr(1) (SOH), beendet. Jeder Tag ist eine Zahl mit vereinbarter Bedeutung: 35 ist der Nachrichtentyp, 55 das Symbol, 54 die Seite, 38 die Menge, 44 der Preis. Das Format ist alt und unglamourös, und die ganze Branche versteht es.

# 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]

Der Aufbau einer Nachricht

Eine Nachricht hat drei Teile. Der Header beginnt mit 8=FIX.4.2 (die Version), dann 9= die Länge des Rumpfs, dann der Nachrichtentyp 35=. Der Rumpf trägt den Inhalt: bei einer New Order Single (35=D) die Kunden-Order-ID, das Symbol, die Seite (1 Kauf, 2 Verkauf), die Menge, den Ordertyp (40=2 Limit) und den Preis. Der Trailer ist 10=, eine Prüfsumme: Summieren Sie die Zeichencodes von allem davor und behalten Sie den Rest der Division durch 256, dreistellig geschrieben. Der Empfänger berechnet sie neu, um Beschädigung zu erkennen, und prüft auch die Rumpflänge. Sitzungen fügen mehr hinzu: Logon (35=A), Heartbeats (35=0) und Sequenznummern wie die aus dem letzten Thema.

# 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
Keine Produktions-Engine von Hand bauenNachrichten zu parsen und zu bauen ist ein guter Weg, FIX zu verstehen, aber eine echte Verbindung braucht Sitzungslogik: Logon, Heartbeats, Sequenz-Resets, Resend-Anfragen und handelsplatzspezifische Dialekte. Im Produktivbetrieb nutzen Sie eine erprobte Engine wie QuickFIX und beschränken Ihren Code auf die Order-Logik. Eine fehlerhafte oder doppelte Order kann echtes Geld kosten: Protokollieren Sie jede gesendete und empfangene Nachricht.
  • Eine FIX-Nachricht besteht aus Tag=Wert-Feldern, jedes durch ein Trennzeichen (chr(1) auf der Leitung) beendet; trennen Sie jedes Feld am ersten =.
  • Header 8 (Version) und 9 (Rumpflänge), Rumpf ab 35 (Typ), Trailer 10 (Prüfsumme).
  • Die Prüfsumme ist die Summe der Zeichencodes modulo 256, dreistellig; nutzen Sie produktiv eine erprobte Engine und protokollieren Sie jede Nachricht.

Als Nächstes: sauberer Code, Namen, kleine Funktionen und die Gewohnheiten, die eine Trading-Codebasis lesbar halten.

Lab: Was bewertet wird

  • Mit parse_fix eine Nachricht lesen25 Pkt.
  • Mit checksum eine Nachricht versiegeln25 Pkt.
  • Mit build_fix Felder schreiben25 Pkt.
  • Mit new_order_message eine Order senden25 Pkt.
Explorer · lab-116-1
▾ lab-116-1
…
bash · im Browser
learner@quantcraft:~/lab-116-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

Alles in lab-116-1 wird auf die Startdateien zurückgesetzt und das Terminal geleert. Ihre aktuelle Lösung geht verloren – das lässt sich nicht rückgängig machen.

Wird zurückgesetzt
  • main.py → Startcode
  • Terminal-Verlauf und Testausgabe
  • Nicht eingereichte Änderungen
Bleibt erhalten
  • Beste Lab-Punktzahl
  • Ihre XP und Ihre Serie
  • Vorlesungsfortschritt und Notizen

Melde dich an, um deinen Code auszuführen.

Alle Lektionen kannst du kostenlos lesen. Erstelle ein Konto oder melde dich an, um Code auszuführen, Tests zu starten und dieses Lab abzugeben.

  • IDE im Browser mit Bash-Terminal — nichts zu installieren
  • Sofortige Bewertung, XP und dein Platz auf der Skill
Konto erstellenAnmelden
ODER
Weiter mit GitHub