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

Rééchantillonnage

Position dans le parcoursModule 2 sur 11 · Sujet 13 sur 20
2.13 Rééchantillonnage
—Score du lab— / 100XP total—Série—

Changer la fréquence

Les données arrivent rarement à la fréquence voulue. Les ticks arrivent à la milliseconde, un modèle veut des barres quotidiennes, un rapport veut des mois. Le rééchantillonnage regroupe une série temporelle en nouvelles périodes. Passer du fin au grossier (jours vers mois) est un sous-échantillonnage : chaque nouvelle période contient plusieurs anciennes observations, il faut donc dire comment les combiner. Passer du grossier au fin (semaines vers jours) est un sur-échantillonnage : il y a de nouvelles périodes sans données, il faut donc dire quoi y mettre.

import pandas as pd

daily = pd.Series(
    [100.0, 101, 103, 102, 104, 105, 103, 106],
    index=pd.bdate_range("2026-02-25", periods=8),    # Wed 25 Feb ... Fri 6 Mar
    name="close",
)

print(daily.resample("ME").last())     # the last price of each month ("ME" = month end)
# 2026-02-28    103.0
# 2026-03-31    106.0
# Freq: ME, Name: close, dtype: float64

print(daily.resample("W-FRI").last())  # the last price of each week, weeks ending on Friday
# 2026-02-27    103.0
# 2026-03-06    106.0
# Freq: W-FRI, Name: close, dtype: float64

Choisir l'agrégation

series.resample("ME") seul ne fait rien : il décrit seulement les périodes. L'agrégation qui suit décide de la valeur et doit correspondre à la signification des données. Un prix est un instantané, donc un mois est représenté par sa valeur last (ou first). Un volume est une quantité échangée, donc un mois est la sum. Une amplitude utilise max et min. Les étiquettes suivent la règle : "ME" étiquette un mois par son dernier jour calendaire, même si c'est un samedi, et "W-FRI" étiquette une semaine par son vendredi.

volume = pd.Series([10, 20, 30, 40, 50, 60, 70, 80], index=daily.index)

print(volume.resample("ME").sum().to_dict())
# {Timestamp('2026-02-28 00:00:00'): 60, Timestamp('2026-03-31 00:00:00'): 300}

# Several summaries at once
print(daily.resample("ME").agg(["first", "last", "max"]))
#             first   last    max
# 2026-02-28  100.0  103.0  103.0
# 2026-03-31  102.0  106.0  106.0

Barres à partir de ticks, et sur-échantillonnage

Les graphiques et les modèles utilisent des barres OHLC : l'ouverture (premier prix), le plus haut, le plus bas et la clôture (dernier prix) de chaque période. resample("D").ohlc() les construit à partir de prix intrajournaliers en un appel. Les jours calendaires sans aucune transaction, comme les week-ends, apparaissent quand même en lignes de NaN : terminez par dropna() si vous ne voulez que les jours négociés. Le sur-échantillonnage va dans l'autre sens : resample("D").ffill() répète la dernière valeur connue les jours sans données, ce que signifie vraiment un prix coté chaque semaine. N'utilisez jamais bfill pour des prix : il recopie une valeur future vers le passé et fait fuiter l'information de demain dans aujourd'hui.

times = ["2026-03-05 09:30", "2026-03-05 11:00", "2026-03-05 15:59",
         "2026-03-09 09:30", "2026-03-09 12:00", "2026-03-09 15:59"]
ticks = pd.Series([100.0, 101.5, 99.8, 100.7, 102.0, 101.0], index=pd.to_datetime(times))

bars = ticks.resample("D").ohlc()
print(bars)
#              open   high    low  close
# 2026-03-05  100.0  101.5   99.8   99.8
# 2026-03-06    NaN    NaN    NaN    NaN
# 2026-03-07    NaN    NaN    NaN    NaN
# 2026-03-08    NaN    NaN    NaN    NaN
# 2026-03-09  100.7  102.0  100.7  101.0

print(bars.dropna().index.strftime("%d %b").tolist())   # ['05 Mar', '09 Mar']   only the days that traded
# Upsampling: observations on the 2nd, 6th and 10th, spread over every day with ffill
weekly = pd.Series([100.0, 103.0, 101.0], index=pd.to_datetime(["2026-03-02", "2026-03-06", "2026-03-10"]))

print(weekly.resample("D").ffill().tolist())
# [100.0, 100.0, 100.0, 100.0, 103.0, 103.0, 103.0, 103.0, 101.0]

print(int(weekly.resample("D").mean().isna().sum()))   # 6   without a fill rule the new days are empty
Le rééchantillonnage peut faire fuiter le futurUne barre mensuelle n'est connue qu'à la fin du mois. Si vous associez la clôture de fin de mois au premier jour de ce mois, une stratégie semble connaître le futur. Gardez l'étiquette à la fin de la période, comme le fait "ME", utilisez ffill (jamais bfill) pour le sur-échantillonnage, et décalez un signal mensuel avant de l'utiliser sur des données quotidiennes.
  • series.resample(règle) décrit les périodes ("D", "W-FRI", "ME", "h") ; l'agrégation qui suit calcule les valeurs.
  • Prix : last ou ohlc() ; volumes : sum ; les périodes vides apparaissent en NaN, que dropna() retire.
  • Le sur-échantillonnage demande une règle de remplissage : ffill() répète la dernière valeur connue ; jamais bfill() pour des prix, il fait fuiter le futur.

À suivre : les fenêtres glissantes, des statistiques comme les moyennes mobiles, calculées sur une fenêtre glissante des périodes récentes.

Lab : ce qui est noté

  • Prendre le dernier prix de chaque mois avec month_end_close25 pts
  • Totaliser le volume de chaque semaine avec weekly_volume25 pts
  • Construire des barres quotidiennes à partir de prix intrajournaliers avec daily_ohlc25 pts
  • Étaler des observations irrégulières sur chaque jour avec fill_to_daily25 pts
Explorateur · lab-46-1
▾ lab-46-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-46-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

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