σμ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.15·~40 minIntermédiaire

Gérer les données manquantes

Position dans le parcoursModule 2 sur 11 · Sujet 15 sur 20
2.15 Gérer les données manquantes
—Score du lab— / 100XP total—Série—

Des trous dans les données

Les vrais tableaux de prix ont des trous : une action n'a pas été échangée ce jour-là, un flux a perdu une cotation, un marché était fermé. pandas les note NaN (« not a number »). Avant de choisir quoi faire, regardez : df.isna() donne un tableau Vrai/Faux, .sum() compte les trous par colonne et .mean() donne leur part. Une colonne vide à 40 % est un autre problème qu'une colonne à qui il manque une seule valeur.

import pandas as pd

nan = float("nan")
df = pd.DataFrame(
    {"AAPL": [184.0, nan, 186.5, 187.0, nan], "MSFT": [410.0, 411.0, nan, nan, 415.0]},
    index=pd.bdate_range("2026-03-02", periods=5),
)

print(df.isna().sum().to_dict())           # {'AAPL': 2, 'MSFT': 2}   holes per column
print(df.isna().mean().round(2).to_dict())   # {'AAPL': 0.4, 'MSFT': 0.4}   share of holes

Reporter, ou supprimer

Pour des prix, le remplissage naturel est le dernier prix connu : tant qu'une nouvelle cotation n'arrive pas, le marché est toujours à l'ancien niveau. C'est ffill() (remplissage vers l'avant). Un long trou signifie probablement des données périmées : ffill(limit=2) ne remplit que deux jours de suite au plus. Les NaN tout au début restent NaN, faute de prix antérieur à reporter. L'alternative est de supprimer : dropna() retire toute ligne avec un trou, et dropna(subset=["AAPL"]) ne regarde que les colonnes qui vous importent. Supprimer est sûr mais réduit les données et modifie l'espacement des dates.

msft = df["MSFT"]
print(msft.ffill().tolist())           # [410.0, 411.0, 411.0, 411.0, 415.0]
print(msft.ffill(limit=1).tolist())    # [410.0, 411.0, 411.0, nan, 415.0]   only one day carried

print(len(df.dropna()))                          # 1   only one row is complete
print(len(df.dropna(subset=["AAPL"])))           # 3   rows where AAPL is known

Interpolation, et ce qu'il ne faut jamais remplir

interpolate() comble un trou par une droite entre les valeurs connues de part et d'autre. Il convient aux grandeurs lisses (une courbe de taux, un niveau de volatilité) et rarement aux prix, qui sautent. Attention aux bords : par défaut, interpolate() recopie aussi la dernière valeur dans les NaN de fin, ce qui invente des données. limit_area="inside" le limite aux trous entre deux valeurs connues. Ne remplissez jamais aveuglément avec 0 : un prix de 0 est un krach, un rendement de 0 est une journée plate, et fillna(0) sur le mauvais tableau modifie sans bruit toutes les moyennes calculées ensuite.

gappy = pd.Series([nan, nan, 10.0, nan, nan, 16.0, nan])

print(gappy.interpolate().tolist())
# [nan, nan, 10.0, 12.0, 14.0, 16.0, 16.0]   the last 16.0 is invented

print(gappy.interpolate(limit_area="inside").tolist())
# [nan, nan, 10.0, 12.0, 14.0, 16.0, nan]    only between known values
# Filling with 0 is a decision, not a default: it changes the statistics
print(gappy.fillna(0).tolist())   # [0.0, 0.0, 10.0, 0.0, 0.0, 16.0, 0.0]
print(gappy.mean())                # 13.0   NaN are skipped
print(gappy.fillna(0).mean())      # 3.7142857142857144   the zeros drag the average down
Remplissez avec le passé, jamais avec le futurbfill() et interpolate() utilisent des valeurs postérieures au trou : à la date du trou, ils emploient une information qui n'existait pas encore. Dans un backtest, c'est un biais d'anticipation. Utilisez ffill() pour tout ce que voit une stratégie en temps réel, et réservez l'interpolation au nettoyage de données historiques analysées dans leur ensemble.
  • df.isna().sum() compte les trous par colonne ; regardez les données avant de décider du traitement.
  • ffill(limit=n) reporte la dernière valeur connue (le bon choix pour des prix) ; dropna(subset=...) retire les lignes incomplètes.
  • interpolate(limit_area="inside") ne comble que les trous intérieurs ; ne remplissez jamais avec 0 ni avec le futur par habitude.

À suivre : la détection des valeurs aberrantes, trouver les valeurs présentes qui ne peuvent pas être justes.

Lab : ce qui est noté

  • Compter les trous de chaque colonne avec count_missing25 pts
  • Reporter le dernier prix avec forward_fill25 pts
  • Ne garder que les lignes fiables avec complete_rows25 pts
  • Combler les trous à l'intérieur des données avec fill_gaps25 pts
Explorateur · lab-48-1
▾ lab-48-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-48-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

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