Хабрахабр

Что нужно знать перед разработкой бэктестера для торговой стратегии: типичные проблемы, виды систем и их параметры

Некоторые из затронутых в статье вопросов мы разбирали в блоге ранее, поэтому на этот раз подготовили адаптированный пересказ тезисов о том, с какими проблемами сталкиваются разработчики, в чем разница между бэктестерами разных типов, и каковы их плюсы и минусы. Редакция портала QuantStart написала материал о том, что следует знать при начале разработки собственной системы для тестирования торговых стратегий.

Что такое бэктестер

Бэктест — это применение правил торговой стратегии к набору исторических данных о ценах финансовых инструментов. Суть подхода в том, что если мы разработаем механизм определения момента для входа и выхода из позиции (покупка/продажа), например, акций из некоторого портфолио, и применим получившиеся правила к историческим данным, то это даст представление о продуктивности торговой стратегии «в прошлом».

Эта фраза отлично подходит к бэктестингу. Однажды кто-то сказал о том, что «все модели ошибочны, но некоторые полезны». Если мы будем знать, как стратегия могла повести себя в прошлом, то это поможет отфильтровать плохие стратегии без необходимости реальных финансовых потерь. Системы для исторического тестирования финансовых стратегий помогают определить, стоит ли вообще применять к реальной торговле имеющийся набор правил.

Это всего лишь модель реальности. Проблем в том, что результат бэктестинга не имеет ничего общего с результатами реальной торговли на бирже. Модель, зачастую содержащая множество допущений.

Существуют два основных типа бэктестеров — циклические (for-loop) и ориентированные на события (event-driven).

Эти два типа бэктестеров представляют весь спектр вариантов такого компромисса. При разработке таких систем всегда встает необходимость компромисса между точностью и сложностью реализации.

Сложности бэктестинга

Тестирование на исторических данных несет в себе множество сложностей. Все они связаны с тем фактом, что весь процесс представляет собой лишь моделирование реальности. Вот лишь некоторые из них:

  • Тестирование на выборке (in-sample testing) — проблема возникает при использовании одних и тех же данных для тренировки торговых моделей и для их дальнейшего тестирования. В таком случае показанная продуктивность значительно обесценивается — ведь результат достигнут на заранее известных системе данных. В реальности данные будут чаще всего значительно отличаться от тренировочных. По сути, это разновидность переобучения.
  • Ошибка выжившего — для фондовых индексов (например, S&P500) характерен процесс листинга и делистинга, когда в них появляются или из них исключаются определенные акции и финансовые инструменты. Если эти изменения в ходе бэктестинга не учитываются, то удачной может быть признана стратегия, которая не учитывает акции компаний, которые были исключены из индекса из-за низкой капитализации. Чтобы избежать таких проблем при запуске бэктестов на длительных временных отрезках нужно использовать данные, не подверженные ошибке выжившего.
  • Ошибки прогнозов (look-ahead bias) — на результат бэктеста могут повлиять и данные из будущего. К примеру, рассмотрим случай, когда на определенном временном интервале вычисляется показатель линейной регрессии. Если этот показатель затем используется в той же выборке, то получится, что в нее проникли данные из будущего, а значит получившаяся продуктивность стратегии в значительной степени обесценивается. Решить эту проблему помогают событийно-ориентированные бэктестеры.
  • Изменение рыночного режима — параметры финансового рынка не стационарны. Это значит, что процессы, выливающиеся в движения цен акций, не опираются на параметры, которые неизменны во времени. Данный факт усложняет обобщение параметризованных моделей (многие торговые стратегии – это частные случаи таких стратегий), что приводит к тому, что результативность стратегии на исторических данных оказывается значительно лучше чем при реальной торговле.
  • Транзакционные издержки — многие циклические бэктестеры не учитывают даже самую базовую информацию о транзакционных издержках, таких как различные комиссии и сборы. Часто этим грешат авторы научных работ, которые предпочитают не опускаться до таких мелочей. Найти стратегию, которая очень прибыльна в идеальных условиях отсутствия издержек, очень легко. Проблема в том, что при торговле в реальных условиях такие стратегии могут оказаться глубоко убыточными. Крайне важно учитывать спред, рыночную ситуацию, различные сборы, проскальзывание (при сделках с высоковолатильными активами реальная цена сделки может немного отличаться от той, которая предполагалась при выставлении заявки – как в выгодную сторону, так и в минус).

Также существуют и другие вопросы, которые не так часто обсуждаются, но тем не менее крайне важны для создания качественно работающего бэктестера. Среди них:

  • OHLC-данные — это информация о цене открытия, наивысшей цене финансового инструмента в течение торговой сессии, ее наименьшее значение и цена закрытия торгового периода (open-high-low-close chart, OHLC). Обычно она импортируется из источников вроде Yahoo Finance. В таком случае это может быть объединение различных фидов данных. Это значит, что получить экстремальные значения (включая цены High и Low) трейдинговой системе, работающей в режиме реального времени, будет трудно. Это тоже нужно учитывать в торговой модели.
  • Емкостные ограничения — при бэктестинге велик соблазн использовать бесконечный запас денег. В реальности же объем средств, доступных для торговли, всегда ограничен (как и возможный объем заемных средств для маржинальной торговли). Важно также не забывать о среднем лимите дневного объема торговли (Average Daily Volume, ADV), особенно для низколиквидных акций, когда велик риск, что операции торговой системы приведут к реальному изменению цены. Такое влияние на рынок также следует учесть.
  • Выбор бенчмарка — необходимо ответить на вопрос о том, верно ли выбран бенчмарк, с которым будет сравниваться тестируемая стратегия. К примеру, если вы торгуете товарными фьючерсами, которые нейтральны к индексу S&P500, стоит ли использовать этот индекс в качестве бенчмарка? Вполне вероятно, что корзина других товарных фондов окажется более корректным выбором.
  • Крепкость (robustness) — если изменить время начала работы стратегии в ходе бэктеста, насколько сильно это влияет на результат? Для долгосрочных стратегий время старта их работы не должно серьезно сказываться на продуктивности — неважно, стартовал бэктест в понедельник или в четверг. Если же она слишком чувствительна к начальным условиям, это значит, что предсказать ее возможную продуктивность при старте реальной торговли нет никакой возможности.
  • Переобучение и дисперсия — мы уже коснулись вопросов переобучения выше, но это более широкая проблема, присущая всем контролируемым (supervised) методам машинного обучения. Решить эту проблему можно только с помощью тщательного использования техник кросс-валидации. И даже в этом случае следует быть крайне осторожным при адаптации стратегий к шуму в тестовых наборах данных.
  • Психологическая толерантность — психологию часто игнорируют при создании автоматизированных торговых систем, ведь ее влияние как раз и должно минимизироваться алгоритмами. Однако люди остаются людьми, даже когда торгуют не руками, а с помощью роботов. В итоге это может сказываться на результатах. К примеру, если в ходе бэктеста просадка депозита на 50% может казаться допустимым риском, то в реальности потеря половины стоимости активов оказывается куда более травмирующим опытом. Удержаться от незапланированных действий в такой ситуации нелегко.

На этом с проблемами тестирования на истории все, теперь перейдем к описанию самих систем для таких тестов.

Два вида бэктестеров

Сначала рассмотрим цикличные системы. Это наиболее простой тип бэктестера, которые чаще всего описываются в различных блог-постах по теме финансов.

Цикличные бэктестеры

Работают они так — система просто итерационно проходит каждый торговый день (или бар OHLC), производит вычисления, связанные с ценой нужного актива (например, вычисляет скользящие средние цены закрытия), а затем совершает соответствующую операцию (вход в длинную или короткую позицию). Далее итерации продолжаются. В процессе сохраняется информация о результативности работы, чтобы по итогу построить график (equity curve).
Вот так выглядит псевдокод подобного алгоритма:

for each trading bar: do_something_with_prices(); buy_sell_or_hold_something(); next_bar();PythonCopy

Как видно, система крайне проста, что делает такие бэктестеры отличным вариантом для получения первых прикидок по поводу перспективности торговой системы.

Плюсы

Цикличный бэктестер очень просто реализовать с применением практически любого языка программирования, и сделать это быстро. Это полезно, когда требуется протестировать влияние множества различных параметров.

Минусы

Главный минус — нереалистичность получаемых результатов. Часто в циклических бэктестерах нет даже базовой функциональности для учета транзакционных издержек, ее приходится реализовывать отдельно. Также обычно используются только MARKET-приказы.

Это увеличивает вероятность появления программных ошибок. Также возможность повторного использования кода для тестовой и продуктивной системы минимальна, так что писать его придется заново.

Использовать их следует исключительно как инструмент фильтрации для отбраковывания явно неудачных стратегий. Цикличные бэктестеры подвержены появлению ошибок прогнозирования. Важно помнить, что в реальной жизни стратегии крайне редко показывают себя лучше, чем в ходе бэктеста. При этом важно сохранять крайне скептической отношение к стратегиям, показавшим хорошие результаты.

Событийно-ориентированные системы

Системы такого типа находятся на противоположной стороне спектра. Они куда ближе к реальности. Обычно они работают в огромных циклах while, в ходе которых в специальной «очереди событий» постоянно ищутся «события», включающие:

  • тики — появление новых рыночных данных;
  • сигнальные события – появление торговых сигналов;
  • событие приказа – приказ на совершение операции готов к отправке в систему брокера;
  • событие сделки – поступление от брокера информации об исполнении заявки.

Когда определенное событие распознано, оно передается соответствующему модулю в инфраструктуре торговой системы для дальнейшей обработки и потенциально генерирует новые события, которые снова попадают в очередь.

Псевдокод такого бэктестера выглядит следующим образом:

while event_queue_isnt_empty(): event = get_latest_event_from_queue(); if event.type == "tick": strategy.calculate_trading_signals(event); else if event.type == "signal": portfolio.handle_signal(event); else if event.type == "order": portfolio.handle_order(event); else if event.type == "fill": portfolio.handle_fill(event) sleep(600); # Sleep for, say, 10 minsPythonCopy

Как видно система крайне зависима от модуля обработки портфолио – это настоящее сердце в событийно-ориентированных системах.

Плюсы

У бэктестеров такого типа есть много плюсов:

  • Снижение вероятности ошибок прогнозирования — благодаря структуре, предполагающей поэтапную передачу сообщений, в событийно-ориентированные системах реже встречаются ошибки прогнозирования, по крайне мере на торговом уровне. Однако вероятность их появления все равно сохраняется, так как ошибки могут содержаться в самой модели.
  • Возможность повторного использования кода – для использования стратегии в реальной торговле необходимо лишь заменить модуль обработки данных и движок исполнения заявок. Описание стратегии, модуль риск-менеджмента и управления позициями, код для оценки продуктивности системы — все это можно использовать без изменений. Это снижает вероятность возникновения новых багов.
  • Уровень портфолио — в событийно-ориентированных стратегиях проще думать на уровне портфолио. В итоге это облегчает внесение изменений в стратегию и разработку методов хеджирования.
  • «Правильный» риск-менеджмент — в таких системах проще «модуляризовать» риск-менеджмент. Трейдер может без проблем использовать методики вроде Критерия Келли, а также включать различные оповещения, устанавливать лимиты (например, на волатильность).
  • Удаленное развертывание и мониторинг — модульный принцип написания кода упрощает его развертывание в облаке или по схеме биржевой колокации.

Минусы

Плюсы событийно-ориентированных систем понятны, но есть и определенные недостатки. Среди них:

  • Сложный код — разработка полностью покрытой тестами системы займет недели и месяцы работы в режиме full-time.
  • Объектная ориентация — модульный дизайн системы требует объектно-ориентированного подхода к программированию. А значит, нужен язык, который поддерживает эти принципы. Юнит-тестирование от этого легче не станет.
  • Высокий порог входа — новичку в программировании не получится создать такую систему. Потребуется достаточно существенный инженерный опыт, который позволит разобраться с написанием кода, реализацией логирования, проведения юнит-тестов, внедрения контроля версий и практик continuous integration.
  • Невысокая скорость — подход, при котором сообщения внутри системы последовательно передаются внутри разных ее уровней, замедляет скорость исполнения заявок по сравнению с векторизированным цикличным подходом. Вычисление различных комбинаций параметров может требовать серьезных временных затрат.

Другие материалы по теме финансов и фондового рынка от ITI Capital:

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть