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

Broadcasting

Position dans le parcoursModule 2 sur 11 · Sujet 4 sur 20
2.4 Broadcasting
—Score du lab— / 100XP total—Série—

Des tableaux de formes différentes qui travaillent ensemble

Jusqu'ici nous combinions des tableaux de même forme. Le broadcasting est l'ensemble des règles qui permet à NumPy de combiner des tableaux de formes différentes sans copier de données. Le cas le plus simple est un scalaire : a + 10 ajoute 10 à chaque élément, comme si 10 avait été étiré à la forme de a. Le même étirement fonctionne entre tableaux : un vecteur de trois nombres peut s'ajouter à chaque ligne d'une matrice de trois colonnes, une valeur par colonne. C'est ainsi que l'on retranche la moyenne de chaque colonne, que l'on met chaque actif à l'échelle de sa volatilité ou que l'on construit un tableau de toutes les différences deux à deux sans une seule boucle.

import numpy as np

a = np.array([[1.0, 2.0, 3.0],
              [4.0, 5.0, 6.0]])       # shape (2, 3)

print(a + 10)                          # a scalar is stretched to every element
# [[11. 12. 13.]
#  [14. 15. 16.]]

per_column = np.array([1, 10, 100])    # shape (3,): one value per column
print(a * per_column)
# [[  1.  20. 300.]
#  [  4.  50. 600.]]

print(a - a.mean(axis=0))              # subtract each column's mean
# [[-1.5 -1.5 -1.5]
#  [ 1.5  1.5  1.5]]

La règle : comparer les formes à partir de la droite

NumPy aligne les deux formes à partir de la droite. À chaque position, les deux tailles doivent être égales, ou l'une doit valoir 1 (elle est alors étirée), ou l'un des tableaux n'a simplement pas de dimension à cet endroit (traitée comme 1). Les formes (2, 3) et (3,) conviennent : 3 rencontre 3, et la dimension manquante est étirée sur les 2 lignes. Les formes (2, 3) et (2,) échouent, car 3 rencontre 2 : NumPy lève ValueError: operands could not be broadcast together. La forme du résultat prend la plus grande taille à chaque position.

import numpy as np

a = np.ones((2, 3))
print((a + np.ones(3)).shape)        # (2, 3)   3 meets 3

try:
    a + np.ones(2)                   # 3 meets 2: no match
except ValueError as error:
    print(error)                     # operands could not be broadcast together with shapes (2,3) (2,)

# Size 1 stretches: (3, 1) with (1, 4) gives (3, 4)
print((np.ones((3, 1)) + np.ones((1, 4))).shape)   # (3, 4)

Vecteurs colonnes et tableaux de paires

Un tableau 1-D de forme (n,) s'aligne toujours sur le dernier axe : il se comporte comme une ligne. Pour appliquer une valeur par ligne, il faut une colonne de forme (n, 1) : écrivez x[:, np.newaxis] ou x.reshape(-1, 1). Combiner une colonne et une ligne construit un tableau entier : x[:, None] - x[None, :] est la matrice n×n de toutes les différences x[i] - x[j], et corr * vols[:, None] * vols[None, :] transforme une matrice de corrélation en matrice de covariance. Attention à l'erreur inverse : additionner des formes (3,) et (3, 1) donne silencieusement un tableau 3×3, pas un vecteur de trois nombres.

import numpy as np

x = np.array([1.0, 2.0, 4.0])
print(x[:, np.newaxis].shape, x.reshape(-1, 1).shape, x[None, :].shape)   # (3, 1) (3, 1) (1, 3)

# All pairwise differences x[i] - x[j]
print(x[:, None] - x[None, :])
# [[ 0. -1. -3.]
#  [ 1.  0. -2.]
#  [ 3.  2.  0.]]

# One factor per row needs a column
a = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
print(a * np.array([1.0, 2.0])[:, None])
# [[ 1.  2.  3.]
#  [ 8. 10. 12.]]

# Correlation matrix to covariance matrix
corr = np.array([[1.0, 0.5], [0.5, 1.0]])
vols = np.array([0.2, 0.3])
print(corr * vols[:, None] * vols[None, :])
# [[0.04 0.03]
#  [0.03 0.09]]

print((np.ones(3) + np.ones((3, 1))).shape)   # (3, 3)  a silent table, not a vector
import numpy as np

# Standardise every column at once: (x - mean) / std, column by column
a = np.array([[1.0, 10.0],
              [2.0, 20.0],
              [3.0, 30.0]])
z = (a - a.mean(axis=0)) / a.std(axis=0)   # (3, 2) - (2,) -> (3, 2), then divided by (2,)
print(z.round(3).tolist())                 # [[-1.225, -1.225], [0.0, 0.0], [1.225, 1.225]]
print(z.mean(axis=0).round(9).tolist())    # [0.0, 0.0]

# keepdims keeps the reduced axis, so the result can be broadcast back by row too
row_share = a / a.sum(axis=1, keepdims=True)
print(row_share.sum(axis=1).tolist())      # [1.0, 1.0, 1.0]
Affichez les formes avant de combinerLe broadcasting ne se plaint jamais quand les formes s'accordent, même si le résultat n'est pas celui voulu. Avant de combiner des tableaux, notez les formes et celle que vous attendez ; ensuite, vérifiez result.shape. Un résultat (n, n) là où l'on attendait (n,), ou un tableau de milliards d'entrées à partir de deux longs vecteurs, est le signe classique d'un [:, None] oublié ou en trop. Le résultat est construit en mémoire : deux vecteurs de 100 000 valeurs font un tableau de 10 milliards d'entrées.
  • Les formes s'alignent à partir de la droite : les tailles doivent être égales ou 1 (ou absentes) ; le résultat prend la plus grande.
  • (n,) se comporte comme une ligne ; faites une colonne avec x[:, None] ou x.reshape(-1, 1).
  • Colonne avec ligne = un tableau : x[:, None] - x[None, :] ; vérifiez result.shape, les écarts échouent avec ValueError.

À suivre : les Series pandas, des tableaux à une dimension qui portent une étiquette avec chaque valeur.

Lab : ce qui est noté

  • Centrer chaque colonne avec demean_columns25 pts
  • Donner à chaque ligne son propre facteur avec scale_rows25 pts
  • Construire le tableau de toutes les différences avec pairwise_differences25 pts
  • Transformer des corrélations en covariances avec covariance_from_correlation25 pts
Explorateur · lab-37-1
▾ lab-37-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-37-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

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