σμ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 5 · Optimisation de portefeuille›Sujet 5.4·~55 minIntermédiaire

Optimisation moyenne-variance

Position dans le parcoursModule 5 sur 11 · Sujet 4 sur 5
5.4 Optimisation moyenne-variance
—Score du lab— / 100XP total—Série—

Rendement et risque en un seul nombre

La variance minimale ignore les rendements. L'optimisation moyenne-variance (Markowitz) utilise les deux : un investisseur veut un rendement espéré w @ mu élevé et une variance w @ cov @ w faible. Une façon simple de les arbitrer est l'utilité w @ mu - 0.5 * lambda * w @ cov @ w, où lambda est l'aversion au risque : plus elle est grande, plus une unité de variance coûte. Deux investisseurs ayant les mêmes anticipations mais un lambda différent choisissent des portefeuilles différents, et le meilleur portefeuille de chacun est le maximum d'une fonction lisse et concave.

import numpy as np

mu = np.array([0.08, 0.05, 0.10])                         # expected annual returns
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])

def utility(weights, mu, cov, risk_aversion):
    return weights @ mu - 0.5 * risk_aversion * weights @ cov @ weights

equal = np.full(3, 1 / 3)
print(round(float(equal @ mu), 4), round(float(equal @ cov @ equal), 4))      # 0.0767 0.0121
print(round(float(utility(equal, mu, cov, 4.0)), 4))                          # 0.0526

La meilleure position pour une aversion donnée

Sans contrainte budgétaire (le reste de l'argent rapporte le taux sans risque, pris ici nul en excès), la meilleure position est celle où le gradient mu - lambda * cov @ w s'annule : w = cov^-1 * mu / lambda. En code, np.linalg.solve(cov, mu) / lambda. Cela se met à l'échelle comme le bon sens le veut : aversion double, position moitié. La somme des poids est ce qu'elle doit être ; le reste, 1 - w.sum(), est en liquidités.

# The best position for several risk aversions: more aversion, smaller bets
import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])

for aversion in (5.0, 10.0, 20.0):
    w = np.linalg.solve(cov, mu) / aversion
    print(aversion, np.round(w, 3), "invested", round(float(w.sum()), 3))

Le portefeuille tangent

Avec un actif sans risque, tous les investisseurs détiennent le même panier risqué, en quantités différentes. Ce panier est celui au ratio de Sharpe (w @ mu - rf) / sqrt(w @ cov @ w) maximal, le portefeuille tangent : w proportionnel à cov^-1 * (mu - rf), remis à l'échelle pour sommer à 1. L'investisseur prudent n'y met qu'une partie de son argent et le reste en liquidités ; l'audacieux emprunte pour en détenir davantage. Décider du niveau de risque et choisir les actifs risqués sont deux problèmes distincts.

# The tangency portfolio: no other mix of the three assets has a higher Sharpe ratio
import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])
rf = 0.02

x = np.linalg.solve(cov, mu - rf)
best = x / x.sum()

def sharpe(w):
    return (w @ mu - rf) / np.sqrt(w @ cov @ w)

rng = np.random.default_rng(1)
trials = rng.normal(size=(2000, 3))
trials = trials / trials.sum(axis=1, keepdims=True)
print(np.round(best, 4), round(float(sharpe(best)), 4))
print(round(max(float(sharpe(w)) for w in trials), 4))      # the best of 2000 random mixes comes close, never above

Viser un rendement cible

Une autre façon de poser la question : parmi tous les portefeuilles de somme 1 ayant un rendement espéré donné, lequel a la plus petite variance ? Avec deux contraintes, la solution est une combinaison des deux vecteurs résolus s1 = cov^-1 * 1 et sm = cov^-1 * mu, avec des coefficients tirés de quatre nombres a, b, c, d qui résument le marché. Chaque rendement cible donne un portefeuille ; tracer le risque de tous est la frontière efficiente du prochain sujet.

# Minimum-variance portfolios for three target returns
import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])
ones = np.ones(3)
s1, sm = np.linalg.solve(cov, ones), np.linalg.solve(cov, mu)
a, b, c = ones @ s1, ones @ sm, mu @ sm
d = a * c - b ** 2

for target in (0.06, 0.08, 0.09):
    w = ((c - b * target) * s1 + (a * target - b) * sm) / d
    print(target, np.round(w, 3), round(float(w @ mu), 4), round(float(np.sqrt(w @ cov @ w)), 4))
L'optimiseur maximise vos erreursLes poids moyenne-variance sont très sensibles à mu : un petit changement d'un rendement espéré peut faire passer le portefeuille d'un actif à un autre. L'optimiseur fait entièrement confiance aux données, donc tout rendement surestimé devient une grosse position. En pratique, on rétrécit les rendements, on borne les poids, et les données viennent de modèles ou de vues plutôt que de moyennes passées brutes. La moyenne-variance est un bon outil de réflexion et un outil dangereux en aveugle.
  • L'utilité est w @ mu - 0.5 * lambda * w @ cov @ w ; la meilleure position sans budget est solve(cov, mu) / lambda, et doubler lambda la divise par deux.
  • Avec un actif sans risque, le meilleur panier risqué est le portefeuille tangent solve(cov, mu - rf), remis à l'échelle pour sommer à 1 : le ratio de Sharpe maximal.
  • Pour un rendement cible, les poids de variance minimale combinent solve(cov, ones) et solve(cov, mu) ; le résultat ne vaut que ce que vaut le mu estimé.

À suivre : la frontière efficiente, la courbe du meilleur risque pour chaque niveau de rendement.

Lab : ce qui est noté

  • Noter un portefeuille avec utility25 pts
  • Trouver la meilleure position avec utility_weights25 pts
  • Maximiser le ratio de Sharpe avec tangency_weights25 pts
  • Atteindre un objectif de rendement avec target_return_weights25 pts
Explorateur · lab-85-1
▾ lab-85-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-85-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

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