1. september 2026 · selskabshandlinger

Splitjusterede data skilt ad: hvad NVDA's 10-for-1 gør ved hver række bagved

Splitjusterede data skilt ad: hvad NVDA's 10-for-1 gør ved hver række bagved

Her er én række fra en daglig aktiefil. NVDA, fredag 7. juni 2024, den sidste handelsdag før 10-for-1-splittet trådte i kraft.

Kolonne Værdi
dato 2024-06-07
close 1208.88
volume 42,800,000 (afrundet)
split_factor 1.0
dividend 0.00
adj_close 120.8781

Jeg har bevidst udeladt OHLC-kolonnerne i denne visning. De kommer tilbage hen mod slutningen, og det er dem, der i det stille skaber problemer.

Alt det interessante ved denne række ligger i afstanden mellem kolonne to og kolonne seks. Børstapen viste 1208.88 den 7. juni. Ingen kommer nogensinde til at handle til den pris igen, fordi den aktieenhed, prisen refererede til, ikke længere findes. De 120.8781 er en rekonstruktion, og det er ikke bare 1208.88 divideret med ti. Lad os tage kolonnerne én ad gangen.

10:1divisor anvendt på hver tidligere række
0.99991789udbyttefaktor påført én dag senere
$90fiktiv kurtage pr. tur-retur-handel
5.6ppårligt afkasttab opfundet af en divisor

date: 2024-06-07 og de to andre datoer, der betyder mere

Splittet blev annonceret 22. maj 2024 sammen med regnskabet. Registreringsdatoen var 6. juni. Handlen på splitjusteret basis begyndte mandag 10. juni. Tre datoer, og din dataleverandørs split_factor-kolonne ligger præcis på én af dem, som regel den første splitjusterede handelsdag. En forskydning på én dag er den mest almindelige fejl i håndteringen af selskabshandlinger, jeg støder på, og den er usynlig i aggregaterne: din equity-kurve får ét fald på 90 % eller én stigning på 900 % på en enkelt dag. Det slår knap nok ud på en Sharpe beregnet over 2,000 dage, men det gør en maksimal drawdown eller en stop-loss-regel bestemt.

Udbyttet har sit eget datoproblem, og reglerne ændrede sig midt under det hele i 2024. NVDA's kvartalsvise udbytte på $0.01 efter splittet havde registreringsdato 11. juni. Afvikling i USA gik over til T+1 den 28. maj 2024, hvilket betyder, at ex-dato og registreringsdato nu er samme dag. Enhver loader, der beregner ex-datoen som »registreringsdato minus én bankdag« — hvilket var korrekt i årtier — begyndte i juni 2024 lydløst at lægge udbyttejusteringerne én handelsdag for tidligt. Der opstår ingen fejl. Faktoren lander bare på den forkerte række.

Fejl i kode til selskabshandlinger udløser aldrig en undtagelse. Det er et tal, der er forskudt én dag og ser helt plausibelt ud.

close: 1208.88 — prisen, der ikke findes i filen

Det her er det rå kursprint, og i de fleste research-pipelines findes det kun som en kolonne, ingen læser. Signaler beregnes på adj_close. Og enhver regel, der bruger et kursniveau i dollars pr. aktie, refererer nu til et tal, ingen markedsdeltager nogensinde så.

NVDA's seje opstigning mod $1,000 i foråret 2024 var virkelig og havde reelle ordrestrømme bag sig: runde tal, der tiltrak handlen, optionsstrikes samlet omkring 950 og 1000 samt overskriftsrisiko ved hver tilgang. I justerede data foregår hele forløbet ved $100. Hvis du tester adfærd omkring psykologiske kursniveauer, logik for lukning af kursgab nær runde tal eller en funktion baseret på nærhed til en strike, tester du mod en kursserie, der er skaleret om af en begivenhed, som endnu ikke havde fundet sted.

Det samme gælder universfiltre. »Udelad aktier under $5« er en legitim stedfortræder for en reel klynge af mikrostrukturproblemer: brede relative spreads, regler for belåning og tick-regimer. Kører du det på justeret historik, udelukker du selskaber i perioder, hvor de blev handlet til $30 og senere gennemførte et omvendt split. Kører du »kurs over $500«, fjerner du lydløst NVDA fra alle år før juni 2024. Kursfiltre hører til på ujusterede kursprint. Punktum.

split_factor: 1.0 — og 0.1 på den næste række

Faktoren er et kumulativt produkt, der beregnes baglæns fra i dag. Hver række før 10. juni 2024 får en faktor på 0.1 fra dette split, ganget med 0.25 fra 4-for-1-splittet i 2021, ganget med alt det, der kom før. NVDA's historik før 2021 skaleres med 0.025, så en bar, der blev handlet til $200 i 2019, vises som $5.00.

Husk især to konsekvenser. For det første ændrer den justerede historik sig, hver gang en ny selskabshandling finder sted. En backtest, du kørte i maj 2024, og en, du kører i dag, giver forskellige tal med identisk kode over identiske datoer. Hvis du cachede funktioner med nøgle på symbol og dato uden et dataversionsstempel, har du nu en cache, der blander to skalaer. Vi versionsmærker justeringsepoken i funktionsnøglen af præcis den grund; det kostede os én meget forvirrende eftermiddag at finde ud af det.

For det andet bevæger en aktie, der blev handlet i trin på $0.01, sig ved en skalering på 0.025 nu i trin på $0.00025. Din tick-afrunding, dine sammenligninger af »er dette en ny top« og dine sammenligninger af flydende kommatal arbejder nu alle langt under den opløsning, markedet faktisk havde.

dividend: 0.01 — tallet, der fjerner centgitteret fra alle tidligere kurser

Én cent. Det ligner støj, men det er grunden til, at adj_close viser 120.8781 i stedet for et pænt 120.888.

Lukkekursen 10. juni var 121.79. Ex-udbyttefaktoren er (121.79 − 0.01) / 121.79 = 0.99991789. Denne faktor ganges på alle kurser før 11. juni, så den splitjusterede kurs på 120.888 bliver til 120.878074. Det er en lille ændring, den er permanent, og den anvendes igen på hver eneste af de godt tres ex-datoer gennem NVDA's historik. Det er den kumulative effekt, der betyder noget: når du ser på 2015, ser du på en kurs, der er blevet ganget med snesevis af faktorer, der ikke går rent op. Ingen justeret historisk kurs ligger på centgitteret.

Det betyder, at enhver ==-sammenligning med et rundt niveau er forkert, at alle kontroller af »ramte vi limitkursen« kræver en tolerance, og at dine rekonstruerede OHLC-værdier ikke længere opfylder invarianten low ≤ open ≤ high efter en naiv afrunding til 4 decimaler. Det betyder også, at adj_close er en totalafkastserie, mens close er en kursafkastserie. Beregner du afkast ud fra den ene og drawdowns ud fra den anden, har du blandet to forskellige definitioner af, hvad der skete.

volume: 42,800,000 — divisoren, som ikke alle anvender ens

Aktievolumen skal ganges med 10 for at kunne sammenlignes med handelsdage efter splittet. Nogle dataleverandører gør det. Andre gør ikke. Nogle justerer OHLC og lader volumen være rå, hvilket er den værste af de tre varianter, fordi filen ser internt konsistent ud, indtil du ganger kurs med volumen.

Det fornuftige er at holde op med at bruge aktievolumen som en funktion og i stedet bruge omsætning i dollars, som i kraft af sin konstruktion er invariant over for splits. Et likviditetsfilter baseret på gennemsnitlig omsætning i dollars over 20 dage kræver slet ingen justeringslogik og kan ikke ødelægges af en selskabshandling. Invariante funktioner slår korrekt justeringskode, for korrekt justeringskode er noget, du hele tiden skal blive ved med at have ret i.

Tre typer datafiler fra leverandører, tre fejlscenarier.

Hvad leveres Hvad går galt
Kun justeret close, rå OHLC Logik for kursgab og intradagshandel beregner på tværs af to kursskalaer
Justeret OHLC, rå volume Omsætning i dollars afviger med splitforholdet; ADV-filtre rammer forkert
Rå OHLCV plus faktorkolonner Intet, hvis du anvender dem. Alt, hvis du anvender dem på den forkerte række

Kolonnerne, der mangler: adj_open, adj_high, adj_low

Sæt nu OHLC tilbage. Hvis et feed kun justerer close, og din strategi beregner et kursgab fra luk til åbning som open / prev_adj_close − 1, beregner den for 10. juni 2024 120.37 / 120.8781 − 1, hvilket er et fornuftigt tal på cirka −0.4%. Kører du den samme kode tilbage til 7. juni 2024, bruger den open fra den rå fil (omkring 1207) op mod en close justeret med 0.025 fra tidligere splits og giver et kursgab på flere tusinde procent.

Alt, der blander en rå kolonne med en justeret, er regning på tværs af to koordinatsystemer. Jeg behandler nu aflæsninger med blandede justeringer som en påstand i loaderen, frem for noget en researcher skal huske, for det gør de ikke — heller ikke jeg.

Hvad ingen kolonne fortæller dig: hvor mange aktier du faktisk ville have købt

Det her er det, der koster penge i backtestens omkostningsmodel, og det er grunden til, at jeg overhovedet skriver om aktiesplit.

Kurtage på amerikanske aktier beregnes ofte pr. aktie. Lad os sige $0.005 med et minimum på $1.00 pr. ordre, en almindelig fast prisklasse hos detailmæglere. Backtest nu en NVDA-position på $400,000 et år før splittet, hvor den rå kurs lå omkring $400, og den justerede kurs vises som $40.

Aktier Kurtage
Det, der faktisk skete (rå $400) 1,000 $5.00
Det, backtesten ser (justeret $40) 10,000 $50.00

Samme eksponering, samme handel, 10 gange så høje modellerede omkostninger. Det er $45 ren fiktion pr. ben, $90 pr. tur-retur-handel, og en strategi med daglig omsætning på positionerne ender med omkring $22,000 om året i omkostninger, der aldrig har eksisteret. På en portefølje på $400k er det 5.6 procentpoint af det årlige afkast, udelukkende skabt af en divisor. Her får det dig til at se dårligere ud end virkeligheden, og det kan man leve med.

Omvendte splits vender regnestykket, og det er den farlige retning. Et omvendt split på 1-for-10 betyder, at den justerede historik viser kurser, der er 10 gange højere, og aktieantal, der er 10 gange lavere, end dem du ville have handlet. Din omkostningsmodel dividerer lydløst kurtagen pr. aktie med ti. Området med almindelige omvendte splits er small-cap-aktier under $5 med brede spreads, hvor gebyrer pr. aktie udgør den største enkeltpost i omkostningsregnskabet. Backtesten smigrer netop de aktier, den burde straffe.

Løsningen er enkel og strukturel: fastsæt positionsstørrelser i dollars, omregn til aktier med den ujusterede kurs for den pågældende dato, og beregn kurtage pr. aktie ud fra det antal. Behold kolonnen med rå kurser i loaderen for altid, ikke som et revisionsspor, men som et aktivt input til fill-motoren.

  1. Signaler og afkast: justeret serie.
  2. Aktieantal, kurtage pr. aktie, tick-afrunding, kursfiltre: ujusteret serie.
  3. Likviditet og kapacitet: omsætning i dollars, der ikke kræver nogen af delene.

Seks kolonner, én række, én ret almindelig selskabshandling, der blev annonceret tre uger i forvejen og ikke overraskede nogen. Markedet håndterede den på en formiddag. Det er langt sværere at rekonstruere den korrekt i en research-pipeline, og tegnet på, at en pipeline ikke har gjort det, er næsten aldrig en fejlmeddelelse.

selskabshandlingersplitjusteringamerikanske aktierdatateknikbacktesting
← Alle indlæg