Le talent, la chance, et un tirage à pile ou face
Un conseil d’investissement ne vaut rien tant qu’on ne l’a pas comparé au hasard. J’ai construit l’instrument qui compare, et je ne m’en sers pas.
Il y a un conseil d’investissement par personne pour le donner. Au bar, en réunion, à un dîner : quelqu’un énonce une conviction avec l’aplomb de celui qui a eu raison une fois, la table acquiesce poliment, et on passe au plat suivant. Ce qui me gêne n’est pas l’aplomb — c’est que personne ne pose jamais la seule question qui compterait, à savoir à quoi on reconnaîtrait que ce conseil est mauvais.
Comme je n’ai pas trouvé de manière élégante de la poser à table, j’en ai fait un outil.
Comparer, oui, mais à quoi
Objectiver, ça veut dire comparer, et tout est dans le choix du point de comparaison.
Un rendement brut ne dit rien du tout. Dix-huit pour cent sur trois ans, c’est remarquable ou franchement médiocre selon ce que le reste du monde a fait pendant ces trois ans. Première référence, donc, et la plus attendue : le marché. On superpose un indice large, on regarde si la stratégie fait mieux que d’avoir acheté bêtement un peu de tout et d’être parti en vacances.
Sauf que ça ne suffit pas, et c’est là que l’exercice devient intéressant. Une stratégie qui bat l’indice peut très bien n’avoir rien battu du tout : elle peut avoir eu de la chance. Il manque une seconde référence, et cette seconde référence est le hasard lui-même — un portefeuille qui respecte exactement les mêmes contraintes, les mêmes plafonds, le même nombre de lignes, mais dont chaque choix est tiré au sort.
Une stratégie qui bat l’indice sans battre la pièce de monnaie n’a rien démontré. Elle a eu de la veine, et la veine ne se reproduit pas sur commande. C’est la seule manière que je connaisse de séparer le talent de la chance, et c’est la raison pour laquelle le tirage à pile ou face est dans le service depuis son tout premier jour, avant même qu’il ait une interface.
Le lecteur attentif reconnaîtra le fantôme qui hante Midas, où dix agents se font juger par la même pièce de monnaie. La différence n’est pas technique, elle est de nature : là-bas, c’est une garantie que je donne — la promesse que je ne vous montrerai pas une courbe flatteuse sans son juge à côté. Ici, c’est un instrument que je vous laisse. Vous n’avez pas à me croire sur parole, vous pouvez lancer le calcul vous-même et me contredire dans la foulée.
Ce qu’il y a sous le capot
Le moteur, lui, existait déjà. Il tournait pour les agents de Midas, en Python, avec bt pour la partie déterministe. Ce qu’il n’avait pas, c’était une porte d’entrée : un service qu’on interroge de l’extérieur, sans cloner un dépôt ni installer quoi que ce soit.
Cette porte, c’est une petite application FastAPI qui enveloppe le moteur et l’expose derrière deux verbes — donne-moi le catalogue des stratégies disponibles, lance-moi ce backtest-là. Elle vit dans son propre conteneur, sur Cloud Run, avec sa propre clé partagée pour que personne ne fasse tourner mes calculs à ma place.
Trois détails de fabrication que je trouve plus parlants que l’architecture générale.
Le premier tient aux calendriers boursiers. Dès qu’un univers mélange des places différentes, les jours fériés ne tombent pas ensemble : une valeur allemande n’a pas de ligne le 1er mai pendant que New York cote normalement. Sans précaution, ces trous se propagent dans les rendements et fabriquent des variations qui n’ont jamais existé. On reporte donc le dernier prix connu sur les jours manquants — un geste minuscule, quelques lignes, qui sépare un résultat d’une fiction.
Le deuxième concerne les opérations qu’on affiche à la fin. Pour dire quelles ont été les meilleures et les pires, il faut apparier chaque vente à un achat, et l’ordre d’appariement change le résultat. Premier entré, premier sorti : la convention est arbitraire, mais elle est explicite, et une convention explicite vaut mieux qu’un chiffre dont personne ne sait comment il a été calculé.
Le troisième est une question de politesse. Le catalogue des stratégies n’est pas chargé à l’ouverture de la page : il est photographié au moment de la construction du site et inscrit directement dans le HTML. Le formulaire est donc complet avant même que la moindre requête soit partie, avec ses huit stratégies, ses douze univers et ses bornes de dates. (Huit, alors que le dépôt en contient quinze. Les sept autres ne sont pas un choix éditorial, contrairement à ce qu’un lecteur bienveillant pourrait supposer — ce sont des choses en attente, qui sortiront quand je remettrai du temps sur l’outil.)
Ce que coûte la gratuité
Tout le portfolio tourne sur des offres gratuites, par principe autant que par radinerie assumée. Sur Cloud Run, la gratuité a une conséquence précise : quand personne ne visite, le service s’éteint. Il ne dort pas, il n’existe plus. Le visiteur suivant paie le redémarrage.
Ce redémarrage prenait entre deux et quatre minutes. Le proxy qui relie mon site au service abandonne au bout de trente secondes, et le visiteur recevait donc une erreur pour une requête qui, côté Google, finissait par parfaitement réussir — deux ou trois minutes plus tard, quand plus personne ne regardait.
J’ai passé un moment à chercher l’application coupable avant de regarder les journaux dans le bon ordre. Le serveur démarre en deux millisecondes. Il n’y avait donc rien à optimiser dans mon code : la totalité du délai était du transport. L’image du conteneur était stockée aux États-Unis, et le service tourne en Europe. Quatre cent cinquante-six mégaoctets tirés à travers l’Atlantique à chaque réveil. Ce n’était pas un problème de poids, c’était un problème de géographie — et aucune quantité d’optimisation n’aurait corrigé un océan.
Le registre déplacé du bon côté, et le conteneur allégé au passage de tout ce qui n’y servait à rien — un compilateur qu’aucune requête n’appelle, une bibliothèque de cache qui ne cachait rien d’utile —, le réveil est tombé à quarante-quatre secondes.
Avec, en chemin, une leçon que je note ici parce qu’elle m’a coûté un déploiement raté. J’avais aussi supprimé les suites de tests embarquées dans les paquets Python, une centaine de mégaoctets qui ne servent manifestement à rien en production. Le conteneur a refusé de démarrer : numpy va chercher son propre module de tests au moment de s’importer. Mes quarante-trois tests passaient parfaitement pendant ce temps — ils s’exécutent contre mon environnement local, pas contre l’image. Aucune suite de tests ne pouvait attraper ça. Seul un conteneur qui démarre le pouvait.
Mesuré pour de bon, en laissant le service s’éteindre puis en revenant vingt et une minutes plus tard : la requête passe en trente-huit secondes. Le premier visiteur d’un service éteint attend donc une quarantaine de secondes et obtient son résultat, là où il recevait une erreur. La page l’avertit quand même qu’elle réveille quelque chose, et réessaie d’elle-même si la première tentative n’aboutit pas — parce qu’une mesure prise une fois n’est pas une garantie, et que je préfère une interface qui dit la vérité sur ce qu’elle est en train de faire. C’est le prix affiché de la gratuité, et l’afficher me paraît mieux que le maquiller.
Deux produits, une petite expérience
Il y a longtemps que je savais que Midas contenait deux choses distinctes : des agents qui délibèrent d’un côté, un moteur de calcul de l’autre. Ce n’est pas un signal technique qui me l’a dit, c’est une gêne — celle de ne plus savoir décrire le projet en une phrase.
Ce qui manquait n’était pas la décision, c’était l’occasion. Et l’occasion, chez moi, ressemble à ceci : dès qu’un nouveau modèle sort, je l’essaie sur une revue de mon portfolio. C’est à la fois un vrai travail de rangement et une excuse honorable pour jouer avec le nouveau jouet, et je ne vois pas de raison de trancher entre les deux. Je ne compare rien, je ne tiens aucun tableau de scores ; je constate simplement que mes outils se sont affinés à mesure que les modèles s’amélioraient.
Ce qui donne une boucle que je trouve assez juste sur l’époque. Construire est devenu facile avec l’IA, donc je commence maximaliste, avec beaucoup trop d’idées, et j’accumule plus vite que je ne range. Et ce qui finit par me faire ranger, c’est encore l’IA — un modèle qui sort et qu’il faut bien essayer sur quelque chose.
Reste l’aveu. Je ne me sers pas de cet outil. L’occasion ne se présente pas si souvent, il n’était pas vraiment prêt jusqu’à ce matin, et surtout c’est une petite expérience, pas un objet du quotidien. J’ai construit l’instrument qui répond à la question du bar, et il ne change rien à ce qui se passe au bar. C’est exactement ce que je racontais à propos d’Untilt : savoir qu’on est biaisé ne suffit pas à cesser de l’être, et savoir qu’on pourrait objectiver ne pousse pas à le faire.
Une expérience n’a pas besoin de devenir une habitude pour avoir valu la peine.
P.S. — Un mot qui n’est pas une clause de style. Ce que l’outil affiche, ce sont des résultats passés calculés sur des données historiques, et une stratégie qui aurait bien fonctionné hier ne dit rigoureusement rien de demain. Ce n’est pas un conseil en investissement, et c’est même à peu près le contraire : un instrument pour douter des conseils, y compris de ceux qu’on se donne à soi-même.