1 septembre 2026 · opérations sur titres

Données ajustées des splits, décortiquées : ce que le 10-pour-1 de NVDA fait à chaque ligne derrière lui

Données ajustées des splits, décortiquées : ce que le 10-pour-1 de NVDA fait à chaque ligne derrière lui

Voici une ligne extraite d'un fichier quotidien d'actions. NVDA, vendredi 7 juin 2024, la dernière séance avant l'entrée en vigueur du split 10-pour-1.

ColonneValeur
date2024-06-07
close1208.88
volume42,800,000 (arrondi)
split_factor1.0
dividend0.00
adj_close120.8781

J'ai volontairement écarté les colonnes OHLC de cette vue. Elles reviennent vers la fin, et ce sont elles qui cassent en silence.

Tout ce qu'il y a d'intéressant dans cette ligne habite l'écart entre la colonne deux et la colonne six. Le ticker du 7 juin a imprimé 1208.88. Plus personne ne transigera jamais à ce prix, en ce sens que l'action à laquelle il se référait n'existe plus comme unité. Le 120.8781 est une reconstruction, et ce n'est pas simplement 1208.88 divisé par dix. Allons-y colonne par colonne.

10:1diviseur appliqué à chaque ligne précédente
0.99991789facteur de dividende, apposé un jour plus tard
$45commission fantôme par aller-retour
2.8ppdrag annuel inventé par un diviseur

date : 2024-06-07, et les deux autres dates qui comptent davantage

Le split a été annoncé le 22 mai 2024 en même temps que les résultats. La date de record était le 6 juin. La négociation a commencé sur une base ajustée du split le lundi 10 juin. Trois dates, et la colonne split_factor de votre fournisseur en occupe exactement une, généralement la première séance ajustée du split. L'off-by-one ici est le bug d'opération sur titres le plus fréquent que je vois, et il est invisible en agrégat : votre courbe d'equity encaisse un gap-down de 90% ou un gap-up de 900% sur une seule journée, qu'un Sharpe calculé sur 2,000 jours enregistre à peine, mais qu'un max-drawdown ou une règle de stop-loss enregistre bel et bien.

Le dividende a son propre problème de dates, et il a changé sous les pieds de tout le monde en 2024. Le dividende trimestriel post-split de $0.01 de NVDA avait une date de record au 11 juin. Le règlement US est passé à T+1 le 28 mai 2024, ce qui signifie que l'ex-date et la date de record tombent désormais le même jour. Tout loader qui dérive l'ex-date comme « date de record moins un jour ouvré », ce qui était correct pendant des décennies, a commencé à produire silencieusement des ajustements de dividende une séance trop tôt en juin 2024. Rien ne lève d'exception. Le facteur atterrit simplement sur la mauvaise ligne.

Le mode de défaillance du code d'opérations sur titres n'est jamais une exception. C'est un chiffre décalé d'un jour et qui a l'air tout à fait plausible.

close : 1208.88 — le prix qui n'est pas dans le fichier

C'est le print brut, et dans la plupart des pipelines de recherche il n'existe que comme une colonne que personne ne lit. Les signaux se calculent sur adj_close. Et toute règle qui référence un niveau de prix par action en dollars référence désormais un chiffre qu'aucun participant de marché n'a jamais vu.

La marche de NVDA vers $1,000 au printemps 2024 était un vrai phénomène, porté par un vrai flux d'ordres : aimants des nombres ronds, strikes d'options regroupés à 950 et 1000, headline risk à chaque approche. Dans les données ajustées, tout cet épisode se joue à $100. Si vous testez un comportement de niveaux psychologiques, une logique de gap-fill près des nombres ronds, ou une feature de proximité de strike, vous le testez contre une série de prix rescalée par un événement qui n'avait pas encore eu lieu.

Il en va de même pour les filtres d'univers. « Exclure les actions sous $5 » est un proxy légitime d'un vrai faisceau de problèmes de microstructure : spreads relatifs larges, règles de marginabilité, régimes de tick. Appliquez-le à l'historique ajusté et vous excluez des sociétés pour des périodes où elles se négociaient à $30 et ont ensuite subi un reverse split. Lancez « prix supérieur à $500 » et vous ferez silencieusement disparaître NVDA de chaque année antérieure à juin 2024. Les filtres de prix appartiennent aux prints non ajustés. Point final.

split_factor : 1.0 — et le 0.1 de la ligne suivante

Le facteur est un produit cumulé qui remonte depuis aujourd'hui. Chaque ligne antérieure au 10 juin 2024 porte un 0.1 issu de ce split, multiplié par le 0.25 du 4-pour-1 de 2021, multiplié par tout ce qui précède. L'historique pré-2021 de NVDA est mis à l'échelle par 0.025, si bien qu'une barre imprimée à $200 en 2019 apparaît à $5.00.

Deux conséquences à retenir. Premièrement, l'historique ajusté change à chaque fois qu'une nouvelle opération sur titres atterrit. Un backtest lancé en mai 2024 et un que vous lancez aujourd'hui produisent des chiffres différents sur un code identique et des dates identiques, et si vous avez mis en cache des features indexées sur le symbole et la date sans estampille de version des données, vous avez désormais un cache qui mélange deux échelles. Nous versionnons l'epoch d'ajustement dans la clé de feature précisément pour cette raison ; ça nous a coûté un après-midi particulièrement confus pour l'apprendre.

Deuxièmement, à l'échelle 0.025, une action qui se négociait par ticks de $0.01 évolue désormais par incréments de $0.00025. Votre logique d'arrondi au tick, vos comparaisons « est-ce un nouveau plus haut », vos tests d'égalité de flottants : tous opèrent désormais bien en deçà de la résolution qu'avait réellement le marché.

dividend : 0.01 — le chiffre qui fait sortir de la grille chaque prix derrière lui

Un centime. Ça ressemble à du bruit, et c'est la raison pour laquelle adj_close affiche 120.8781 plutôt qu'un 120.888 bien propre.

Le close du 10 juin était 121.79. Le facteur ex-dividende est (121.79 − 0.01) / 121.79 = 0.99991789. Ce facteur multiplie chaque prix antérieur au 11 juin, si bien que le 120.888 ajusté du split devient 120.878074. Petit, et permanent, et réappliqué à chacune des soixante et quelques ex-dates qui remontent dans l'historique de NVDA. C'est l'effet composé qui compte : le jour où vous regardez 2015, vous regardez un prix multiplié par des dizaines de facteurs plus ou moins irrationnels. Pas un seul prix historique ajusté ne repose sur la grille du penny.

Ce qui signifie que chaque comparaison == contre un niveau rond est fausse, que chaque test « avons-nous touché le prix limite » a besoin d'une tolérance, et que votre OHLC reconstruit ne satisfait plus l'invariant low ≤ open ≤ high après un arrondi naïf à 4 décimales. Cela signifie aussi que adj_close est une série de total-return tandis que close est une série de price-return, et si vous calculez les rendements sur l'une et les drawdowns sur l'autre, vous avez mélangé deux définitions différentes de ce qui s'est passé.

volume : 42,800,000 — le diviseur que personne n'applique de façon cohérente

Le volume en actions doit être multiplié par 10 pour être comparable aux séances post-split. Certains fournisseurs le font. D'autres non. Certains ajustent l'OHLC et laissent le volume brut, ce qui est le pire des trois, parce que le fichier a l'air cohérent en interne jusqu'à ce que vous multipliiez le prix par le volume.

Le geste honnête est d'arrêter d'utiliser le volume en actions comme feature et d'utiliser le volume en dollars, invariant aux splits par construction. Un filtre de liquidité sur le volume dollar moyen à 20 jours n'a besoin d'aucune logique d'ajustement et ne peut pas être cassé par une opération sur titres. L'invariance des features l'emporte sur un code d'ajustement correct, parce qu'un code d'ajustement correct est une chose sur laquelle il faut continuer d'avoir raison.

Trois formes de fichier fournisseur, trois modes de défaillance.

Ce qui est livréCe qui casse
Close ajusté seulement, OHLC brutLa logique de gap et d'intrabar calcule à cheval sur deux échelles de prix
OHLC ajusté, volume brutVolume en dollars décalé du ratio de split ; les filtres ADV se déclenchent à tort
OHLCV brut plus colonnes de facteursRien, si vous les appliquez. Tout, si vous les appliquez sur la mauvaise ligne

Les colonnes qui ne sont pas ici : adj_open, adj_high, adj_low

Remettez maintenant l'OHLC. Si un flux n'ajuste que le close et que votre stratégie calcule un gap overnight comme open / prev_adj_close − 1, alors le 10 juin 2024 elle calcule 120.37 / 120.8781 − 1, ce qui est un chiffre tout à fait correct, environ −0.4%. Reculez le même code au 7 juin 2024 et il calcule l'open du fichier brut (environ 1207) contre un close ajusté de 0.025 par des splits plus anciens, et il produit un gap de plusieurs milliers de pour cent.

Tout ce qui mélange une colonne brute et une colonne ajustée est de l'arithmétique à cheval sur deux systèmes de coordonnées. Je traite désormais les lectures à ajustement mixte comme une assertion au niveau du loader plutôt que comme quelque chose qu'un chercheur doit retenir, parce que les chercheurs ne le feront pas, moi y compris.

Ce qu'aucune colonne ne vous dit : combien d'actions vous auriez réellement achetées

C'est celui-là qui coûte de l'argent dans le modèle de coûts du backtest, et c'est la raison pour laquelle j'écris sur un split d'actions tout court.

Les commissions sur actions US sont souvent par action. Disons $0.005 avec un minimum d'ordre de $1.00, un palier fixe courant chez les courtiers retail. Backtestez maintenant une position NVDA de $400,000 un an avant le split, quand le prix brut était près de $400 et que le prix ajusté s'affiche à $40.

ActionsCommission
Ce qui s'est réellement passé (brut $400)1,000$5.00
Ce que le backtest voit (ajusté $40)10,000$50.00

Même exposition, même trade, 10x le coût modélisé. Ça fait $45 de fiction par jambe, $90 par aller-retour, et une stratégie à rotation quotidienne avale environ $22,000 par an de coûts qui n'ont jamais existé. Sur un book de $400k, 5.6 points de pourcentage de rendement annuel, entièrement fabriqués par un diviseur. Ici ça vous fait paraître plus mauvais que la réalité, ce qui est tenable.

Les reverse splits vont dans l'autre sens, et c'est le sens dangereux. Un reverse split 1-pour-10 signifie que l'historique ajusté affiche des prix 10x plus élevés et des nombres d'actions 10x plus bas que ce que vous auriez négocié. Votre modèle de coûts divise silencieusement la commission par action par dix. L'univers où les reverse splits sont courants est l'univers small-cap, sous $5, à spreads larges, où les frais par action sont la plus grosse ligne du stack de coûts. Le backtest flatte exactement les noms qu'il devrait punir.

Donc le correctif est ennuyeux et structurel : dimensionnez les positions en dollars, convertissez en actions avec le prix non ajusté de cette date, et facturez les frais par action sur ce nombre. Gardez la colonne de prix brut dans le loader pour toujours, non pas comme artefact d'audit mais comme entrée live du moteur de fills.

  1. Signaux et rendements : série ajustée.
  2. Nombres d'actions, frais par action, arrondi au tick, filtres de niveau de prix : série non ajustée.
  3. Liquidité et capacité : volume en dollars, qui n'a besoin ni de l'une ni de l'autre.

Six colonnes, une ligne, une opération sur titres assez ordinaire, annoncée trois semaines à l'avance et qui n'a surpris personne. Le marché l'a gérée en une matinée. La reconstruire fidèlement dans un pipeline de recherche est nettement plus difficile, et le signe qu'un pipeline ne l'a pas fait n'est presque jamais un message d'erreur.

opérations sur titresajustement des splitsactions USingénierie des donnéesbacktesting
← Tous les articles