Skip to content

Repository files navigation

1/N contre l'optimisation : la réplication exacte de DeMiguel, Garlappi et Uppal (2009)

Réplication en Python, depuis le code et les données officiels des auteurs, du papier « Optimal versus naive diversification » (Review of Financial Studies, 22(5)) : quatorze règles d'allocation contre le portefeuille naïf 1/N, sur six jeux de données, fenêtre roulante de 120 mois.

ci python licence

Le même contenu en PDF : rapport/rapport.pdf.

Résultat en une phrase. Les tables 3 et 4 du papier sont reproduites cellule par cellule : 312 valeurs sur 312 identiques à la précision imprimée (84 ratios de Sharpe, le rendement gagné par unité de risque pris ; 84 équivalents certains, le rendement sûr qui rendrait l'investisseur indifférent au portefeuille ; 144 p-valeurs, la probabilité d'observer un écart au moins aussi grand si les deux règles se valaient), et la réplication a mis au jour une cellule numériquement dégénérée de la table originale, dont la valeur publiée dépend d'un comportement du solveur Matlab de 2009. Tous les chiffres viennent de results/tables/ (synthese_ecarts.csv pour le bilan).

English summary. Exact Python replication of DeMiguel, Garlappi and Uppal (2009, RFS), from the authors' official Matlab code and data: 14 allocation rules versus 1/N on six datasets, 120-month rolling windows. All 312 printed cells of Tables 3 and 4 (Sharpe ratios, certainty equivalents, p-values) are reproduced exactly; Table 5's relative turnovers match except one 8th-significant-digit rounding. The replication also uncovered one numerically degenerate cell (BS-C on the international dataset) whose published value depends on Matlab's quadprog returning exact zeros where conic solvers return near-zeros; the repository documents and reproduces the convention. Extending the horse race to 2026 (636 out-of-sample months, HAC p-values, Ledoit-Wolf and volatility-timing additions) upholds the paper's verdict: mean-variance stays significantly below 1/N, a few covariance-only rules win on single universes, none wins consistently.

1. La question posée

Celle du papier : les règles d'allocation « optimales », qui estiment moyennes et covariances pour placer au mieux, battent-elles hors échantillon, c'est-à-dire sur des mois que l'estimation n'a jamais vus, la règle la plus bête qui existe, mettre 1/N dans chacun des N actifs ? En mots simples : quand on croit optimiser, on optimise surtout les erreurs d'estimation ; DGU montrent qu'avec des fenêtres de 120 mois, aucune des quatorze règles ne bat 1/N de façon consistante. Ce dépôt vérifie chacun de ces chiffres, puis servira à poser la même question avec vingt ans de données de plus.

2. D'où vient le projet, et ce qu'il apporte

Le papier est un des plus cités de la gestion de portefeuille (l'argument central contre l'optimisation naïve des moyennes-variances), et les auteurs distribuent leur code Matlab et leurs données. Or une réplication indépendante, dans un autre langage, avec des solveurs modernes, est le seul moyen de savoir si les chiffres tiennent au protocole ou à l'implémentation. Ce que ce dépôt apporte :

  • La réplication exacte, vérifiable en une commande (eelab replicate), avec l'écart cellule par cellule contre le papier dans results/tables/ecarts_*.csv.
  • Une spécification du protocole en français (docs/SPEC_DGU.md), tirée d'une lecture ligne à ligne du Matlab : les trois covariances qui coexistent, les réglages non imprimés dans le papier (poids renormalisés sur les actifs risqués, aversion au risque de 1), et dix pièges d'implémentation documentés.
  • Une découverte de réplication : la cellule BS-C du jeu international dépend du solveur (section 6).

3. Les données

Toutes les données sont celles des auteurs, téléchargées par script (scripts/fetch_data.py), jamais commitées. Le tableau reprend la Table 2 du papier ; tous les fichiers contiennent des rendements excédentaires mensuels, le taux sans risque en deuxième colonne.

Jeu N actifs Période Source
Secteurs S&P 10 + marché 1981-01 à 2002-12 zip officiel DGU (données de R. Wessels)
Industries 10 + marché 1963-07 à 2004-11 Ken French, vintage 2004 du zip DGU
International 8 pays + monde 1970-01 à 2001-07 MSCI, zip DGU
Mkt/SMB/HML 3 facteurs 1963-07 à 2004-11 Ken French, zip DGU
FF 1 facteur 20 + marché 1963-07 à 2004-11 Ken French, zip DGU
FF 4 facteurs 20 + 4 facteurs 1963-07 à 2004-11 Ken French, zip DGU

Les fichiers Ken French frais (jusqu'à 2026-06) sont aussi téléchargés, pour l'extension à venir ; les millésimes divergent (le Mkt-RF de novembre 2004 vaut 0,0468 dans le zip de 2004 et 4,53 % dans le fichier de 2026), c'est pourquoi la réplication exacte se fait sur les données d'époque.

4. La méthode, pas à pas

  1. Quatorze règles. Le naïf 1/N ; moyenne-variance (MV) ; Bayes-Stein (BS, moyennes rétrécies vers celle du portefeuille de variance minimale) ; « data-and-model » de Pástor (DM, un prior sur un modèle de facteurs) ; variance minimale (MIN) ; le marché (VW) ; MacKinlay-Pástor (MP) ; les versions sous contrainte de vente à découvert MV-C, BS-C, MIN-C et G-MIN-C ; et les mélanges de Kan-Zhou (MV-MIN) et 1/N-variance minimale (EW-MIN). Chaque formule est dans docs/SPEC_DGU.md, transcrite du Matlab.
  2. Fenêtre roulante de 120 mois. À chaque mois, moyennes et covariances sont estimées sur les 120 mois précédents, les poids calculés, et le portefeuille tenu un mois. La performance est donc entièrement hors échantillon (sauf la ligne « MV in-sample », affichée par le papier comme borne supérieure théorique).
  3. Poids « risky only ». Convention non imprimée dans le papier : les poids sont renormalisés par la valeur absolue de leur somme sur les seuls actifs risqués. Sans elle, aucun chiffre ne colle.
  4. Trois mesures. Le ratio de Sharpe mensuel ; l'équivalent certain (CEQ), avec une aversion au risque de 1 ; la rotation (la part du portefeuille rebrassée chaque mois). P-valeurs de Jobson-Korkie avec la correction de Memmel contre 1/N, unilatérales comme dans le code d'origine.
  5. Comparer au papier, cellule par cellule. eelab replicate écrit nos tables, les écarts contre les valeurs imprimées (extraites du PDF et recoupées sur deux extractions indépendantes), et une synthèse.

5. Les résultats de réplication (mesurés)

Table du papier Cellules Identiques à la précision imprimée Écart maximal
Table 3, ratios de Sharpe 84 84 0,0000
Table 3, p-valeurs 72 72 0,00
Table 4, équivalents certains 84 84 0,0000
Table 4, p-valeurs 72 72 0,00
Table 5, rotations (niveau et relatif) 78 77 0,01

Comment lire ce tableau, en trois constats : d'abord, les 312 cellules des tables 3 et 4 sont identiques, p-valeurs comprises, ce qui valide à la fois le protocole du papier et notre transcription ; ensuite, la seule cellule non identique de la table 5 est la rotation relative du MV sur les industries, 606 594,36 dans le papier contre 606 594,35 chez nous, un écart au huitième chiffre significatif ; enfin, cette réplication exacte n'a été possible qu'en reproduisant des conventions absentes du papier (renormalisation risky-only, trois covariances différentes selon la règle, dérive des poids décalée d'un mois dans la rotation), toutes documentées dans docs/SPEC_DGU.md.

Réplication contre papier

Comment lire cette figure : dans les deux panneaux de gauche, chaque point est une cellule d'une table du papier, avec en abscisse la valeur imprimée en 2009 et en ordonnée notre valeur de 2026 ; un point sur la diagonale grise est une cellule parfaitement reproduite, et les 168 points y sont tous. Le panneau de droite rend le « 312/312 » vérifiable d'un coup d'œil : l'histogramme des écarts papier moins réplication (ratios de Sharpe, équivalents certains et p-valeurs des tables 3 et 4) n'occupe qu'une classe, la classe zéro, avec 312 cellules sur 312.

6. La cellule dégénérée, une découverte de réplication

En route vers ces 312 cellules, une seule résistait : le Sharpe de BS-C (Bayes-Stein sous contrainte) sur le jeu international, 0,0848 dans le papier, 0,0958 avec notre premier solveur, 0,0662 avec un second, alors que les deux solveurs trouvaient le même optimum à 10⁻¹³ près. L'explication, mesurée : sur 10 des 259 mois, l'optimum contraint ne détient aucun actif risqué (tout en cash) ; la renormalisation risky-only divise alors un vecteur quasi nul par sa somme quasi nulle, et le portefeuille de ces mois est du bruit de solveur. Le quadprog de Matlab rend des zéros exacts, 0/0 donne NaN, et le code d'origine remplace NaN par zéro : la valeur publiée repose sur ce comportement. En reproduisant la convention par son critère exact (position nulle quand aucune moyenne, rétrécie pour BS-C, n'est positive : le vecteur nul est alors l'optimum mathématique du programme contraint), le 0,0848 revient exactement. Autrement dit, une cellule d'une table d'un des papiers les plus cités de la discipline n'est pas définie par le protocole mais par le solveur ; elle est inoffensive pour les conclusions du papier, et documentée ici parce qu'une réplication doit dire aussi cela.

7. L'extension 1963-2026 : le verdict tient, avec une nuance (mesuré)

Vingt ans de données de plus changent-ils la conclusion du papier ? Les quatre jeux reconstructibles depuis la bibliothèque Ken French de 2026 (industries, facteurs, 20 portefeuilles taille/valeur avec 1 ou 4 facteurs) sont réévalués sur 1963-07 à 2026-06 (636 mois hors échantillon), même protocole, quinze règles (les treize du papier plus deux ajouts étiquetés : la variance minimale Ledoit-Wolf constante-corrélation, qui rétrécit la covariance estimée vers une matrice où toutes les paires d'actifs partagent la même corrélation, et le « volatility timing » de Kirby-Ostdiek, qui pondère chaque actif par l'inverse de sa variance estimée, sans aucune covariance à inverser). Les p-valeurs contre 1/N sont données dans les deux conventions, Jobson-Korkie unilatérale (celle du papier) et Ledoit-Wolf 2008 HAC bilatérale, robuste à l'autocorrélation. Chiffres : results/tables/extension_2026_*.csv.

Sharpe de l'extension 1963-2026

Comment lire cette figure : chaque panneau est un univers, chaque barre le ratio de Sharpe mensuel d'une règle sur 1963-2026, et la ligne pointillée le niveau de 1/N sur cet univers ; une barre qui dépasse la ligne fait mieux que 1/N, mais seuls les marqueurs signalent un écart significatif (« † » au-dessus, « * » en dessous, au seuil de p HAC bilatérale 0,05). Aucune règle ne porte de « † » sur les quatre panneaux à la fois : c'est le résultat principal du dépôt.

Règle Industries Mkt/SMB/HML FF 1 facteur FF 4 facteurs
1/N 0,158 0,178 0,156 0,164
MV −0,004 * 0,042 * 0,039 * 0,119
MIN 0,157 0,126 * 0,238 † 0,015 *
G-MIN-C 0,171 0,152 0,163 0,246 †
EW-MIN 0,167 0,140 0,228 † 0,018 *
MIN-LW (ajout) 0,160 0,134 0,174 0,130
KO-VT (ajout) 0,165 0,136 * 0,165 † 0,174

Ratios de Sharpe mensuels, extrait des quinze règles (table complète dans le CSV). Marqueurs, au seuil de p HAC bilatérale sous 0,05 : « † » significativement au-dessus de 1/N, « * » significativement en dessous.

Comment lire ce tableau, en trois constats : d'abord, la conclusion centrale du papier survit à vingt ans de données de plus, la moyenne-variance et Bayes-Stein restent significativement SOUS 1/N partout où la p HAC tranche ; ensuite, quelques règles fondées sur la seule covariance passent devant 1/N sur certains univers (MIN et EW-MIN sur les 20 portefeuilles à 1 facteur, G-MIN-C sur la version 4 facteurs, KO-VT), mais aucune ne gagne sur les quatre univers à la fois, et MIN, gagnante sur l'un, est perdante significative sur l'autre ; enfin, l'ajout Ledoit-Wolf constante-corrélation n'améliore jamais significativement, et sa rotation (0,10 à 0,30 par mois contre 0,02 pour 1/N) le pénaliserait encore après coûts. En une phrase : avec 63 ans de données, il n'existe toujours pas de règle d'optimisation qui batte 1/N de façon consistante.

Le même verdict tient en sous-période de crise. La table results/tables/extension_2026_crises.csv découpe la série hors échantillon en trois sous-fenêtres (2007-07 à 2009-06, 2020-01 à 2021-12, 2022-01 à 2023-12), sans réestimation : sur la fenêtre 2008, 58 des 60 cellules de Sharpe sont négatives, et les deux seules positives, MV (0,049) et BS (0,015) sur les industries, sont justement les règles perdantes sur la période pleine. Sur la fenêtre 2020, les règles de variance minimale qui rivalisent avec 1/N sur 63 ans manquent le rebond (0,022 pour MIN et 0,009 pour MIN-LW sur les industries, contre 0,303 pour 1/N) ; sur la fenêtre 2022, aucun Sharpe ne dépasse 0,16 en valeur absolue, cette sous-fenêtre ne départage rien.

Richesse cumulée sur les industries

Comment lire cette figure : chaque courbe suit la valeur d'un dollar investi en 1973-07 sur l'univers des industries, en rendements excédentaires du taux sans risque, sur une échelle logarithmique où une pente constante est un taux de croissance constant ; les bandes grises sont les trois sous-fenêtres de la table des crises citée au paragraphe précédent. La courbe MV s'arrête en octobre 1974 : le portefeuille non contraint y perd plus de 100 % sur un mois, sa richesse devient négative, et la ruine est définitive ; les deux variantes de variance minimale survivent mais finissent sous 1/N (23,9 $ et 25,8 $ contre 42,5 $).

8. Reproduire

uv sync --locked --all-extras            # environnement verrouillé (Python 3.12, cvxpy/Clarabel)
uv run python scripts/fetch_data.py      # zip officiel DGU (480 Ko), Ken French, FRED, Banque du Canada
uv run pytest                            # 18 tests ; ceux qui exigent les données se sautent sans elles
uv run eelab replicate                   # les 6 jeux, ~11 s ; écrit results/tables/*.csv et la synthèse
uv run eelab extend                      # extension 1963-2026, 4 jeux, ~14 s
uv run python scripts/make_figures.py    # figure de réplication (section 5)
uv run python scripts/make_extension_figures.py   # figures de l'extension (section 7)

Durée mesurée : la réplication complète des six jeux prend 11 secondes (Apple M2, un cœur).

9. Limites, avec leur statut

Limite Statut
La table 6 (données simulées), les fenêtres de 60 mois et la détention de 12 mois ne sont pas encore répliquées reconnu ; le protocole est déjà documenté dans la spec
Le panneau « rendement perdu à 50 pb » de la table 5 n'est pas répliqué reconnu ; la spec documente en outre un bug du code d'origine dans ce panneau (la ligne VW y affiche une autre stratégie)
Volet canadien, autres covariances (QIS), coûts de transaction dans l'extension à venir ; l'extension 1963-2026 avec Ledoit-Wolf et p-valeurs HAC est faite (section 7)
Les valeurs cibles sont extraites du PDF du papier mesuré : deux extractions indépendantes concordent cellule par cellule, et recoupent 8 valeurs citées dans la prose

10. Crédits, licence, citation

Papier et matériaux originaux : Victor DeMiguel, Lorenzo Garlappi et Raman Uppal, « Optimal versus naive diversification: How inefficient is the 1/N portfolio strategy? », Review of Financial Studies, 22(5), 2009 ; code et données distribués par les auteurs (révision 2019 de Shiming Wu). Données : Ken French (bibliothèque de Dartmouth), MSCI et données de Roberto Wessels telles qu'incluses dans le zip officiel. Réplication Python : Guillaume Vaudescal, 2026. Code sous licence MIT ; les données restent aux conditions de leurs distributeurs et ne sont pas redistribuées ici.

About

Réplication exacte de DeMiguel, Garlappi et Uppal (2009, RFS) : 1/N contre 14 règles d'optimisation, 312/312 cellules des tables reproduites depuis le code et les données officiels ; extension 2026 à venir

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages