σμ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 AcademyParcours
Ctrl K
AO
+1,2 k apprenants
ConnexionRejoindre ↗
Parcours
AO
+1,2 k apprenants
Connexion
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Parcours Python›Module 9 · Données de marché et microstructure›Sujet 9.1·~1 hAvancé

Le carnet d'ordres limites

Position dans le parcoursModule 9 sur 11 · Sujet 1 sur 5
9.1 Le carnet d'ordres limites
—Score du lab— / 100XP total—Série—

Là où les prix se forment

Un prix à l'écran est le résultat d'une file d'attente. En bourse, acheteurs et vendeurs placent des ordres à cours limité : « acheter 300 à 99,50 », « vendre 200 à 100,00 ». Ceux qui ne sont pas exécutés restent dans le carnet d'ordres : les offres d'achat (bids), la meilleure au prix le plus élevé, et les offres de vente (asks), la meilleure au prix le plus bas. Une transaction a lieu quand un ordre entrant rencontre un ordre en attente. Tout ce que les sujets précédents appellent prix, écart, glissement et impact vient de cette structure.

# A side of the book as a dict {price: total size}
bids = {99.5: 300, 99.4: 500, 99.0: 1200}
asks = {100.0: 200, 100.1: 400, 100.5: 800}

best_bid, best_ask = max(bids), min(asks)
print(best_bid, best_ask)                                 # 99.5 100.0
print(round(best_ask - best_bid, 2), (best_bid + best_ask) / 2)   # the spread 0.5 and the mid 99.75

Écart, prix milieu et profondeur

Le meilleur bid et le meilleur ask forment le haut du carnet. Leur différence est l'écart (spread), prix de la négociation immédiate : un acheteur qui prend l'ask et revend au bid perd l'écart. À mi-chemin se trouve le prix milieu, la référence usuelle d'un prix juste. La profondeur est la taille en attente à chaque niveau et au-delà, et dit combien peut s'échanger avant que le prix bouge. Un côté vide signifie qu'il n'y a aucun prix de ce côté, donc écart et milieu sont indéfinis : None, pas zéro.

def best_bid_ask(bids, asks):
    return (max(bids) if bids else None, min(asks) if asks else None)

def spread_and_mid(bids, asks):
    bid, ask = best_bid_ask(bids, asks)
    if bid is None or ask is None:
        return None, None
    return ask - bid, (bid + ask) / 2

print(spread_and_mid({99.5: 300, 99.4: 500}, {100.0: 200, 100.1: 400}))      # (0.5, 99.75)
print(spread_and_mid({}, {100.0: 200}))                                       # (None, None): one side is empty

Ajouter des ordres sans modifier le passé

Un nouvel ordre à cours limité rejoint un niveau de prix existant, ajoutant à sa taille totale, ou ouvre un nouveau niveau. L'écrire comme une fonction qui renvoie un nouveau dict plutôt que de modifier l'ancien présente un avantage pratique : on garde un instantané du carnet avant l'ordre, utile pour tester et rejouer. Copiez avec dict(side), modifiez la copie, renvoyez-la. Une fonction qui modifie en silence son argument est une source classique de bugs quand le même carnet sert à deux endroits.

def add_limit_order(side, price, size):
    new = dict(side)                                   # a copy: the original book is not touched
    new[price] = new.get(price, 0) + size
    return new

bids = {99.5: 300, 99.4: 500}
after = add_limit_order(bids, 99.5, 100)               # joins the existing level
after = add_limit_order(after, 99.3, 50)               # opens a new level
print(after)                                           # {99.5: 400, 99.4: 500, 99.3: 50}
print(bids)                                            # {99.5: 300, 99.4: 500}  unchanged

Apparier un ordre au marché

Un achat au marché prend les asks du prix le plus bas vers le haut : tout le premier niveau, puis le deuxième, jusqu'à ce que l'ordre soit exécuté ou le carnet vide. Parcourez les prix triés, prenez min(left, size_at_price) à chacun, enregistrez l'exécution, puis supprimez le niveau (pris entièrement) ou réduisez-le (pris en partie). La liste des exécutions donne le prix moyen vu dans le sujet sur les exécutions, et le carnet restant est le marché après votre transaction : plus mince en haut, avec un moins bon meilleur ask.

def match_market_buy(asks, size):
    remaining = dict(asks)
    fills = []
    left = size
    for price in sorted(asks):                          # cheapest first
        if left <= 0:
            break
        take = min(left, asks[price])
        fills.append((price, take))
        left -= take
        if take == asks[price]:
            del remaining[price]                        # the level is used up
        else:
            remaining[price] = asks[price] - take
    return fills, remaining

asks = {100.0: 200, 100.1: 400, 100.5: 800}
fills, remaining = match_market_buy(asks, 500)
print(fills)                                            # [(100.0, 200), (100.1, 300)]
print(remaining)                                        # {100.1: 100, 100.5: 800}
Les vrais carnets sont des filesUn dict de taille totale par prix cache la file : à chaque niveau, les ordres sont exécutés dans l'ordre d'arrivée (priorité prix-temps), et la place de votre propre ordre dans cette file décide s'il est exécuté. Les flux réels annulent et modifient aussi des ordres, ce qui domine le trafic de messages. Le carnet agrégé ici est le bon modèle pour comprendre profondeur, écart et impact, et le point de départ du déséquilibre du flux d'ordres du prochain sujet.
  • Chaque côté est un dict {price: size} : le meilleur bid est max(bids), le meilleur ask min(asks) ; l'écart est ask - bid, le milieu leur moyenne, et les deux valent None si un côté est vide.
  • Ajoutez un ordre en copiant le dict, en ajoutant au prix, puis en renvoyant la copie ; le carnet passé reste inchangé.
  • Un achat au marché parcourt les asks triés, prenant min(left, size) par niveau, supprimant les niveaux épuisés, réduisant ceux pris en partie ; les vrais carnets ont aussi une file à chaque niveau.

À suivre : le déséquilibre du flux d'ordres, lire la pression dans le carnet pour anticiper le prochain mouvement de prix.

Lab : ce qui est noté

  • Trouver le haut du carnet avec best_bid_ask25 pts
  • Mesurer l'écart avec spread_and_mid25 pts
  • Poser un ordre avec add_limit_order25 pts
  • Consommer les ventes avec match_market_buy25 pts
Explorateur · lab-112-1
▾ lab-112-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-112-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-112-1 revient aux fichiers de départ et le terminal est vidé. Votre solution actuelle sera perdue : cette action est irréversible.

Sera réinitialisé
  • main.py → code de départ
  • Historique du terminal et sortie des tests
  • Modifications non soumises
Sera conservé
  • Meilleur score du lab
  • Votre XP et votre série
  • Progression du cours et notes

Connectez-vous pour exécuter votre code.

Tous les cours sont gratuits à lire. Créez un compte ou connectez-vous pour exécuter du code, lancer les tests et soumettre ce lab.

  • IDE dans le navigateur avec terminal bash — rien à installer
  • Correction instantanée, XP et votre place dans le parcours
Créer un compteSe connecter
OU
Continuer avec GitHub