σμ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 2 · NumPy et pandas pour les données de marché›Sujet 2.19·~40 minIntermédiaire

Graphiques en chandeliers

Position dans le parcoursModule 2 sur 11 · Sujet 19 sur 20
2.19 Graphiques en chandeliers
—Score du lab— / 100XP total—Série—

Quatre prix en une image

Un graphique en courbe des clôtures jette l'essentiel d'une journée. Un chandelier garde quatre prix à la fois : l'ouverture, le plus haut, le plus bas et la clôture. Le corps épais va de l'ouverture à la clôture et se colore selon la direction (vert quand la clôture est au moins égale à l'ouverture, rouge sinon). La mèche fine va du plus bas au plus haut. D'un coup d'œil, on voit où la journée est allée, sur quelle amplitude, et si les acheteurs ou les vendeurs ont gagné.

import numpy as np
import pandas as pd

df = pd.DataFrame(
    {
        "open":  [100.0, 103.0, 102.0, 104.0],
        "high":  [104.0, 105.0, 106.0, 104.5],
        "low":   [ 99.0, 101.0, 101.5, 101.0],
        "close": [103.0, 102.0, 105.5, 104.0],
    },
    index=pd.bdate_range("2026-03-02", periods=4),
)

# Green when the day closed at or above its open, red otherwise: one np.where on whole columns
colors = np.where(df["close"] >= df["open"], "green", "red")
print(colors.tolist())   # ['green', 'red', 'green', 'green']

Calculer le corps

Un corps est un rectangle. Il commence au plus bas de l'ouverture et de la clôture (df[["open", "close"]].min(axis=1) prend le minimum ligne par ligne) et sa hauteur est la différence absolue abs(close - open). Une journée qui ouvre et clôture au même prix a un corps de hauteur 0 : un doji, un chandelier d'indécision. Comparer le corps à l'amplitude high - low dit à quel point la journée a été décisive, et le faire sur des colonnes entières trouve tous les dojis d'une année en une ligne.

body = pd.DataFrame({
    "bottom": df[["open", "close"]].min(axis=1),    # the lower of open and close, row by row
    "height": (df["close"] - df["open"]).abs(),
})
print(body)
#             bottom  height
# 2026-03-02   100.0     3.0
# 2026-03-03   102.0     1.0
# 2026-03-04   102.0     3.5
# 2026-03-05   104.0     0.0

# Body as a share of the day's range: the last day is a doji
share = body["height"] / (df["high"] - df["low"])
print(share.round(2).tolist())          # [0.6, 0.25, 0.78, 0.0]
print((share <= 0.1).tolist())          # [False, False, False, True]

Dessiner : mèches et barres

matplotlib n'a pas d'appel pour les chandeliers, mais deux appels simples suffisent. ax.vlines(x, ymin, ymax) trace d'un coup une ligne verticale pour chaque x : ce sont les mèches, du plus bas au plus haut. ax.bar(x, height, bottom=..., width=0.6, color=...) trace une barre pour chaque x en partant de bottom : ce sont les corps, et color accepte une liste avec une couleur par barre. Placez les chandeliers aux positions 0, 1, 2, ... (np.arange(len(df))) plutôt qu'aux dates, pour que les week-ends ne laissent pas de trous. Passer des colonnes entières évite toute boucle sur les jours.

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
x = np.arange(len(df))
ax.vlines(x, df["low"], df["high"], color="black", linewidth=1)                       # the wicks
ax.bar(x, body["height"], bottom=body["bottom"], width=0.6, color=colors)               # the bodies

print(len(ax.collections), len(ax.patches))            # 1 4   one set of wicks, four bodies
print([p.get_y() for p in ax.patches])                  # [100.0, 102.0, 102.0, 104.0]   body bottoms
print(ax.collections[0].get_segments()[0].tolist())     # [[0.0, 99.0], [0.0, 104.0]]    the first wick, low to high
# Candles whose body is at most 10% of the day's range are dojis
doji = share <= 0.1
print(df.index[doji].strftime("%d %b").tolist())   # ['05 Mar']
Les images peuvent être reluesUn graphique est aussi une donnée : ax.patches contient les barres et ax.collections les mèches, avec des positions, des tailles et des couleurs que l'on peut vérifier. Tester l'Axes, et non les pixels, est la manière de vérifier automatiquement une fonction de tracé, et c'est aussi ainsi qu'on déboggue un graphique qui paraît faux.
  • Un chandelier montre ouverture, plus haut, plus bas et clôture : un corps de l'ouverture à la clôture, une mèche du plus bas au plus haut.
  • Le bas du corps est min(open, close) ligne par ligne (min(axis=1)), sa hauteur abs(close - open) ; un corps de 0 est un doji.
  • Dessinez toutes les mèches avec un seul appel ax.vlines et tous les corps avec un seul appel ax.bar (liste de couleurs) ; pas de boucle sur les jours.

À suivre : les histogrammes et les distributions, pour compter la fréquence des rendements dans chaque intervalle.

Lab : ce qui est noté

  • Colorer chaque chandelier selon sa direction avec candle_colors25 pts
  • Mesurer le corps de chaque chandelier avec candle_body25 pts
  • Trouver les jours d'indécision avec doji_days25 pts
  • Dessiner les chandeliers sur un Axes avec draw_candles25 pts
Explorateur · lab-52-1
▾ lab-52-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-52-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-52-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