Une fenêtre qui glisse
Le prix du jour signifie peu à lui seul ; les traders le comparent au passé récent. Une fenêtre glissante garde les n dernières observations et avance d'un pas à la fois, si bien que chaque date reçoit une statistique calculée sur son propre passé récent : une moyenne mobile, une volatilité récente, un plus haut récent. Avec pandas, series.rolling(n) décrit la fenêtre et une statistique comme .mean() la calcule à chaque position d'un coup.
import pandas as pd
prices = pd.Series(
[100.0, 102, 101, 105, 107, 106, 110],
index=pd.bdate_range("2026-03-02", periods=7),
name="close",
)
moving_average = prices.rolling(3).mean()
print(moving_average.round(2).tolist())
# [nan, nan, 101.0, 102.67, 104.33, 106.0, 107.67]
print(prices.rolling(3).max().tolist()) # [nan, nan, 102.0, 105.0, 107.0, 107.0, 110.0] the 3-day highLe début de la série
Les n - 1 premières positions n'ont pas encore de fenêtre complète, le résultat y est donc NaN. C'est honnête : la moyenne de deux prix n'est pas une moyenne sur 3 jours. Si vous voulez vraiment une valeur plus tôt, min_periods=1 calcule avec ce qui est disponible, et expanding() utilise tout depuis le début au lieu d'une fenêtre fixe. Les statistiques qui demandent plusieurs points, comme l'écart type, restent NaN tant qu'il n'y a pas assez d'observations. Une série qui commence déjà par NaN, comme les rendements simples, repousse d'un cran la première fenêtre valide.
# min_periods=1: use whatever is available at the start
print(prices.rolling(3, min_periods=1).mean().round(2).tolist()) # [100.0, 101.0, 101.0, 102.67, 104.33, 106.0, 107.67]
# expanding(): everything since the first day, not a fixed window
print(prices.expanding().mean().round(2).tolist()) # [100.0, 101.0, 101.0, 102.0, 103.0, 103.5, 104.43]
# Rolling volatility of the returns: the first return is NaN, so three returns exist only from the 4th day
returns = prices.pct_change()
print(returns.rolling(3).std().round(4).tolist()) # [nan, nan, nan, 0.0249, 0.0248, 0.0246, 0.0237]Des fenêtres aux signaux
Les statistiques glissantes deviennent des signaux de trading quand on les compare. Un z-score dit à quelle distance le prix du jour se trouve de sa propre moyenne récente, en unités de son écart type récent : (price - rolling mean) / rolling std. Construisez l'objet glissant une fois (r = prices.rolling(3)) et utilisez-le deux fois. Un croisement de moyennes mobiles compare une moyenne rapide à une lente : tant que la rapide est au-dessus, la tendance récente est haussière. Une comparaison donne des booléens, et astype("int64") les transforme en signal 0/1. Les comparaisons avec NaN valent False, donc le signal vaut 0 tant que les deux moyennes n'existent pas.
# z-score of each price against its own 3-day window
rolling = prices.rolling(3)
zscore = (prices - rolling.mean()) / rolling.std()
print(zscore.round(2).tolist()) # [nan, nan, 0.0, 1.12, 0.87, 0.0, 1.12]# Moving-average crossover: 1 while the 2-day average is above the 4-day average
fast = prices.rolling(2).mean()
slow = prices.rolling(4).mean()
signal = (fast > slow).astype("int64")
print(signal.tolist()) # [0, 0, 0, 1, 1, 1, 1]
# Trade on the next day: the signal of today's close cannot be traded before tomorrow
print(signal.shift(1).fillna(0).astype("int64").tolist()) # [0, 0, 0, 0, 1, 1, 1]center=True place la ligne courante au milieu de la fenêtre et utilise donc des prix futurs : c'est superbe sur un graphique et impossible à trader. Un signal calculé sur la clôture du jour doit être appliqué demain, d'où shift(1).series.rolling(n).mean()(oustd(),max()...) calcule une statistique sur lesndernières observations à chaque position.- Les
n - 1premières entrées sontNaN;min_periodsetexpanding()changent cela volontairement. - Les z-scores et les croisements de moyennes mobiles transforment les fenêtres en signaux ; décalez un signal avant de l'exploiter et évitez
center=True.
À suivre : la gestion des données manquantes, que faire des valeurs NaN que contiennent toujours les vrais tableaux de prix.
Lab : ce qui est noté
- Lisser les prix avec
moving_average25 pts - Mesurer le risque récent avec
rolling_volatility25 pts - Standardiser chaque prix par rapport à sa fenêtre avec
rolling_zscore25 pts - Transformer deux moyennes en signal avec
ma_crossover25 pts