Apparence
06 — Hypothèses et limites du moteur
Un backtest n'est pas une mesure, c'est une simulation sous hypothèses. Chaque hypothèse déplace le résultat dans un sens ou dans l'autre, et un chiffre dont on ignore les hypothèses ne veut rien dire. Les outils sérieux publient les leurs — TradingView documente les limites de son émulateur de broker, AmiBroker les caveats de son Monte Carlo. Cette page fait la même chose pour Evotrade : elle énumère noir sur blanc ce que le moteur suppose, ce qu'il ne modélise pas, et dans quel sens chaque approximation tire.
Elle ne remplace pas 03 — Lancer et lire un backtest (comment lancer un run et lire les résultats) ni le Lexique (définition des termes) : elle explique pourquoi les chiffres valent ce qu'ils valent.
En bref
Les approximations qui changent le plus la lecture d'un résultat :
| Hypothèse | Sens du biais |
|---|---|
| Exécution à l'ouverture de la barre suivant le signal (les stops, eux, sont remplis dans la barre) | Réaliste — ni optimiste ni pessimiste, mais retarde d'une barre toutes les exécutions sur signal |
| Exécutions toujours intégrales, aucune contrainte de liquidité | Optimiste sur les actifs peu liquides et les grosses tailles |
| Stop et take-profit touchés dans la même barre → le stop l'emporte | Conservateur par construction |
| Coûts par défaut non calibrés empiriquement | Indéterminé — à recalibrer par stratégie |
| Slippage forfaitaire en bps, sans impact de marché | Optimiste quand la taille grossit |
| Short sans coût d'emprunt ni appel de marge | Optimiste sur les shorts longs à porter |
| Dividendes non versés en cash (mode Splits, défaut) | Pessimiste sur les actions à fort rendement |
| Un seul instrument par run, choisi a posteriori | Optimiste (biais de survivance du choix de symbole) |
| Indicateurs calculés sur les clôtures seules | Restreint l'espace des stratégies, ne fausse pas les chiffres |
| Le compteur d'essais ne voit que les runs faits dans l'app | Optimiste — le Deflated Sharpe est sous-déflaté |
1. Modèle d'exécution
Timing : next-bar-open pour les signaux
Une condition est évaluée à la clôture de la barre N ; l'ordre correspondant est exécuté à l'ouverture de la barre N+1. Il n'existe pas d'option « cheat-on-close » (exécuter au cours de clôture qui vient de déclencher le signal), qui est la source classique de résultats de backtest impossibles à reproduire en réel.
Attention : cela vaut pour les ordres issus d'un signal. Les sorties en pourcentage (stop loss, trailing stop, take profit) suivent l'autre mécanique — elles sont remplies dans la barre, au niveau du seuil (voir plus bas). Il y a donc deux régimes d'exécution dans le moteur, et c'est voulu : un stop qui attendrait l'ouverture suivante ne serait pas un stop.
Conséquences directes :
- La dernière barre de la période ne génère aucune entrée — il n'y a pas de barre suivante pour l'exécuter.
- Les positions encore ouvertes à la fin sont fermées au cours de clôture de la dernière barre, et signalées comme des sorties de fin de données. Ce n'est pas une décision de la stratégie : ces sorties forcées sont à lire comme un artefact de bord, surtout sur les segments courts.
- Un gap entre la clôture du signal et l'ouverture suivante est subi, dans les deux sens.
Biais connu sur la clôture forcée : cette dernière sortie a lieu après la boucle de simulation et n'ajoute pas de point à la courbe d'equity. Ses frais et son slippage sont bien débités du cash et comptés dans les totaux de coûts et dans le P&L du trade, mais ils n'apparaissent ni dans le rendement total, ni dans la courbe d'equity persistée, qui s'arrêtent au dernier point calculé. Le biais est optimiste, d'un ordre de grandeur faible (les coûts d'une seule sortie), mais il grandit avec le nombre de lots restés ouverts. La date de cette sortie forcée est par ailleurs celle demandée pour le run, pas celle de la dernière barre — ce qui peut allonger légèrement la durée de détention moyenne.
Exécutions intégrales, aucune modélisation de la liquidité
La quantité calculée est exécutée en entier, en une fois, au prix d'exécution retenu. Le moteur ne lit pas le volume, ne modélise ni carnet d'ordres, ni exécution partielle, ni file d'attente, ni rejet pour cause de marché illiquide. La seule chose qui peut réduire une quantité est la contrainte de capital (section 2), jamais le marché.
C'est l'hypothèse la plus optimiste du moteur. Elle est raisonnable sur une large cap liquide avec des tailles modestes ; elle ne l'est pas sur une small cap, un altcoin, ou dès que la position pèse dans le volume quotidien. Rien dans les résultats ne signalera que ce seuil a été franchi — c'est à vous de le garder en tête.
Sorties intrabar : règle du pire cas
Stops et take-profits sont vérifiés à l'intérieur de la barre, contre le plus haut et le plus bas. Le moteur ne descend pas à un timeframe inférieur pour reconstituer le chemin réel du prix (pas d'équivalent du Bar Magnifier de TradingView) : à l'intérieur d'une barre, l'ordre des événements est inconnu.
Face à cette ambiguïté, la règle est le pire cas d'abord. Les niveaux sont vérifiés dans cet ordre : stop-loss → trailing stop → take-profit. Si le plus bas d'une barre touche le stop et que son plus haut touche la cible, c'est le stop qui est réputé touché en premier. Le trade est enregistré perdant. C'est le consensus conservateur de la profession : à ambiguïté égale, on ne s'accorde pas le bénéfice du doute.
Gaps
- Une ouverture qui saute par-dessus un stop est exécutée à l'ouverture réelle, jamais au niveau fictif du stop. La perte enregistrée est donc bien celle du gap. C'est le comportement d'un stop marché, et c'est plus dur que ce que produirait un moteur naïf qui exécuterait au niveau demandé.
- Une ouverture qui saute au-delà d'un take-profit est exécutée à l'ouverture, donc améliore le gain : sémantique d'ordre limite, un ordre limite s'exécute au prix disponible s'il est meilleur.
Trailing stop
L'extrême de référence d'un lot (plus haut pour un long, plus bas pour un short) est mis à jour en fin de barre. Le stop d'une barre ne peut donc pas être armé par le plus haut de cette même barre : le moteur refuse de savoir, en début de barre, où le prix ira ensuite. C'est une protection anti-lookahead intrabar, au prix d'un léger retard de suivi.
Échauffement des indicateurs
Chaque segment simulé recalcule son propre échauffement (warm-up) depuis sa première barre, et aucun signal n'est émis pendant cette fenêtre. Sa longueur est le plus grand paramètre numérique strictement positif de tous les indicateurs référencés — pas seulement les périodes : un multiplicateur ou une déviation entre aussi dans le calcul, ce qui est volontairement grossier mais du bon côté. Une référence d'indicateur sans aucun paramètre numérique compte pour 50 barres. Une stratégie qui ne référence aucun indicateur (règles purement en pourcentage) a un échauffement nul et trade dès la deuxième barre.
Si la période demandée est plus courte que cet échauffement, le run échoue explicitement plutôt que de simuler sur trois barres.
Limite connue : les indicateurs à convergence lente (EMA longue, MACD) restent approximatifs, voire incalculables, un peu au-delà de l'échauffement nominal. Dans ce cas la condition est simplement fausse — jamais devinée, jamais calculée à cheval sur une frontière. Le biais est un léger retard à l'entrée, pas une fuite d'information.
2. Capital et positions
Cash-only, levier 1x strict
Le notionnel ouvert ne dépasse jamais le cash disponible. Une entrée trop grosse est réduite à ce qui est finançable, et rejetée s'il ne reste rien. Les deux cas sont comptés sur le run (entrées réduites, entrées rejetées) : si ces compteurs sont élevés, la stratégie testée n'est pas celle que vous croyez avoir configurée — elle a été bridée par le capital.
Il n'y a ni levier, ni marge, ni intérêts créditeurs sur le cash non investi.
Short : pas de coût d'emprunt
Un short réserve un notionnel équivalent (même contrainte 1x qu'un long) et son P&L est simplement inversé. Le moteur ne modélise ni frais d'emprunt de titres, ni appel de marge, ni rappel du prêteur, ni interdiction réglementaire de vente à découvert. Sur un short porté longtemps, ou sur un titre difficile à emprunter, le résultat réel serait sensiblement moins bon.
Corollaire important : le 1x borne l'exposition à l'entrée, pas la perte. Si le prix d'un short plus que double, le cash et l'equity deviennent négatifs — la perte d'un short n'est pas bornée, et le moteur ne liquide pas d'office : il se contente de rejeter les entrées suivantes. Un résultat contenant une equity négative n'est pas un résultat, c'est un signal que la stratégie aurait explosé.
Graphe d'états et exécution sont découplés
Le graphe d'états avance au signal, même si l'entrée correspondante est ensuite rejetée faute de cash à l'ouverture suivante. La séquence d'états reflète donc la logique de la stratégie, pas l'historique des exécutions. C'est délibéré : une machine à états dont les transitions dépendraient du solde deviendrait imprévisible.
Pyramiding
Un signal d'entrée dans le sens d'une position déjà ouverte ajoute un lot au lieu d'être ignoré. Chaque lot garde son prix d'entrée, ses frais et son extrême de trailing propres ; les sorties en pourcentage sont évaluées lot par lot, une sortie sur indicateur ferme tous les lots. Un signal en sens opposé d'une position ouverte est ignoré : le moteur ne retourne jamais une position en un seul ordre.
Filtres calendaires : le fuseau qui fait foi
Une feuille de condition peut porter un filtre calendaire (jour de la semaine, mois, heure) au lieu d'une condition sur indicateur. Il est évalué sur l'horodatage de la barre courante, stocké et lu en UTC.
Un fuseau explicite (nom IANA, par exemple America/New_York) est accepté uniquement sur un run intraday, où l'horodatage est un instant réel dont on peut dériver l'heure locale d'une place. Sur des barres journalières ou hebdomadaires, l'horodatage est une étiquette de date et non un instant : le convertir ferait basculer une barre du lundi au dimanche soir. Le schéma refuse donc (422) un fuseau hors intraday, comme il refuse un filtre plus fin que les barres du run — l'heure exige des barres 1Hour ou plus fines, le jour de la semaine des barres 1Day ou plus fines. Ces refus sont délibérés : évalués silencieusement, ces filtres seraient toujours faux, et une stratégie qui ne trade jamais ressemble à une stratégie prudente.
Conséquence pratique : « vendredi » pour une action américaine testée en journalier est le vendredi de l'horodatage stocké, pas celui de la séance de New York. Sur des barres journalières les deux coïncident ; sur de l'intraday, précisez le fuseau.
Temps passé dans l'état
Une feuille temps passé dans l'état compare le nombre de barres écoulées depuis l'entrée dans l'état courant (la barre qui a fait entrer compte pour 0). Toute transition qui tire réinitialise le compteur, y compris une auto-transition : dans un graphe à un seul état, chaque entrée remet le compteur à zéro.
C'est le primitif du cooldown : router la sortie vers un état dédié et conditionner la sortie de cet état à at_least N empêche la re-entrée dans les N barres qui suivent. Sans lui, une stratégie stoppée le lundi se remet en position à l'ouverture du mardi — ce qu'aucun opérateur ne ferait, et qui gonfle artificiellement le nombre de trades.
Le compteur est en barres du timeframe de base, pas en jours calendaires : sur un run horaire, 5 barres valent 5 heures de séance et non 5 jours.
3. Coûts de transaction
Les défauts ne sont pas calibrés
Les valeurs par défaut sont directionnellement raisonnables, pas mesurées : elles reflètent l'idée qu'une action porte des commissions de courtage plus élevées qu'une plateforme crypto et que les paires forex majeures ont les spreads les plus serrés. Aucune n'a été calibrée sur des exécutions réelles.
| Classe d'actifs | Frais | Slippage | Spread |
|---|---|---|---|
| Actions | 10 bps | 5 bps | 5 bps |
| Crypto | 10 bps | 10 bps | 10 bps |
| Forex | 5 bps | 2 bps | 2 bps |
| Matières premières | 8 bps | 5 bps | 5 bps |
(1 bps = 0,01 %.) Ces valeurs sont surchargeables par stratégie — en important une stratégie qui porte son propre modèle de coûts — et le modèle effectivement appliqué est figé dans la configuration du run. Elles ne se règlent pas au lancement d'un backtest : deux runs de la même stratégie partagent forcément le même modèle de coûts.
Si votre courtier est connu, remplacez-les. Le seul chiffre inacceptable serait zéro — et le moteur ne le propose pas.
Comment ils s'appliquent
À chaque exécution (entrée et sortie), le prix est dégradé de slippage + demi-spread, toujours dans le sens défavorable : un achat paie plus cher, une vente encaisse moins. Le spread est divisé par deux parce qu'une exécution ne traverse qu'un côté du carnet — le spread complet est payé sur l'aller-retour, pas sur chaque jambe. Les frais sont ensuite prélevés sur le notionnel ainsi ajusté.
Dans les résultats, slippage et demi-spread sont agrégés en une seule colonne ; seuls les frais sont isolés.
Ce qui n'est pas modélisé
- Impact de marché : le slippage est un forfait en bps, indépendant de la taille de l'ordre et de la liquidité du moment. Doubler la taille ne coûte pas plus cher par unité — irréaliste au-delà d'une certaine taille.
- Spread variable : pas d'élargissement à l'ouverture, en clôture, ni pendant les chocs de volatilité, précisément là où il coûte le plus.
- Frais de financement, intérêts, emprunt de titres.
- Fiscalité : aucune. Les rendements sont bruts d'impôt.
- Commissions minimales, frais fixes par ordre, frais de garde.
4. Données de marché
Ajustement des prix
Les barres sont stockées brutes, telles que traitées, et ajustées à la lecture. Deux modes sont exposés :
- Splits (défaut) : les prix sont corrigés des splits postérieurs à chaque barre. Les dividendes ne sont pas versés en cash — le moteur n'a pas de flux de dividendes, et le rendement du dividende est donc purement et simplement absent du résultat. Sur une action à fort rendement tenue longtemps, c'est un biais pessimiste non négligeable.
- Total return : splits + réinvestissement des dividendes dans le prix, méthode CRSP (chaque dividende applique rétroactivement un facteur
1 − dividende / clôture précédente). Là non plus il n'y a aucun flux de cash : le rendement du dividende arrive par le prix, pas par le solde. C'est le mode à choisir pour comparer honnêtement une stratégie actions à un buy & hold.
Le mode d'ajustement fait partie de la configuration figée du run : rejouer un run le rejoue dans son mode d'origine.
Limite : un dividende dont le montant est aberrant (négatif, ou supérieur à la clôture précédente), ou qui précède la première barre chargée, est ignoré — la série est alors silencieusement sous-ajustée sur cet événement.
En crypto, l'ajustement est sans effet : il n'existe pas d'action sur titre, les barres ajustées sont les barres brutes.
Sources et couverture
Les données proviennent de plusieurs fournisseurs, essayés dans cet ordre selon la classe d'actifs :
| Classe d'actifs | Fournisseurs |
|---|---|
| Actions | Alpaca → Yahoo Finance |
| Crypto | Binance → Kraken → Alpaca → Yahoo Finance |
| Forex | Twelve Data → Yahoo Finance |
| Matières premières | aucun — un backtest sur cette classe échoue faute de fournisseur |
Le remplissage automatique déclenché par un backtest, lui, passe uniquement par Yahoo Finance. Il fait au mieux : s'il échoue, le run continue sur les données déjà présentes plutôt que de s'arrêter — ce sont les contrôles préalables (ci-dessous) qui décident si les données sont exploitables.
Les données actions d'Alpaca viennent du flux IEX (gratuit), et non du flux consolidé américain. Deux limites en découlent :
- Cet historique ne remonte pas avant le 27 juillet 2020. Toute fenêtre antérieure provient de Yahoo Finance.
- IEX ne représente qu'une fraction du volume consolidé : ses cours ne sont pas la meilleure fourchette nationale. En journalier, l'écart est marginal ; en intraday, il grandit.
Limites d'historique intraday
Elles viennent des fournisseurs, pas du moteur, et sont silencieuses :
- Yahoo Finance : 1 minute sur 7 jours glissants, 5 et 15 minutes sur 60 jours. Au-delà, la fenêtre demandée revient tronquée, sans message d'erreur.
- Binance : 1000 barres par appel, sans pagination.
- Kraken : un seul appel, sans pagination.
- Twelve Data : 5000 barres par appel.
En pratique, les backtests intraday longs ne sont pas fiables aujourd'hui : demandez trois ans en 5 minutes et vous obtiendrez ce que le fournisseur a bien voulu donner. Les contrôles de couverture ci-dessous rattrapent la plupart de ces cas, mais visez le journalier tant que ce point n'est pas traité.
Les barres 4Hour sont toujours reconstruites à partir des barres 1Hour — elles ne sont ni téléchargées ni stockées telles quelles.
Contrôles avant lancement
Avant de simuler, le moteur vérifie les données de la période demandée et bloque le run plutôt que de produire un chiffre faux :
| Contrôle | Seuil | Effet |
|---|---|---|
| Couverture des données | 95 % | Bloquant — barres présentes par rapport au calendrier de marché (voir ci-dessous) |
| Saut de prix | 40 % | Bloquant — variation brute de clôture à clôture sans action sur titre à ±1 jour |
| Saut de prix | 25 % | Avertissement seulement |
Le calendrier de référence de la couverture dépend de la classe d'actifs — les trois ne cotent pas aux mêmes heures :
| Classe | Jours attendus |
|---|---|
| Actions | séances de la Bourse de New York |
| Forex | du lundi au vendredi — le marché est 24/5, fermé du vendredi soir au dimanche soir |
| Crypto | tous les jours calendaires (seule classe réellement 24/7) |
Les fériés forex (Vendredi saint, Noël, Nouvel An) ne sont pas retirés du calendrier attendu : ils apparaissent comme de légers trous de données, en avertissement, sans bloquer le run.
Le seuil bloquant à 40 % sépare le krach réel de la falaise de données. Une vérification menée sur les symboles alors suivis a recensé 17 mouvements journaliers réels au-delà de 25 % (les bancaires en 2008-2009, META en 2013 et 2022, NVDA, SLB en mars 2020…), le plus violent autour de 38 %. Un split non appliqué produit mécaniquement au moins 50 % (un 2:1). Entre les deux, 40 % tranche proprement : le krach passe avec un avertissement, la falaise de données bloque.
Faux négatifs et angles morts assumés :
- Un split 3:2 manqué (falaise de −33 %) passe sous le seuil bloquant et n'apparaît qu'en avertissement. C'est au moment du chargement des données qu'il doit être attrapé.
- Aucun contrôle de saut sur la crypto : la logique repose sur les actions sur titre, qui n'existent pas là-bas, et un altcoin peut légitimement bouger de plus de 40 % en une journée. Seule la couverture est vérifiée.
- Tolérance de ±1 jour sur les dates d'ex-dividende du fournisseur, parfois décalées.
- Couverture intraday approchée : le nombre de barres attendues par séance est calculé au prorata (demi-séances comprises) ; l'à-peu-près est absorbé par la marge des 95 %.
- Le contrôle lit les barres brutes : une falaise reste invisible en mode Splits quand c'est précisément le facteur de split qui manque.
- Le réaffichage du graphique d'un ancien run saute ces contrôles, volontairement : il doit rester identique au run enregistré même si les données ont changé depuis.
Reproductibilité
Chaque run enregistre une copie figée de sa configuration (graphe de règles, capital, mode d'ajustement, modèle de coûts, version du moteur) et une empreinte des données : symbole, timeframe, nombre de barres, bornes temporelles et signature des couples horodatage / clôture ajustés — ajustés et non bruts, car une nouvelle action sur titre change la vue ajustée sans toucher aux barres brutes.
Au rejeu, un écart d'empreinte est signalé dans les avertissements, jamais absorbé en silence. Les runs antérieurs à ce mécanisme retombent sur la configuration courante de la stratégie, avec un bandeau explicite : ce qui est affiché peut ne pas être ce qui a été exécuté.
La version du moteur est affichée avec la configuration du run. Elle change dès qu'une évolution peut altérer un résultat à configuration et données identiques : exécution, stops, dimensionnement, coûts, échauffement, découpage des folds, ajustement des prix. Deux runs exécutés sur des versions différentes ne sont donc pas strictement comparables.
5. Conventions de calcul des métriques
Facteur d'annualisation
C'est une constante conventionnelle, pas un comptage de barres réelles :
| Timeframe | Actions | Tout le reste (crypto, forex, matières premières) |
|---|---|---|
1Day | 252 | 365 |
1Week | 52 | 52 |
| Intraday | (390 min de séance / largeur) × 252 | (1440 min / largeur) × 365 |
Annualiser avec le nombre réel de barres ferait varier le Sharpe d'un run à l'autre au gré des jours fériés, pour la même stratégie sur la même période. Le comptage exact existe là où il compte vraiment : dans le contrôle de couverture des données.
Deux approximations dans cette table : l'hebdomadaire vaut 52 même pour un actif traité en continu (qui compte plutôt 52,18 semaines par an — négligeable), et tout ce qui n'est pas les actions est annualisé en 24/7, ce qui est juste pour la crypto mais discutable pour des matières premières à sessions.
Le CAGR fait exception — il est calculé sur le temps calendaire écoulé (années de 365,25 jours), et il est indéfini sur moins d'un jour ou si le capital final est nul ou négatif.
Taux sans risque
Réglage de la plateforme, à 0 par défaut, non exposé dans l'interface. Il est converti en taux par barre par simple division par le facteur d'annualisation, puis retranché aux rendements avant le calcul du Sharpe et du Sortino. À 0, les ratios affichés sont donc des ratios bruts : sur une période de taux élevés, ils flattent la stratégie par rapport à un placement sans risque.
Conventions statistiques
- Écart-type de population (et non d'échantillon) pour le Sharpe et la volatilité. Cette convention vient des premières versions du moteur ; en changer casserait la comparabilité avec tous les runs antérieurs.
- Un Sharpe affiché à 0,00 peut vouloir dire « indéfini » : c'est la valeur retournée quand la série compte moins de deux barres ou que son écart-type est nul, faute d'un valeur « indéfini » distincte. Le Sortino, lui, est bien indéfini dans ces cas.
- Sortino : déviation à la baisse calculée sur l'ensemble de la série de rendements en excès — la somme des carrés des pertes est divisée par le nombre total de barres, pas par le nombre de barres négatives (convention standard de la downside deviation). Même annualisation en √N que le Sharpe. Indéfini s'il n'y a aucun rendement en excès négatif.
- MAE/MFE : bornes prises sur les plus hauts / plus bas des barres pendant lesquelles le lot était ouvert, plus le prix d'exécution de la sortie, le tout planché à zéro. Deux asymétries assumées : les extrêmes de la barre d'entrée sont comptés en entier (y compris avant l'exécution), ceux de la barre de sortie au-delà de l'exécution ne le sont pas — inconnaissables intrabar, comme pour le modèle d'exécution.
- Benchmark buy & hold : ouverture de la première barre → clôture de la dernière, dans le mode d'ajustement du run, sans aucun frais. C'est une borne optimiste pour le benchmark, donc conservatrice pour juger la stratégie.
- Courbe d'equity out-of-sample : chaque segment repart du capital initial ; la concaténation brute donnerait des dents de scie, les segments sont donc rescalés par composition des rendements. Le max drawdown out-of-sample agrégé est mesuré sur cette courbe recousue.
- Equity persistée sous-échantillonnée à environ 500 points par ligne de métriques (un point sur N, plus le dernier point toujours conservé — d'où 501 au maximum). Suffisant pour le graphique ; ne cherchez pas à en tirer une analyse fine.
6. Ce que le walk-forward valide (et ce qu'il ne valide pas)
La période est découpée en folds successifs, chacun composé d'une fenêtre in-sample et de la tranche out-of-sample qui la suit, en mode anchored (in-sample partant toujours du début, défaut) ou rolling (fenêtre glissante de taille fixe).
Chaque segment est une simulation indépendante, repartant à plat. Aucun historique de prix, aucune position, aucun état de la machine, aucun capital n'est reporté d'un segment au suivant : chaque fold recommence avec le capital initial et refait son propre échauffement. C'est ce qui garantit l'absence de fuite entre fenêtres, et c'est aussi pourquoi la courbe d'equity out-of-sample doit être recousue par composition des rendements plutôt que concaténée telle quelle.
La nuance qui compte : au sens historique, « walk-forward » suppose qu'on calibre des paramètres sur l'in-sample puis qu'on valide sur l'out-of-sample. Ce n'est pas ce que fait le moteur : la configuration de la stratégie est fixe et strictement identique sur les deux fenêtres. Ce que vous obtenez est donc un contrôle de cohérence dans le temps — l'edge apparent tient-il en dehors de la fenêtre sur laquelle la stratégie a été pensée, ou est-ce un artefact d'un régime de marché précis ? Ce n'est pas une détection de surapprentissage au sens de l'apprentissage automatique, qui exigerait une recherche de paramètres intégrée aux folds.
WFE = CAGR out-of-sample / CAGR in-sample, par fold, seuil indicatif ≥ 50 %. Elle est indéfinie (affichée « N/A », jamais 0) quand le CAGR in-sample est nul ou négatif : diviser par un in-sample négatif produirait un ratio dont le signe n'a aucun sens — un out-of-sample négatif sur un in-sample négatif donnerait une WFE positive « rassurante ».
Folds sans trade : un fold dont l'out-of-sample ne produit aucun trade a une equity plate. Il est compté à part (folds sans trade), n'a pas de WFE, et sort des dénominateurs de la WFE médiane et du pourcentage de folds profitables. « La stratégie n'a rien fait » ne doit pas se lire comme « la stratégie a perdu ».
Exception à connaître : ces folds restent inclus dans les deux cartes de synthèse in-sample et out-of-sample, dont les moyennes et écarts-types sont donc dilués par des zéros. Quand le compteur de folds sans trade est élevé, lisez la WFE médiane et la part de folds profitables, pas la moyenne des rendements.
Pas de purge ni d'embargo explicite entre in-sample et out-of-sample, et c'est suffisant ici. Chaque segment est un run indépendant qui recalcule son échauffement depuis sa propre première barre : aucune décision de trade dans l'out-of-sample ne peut dépendre d'une valeur d'indicateur calculée à cheval sur la frontière, et aucun ordre en attente ne franchit la limite. Le motif classique de López de Prado (purge + embargo) vise le recouvrement des labels dans un pipeline supervisé, où l'étiquette d'un échantillon dépend de rendements futurs. Ici rien n'est étiqueté ni calibré sur l'in-sample. Le point serait à revoir si une recherche de paramètres intégrée aux folds voyait le jour.
Réduction automatique des folds : la période est découpée en folds + 1 segments égaux, et le nombre de folds est réduit tant qu'un segment ferait moins de 20 barres — jusqu'à 1 minimum, plutôt que de faire échouer le run. Si même un seul fold n'atteint pas ce minimum, le run se lance quand même, avec un avertissement. Un résultat sur 2 folds n'a pas le poids statistique d'un résultat sur 10 : l'interface signale la réduction, lisez-la.
Le contrôle qualité des données est fait une fois, sur la période complète, avant le découpage ; les folds en héritent. Un problème de données localisé sur un seul segment n'est donc pas isolé segment par segment.
7. Batterie de robustesse post-run
Ces tests complètent le walk-forward, ils ne le remplacent pas. Ils tournent après coup, au mieux de ce qui est calculable : un échec retire une section du rapport sans jamais faire échouer le backtest. Ils s'appuient tous sur un run de référence — un backtest simple sur la période complète, non découpé.
Monte Carlo : bootstrap (tirage avec remise) des variations d'equity barre par barre, jamais des trades. Rééchantillonner les trades double-compterait l'exposition dès qu'il y a du pyramiding, puisque des lots simultanés se recouvrent (c'est le caveat d'AmiBroker). Une permutation pure est écartée pour une raison mathématique : le produit des (1 + r) est invariant par réordonnancement, l'equity finale serait identique à chaque tirage. 1000 tirages, graine fixe (la reproductibilité vaut aussi pour les tests), ruine définie comme un drawdown ≥ 50 %.
Limite : le bootstrap casse l'autocorrélation des rendements. Il répond à « et si les mêmes barres étaient arrivées dans un autre ordre ? », pas à « et si le marché avait été différent ? ». Il ne teste pas non plus la stratégie sur des données inédites — pour cela il faudrait un test de permutation Monte Carlo sur données permutées ou une injection de bruit OHLC, tous deux hors périmètre pour l'instant.
Stress des coûts : slippage et spread multipliés par 2 et par 3, frais inchangés — les commissions sont contractuelles et connues, alors que slippage et spread sont les parts estimées. Une stratégie qui ne survit pas au ×2 vit de son modèle de coûts, pas d'un edge.
Sous-périodes : années civiles, plus les fenêtres de crise entièrement couvertes par la période (crise financière 2007-10-09 → 2009-03-09, krach COVID 2020-02-19 → 2020-04-30, marché baissier 2022-01-03 → 2022-10-12). Le rendement d'une année se calcule à partir de la clôture de l'année précédente. Aucune simulation n'est relancée : les tranches sont découpées dans la courbe d'equity du run de référence. Une crise seulement partiellement couverte n'est pas rapportée du tout — mieux vaut rien qu'un chiffre tronqué.
Sensibilité à la date de départ : la même simulation relancée en décalant le départ de +1, +5, +10 et +21 barres. Le résumé donne le min, le max, l'écart, l'écart-type des rendements et la stabilité du signe. Une stratégie dont le résultat s'effondre parce qu'on a commencé une semaine plus tard n'a pas d'edge, elle a eu de la chance sur un point d'entrée. Un décalage est simplement omis s'il ne laisse pas assez de barres après le l'échauffement, et la section entière disparaît s'il ne reste qu'une ligne.
Les re-runs de cette batterie ne comptent pas comme des essais au sens du compteur ci-dessous : ce sont des perturbations d'une même configuration, pas des tentatives de sélection.
8. Surapprentissage : ce qui est mesuré et ce qui ne l'est pas
Compteur d'essais
Chaque stratégie porte un compteur d'essais : +1 par run walk-forward terminé, +1 par variante de sweep exécutée. Il mesure la pression de sélection — plus on essaie de configurations, plus le meilleur résultat obtenu doit être escompté.
Limite assumée, et elle est importante : les essais faits hors de l'application, ou sur une stratégie dupliquée, ne sont pas comptés. Le compteur est un plancher, jamais un décompte exact. Toute mesure qui en dépend est donc optimiste.
Le compteur ne regarde pas ce qui a changé entre deux runs : ajuster une période d'indicateur, ajouter un filtre calendaire ou retirer le mois d'août comptent chacun pour un essai, comme n'importe quel run. C'est voulu — un filtre calendaire est un vecteur de surapprentissage classique (retirer un mois parce que la courbe y était moche in-sample), et il consomme des degrés de liberté exactement comme un paramètre.
Deflated Sharpe Ratio
Le DSR (Bailey & López de Prado) répond à : « quelle est la probabilité que ce Sharpe soit réel, sachant qu'il est le meilleur de N essais, et que les rendements ne sont ni normaux ni infiniment nombreux ? »
- Calculé sur les rendements barre par barre du run de référence pleine période, pas sur les folds.
- Tous les Sharpe entrent dans les formules en unités par barre (convention du papier). Les valeurs annualisées ne servent qu'à l'affichage.
- Asymétrie et kurtosis sont non-excess (la normale vaut 3).
- N = le compteur d'essais au moment du calcul, run courant inclus.
- La variance des essais est calculée sur les Sharpe par barre des essais persistés : une valeur par variante de sweep, une par run walk-forward (moyenne de ses Sharpe out-of-sample — l'in-sample ne compte jamais). En dessous de 2 essais exploitables, cette variance est indéfinie, le seuil se réduit à 0 et le DSR dégénère en simple Probabilistic Sharpe Ratio contre zéro.
- La section est omise — pas remplie d'un chiffre creux — si la série fait moins de 3 barres, si elle est plate, ou si la variance ajustée est négative ou nulle.
- Lecture : ≥ 95 % significatif (le seuil du papier), 75 à 95 % incertain, en dessous de 75 % compatible avec le hasard.
Les essais menés sur d'autres symboles ou d'autres périodes comptent quand même : ce qui est mesuré est la pression de sélection, pas la comparabilité des runs.
Le sweep est une analyse de sensibilité, pas un classement
Un sweep fait varier un seul champ d'une règle d'entrée ou de sortie, sur 8 variantes au maximum, chacune exécutée en backtest simple sur la période complète — sans validation walk-forward.
Choisir la meilleure de N variantes surestime la performance future par construction. L'interface ne met donc plus en avant de « meilleure variante » : elle affiche la médiane des variantes (l'espérance honnête, dans l'esprit du System Parameter Permutation de Walton), le pire et le meilleur cas, et une lecture plateau vs pic isolé. Un pic est jugé isolé quand (meilleure − moyenne des voisines immédiates) / (meilleure − pire) > 0,5 ; la mesure est indéfinie en dessous de 3 variantes (il faut des voisines pour parler de voisinage), et vaut 0 sur une plage parfaitement plate. Sous 2 variantes, il n'y a pas de rapport de stabilité du tout. Un plateau se tient ; un pic isolé est presque toujours du bruit.
Hors périmètre pour l'instant : PBO/CSCV (probability of backtest overfitting par validation croisée combinatoire).
9. Portée
Un seul instrument par run
Un backtest est scopé à exactement une stratégie, un symbole, une période. Il n'existe ni portefeuille, ni allocation entre instruments, ni rééquilibrage, ni corrélation croisée, ni contrainte de risque globale.
Conséquence à ne pas rater : on ne somme pas naïvement plusieurs backtests. Trois runs à +20 % sur trois symboles ne font pas un portefeuille à +20 % — ils ignorent la concurrence pour le même capital, les corrélations, et le fait que les drawdowns surviennent souvent en même temps. Le drawdown d'un portefeuille est presque toujours pire que le pire des drawdowns individuels.
Biais de survivance du choix de symbole
Le moteur teste le symbole que vous lui donnez, aujourd'hui, en sachant ce qu'il est devenu. Backtester une stratégie sur NVDA depuis 2015 mesure en partie le fait que vous savez déjà que NVDA a monté. Les sociétés délistées, faillies ou absorbées ne sont pas dans l'univers de symboles, et rien dans les résultats ne le rappelle. C'est le biais le plus difficile à corriger, parce qu'il naît avant le backtest.
Les tests de sous-périodes et la sensibilité à la date de départ (section 7) en atténuent une part — mais uniquement la part temporelle, pas le choix du titre lui-même.
Indicateurs sur les clôtures seules
Le catalogue expose 98 indicateurs, et exclusivement ceux qui se calculent à partir des seules clôtures. Les indicateurs qui ont besoin de l'ouverture, du plus haut, du plus bas ou du volume — ATR, ADX, Stochastique, CCI, VWAP, tous les patterns de chandeliers — ne sont pas disponibles comme conditions de règle.
Nuance : l'ATR est calculé, mais uniquement pour le dimensionnement basé sur le risque, et les plus hauts / plus bas sont bien utilisés pour les stops intrabar. C'est le catalogue des conditions qui est close-only, pas le moteur entier.
Autre limite : les bornes de paramètres du catalogue sont génériques par type (1 à 1000 pour un entier), pas ajustées indicateur par indicateur. Une valeur acceptée n'est pas forcément une valeur sensée.
Ce que le moteur ne fait pas du tout
Pour lever toute ambiguïté : ni trading réel, ni paper trading, ni ordres réels de quelque nature ; pas d'optimisation autonome ni de recherche de paramètres au-delà du sweep mono-champ ; pas de modèles d'apprentissage automatique ; pas de données fondamentales, de carnet d'ordres, de tick data, de flux d'actualités ni de sentiment ; pas d'options, de futures, de contrats à terme roulés ni d'instruments à échéance.
Comment lire un résultat, en résumé
Une bonne lecture consiste à demander, dans l'ordre :
- Le run a-t-il été bridé ? (folds réduits, entrées rejetées, folds sans trade, avertissements sur la qualité des données)
- L'out-of-sample tient-il ? (WFE médiane, part de folds profitables, écart avec l'in-sample)
- Est-ce que ça survit aux perturbations ? (stress des coûts, décalage de la date de départ, sous-périodes)
- Combien d'essais ont mené jusqu'ici ? (compteur d'essais, DSR, plateau vs pic isolé du sweep)
- Et enfin : les hypothèses de cette page sont-elles tenables pour cet instrument et cette taille ? (liquidité, coût d'emprunt en short, dividendes, historique intraday)
Un résultat qui ne passe pas les quatre premières questions n'a pas besoin de la cinquième.
