Ось один рядок із файлу денних даних по акціях. NVDA, п’ятниця, 7 червня 2024 року — остання сесія перед набуттям чинності сплітом 10:1.
| Стовпець | Значення |
|---|---|
| дата | 2024-06-07 |
| ціна закриття | 1208.88 |
| обсяг | 42,800,000 (округлено) |
| коефіцієнт_спліту | 1.0 |
| дивіденд | 0.00 |
| ціна_закриття_з_поправкою | 120.8781 |
Я навмисно не показав тут стовпці OHLC. Повернемося до них ближче до кінця — саме вони непомітно створюють проблеми.
Усе цікаве в цьому рядку — у проміжку між другим і шостим стовпцями. 7 червня стрічка показувала 1208.88. За цією ціною вже ніхто не торгуватиме: акції, до яких вона стосувалася, більше не існують як окрема одиниця. Значення 120.8781 — це реконструкція, і воно не просто дорівнює 1208.88, поділеному на 10. Розгляньмо кожен стовпець по черзі.
дата: 2024-06-07 та 2 інші дати, важливіші за неї
Про спліт оголосили 22 травня 2024 року разом із фінансовими результатами.
Дата фіксації власників акцій — 6 червня. Торги з поправкою на спліт почалися
в понеділок, 10 червня. Є 3 дати, а стовпець split_factor у
вашого постачальника даних припадає рівно на одну з них — зазвичай на першу
сесію після спліту. Помилка на один день — найпоширеніший збій в обробці
корпоративних дій, який я бачу, і в агрегованих даних її не помітити: крива
капіталу покаже одноразове падіння на 90% або стрибок на 900%. Sharpe за 2,000
днів це ледве зауважить, а максимальна просадка чи правило стоп-лосу —
неодмінно.
З дивідендом теж пов’язана проблема з датами, і у 2024 році правила змінилися для всіх. Дата фіксації власників акцій для квартального дивіденду NVDA у розмірі $0.01 після спліту припала на 11 червня. 28 травня 2024 року в США перейшли на розрахунки T+1, тобто дата без дивіденду тепер збігається з датою фіксації. Будь-який завантажувач, який визначає дату без дивіденду як «дата фіксації мінус один робочий день» — так було правильно протягом десятиліть — із червня 2024 року почав непомітно застосовувати поправку на дивіденд на одну сесію раніше. Жодної помилки не виникає. Просто коефіцієнт потрапляє не в той рядок.
Збої в коді обробки корпоративних дій ніколи не спричиняють виняток. Це число, зміщене на один день, яке виглядає цілком правдоподібно.
ціна закриття: 1208.88 — ціна, якої немає у файлі
Це фактична ціна угоди, і в більшості дослідницьких конвеєрів вона є лише у
стовпці, на який ніхто не дивиться. Сигнали обчислюють за
adj_close. А будь-яке правило, що спирається на рівень ціни за
акцію в доларах, тепер посилається на число, якого жоден учасник ринку не
бачив.
Зростання NVDA до $1,000 навесні 2024 року було реальним рухом із реальним потоком ордерів: круглі рівні притягували ціну, страйки опціонів скупчилися на 950 і 1000, а кожне наближення супроводжувалося ризиком гучних новин. У скоригованих даних увесь цей епізод відбувається на рівні $100. Якщо ви тестуєте поведінку біля психологічних рівнів, логіку закриття цінових розривів поблизу круглих значень або ознаку близькості до страйку, то робите це на ціновому ряді, масштаб якого змінила подія, що на той момент ще не відбулася.
Те саме стосується фільтрів для вибору інструментів. «Виключити акції дешевші за $5» — це цілком обґрунтований наближений показник реальних проблем мікроструктури: широких відносних спредів, правил щодо маржинальності, режимів кроку ціни. Застосуйте його до скоригованої історії — і виключите компанії за періоди, коли вони торгувалися по $30, а згодом пройшли зворотний спліт. Застосуйте фільтр «ціна понад $500» — і непомітно вилучите NVDA з кожного року до червня 2024 року. Цінові фільтри слід застосовувати до нескоригованих цін угод. Крапка.
коефіцієнт_спліту: 1.0 — і 0.1 у наступному рядку
Коефіцієнт — це кумулятивний добуток, який обчислюють у зворотному напрямку від сьогоднішньої дати. Кожен рядок до 10 червня 2024 року містить коефіцієнт 0.1 від цього спліту, помножений на 0.25 від спліту 4:1 у 2021 році, а також на всі попередні коефіцієнти. Для історичних даних NVDA до 2021 року застосовано масштаб 0.025, тому бар із ціною $200 у 2019 році тепер показує $5.00.
Варто пам’ятати про 2 наслідки. По-перше, скоригована історія змінюється щоразу, коли відбувається нова корпоративна дія. Бектест, запущений у травні 2024 року, і бектест, запущений сьогодні на тому самому коді та за ті самі дати, дадуть різні результати. Якщо ви кешували ознаки за символом і датою без позначки версії даних, то тепер ваш кеш поєднує 2 різні масштаби. Саме тому ми додаємо версію епохи поправок до ключа ознаки; щоб це зрозуміти, нам вистачило одного дуже заплутаного пообіддя.
По-друге, за масштабу 0.025 ціна акції, що торгувалася з кроком $0.01, тепер змінюється з кроком $0.00025. Логіка округлення до кроку ціни, перевірки на «новий максимум» і перевірки рівності чисел із плаваючою комою — тепер усе це працює з точністю, значно вищою за ту, що була на реальному ринку.
дивіденд: 0.01 — число, яке руйнує центову сітку всіх попередніх цін
Один цент. На вигляд — дрібниця, але саме через нього
adj_close дорівнює 120.8781, а не рівному 120.888.
Ціна закриття 10 червня становила 121.79. Коефіцієнт поправки на дивіденд дорівнює (121.79 − 0.01) / 121.79 = 0.99991789. Він множить усі ціни до 11 червня, тож скориговане з урахуванням спліту значення 120.888 стає 120.878074. Зміна невелика, але вона лишається назавжди й повторно застосовується на кожну з приблизно 60 дат без дивіденду в історії NVDA. Важливе саме накопичення: відкривши дані за 2015 рік, ви побачите ціну, помножену на десятки майже ірраціональних коефіцієнтів. Жодна скоригована історична ціна не лежить точно на центовій сітці.
Отже, кожне порівняння == з круглим рівнем дає хибний результат,
для кожної перевірки «чи торкнулися ми лімітної ціни» потрібен допуск, а
реконструйовані OHLC після наївного округлення до 4 знаків після коми вже не
задовольняють умову low ≤ open ≤ high. Крім того, adj_close — це
ряд повної дохідності, а close — ряд цінової дохідності. Якщо
обчислювати дохідність за одним рядом, а просадки — за іншим, у розрахунок
потрапляють 2 різні визначення того, що сталося.
обсяг: 42,800,000 — дільник, який застосовують непослідовно
Щоб обсяг акцій можна було порівнювати із сесіями після спліту, його треба помножити на 10. Одні постачальники даних це роблять, інші — ні. Деякі коригують OHLC, але залишають обсяг незмінним. Це найгірший варіант із трьох, бо файл здається внутрішньо узгодженим, доки ви не перемножите ціну на обсяг.
Найкраще взагалі перестати використовувати обсяг акцій як ознаку й перейти на доларовий обсяг, який за означенням не залежить від сплітів. Фільтр ліквідності за середнім доларовим обсягом за 20 днів узагалі не потребує логіки коригування, тож корпоративна дія його не зламає. Інваріантні ознаки кращі за правильний код коригування, бо правильність такого коду потрібно постійно підтримувати.
3 формати файлів постачальників даних — 3 причини збоїв.
| Що постачають | Що ламається |
|---|---|
| Лише ціна закриття скоригована, OHLC — сирі дані | Розриви й внутрішньосесійна логіка обчислень працюють із 2 різними ціновими масштабами |
| OHLC скориговані, обсяг — сирі дані | Доларовий обсяг не враховує коефіцієнт спліту; фільтри ADV спрацьовують неправильно |
| Сирі OHLCV і стовпці з коефіцієнтами | Нічого, якщо застосувати коефіцієнти; усе, якщо застосувати їх до неправильного рядка |
Чого тут немає: adj_open, adj_high, adj_low
Повернімо OHLC. Якщо потік даних коригує лише ціну закриття, а ваша стратегія
обчислює нічний розрив за формулою open / prev_adj_close − 1, то
10 червня 2024 року вона отримає 120.37 / 120.8781 − 1 — цілком прийнятне
число, приблизно −0.4%. Запустіть той самий код для 7 червня 2024 року — і він
візьме ціну відкриття із сирого файлу (близько 1207), а ціну закриття скоригує
коефіцієнтом 0.025 від попередніх сплітів. Результат — розрив у кілька тисяч
відсотків.
Будь-які обчислення, що поєднують сирий стовпець зі скоригованим, виконують арифметику в 2 різних системах координат. Тепер я перевіряю змішування рівнів поправки на рівні завантажувача, а не покладаюся на пам’ять дослідника — дослідники про це забувають, я теж.
Чого не покаже жоден стовпець: скільки акцій ви насправді придбали б
Саме цей чинник впливає на витрати в моделі комісій бектесту, і саме тому я взагалі пишу про спліт акцій.
Комісії за торгівлю акціями у США часто нараховують за кожну акцію. Візьмімо $0.005 за акцію з мінімумом $1.00 за ордер — поширений фіксований тариф роздрібного брокера. Тепер запустімо бектест позиції в NVDA на $400,000 за рік до спліту: тоді фактична ціна була близько $400, а у скоригованих даних відображалася як $40.
| Акції | Комісія | |
|---|---|---|
| Як було насправді (сирі дані, $400) | 1,000 | $5.00 |
| Що бачить бектест (скориговані дані, $40) | 10,000 | $50.00 |
Експозиція та угода ті самі, а змодельовані витрати у 10 разів вищі. Це $45 вигаданих витрат на одну сторону, $90 за повний цикл угоди, а стратегія, що торгує щодня, втрачає близько $22,000 на рік на витрати, яких ніколи не було. Для портфеля на $400k це 5.6 відсоткового пункту річної дохідності, цілком створеного дільником. Тут бектест показує гірший результат, ніж було насправді, а з цим можна жити.
Зворотні спліти працюють навпаки, і це небезпечний бік проблеми. За зворотного спліту 1:10 скориговані історичні дані показують ціни в 10 разів вищі, а кількість акцій — у 10 разів меншу, ніж у реальній торгівлі. Модель витрат непомітно ділить комісію за акцію на 10. Зворотні спліти поширені серед компаній із малою капіталізацією та акціями дешевшими за $5, де спреди широкі, а комісії за акцію становлять найбільшу статтю витрат. Бектест прикрашає результати саме тих компаній, які мав би карати.
Тож виправлення просте й структурне: визначайте розмір позиції в доларах, переводьте його в акції за нескоригованою ціною на відповідну дату й нараховуйте комісію за їхньою кількістю. Назавжди залиште стовпець сирої ціни в завантажувачі — не як матеріал для аудиту, а як активний вхідний параметр рушія виконання угод.
- Сигнали й дохідність: скоригований ряд.
- Кількість акцій, комісії за акцію, округлення до кроку ціни, фільтри за рівнем ціни: нескоригований ряд.
- Ліквідність і місткість: доларовий обсяг, який не потребує ні того, ні іншого.
6 стовпців, 1 рядок, цілком звичайна корпоративна дія, про яку оголосили за 3 тижні й яка нікого не здивувала. Ринок упорався з нею за один ранок. Точно відтворити її в дослідницькому конвеєрі набагато складніше, а виявити, що конвеєр цього не зробив, майже ніколи не вдається за повідомленням про помилку.
← Усі статті


