Чому multi-timeframe бектестинг ламається на реальних даних
Найчастіша причина — старший таймфрейм читається як уже закритий. Стратегія ухвалює рішення за баром H4, але на цей момент бар ще формується, і частина руху, на якому «спрацював» сигнал, з’явилася вже після входу.
На історії така логіка дає рівну висхідну криву, у робочому контурі — входи за ціною, якої на той момент не існувало.
Друге джерело — розбіжність таймфреймів. Межі барів старшого й молодшого ряду не збігаються: різні торгові сесії, вихідні, пропуски в котируваннях, переходи на літній час.
Вирівнювання за міткою відкриття або підстановка останнього відомого значення затягують у розрахунок дані з майбутнього, а один зсунутий бар змінює не лише вхід, а й усі залежні індикатори.
Третій — підгонка під історію. Чим більше комбінацій параметрів проганяється на одному відрізку, тим вищий шанс, що найкращий результат — випадковість: про це докладно писав Лопес де Прадо.
На старшому таймфреймі угод мало, і «прибуткова» конфігурація часто тримається на десятку входів, які не переживають перенесення на іншу ділянку даних.
Четверта група — помилки прогону стратегій у виконанні та даних: момент спрацювання всередині бару, комісії та прослизання, розриви котирувань, розбіжність історичного й робочого джерела цін за часом надходження.
Розбираємо, як це закривається: від суворого вирівнювання рядів і заборони незакритих барів до перевірки конфігурації на стійкість поза вибіркою.
Ефект від узгодженого розрахунку на кількох таймфреймах
Поки стратегія ухвалює рішення за одним таймфреймом, розрахунок прозорий: один потік свічок, одна часова шкала.
Але щойно додається підтвердження зі старшого періоду, з’являється джерело розбіжностей — молодший бар устигає закритися кілька разів усередині одного старшого, і вхід може спиратися на дані, яких на момент розрахунку ще не було.
Ми збираємо multi-timeframe бектестинг в одному ядрі подій (в основі — Backtrader і власні розширення), тому узгодженість сигналів перевіряється відтворюваним прогоном на історії, а не очима.
Перемальовування індикаторів закриваємо режимом підтверджених барів: значення старшого таймфрейму перераховуються лише в момент його закриття, молодші свічки вирівнюються за межею старшого, а незакритий старший бар виключається з вікна розрахунку.
Це прибирає клас відмов, який у звітах виглядає як гладка крива дохідності й розходиться з реальними угодами.
Час прогону стратегії змінюється нелінійно. Старші серії агрегуються один раз і кешуються, стратегія звертається до готових зрізів, а не перераховує їх на кожному кроці: прогон на трьох таймфреймах дорожчий за одиночний приблизно на 20–40%, а не втричі.
Частка хибних входів падає завдяки фільтру: сигнал молодшого таймфрейму приймається лише за збігу напрямку старшого.
За нашими прогонами таке правило відсікає 30–50% входів проти старшого тренду — але частину прибуткових угод воно теж зрізає, тому поріг підтвердження добирається за метриками, а не вмикається «про всяк випадок».
Формати прогону multi-timeframe бектестингу: історія, потік, гібрид
Режим прогону задає, як стратегія отримує свічки молодшого й старших таймфреймів і в який момент вони стають видимими. За пакетного розрахунку архів котирувань завантажується повністю, старші ряди агрегуються заздалегідь, а цикл іде за загальним масивом. Це найшвидший варіант на довгій історії, але саме тут найчастіше протікає інформація з майбутнього.
Потоковий розрахунок подає події послідовно, свічка за свічкою: старший таймфрейм закривається лише тоді, коли закрилася остання молодша свічка всередині нього.
Підглядання в майбутнє зникає, зате з’являється своя ціна — стан індикаторів доводиться зберігати й коректно перегравати під час переходу між рядами.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Пакетний розрахунок | Налагодження правил входу, перевірка гіпотез на довгій історії, прогон за набором інструментів | Витрати пам’яті зростають із числом таймфреймів; синхронізацію закриттів доводиться перевіряти вручну |
| Потоковий розрахунок | Фінальна перевірка стратегії, де критична чесність порядку подій | Помітно повільніше; складніше відтворити збійний прогон і налагодити логіку переходу |
| Гібридна схема | Робочий режим multi-timeframe бектестингу: молодший ряд іде потоком, старші рахуються інкрементально | Потребує явного правила, у який момент старший таймфрейм вважається доступним |
Гібридна схема зазвичай і стає основним режимом: молодший ряд обробляється потоком, старші перераховуються в момент закриття, тому прогон не впирається в обсяг пам’яті й не втрачає достовірність порядку.
Пакетний залишається для швидких перевірок, потоковий — для звірки спірних ділянок на короткому відрізку, де розбіжність результатів видно відразу.
Етапи впровадження: від аудиту даних до передачі контуру
Мультитаймфреймовий бектестинг ламається не на логіці стратегії, а на даних: старші свічки збираються з молодших, і помилка в цьому складанні дає гарну, але хибну криву дохідності.
Тому впровадження починаємо з аудиту джерела, а не з коду, і лише після нього фіксуємо розрахункові правила.
- Аудит історичних даних — перевіряємо повноту рядів за інструментами та таймфреймами, шукаємо пропуски, дублі й розриви, звіряємо ціни закриття з незалежним джерелом.
- Схема перезбирання свічок — описуємо правила агрегації: межі старшого інтервалу, момент закриття бару, поведінку на неповних і аномальних ділянках.
- Налаштування контуру — розгортаємо розрахункове середовище, версіонуємо набори даних і конфігурації, розмежовуємо сховище історії та обчислювальну частину.
- Перевірка на стійкість — проганяємо правила на різних періодах і підвибірках, окремо контролюємо підглядання в майбутнє та розбіжність історії з онлайн-потоком.
- Приймання розрахунків — звіряємо контрольні приклади й вручну розібрану вибірку угод, фіксуємо допустимі відхилення й поріг, за яким результат вважається недостовірним.
- Передача контуру — віддаємо документацію, регламент оновлення даних і доступи, навчаємо команду повторювати розрахунок без нашої участі.
Ключовий принцип: правила агрегації та перевірки живуть в одному місці для історії й реального часу. Інакше результати на історії та в роботі розходитимуться, і довіри до системи не виникне.
Що передаємо на руки: конфігурації, схеми та регламенти
Здача — це не архів із кодом, а набір артефактів, за якими ваша команда сама проганяє тест, змінить параметри й отримає той самий результат. Нижче — те, що залишається у вашому репозиторії та внутрішній базі знань; кожен пункт перевіряємо на прийманні.
- Конфігурації прогону — окремий профіль на кожен сценарій: склад таймфреймів, правило ресемплінгу старших інтервалів з молодших, вікно синхронізації, комісії та прослизання. Змінюються правкою одного файлу, без втручання в код.
- Схема даних — джерело свічок, таймзони, момент закриття бару, обробка пропусків і корпоративних дій, плюс чек-ліст валідації на дублі та розриви історії.
- Еталонний зріз історії — зафіксований набір даних, на якому прогон відтворюється до останньої угоди: за ним звіряють результат після будь-яких правок.
- Регламент запуску — порядок кроків: підготовка даних, прогрів індикаторів, прогон, збір метрик, розбір розбіжностей; із позначками, де обчислення впирається в ресурси.
- Політики доступу — ролі та права на зміну конфігурацій, ключі до ринкових даних лише на читання, журнал правок параметрів з автором і причиною.
- Шаблони звітів — метрики за прогоном, включно з часткою угод, де вхід за молодшим таймфреймом підтверджено старшим, і розбір розбіжностей між інтервалами.
- Документація — опис моделі даних і домовленостей про час закриття бару, інструкція «як додати новий таймфрейм», журнал змін методики.
- План передачі — розбір із вашими інженерами та список відкритих питань, які закриваємо після здачі.
Кейс: прибрали розбіжність сигналів на різних таймфреймах
Замовник прийшов із контуром, де стратегія на історії давала рівну криву, а на живих даних — угоди, яких у звіті не було.
Розбір показав розбіжність сигналів: підтвердження надходило зі старшого таймфрейму, а вхід виконувався за молодшим, і частина барів на момент рішення ще не була закрита.
У мультитаймфреймовому бектестингу це типова пастка — ряди склеєні в один прохід, момент закриття бару не враховується, а результат виглядає переконливіше, ніж є.
Що було на вході
Прогон однієї сітки параметрів займав близько трьох годин, тому гіпотези перевіряли пачками вночі. Частка угод, де сигнал старшого таймфрейму розходився з фактичним входом, сягала 6,4% — на дистанції в сотні угод це з’їдало перевагу стратегії.
Покриття обмежувалося двома таймфреймами: додавання третього подвоювало час прогону й ламало відтворюваність.
Що змінили
Розрахунок розвели на незалежні календарі таймфреймів, а рішення ухвалювали строго за фактом закриття бару — сигнал потрапляє у виконання з явним детермінованим лагом.
Агрегати старших рядів рахуються один раз і кладуться в кеш, тому додавання таймфрейму більше не перераховує всю історію. Ядро залишили на Backtrader: бібліотека дає подієву модель, але синхронізацію рядів і порядок виконання довелося вибудовувати вручну.
Що стало
Частка розбіжностей упала до 0,2% — це угоди на межі пропусків у даних, вони позначаються й розбираються окремо. Повний прогон займає 22 хвилини, у сітці тепер чотири таймфрейми замість двох.
Повторний запуск на тих самих даних відтворює результат до останньої угоди, а версія розрахункової конфігурації зберігається разом зі звітом — відкат до попередньої займає хвилини.
Робочий контур тепер один: тестова й жива торгівля читають ті самі правила закриття бару, тому розбіжності між ними перестали бути нормою.
Чим відрізняється перезбирання свічок від потокового розрахунку?
Різниця в тому, у який момент формується значення бару. Перезбирання свічок розгортає первинний потік угод в агрегати заново на кожному прогоні: змінюється таймфрейм, правило закриття бару або фільтр викидів — і вся історія перераховується, даючи відтворюваний результат.
Потоковий розрахунок тримає агрегат інкрементально: стан оновлюється в міру надходження даних, без повторного проходу по історії.
Перезбирання свічок платить за точність розрахунку затримкою даних — поки ряд не розгорнуто й не агреговано, multi-timeframe бектестинг не стартує, а на глибокій історії це помітна пауза.
Потоковий розрахунок відповідає майже миттєво, але його стан живе в пам’яті: у разі розриву каналу або перезапуску агрегатор потрібно відновлювати, інакше бар «поїде».
| Підхід | Коли підходить | Обмеження |
|---|---|---|
| Перезбирання свічок | Дослідження, зміна логіки, звірка та відтворюваність прогонів | Затримка даних на старті, зростає з глибиною історії |
| Потоковий розрахунок | Реальний час, тривалі прогони, інкрементальне оновлення | Точність розрахунку залежить від відновлення стану після збою |
Робоча схема — гібрид: історію віддаємо перезбиранню свічок, «живий» хвіст рахуємо потоково, а після закриття сесії звіряємо хвіст із повним перерахунком.
Розбіжність навіть в одну свічку на стику — перша ознака, що агрегатор втратив стан, і точність розрахунку на цій ділянці вже не гарантована.
Часті технічні сумніви перед стартом робіт
Сумніви перед стартом зазвичай інженерні: чи вистачить історії, чи не виявиться результат підгонкою під минуле, чи не впремося в контур, коли додадуться нові таймфрейми. Розбираємо чотири питання, які найчастіше вирішують, чи рухатися далі.
Як ви перевіряєте якість історичних даних?
Звіряємо джерело з незалежним, шукаємо пропуски, дублікати й розриви торгових сесій, приводимо бари до єдиного часового поясу.
Для multi-timeframe бектестингу критичне вирівнювання: старший таймфрейм збирається лише із закритих молодших барів, інакше в розрахунок просочується майбутнє. Дані з дірами та невірною агрегацією дають гарну криву на історії й нульовий результат на живому ринку.
Як переконатися, що результат не підігнано під минуле?
Ділимо історію на періоди: налаштування на одному, перевірка на даних, яких стратегія не бачила. Дивимося на стійкість параметрів — якщо результат тримається лише у вузькому коридорі значень, говоримо про це до виведення в роботу, а не після перших угод.
Що буде, якщо ми додамо новий таймфрейм або інструмент?
Стратегія описує правила, а не конкретний набір барів: таймфрейми, інструменти та джерела підключаються налаштуванням. Новий ряд додається без переписування логіки й тестів — контур розрахований на зростання числа таймфреймів та інструментів.
Чи можна перевірити стратегію на демо-рахунку?
Так. Той самий код стратегії запускається на живому потоці в демо-режимі, а сигнали звіряються з розрахунком на історії. Так видно розбіжність через затримки, комісії та прослизання — модель перестає бути відірваною від ринку.
Обговоримо задачу й повернемося з планом робіт
Щоб обговорення задачі було предметним, до нього варто зібрати вхідні дані, які визначають архітектуру: як зберігаються й синхронізуються дані різних таймфреймів, де вузькі місця за швидкістю й що вважається коректним результатом. Для системи бектестингу з підтримкою multi-timeframe це ядро майбутнього рішення.
- Перелік інструментів і таймфреймів, які потрібно покрити, — від хвилинних до денних, із зазначенням старших серій, що впливають на рішення.
- Джерело та глибина котирувань: тикові дані чи свічки, чи є пропуски й розриви, як їх відновлювати.
- Логіка стратегії: на якому таймфреймі ухвалюється рішення, а на якому підтверджується сигнал, де допустима розбіжність за часом.
- Як моделюються витрати — комісія, прослизання, затримка виконання ордера.
- Що вважається результатом: набір метрик, форми звітів, вивантаження для подальшого аналізу.
- Режим роботи: одиночні прогони чи перебір параметрів, скільки часу допустимо чекати один результат.
- Обмеження за інфраструктурою та доступами: де розміщуємо систему й хто власник історичних даних.
З нашого боку перша відповідь — робочий документ, а не лист про наміри.
У ньому буде план робіт за етапами, оцінка строків на кожен етап, склад команди з ролями (архітектор, інженер з даних, розробник розрахункового ядра, тестувальник) і перелік ризиків із тим, як ми їх закриваємо.
Якщо під час розбору виявиться, що частина задачі розв’язується простіше, скажемо про це прямо. Опишіть задачу — повернемося з оцінкою та планом.







