σμ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.3·~45 minDébutant

Vectorisation

Position dans le parcoursModule 2 sur 11 · Sujet 3 sur 20
2.3 Vectorisation
—Score du lab— / 100XP total—Série—

Penser en tableaux entiers, pas en éléments

La vectorisation consiste à écrire un calcul comme des opérations sur des tableaux entiers et à laisser NumPy exécuter la boucle en code compilé rapide. a + b additionne deux tableaux élément par élément, a * b les multiplie, a ** 2 met chaque élément au carré et np.sqrt(a) extrait chaque racine carrée. Ce sont des fonctions universelles (ufuncs). Le résultat est plus court à écrire, plus lisible et, sur de grandes données, souvent cinquante fois plus rapide que la boucle Python for équivalente, qui paie le coût de l'interpréteur pour chaque élément.

import numpy as np

a = np.array([1.0, 2.0, 3.0])
b = np.array([10.0, 20.0, 30.0])

print(a + b)             # [11. 22. 33.]
print(a * b)             # [10. 40. 90.]
print(a ** 2)            # [1. 4. 9.]
print(np.sqrt(a))        # [1.         1.41421356 1.73205081]

# The loop version of a * b, which vectorisation replaces
result = np.empty(3)
for i in range(3):
    result[i] = a[i] * b[i]
print(result)            # [10. 40. 90.]

Des rendements sans boucle : décalage par tranches

Un calcul qui compare chaque élément à son voisin a besoin d'une seconde copie du tableau décalée d'un cran, et les tranches la fournissent gratuitement. p[1:] est le prix d'aujourd'hui et p[:-1] celui d'hier, tous deux de longueur n - 1 : les rendements simples sont donc p[1:] / p[:-1] - 1. La même paire donne les différences (p[1:] - p[:-1], ou np.diff(p)). Les sommes et produits cumulés sont np.cumsum et np.cumprod ; une trajectoire de croissance est np.cumprod(1 + returns). Les comparaisons de tableaux entiers (r > 0) et np.where(condition, si_vrai, si_faux) remplacent le if dans une boucle.

import numpy as np

p = np.array([100.0, 102.0, 101.0, 103.0])

returns = p[1:] / p[:-1] - 1                 # today / yesterday - 1, no loop
print(np.round(returns, 4))                  # [ 0.02   -0.0098  0.0198]
print(np.diff(p))                            # [ 2. -1.  2.]
print(np.cumprod(1 + np.array([0.01, 0.02])))   # [1.01   1.0302]

# np.where replaces if/else inside a loop
r = np.array([0.01, -0.02, 0.03, -0.01])
print(np.where(r > 0, "up", "down"))         # ['up' 'down' 'up' 'down']
print(np.where(r > 0, r, 0.0))               # [0.01 0.   0.03 0.  ]

Agrégations selon un axe, et produits matriciels

Des fonctions comme sum, mean, std, min et max réduisent un tableau. Avec un tableau 2-D de rendements (une ligne par jour, une colonne par actif), axis=0 réduit les lignes et donne une valeur par colonne (la moyenne de chaque actif dans le temps), tandis que axis=1 donne une valeur par ligne (la moyenne de chaque jour sur les actifs). Le produit matriciel R @ w, d'un tableau (jours, actifs) par un vecteur de poids de longueur actifs, donne le rendement du portefeuille de chaque jour en un seul appel : c'est le produit scalaire du sujet sur les vecteurs, fait pour toutes les lignes à la fois.

import numpy as np

# 2 days x 3 assets
R = np.array([[0.02, -0.01, 0.03],
              [0.01,  0.00, 0.02]])
w = np.array([0.5, 0.3, 0.2])

print(R.shape)            # (2, 3)
print(R.mean(axis=0))     # [ 0.015 -0.005  0.025]   one value per asset
print(R.sum(axis=1))      # [0.04 0.03]              one value per day
print(R @ w)              # [0.013 0.009]            portfolio return each day

# Standardise: how many standard deviations from the mean?
z = np.array([1.0, 2.0, 3.0, 4.0])
print((z - z.mean()) / z.std())   # [-1.34164079 -0.4472136   0.4472136   1.34164079]

Moyennes mobiles avec cumsum, et les limites de la vectorisation

Une moyenne mobile sur une fenêtre w semble exiger une boucle, mais avec un total cumulé ce n'est pas le cas : placez un 0 devant np.cumsum(x) et la somme de w valeurs consécutives est une différence de deux totaux cumulés, cs[w:] - cs[:-w] ; divisez par w. Le résultat contient len(x) - w + 1 valeurs. Vectorisez l'arithmétique, pas la logique qui dépend du résultat précédent (une position qui dépend de l'exécution d'hier, par exemple) : celle-ci reste dans une boucle, ou passe plus tard à des outils compilés comme Numba. Surveillez aussi la mémoire, car chaque tableau intermédiaire est une copie complète.

import numpy as np

x = np.array([1.0, 2.0, 4.0, 8.0, 16.0])
w = 3

cs = np.concatenate(([0.0], np.cumsum(x)))   # [0, 1, 3, 7, 15, 31]
print((cs[w:] - cs[:-w]) / w)                # [2.33333333 4.66666667 9.33333333]

# Check against the plain definition
print([x[i:i + w].mean() for i in range(len(x) - w + 1)])   # three values, the same
Vectorisez, puis comparez à la version lenteUn calcul rapide mais faux est pire qu'un calcul lent mais juste. Gardez la version évidente avec boucle, écrivez la version vectorisée et comparez-les avec np.allclose(rapide, lent) sur des données aléatoires avant de vous y fier. Soignez aussi les bords : un tableau vide, un seul élément, une série constante (écart type nul, donc un z-score divise par zéro) et des valeurs nan méritent une décision, pas un plantage ni un nombre faux silencieux.
  • Les opérations sur tableaux entiers (a + b, a ** 2, np.sqrt(a)) remplacent les boucles ; comparez avec np.where.
  • Tranches décalées : p[1:] / p[:-1] - 1 ; cumsum et cumprod pour les totaux cumulés et la croissance.
  • axis=0 réduit les lignes (par colonne), axis=1 réduit les colonnes (par ligne) ; R @ w est un produit scalaire par ligne.

À suivre : le broadcasting, la règle qui permet à des tableaux de formes différentes de travailler ensemble.

Lab : ce qui est noté

  • Calculer tous les rendements d'un coup avec simple_returns25 pts
  • Obtenir le rendement du portefeuille de chaque jour avec portfolio_returns25 pts
  • Lisser une série sans boucle avec moving_average25 pts
  • Standardiser des valeurs avec zscore25 pts
Explorateur · lab-36-1
▾ lab-36-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-36-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

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