Une série qui se souvient d'elle-même
De nombreuses séries portent de l'information sur leur propre avenir. Les spreads de taux, la volatilité, l'écart entre deux prix liés reviennent vers un niveau plutôt que de vagabonder librement. Les modèles ARIMA le capturent avec trois idées : I, différencier la série pour la rendre stationnaire ; AR, la régresser sur ses propres retards ; MA, utiliser les erreurs de prévision récentes. Les rendements d'actions eux-mêmes ne montrent presque aucune mémoire de ce type, donc ARIMA convient aux séries persistantes ou à retour à la moyenne.
import numpy as np
prices = np.array([100.0, 101.5, 103.2, 104.1, 106.0, 107.2])
print(np.diff(prices)) # first differences: the changes [1.5 1.7 0.9 1.9 1.2]
print(np.diff(prices, n=2)) # second differences: the change of the changes
print(np.diff(np.log(prices))) # the differenced log price is the log returnDifférenciation et autocorrélation
Les prix errent et n'ont pas de moyenne stable ; leurs variations en ont souvent une. Prendre la première différence (ordre d = 1) supprime une tendance, une seconde (d = 2) une tendance courbe. La fonction d'autocorrélation (ACF) montre alors la mémoire : sa valeur au retard k est la corrélation de la série avec elle-même k pas plus tôt, sum((x[t] - m) * (x[t+k] - m)) / sum((x[t] - m)**2). Une ACF qui décroît lentement suggère un modèle AR ; une ACF proche de zéro à tous les retards signifie qu'il n'y a rien à prévoir.
# The ACF of a persistent series decays slowly; the ACF of noise is near zero
import numpy as np
def acf(series, lags):
dev = series - series.mean()
total = np.sum(dev ** 2)
return np.array([np.sum(dev[:len(series) - k] * dev[k:]) / total for k in range(1, lags + 1)])
rng = np.random.default_rng(1)
noise = rng.normal(size=500)
persistent = np.empty(500)
persistent[0] = 0.0
for t in range(1, 500):
persistent[t] = 0.8 * persistent[t - 1] + noise[t] # an AR(1) with phi = 0.8
print(np.round(acf(persistent, 4), 3)) # decays slowly: 0.74, 0.58, 0.48, 0.39 in this sample
print(np.round(acf(noise, 4), 3)) # all near 0# Differencing a trending series makes its mean stable
import numpy as np
rng = np.random.default_rng(6)
trend = 100 + 0.5 * np.arange(200) + rng.normal(0, 1, size=200).cumsum() # a trending random walk
changes = np.diff(trend)
print(round(float(trend[:100].mean()), 1), round(float(trend[100:].mean()), 1)) # the level drifts: the halves differ a lot
print(round(float(changes[:100].mean()), 2), round(float(changes[100:].mean()), 2)) # the changes have a similar mean in both halvesAjuster un AR(1) et prévoir
Un AR(1) dit x[t] = c + phi * x[t-1] + bruit. C'est une régression en droite de chaque valeur sur la précédente : phi est la pente et c l'ordonnée, avec les mêmes sommes que le bêta du sujet MEDAF. La prévision est récursive : le premier pas est c + phi * last, et chaque suivant utilise la prévision précédente. Pour |phi| < 1, les prévisions convergent vers la moyenne de long terme c / (1 - phi), à une vitesse fixée par phi : une série à retour à la moyenne.
import numpy as np
def fit_ar1(series):
a, b = series[:-1], series[1:]
phi = np.sum((a - a.mean()) * (b - b.mean())) / np.sum((a - a.mean()) ** 2)
return float(b.mean() - phi * a.mean()), float(phi)
def forecast_ar1(last, c, phi, steps):
out, value = [], last
for _ in range(steps):
value = c + phi * value
out.append(value)
return np.array(out)
rng = np.random.default_rng(3)
x = np.empty(400)
x[0] = 2.0
for t in range(1, 400):
x[t] = 0.5 + 0.75 * x[t - 1] + rng.normal(0, 0.3) # true c = 0.5, phi = 0.75, mean 2.0
c, phi = fit_ar1(x)
print(round(c, 3), round(phi, 3))
print(np.round(forecast_ar1(4.0, c, phi, 5), 3), round(c / (1 - phi), 3))phi statistiquement significatif sur un spread ne garantit pas un profit : les coûts, la taille du mouvement face au bruit et l'instabilité de l'estimation comptent. Gardez la discipline habituelle : ajuster sur une période, prévoir la suivante et comparer à la prévision naïve « pas de changement ». Un modèle qui ne la bat pas n'a rien trouvé.- ARIMA = différenciation (I) + autorégression (AR) + erreurs passées (MA) ; la différenciation transforme une série à tendance en série stationnaire.
- L'ACF au retard
kest la corrélation de la série avec elle-mêmekpas plus tôt ; une décroissance lente suggère un modèle AR. - Un ajustement AR(1) est une régression de
x[1:]surx[:-1]; les prévisions se nourrissent les unes des autres et convergent versc / (1 - phi)si|phi| < 1; battez toujours la prévision « sans changement ».
À suivre : les modèles de volatilité GARCH, prévoir non le niveau des rendements mais l'ampleur de leurs mouvements.
Lab : ce qui est noté
- Retirer la tendance avec
difference25 pts - Mesurer la mémoire avec
acf25 pts - Ajuster le modèle avec
fit_ar125 pts - Regarder devant avec
forecast_ar125 pts