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

DatetimeIndex et indexation temporelle

Position dans le parcoursModule 2 sur 11 · Sujet 12 sur 20
2.12 DatetimeIndex et indexation temporelle
—Score du lab— / 100XP total—Série—

Les dates ne sont pas des chaînes

Une série de prix est une série temporelle : ce qui compte, c'est quand chaque prix s'est produit. Les dates lues dans un fichier sont de simples chaînes, et une chaîne ne sait pas que mars vient après février ni qu'un lundi suit un dimanche. Convertissez-les avec pd.to_datetime et utilisez le résultat comme index : un DatetimeIndex contient de vrais horodatages que pandas sait trier, découper, comparer et décomposer. Triez-le toujours (sort_index()) pour que l'observation la plus ancienne vienne en premier.

import pandas as pd

raw_dates = ["2026-03-04", "2026-03-02", "2026-03-03"]      # strings, in a messy order
closes = [102.0, 100.0, 101.0]

series = pd.Series(closes, index=pd.to_datetime(raw_dates), name="close").sort_index()
print(series)
# 2026-03-02    100.0
# 2026-03-03    101.0
# 2026-03-04    102.0
# Name: close, dtype: float64

print(isinstance(series.index, pd.DatetimeIndex))   # True

Construire un calendrier

On a souvent besoin de dates que personne ne vous a données : une grille de comparaison, ou les jours d'un backtest. pd.date_range(start, periods=n, freq="D") produit n jours calendaires consécutifs, et pd.bdate_range saute les week-ends et donne des jours ouvrés. (Il ignore les jours fériés.) L'argument freq règle le pas : "D" est un jour, "B" un jour ouvré, "h" une heure.

# Four calendar days, then six business days (the weekend is skipped)
print(pd.date_range("2026-03-01", periods=4, freq="D").strftime("%a %d %b").tolist())
# ['Sun 01 Mar', 'Mon 02 Mar', 'Tue 03 Mar', 'Wed 04 Mar']

days = pd.bdate_range("2026-02-26", periods=6)
print(days.strftime("%a %d %b").tolist())
# ['Thu 26 Feb', 'Fri 27 Feb', 'Mon 02 Mar', 'Tue 03 Mar', 'Wed 04 Mar', 'Thu 05 Mar']

Sélectionner par date

Avec un DatetimeIndex trié, .loc comprend les dates écrites en chaînes. Une chaîne partielle comme "2026-03" sélectionne tout le mois, "2026" toute l'année et "2026-03-04" un seul jour. Une tranche .loc["2026-03-04":"2026-03-06"] sélectionne une plage et, contrairement à une tranche de positions, les deux bornes sont incluses. Les bornes n'ont pas besoin d'exister dans les données : les dates de week-end ne correspondent à rien, ce qui est voulu quand on demande « tout depuis le premier du mois ».

prices = pd.Series(
    [float(i) for i in range(20)],
    index=pd.bdate_range("2026-02-23", periods=20),   # Mon 23 Feb ... Fri 20 Mar
)

print(len(prices.loc["2026-03"]))      # 15   the business days of March in the data
print(prices.loc["2026-03-04"])        # 7.0  a single day

print(prices.loc["2026-03-04":"2026-03-06"])
# 2026-03-04    7.0
# 2026-03-05    8.0
# 2026-03-06    9.0
# Freq: B, dtype: float64

print(prices.loc["2026-03-01":"2026-03-03"].tolist())   # [5.0, 6.0]   Sunday the 1st matches nothing

Les composantes d'une date

Un DatetimeIndex expose les composantes de chaque date comme attributs : year, month, day, dayofweek (le lundi vaut 0, le dimanche 6). Chacune est un tableau avec une entrée par ligne, utilisable comme masque ou comme clé de groupe. C'est ainsi que l'on demande « combien d'observations tombent chaque jour de la semaine ? » ou « que se passe-t-il le lundi ? » sans boucle. N'oubliez pas de trier l'index d'abord : découper un DatetimeIndex désordonné peut donner des résultats surprenants ou une erreur.

# The parts of the dates, one entry per row
print(prices.index.dayofweek[:7].tolist())   # [0, 1, 2, 3, 4, 0, 1]   Monday is 0
print(prices.index.month[:7].tolist())       # [2, 2, 2, 2, 2, 3, 3]

# How many observations fall on each weekday?
print(prices.groupby(prices.index.dayofweek).size().to_dict())   # {0: 4, 1: 4, 2: 4, 3: 4, 4: 4}

# What do the Mondays look like?
print(prices[prices.index.dayofweek == 0].tolist())   # [0.0, 5.0, 10.0, 15.0]
Attention à la fin de la plageUne chaîne de date sans heure signifie minuit. Avec des données quotidiennes, .loc["2026-03-04":"2026-03-06"] inclut le 6, mais avec des données intrajournalières il s'arrête à 00:00 le 6 et perd toute la journée. Vérifiez le dernier horodatage du résultat quand vos données sont plus fines qu'un jour.
  • pd.to_datetime(chaînes) crée un DatetimeIndex ; sort_index() met le plus ancien en premier ; date_range et bdate_range construisent des calendriers.
  • .loc["2026-03"] sélectionne un mois, .loc["2026-03-04":"2026-03-06"] une plage, bornes incluses.
  • index.year, index.month, index.dayofweek donnent les composantes de chaque date, pour filtrer ou grouper sans boucle.

À suivre : le rééchantillonnage, qui transforme des prix quotidiens en barres hebdomadaires, mensuelles ou plus fines.

Lab : ce qui est noté

  • Construire une série de prix datée avec parse_prices25 pts
  • Sélectionner un mois avec prices_in_month25 pts
  • Sélectionner une plage de dates avec prices_between25 pts
  • Compter les observations par jour de la semaine avec count_by_weekday25 pts
Explorateur · lab-45-1
▾ lab-45-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-45-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

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