σμ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 7 · Recherche d'alpha et risque›Sujet 7.8·~1 hAvancé

Modèles ARIMA

Position dans le parcoursModule 7 sur 11 · Sujet 8 sur 9
7.8 Modèles ARIMA
—Score du lab— / 100XP total—Série—

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 return

Diffé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 halves

Ajuster 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))
Prévoir n'est pas négocierUn 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 k est la corrélation de la série avec elle-même k pas plus tôt ; une décroissance lente suggère un modèle AR.
  • Un ajustement AR(1) est une régression de x[1:] sur x[:-1] ; les prévisions se nourrissent les unes des autres et convergent vers c / (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
Explorateur · lab-100-1
▾ lab-100-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-100-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

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