Iată un rând dintr-un fișier zilnic cu acțiuni. NVDA, vineri, 7 iunie 2024, ultima sesiune înainte ca splitul de 10 la 1 să intre în vigoare.
| Coloană | Valoare |
|---|---|
| dată | 2024-06-07 |
| închidere | 1208.88 |
| volum | 42,800,000 (rotunjit) |
| split_factor | 1.0 |
| dividend | 0.00 |
| adj_close | 120.8781 |
Am omis în mod deliberat coloanele OHLC din această perspectivă. Revin aproape de final și sunt cele care provoacă probleme pe nesimțite.
Tot ce e interesant la acest rând se află în diferența dintre coloana a doua și coloana a șasea. Pe 7 iunie, tranzacțiile s-au făcut la 1208.88. Nimeni nu va mai tranzacționa vreodată la acel preț, în sensul că acțiunea la care se referea nu mai există ca unitate. Valoarea 120.8781 este o reconstrucție și nu rezultă pur și simplu din împărțirea lui 1208.88 la zece. Să luăm coloanele pe rând.
dată: 2024-06-07 și celelalte două date care contează mai mult
Splitul a fost anunțat pe 22 mai 2024, odată cu rezultatele financiare. Data
de înregistrare a fost 6 iunie. Tranzacționarea pe baza ajustată la split a
început luni, 10 iunie. Trei date, iar coloana
split_factor furnizorului tău de date corespunde exact uneia
dintre ele, de obicei primei sesiuni ajustate la split. Eroarea de o zi este
cea mai frecventă greșeală de corporate action pe care o întâlnesc și rămâne
invizibilă în agregate: curba capitalului tău înregistrează o singură scădere
de 90% sau o creștere de 900% într-o zi, lucru pe care un Sharpe calculat pe
2,000 de zile abia îl surprinde, dar pe care o regulă de drawdown maxim sau de
stop-loss îl detectează imediat.
Dividendul are propria problemă de dată, iar în 2024 regulile s-au schimbat fără ca mulți să observe. Dividendul trimestrial al NVDA de $0.01 după split avea data de înregistrare pe 11 iunie. Decontarea în SUA a trecut la T+1 pe 28 mai 2024, ceea ce înseamnă că data ex-dividend și data de înregistrare sunt acum aceeași zi. Orice loader care calculează data ex-dividend ca „data de înregistrare minus o zi lucrătoare”, metodă corectă timp de decenii, a început în iunie 2024 să aplice în tăcere ajustările de dividend cu o sesiune prea devreme. Nu apare nicio eroare. Factorul ajunge pur și simplu pe rândul greșit.
Codul pentru corporate actions nu eșuează niciodată printr-o excepție. Produce un număr deplasat cu o zi, care pare perfect plauzibil.
close: 1208.88 — prețul care lipsește din fișier
Acesta este prețul brut afișat și, în majoritatea fluxurilor de cercetare,
există doar ca o coloană pe care nimeni nu o citește. Semnalele se calculează
pe adj_close. Iar orice regulă care folosește un nivel de preț
per acțiune, în dolari, se raportează acum la o valoare pe care niciun
participant la piață n-a văzut-o vreodată.
Creșterea constantă a NVDA spre $1,000 în primăvara lui 2024 a fost un fenomen real, susținut de fluxuri reale de ordine: pragurile rotunde atrăgeau prețul, strike-urile opțiunilor se grupau la 950 și 1000, iar fiecare apropiere aducea riscuri de știri. În datele ajustate, întregul episod are loc la $100. Dacă testezi comportamentul în jurul pragurilor psihologice, logica de umplere a gapurilor aproape de numere rotunde sau un indicator bazat pe proximitatea față de strike, îl testezi pe o serie de prețuri rescalată de un eveniment care încă nu avusese loc.
Același lucru se aplică filtrelor de univers. „Exclude acțiunile sub $5” este un indicator legitim pentru un grup real de probleme de microstructură: spreaduri relative mari, reguli privind eligibilitatea pentru marjă și regimuri de tick. Aplică-l pe istoricul ajustat și vei exclude companii în perioade în care se tranzacționau la $30 și au trecut ulterior printr-un reverse split. Aplică filtrul „preț peste $500” și NVDA va dispărea pe nesimțite din fiecare an anterior lui iunie 2024. Filtrele de preț trebuie aplicate prețurilor brute. Fără excepție.
split_factor: 1.0 — și valoarea 0.1 de pe rândul următor
Factorul este un produs cumulativ calculat înapoi pornind de la ziua de azi. Fiecare rând anterior lui 10 iunie 2024 include un factor de 0.1 de la acest split, înmulțit cu 0.25 de la splitul de 4 la 1 din 2021, apoi cu orice factor anterior. Istoricul NVDA dinainte de 2021 este scalat cu 0.025, așa că o bară tranzacționată la $200 în 2019 apare ca $5.00.
Merită să reții două consecințe. În primul rând, istoricul ajustat se schimbă de fiecare dată când apare o nouă acțiune corporativă. Un backtest rulat în mai 2024 și unul rulat astăzi produc rezultate diferite pe același cod și aceleași date. Dacă ai pus în cache indicatori indexați după simbol și dată, fără o versiune a datelor, acum ai un cache care amestecă două scări. Din acest motiv includem epoca de ajustare în cheia indicatorului; a fost nevoie de o după-amiază foarte confuză ca să învățăm asta.
În al doilea rând, la o scalare de 0.025, o acțiune care se tranzacționa în tickuri de $0.01 se mișcă acum în pași de $0.00025. Logica de rotunjire la tick, verificările de tipul „este un nou maxim”, comparațiile de egalitate între valori float: toate operează acum la o precizie mult mai mare decât cea disponibilă efectiv pe piață.
dividend: 0.01 — cifra care scoate fiecare preț anterior din grila de cenți
Un cent. Pare un detaliu neglijabil și totuși acesta este motivul pentru care
adj_close indică 120.8781 în loc de o valoare rotundă, 120.888.
Închiderea din 10 iunie a fost 121.79. Factorul ex-dividend este (121.79 − 0.01) / 121.79 = 0.99991789. Acest factor multiplică fiecare preț anterior datei de 11 iunie, astfel că valoarea 120.888 ajustată la split devine 120.878074. Diferența e mică, dar permanentă, și se aplică din nou la fiecare dintre cele peste șaizeci de date ex-dividend din istoricul NVDA. Efectul cumulat contează: când ajungi la 2015, prețul a fost multiplicat cu zeci de factori ușor iraționali. Niciun preț istoric ajustat nu mai este multiplu exact de un cent.
Asta înseamnă că fiecare == comparație cu un prag rotund este
falsă, fiecare verificare de tipul „am atins prețul limită?” are nevoie de o
toleranță, iar valorile OHLC reconstruite nu mai respectă invariantul low ≤
open ≤ high după o rotunjire simplă la 4 zecimale. Înseamnă și că
adj_close este o serie de randament total, în timp ce
close este o serie de randament al prețului; dacă calculezi
randamentele dintr-una și drawdownurile din cealaltă, ai amestecat două
definiții diferite ale evenimentelor.
volume: 42,800,000 — divizorul care nu se aplică consecvent
Volumul de acțiuni trebuie înmulțit cu 10 pentru a putea fi comparat cu sesiunile de după split. Unii furnizori fac asta. Alții nu. Unii ajustează OHLC, dar lasă volumul brut — cea mai proastă variantă dintre cele trei, pentru că fișierul pare coerent până când înmulțești prețul cu volumul.
Soluția corectă este să nu mai folosești volumul de acțiuni ca indicator și să folosești volumul în dolari, care prin construcție nu se schimbă la splituri. Un filtru de lichiditate bazat pe media volumului în dolari pe 20 de zile nu are nevoie de nicio logică de ajustare și nu poate fi stricat de o acțiune corporativă. Invarianța indicatorului e preferabilă unui cod de ajustare corect, fiindcă trebuie să te asiguri mereu că acel cod rămâne corect.
Trei forme de fișiere de la furnizori, trei moduri de a da greș.
| Ce conține fișierul | Ce se strică |
|---|---|
| Doar închiderea ajustată, OHLC brut | Logica pentru gapuri și mișcări intraday calculează între două scări de preț |
| OHLC ajustat, volum brut | Volumul în dolari diferă cu raportul splitului; filtrele ADV dau rezultate greșite |
| OHLCV brut plus coloane cu factori | Nimic, dacă aplici factorii. Totul, dacă îi aplici pe rândul greșit |
Coloanele care lipsesc: adj_open, adj_high, adj_low
Să adăugăm acum OHLC. Dacă un flux ajustează doar închiderea, iar strategia ta
calculează un gap overnight ca open / prev_adj_close − 1, atunci
pe 10 iunie 2024 calculează 120.37 / 120.8781 − 1, o valoare rezonabilă, de
aproximativ −0.4%. Aplică același cod la 7 iunie 2024 și va folosi deschiderea
din fișierul brut (aproximativ 1207) și o închidere ajustată cu 0.025 din
cauza spliturilor anterioare, rezultând un gap de câteva mii la sută.
Orice operație care combină o coloană brută cu una ajustată face calcule între două sisteme de coordonate. Acum tratez citirile cu ajustări amestecate ca pe o verificare obligatorie la nivelul loaderului, nu ca pe ceva ce trebuie să-și amintească cercetătorul, fiindcă nu-și va aminti — nici eu.
Ce nu-ți spune nicio coloană: câte acțiuni ai fi cumpărat efectiv
Aici apar costuri în modelul de costuri al backtestului și acesta este motivul pentru care scriu despre un split de acțiuni.
Comisioanele pentru acțiuni americane sunt adesea calculate per acțiune. Să presupunem un comision de $0.005, cu un minim de $1.00 per ordin, o grilă fixă uzuală la brokerii pentru investitori individuali. Acum rulează un backtest pentru o poziție NVDA de $400,000, cu un an înainte de split, când prețul brut era aproape de $400, iar prețul ajustat apare ca $40.
| Acțiuni | Comision | |
|---|---|---|
| Ce s-a întâmplat în realitate (brut $400) | 1,000 | $5.00 |
| Ce vede backtestul (ajustat $40) | 10,000 | $50.00 |
Aceeași expunere, aceeași tranzacție, de 10x mai multe costuri modelate. Asta înseamnă $45 fictivi pe sens, $90 dus-întors, iar o strategie cu rulaj zilnic ajunge să consume anual aproximativ $22,000 în costuri inexistente. Pentru un portofoliu de $400k, sunt 5.6 puncte procentuale din randamentul anual, inventate în întregime de un divizor. Aici te face să pari mai slab decât în realitate, ceea ce e suportabil.
Reverse spliturile funcționează în direcția opusă, iar asta e periculos. Un reverse split de 1 la 10 înseamnă că istoricul ajustat arată prețuri de 10x mai mari și numere de acțiuni de 10x mai mici decât cele pe care le-ai fi tranzacționat. Modelul tău reduce pe nesimțite de zece ori comisionul per acțiune. Reverse spliturile sunt frecvente în universul acțiunilor cu capitalizare mică, sub $5 și cu spreaduri largi, unde comisioanele per acțiune reprezintă cea mai mare componentă individuală a costurilor. Backtestul face să arate mai bine exact acțiunile pe care ar trebui să le penalizeze.
Soluția e simplă și structurală: stabilește dimensiunea poziției în dolari, convertește în acțiuni folosind prețul neajustat pentru data respectivă și calculează comisioanele per acțiune pe baza acelui număr. Păstrează coloana cu prețul brut în loader permanent, nu ca simplu artefact de audit, ci ca intrare activă pentru motorul de executare.
- Semnale și randamente: serie ajustată.
- Număr de acțiuni, comisioane per acțiune, rotunjire la tick, filtre de nivel al prețului: serie neajustată.
- Lichiditate și capacitate: volum în dolari, care nu necesită niciuna dintre ele.
Șase coloane, un rând, o acțiune corporativă destul de obișnuită, anunțată cu trei săptămâni înainte și care n-a surprins pe nimeni. Piața a procesat-o într-o dimineață. S-o reconstruiești fidel într-un flux de cercetare e cu totul altă poveste, iar indiciul că fluxul nu o face corect este rareori un mesaj de eroare.
← Toate articolele


