<< Sommaire QC | Précédent : QC-Py-Cloud-06-PCA-StatArb << | Suivant : QC-Py-Cloud-07-TemporalCNN >>

QC-Py-Cloud-13 – Volatility Targeting : Risk Management by Volatility Scaling

Module: Hands-On AI Trading, Ch.10 – Volatility Targeting & Risk Management

Objectif: Implementer et comparer des variantes de volatility targeting (ciblage de volatilite) sur un univers multi-actifs, en demontrant l’impact du contrôle de volatilite sur le ratio rendement/risque.

Approche cloud-native: L’algorithme est execute sur QuantConnect Cloud. Les résultats sont syncs ci-dessous.

Note de conception : Ce notebook est un descriptif pedagogique. Le code executable se trouve dans le projet QuantConnect Cloud correspondant (voir le lien dans le notebook). L’absence d’outputs est intentionnelle.

1. Concept : Volatility Targeting

Le volatility targeting (ciblage de volatilite) ajuste l’exposition d’un portefeuille pour maintenir un niveau de volatilite constant. L’idee est simple : quand la volatilite augmente, on reduit les positions ; quand elle diminue, on les augmente.

Formule : weight = target_vol / realized_vol

Ou : - target_vol : volatilite annuelle cible (ex: 10-12%) - realized_vol : volatilite realisee sur une fenêtre glissante (ex: 21 jours) - weight : fraction du capital alloue

Pourquoi ca fonctionne

La volatilite des marches est heteroscedastique : elle varie dans le temps, avec des periodes de haute volatilite (crises) et de basse volatilite (bull markets calmes). Le volatility targeting exploite cette propriete :

  1. En periode de haute volatilite (crises, bear markets) : les positions sont reduites, limitant les pertes
  2. En periode de basse volatilite (bull markets calmes) : les positions sont augmentees, captant plus de rendement
  3. Lissage des rendements : le portefeuille a une volatilite plus stable, ce qui ameliore le Sharpe ratio

Reference academique

Moreira et Muir (2017) ont montre que le volatility targeting ameliore les Sharpe ratios dans la plupart des classes d’actifs. L’intuition : la volatilite est predictive de la volatilite future (clustering), mais pas du rendement futur. Donc reduire l’exposition quand la vol est haute ne coute pas en rendement espere, mais reduit le risque.

Tension pedagogique : vol targeting vs simple allocation

Le volatility targeting semble elegant en théorie. Mais en pratique : - Le choix de la fenêtre de volatilite (21, 63, 126 jours) change les résultats - Les caps (min/max allocation) sont cruciaux pour eviter les leviers extremes - Sur un seul actif (SPY), le vol targeting ne diversifie pas – il ajuste juste l’exposition

Exercice 1 : Calcul du poids de volatilite targeting

Le volatility targeting ajuste l’exposition selon la formule weight = target_vol / realized_vol. Quand la vol est haute, on reduit les positions ; quand elle est basse, on les augmente.

Objectif : Implementez vol_target_weight(realized_vol, target_vol=0.10, caps=(0.3, 1.5)) qui calcule le poids avec des bornes min/max. Testez avec différentes valeurs de vol realisee.

Indices : - Indice : Poids = 0.10 / vol_realisee. Si vol = 0.05, poids = 2.0 mais plafonne a 1.5. - Indice : Les caps evitent un levier excessif en basse vol et une sous-exposition en haute vol.

# Exercice 1 : Calcul du poids de volatilite targeting
# TODO etudiant : implementer vol_target_weight(realized_vol, target_vol, caps)
# Indice : weight = target_vol / realized_vol, clip entre caps

import numpy as np

def vol_target_weight(realized_vol, target_vol=0.10, caps=(0.3, 1.5)):
    # TODO etudiant : calculer le poids et appliquer les bornes
    return None  # TODO etudiant : retourner le poids borne

# Test avec differentes valeurs de vol
test_vols = [0.05, 0.08, 0.10, 0.15, 0.25, 0.40]
result_vt = None  # TODO etudiant : calculer les poids pour chaque vol
print("Exercice a completer : volatilite targeting poids")

2. Les trois variantes

v1 – Single Asset Vol Targeting (SPY)

Paramètre Valeur
Univers SPY seul
Target vol 12% annuel
Lookback 21 jours (realized vol)
Allocation weight = 0.12 / realized_vol
Caps [30%, 150%]
Rebalance Mensuel

Version la plus simple : on ajuste l’exposition a SPY selon sa volatilite recente. Quand la vol monte (crise), on reduit. Quand elle baisse (bull calme), on augmente (jusqu’a 150% = levier 1.5x).

v2 – Multi-Asset Equal Risk Contribution

Paramètre Valeur
Univers SPY, QQQ, IEF, GLD
Target vol 10% annuel (portefeuille)
Lookback 21 jours
Allocation Inverse-vol weighted (equal risk)
Caps [0%, 50%] par actif
Rebalance Mensuel

Extension multi-actifs : chaque actif recoit un poids proportionnel a l’inverse de sa volatilite, de sorte que chaque actif contribue equitablement au risque total. Le poids total est ensuite ajuste pour cibler 10% de vol.

v3 – Vol Targeting + Momentum Filter

Paramètre Valeur
Univers SPY, QQQ, IEF, GLD
Target vol 10% annuel
Lookback 21 jours (vol), 126 jours (momentum)
Momentum 6 mois > 0 pour qualifie
Allocation Inverse-vol + momentum filter
Caps [0%, 50%] par actif
Defensif 100% IEF si aucun actif qualifie
Rebalance Mensuel

Ajout d’un filtre de momentum : parmi les 4 actifs, seuls ceux avec un momentum 6 mois positif sont eligibles. Les autres sont exclus. Si aucun actif ne qualifie, 100% en IEF (defensif).

3. Résultats QC Cloud

Projet QC Cloud: 30823845 (Cloud-VolTargeting) Periode: 2014-01-01 au 2025-01-01 (11 ans) Capital initial: $100,000

Version Stratégie Sharpe CAGR MaxDD Net Profit Ordres Win Rate
v1 (Single SPY) Vol target 12% 0.425 10.26% 38.3% +193.0% 86 87%
v2 (Multi-Asset) Equal risk 10% 0.413 6.18% 14.3% +93.4% 332 75%
v3 (Vol+Momentum) Vol target + 6m mom 0.464 7.16% 18.8% +114.0% 236 86%

Benchmark : SPY Buy & Hold

Sur la même periode, SPY a un CAGR ~12.8% et un MaxDD ~24%.

Exercice 2 : Allocation inverse-volatilite multi-actifs

La v2 alloue les poids proportionnellement a l’inverse de la volatilite (equal risk contribution). Chaque actif contribue equitablement au risque total du portefeuille.

Objectif : Implementez inverse_vol_allocation(volatilities, target_vol=0.10) qui calcule les poids inverse-vol pour chaque actif, puis ajuste l’exposition totale pour cibler la vol souhaitee.

Indices : - Indice : Poids inverse-vol normalises doivent sommer a 1, puis multiplier par target_vol / vol_portefeuille. - Indice : La volatilite du portefeuille est la somme ponderee des vols individuelles (approximation).

# Exercice 2 : Allocation inverse-volatilite multi-actifs
# TODO etudiant : implementer inverse_vol_allocation(volatilities, target_vol)
# Indice : normaliser 1/vol pour sommer a 1, puis ajuster pour target_vol

import numpy as np

def inverse_vol_allocation(volatilities, target_vol=0.10):
    # volatilities : {ticker: vol_annuelle}
    # TODO etudiant : calculer poids 1/vol
    # TODO etudiant : ajuster pour cibler target_vol
    return None  # TODO etudiant : retourner {ticker: weight}

vols = {"SPY": 0.15, "QQQ": 0.20, "IEF": 0.06, "GLD": 0.16}
result_inv_vol = None  # TODO etudiant : tester
print("Exercice a completer : allocation inverse-volatilite")

4. Analyse : vol targeting et ses trade-offs

v1 : Le single-asset vol targeting a un MaxDD eleve

La v1 (SPY seul avec vol targeting) atteint un CAGR de 10.26% et un Sharpe de 0.425. Le rendement est correct, mais le MaxDD de 38.3% est catastrophique – pire que SPY buy-and-hold (24%).

Pourquoi : Le levier autorise (jusqu’a 150%) augmente l’exposition pendant les periodes de basse volatilite. En 2017-2019, la vol de SPY etait très basse (~8%), donc le weight = 12%/8% = 150%. Quand la crise COVID a frappe en fevrier 2020, la vol a explose, mais le signal retarde (lookback 21 jours) n’a pas reduit l’exposition assez vite. Le levier a amplifie les pertes.

Le vol targeting seul, sur un seul actif, ne protege pas suffisamment. Il ajuste l’exposition mais ne diversifie pas.

v2 : La diversification multi-actifs reduit le risque

La v2 (multi-asset equal risk) reduit le MaxDD de 38.3% a 14.3% – une division par 2.7. C’est le MaxDD le plus bas de toute la serie cloud. La volatilite annuelle du portefeuille n’est que de 5.6%.

Pourquoi : L’allocation inverse-volatilite repartit le risque equitablement entre SPY (haute vol), QQQ (haute vol), IEF (basse vol) et GLD (vol moyenne). Les actifs defensifs (IEF, GLD) servent de tampon quand les actions chutent.

Le cout : le CAGR tombe a 6.18% et le Net Profit a +93.4%. C’est la stratégie la plus conservative de la serie – un compromis rendement/risque différent des autres.

v3 : Le momentum filter ameliore le Sharpe

La v3 ajoute un filtre de momentum (6 mois > 0) a la v2. Résultat : Sharpe ameliore de 0.413 a 0.464, CAGR de 6.18% a 7.16%, MaxDD de 14.3% a 18.8%.

Pourquoi le momentum aide : Quand un actif a un momentum negatif (bear market), il est exclu du portefeuille. Cela evite d’allouer du capital a des actifs en chute libre, même si leur volatilite basse suggerait une allocation elevee. Le filtre momentum complemente le vol targeting : le vol targeting contrôle le combien, le momentum contrôle le quoi.

Le MaxDD augmente legerement (14.3% a 18.8%) car le portefeuille est plus concentre (moins d’actifs qualifies a un instant donne).

Comparaison des profils risque

Version Ann. Std Dev Beta SPY Win Rate Sortino
v1 14.1% 0.907 87% 0.396
v2 5.6% 0.287 75% 0.438
v3 6.6% 0.326 86% 0.502

La v2 a le beta le plus bas (0.287) et la plus faible volatilite (5.6%). La v3 offre un meilleur ratio Sortino (0.502) grace au filtre momentum qui evite les pertes pendant les bear markets.

5. Lecon principale : le vol targeting ameliore le ratio rendement/risque mais ne bat pas le regime switching

Comparaison avec toutes les stratégies cloud :

Stratégie Sharpe CAGR MaxDD Edge
Risk Parity v4 (Cloud-01) 0.278 6.17% 20.4% Allocation inverse-vol
Sector Rotation v3 (Cloud-02) 0.614 10.76% 15.5% Trend multi-asset
Dual Momentum v2 (Cloud-03) 0.392 8.79% 23.6% Momentum + univers
Mean Reversion v2 (Cloud-04) 0.307 5.89% 14.6% RSI + regime filter
Regime Switch v2 (Cloud-05) 0.622 12.42% 26.8% Regime + momentum
Vol Target v3 (Cloud-06) 0.464 7.16% 18.8% Vol scaling + momentum

Observations :

  1. Le vol targeting est solide mais pas dominant : Sharpe de 0.464, entre le Dual Momentum (0.392) et le Sector Rotation (0.614). Il offre un bon compromis rendement/risque sans etre le meilleur.

  2. Le MaxDD est un point fort : 18.8% pour la v3, mieux que la plupart des stratégies (sauf Mean Reversion a 14.6% et Sector Rotation a 15.5%). Le vol targeting protege effectivement contre les drawdowns extremes.

  3. Le momentum filter est synergique : v3 > v2 sur tous les metrics (Sharpe, CAGR, Sortino) sauf le MaxDD. Combiner vol targeting et momentum est meilleur que chaque signal seul.

  4. Le Risk Parity (Cloud-01) et le Vol Targeting sont proches : Tous deux utilisent une allocation basee sur la volatilite. La différence est que le Risk Parity alloue statiquement (inverse-vol), tandis que le Vol Targeting ajuste dynamiquement (target_vol / realized_vol). Le vol targeting est legerement superieur (0.464 vs 0.278).

  5. Le regime switching (Cloud-05) reste le meilleur : Avec un signal binaire (bull/bear), le regime switching atteint un Sharpe de 0.622. Le vol targeting est plus sophistique mathematiquement mais moins performant. La lecon : un signal simple mais correct (detecter le regime) bat un mécanisme complexe (scaling continu).

  6. Le single-asset vol targeting est dangereux : La v1 (SPY seul) a un MaxDD de 38.3% avec levier. Sans diversification, le vol targeting amplifie les pertes au lieu de les reduire.

Exercice 3 : Combinaison vol targeting + momentum

La v3 combine le vol targeting avec un filtre de momentum (6 mois > 0). Le momentum elimine les actifs en bear market que le vol targeting seul continuerait a devoir.

Objectif : Implementez vol_momentum_strategy(volatilities, momentum_scores, target_vol=0.10) qui filtre d’abord les actifs avec momentum > 0, puis alloue en inverse-vol parmi les eligibles.

Indices : - Indice : Première étape : ne garder que les actifs avec momentum positif. - Indice : Si aucun actif ne qualifie, tout allouer en defensif (IEF).

# Exercice 3 : Combinaison vol targeting + momentum
# TODO etudiant : implementer vol_momentum_strategy
# Indice : filtrer momentum > 0, puis allouer inverse-vol

def vol_momentum_strategy(volatilities, momentum_scores, target_vol=0.10):
    # TODO etudiant : filtrer les actifs avec momentum > 0
    # TODO etudiant : allouer en inverse-vol parmi les eligibles
    return None  # TODO etudiant : retourner {ticker: weight}

vols = {"SPY": 0.15, "QQQ": 0.20, "IEF": 0.06, "GLD": 0.16}
momentum = {"SPY": 0.08, "QQQ": -0.03, "IEF": 0.01, "GLD": 0.05}
result_vol_mom = None  # TODO etudiant : tester
print("Exercice a completer : vol targeting + momentum")

6. Code source (v3 – meilleur résultat)

Le code est disponible sur QC Cloud (projet 30823845). Le notebook local ne contient que les résultats et l’analyse, conformement au workflow cloud-native.

# Lien QC Cloud : https://www.quantconnect.com/project/30823845
# Approche : Volatility targeting + momentum filter
# Univers : SPY, QQQ, IEF, GLD
# v1 : SPY seul, target 12%, caps [30%, 150%]
# v2 : Multi-asset equal risk, target 10%, caps [0%, 50%]
# v3 : Multi-asset + momentum filter (6m > 0), defensif IEF
#
# Points cles :
# 1. Realized vol = rolling 21j std * sqrt(252)
# 2. weight = target_vol / realized_vol (avec caps)
# 3. Equal risk contribution = poids inverse-vol
# 4. Momentum filter elimine les actifs en bear

7. Pour aller plus loin

  1. GARCH volatility : Remplacer la volatilite realisee (rolling std) par un modèle GARCH(1,1) qui capture mieux le clustering de volatilite.

  2. Correlation-adjusted vol targeting : En multi-asset, tenir compte de la matrice de correlation complete (pas juste les vols individuelles) pour un vrai risk budgeting.

  3. Dynamic target vol : Ajuster le target vol selon le regime (ex: 8% en bear, 14% en bull) pour etre plus ou moins aggressif.

  4. Implied volatility : Utiliser le VIX au lieu de la vol realisee pour un signal plus prospectif.

Reference : Moreira, A. & Muir, T. (2017) – “Volatility-Managed Portfolios”, Journal of Finance. Harvey, C. et al. (2018) – “…and the Cross-Section of Expected Returns”, Review of Financial Studies.

Retour au sommet