Блог им. Grin_7

Что же такое бэктестинг и есть ли у него сердце?

    • 02 июля 2020, 10:23
    • |
    • Grin
  • Еще
Не понятно, к чему это все? Почитай тут

Доброго дня! 
Вашему вниманию представляется продолжение потуг начинающего программиста / аналитика по созданию самопальной системы бэктестинга на python. 
Настала пора поближе понять, что же такое backtesting торговых стратегий. Расскажу как обычно своими словами.

Вот сидел я, смотрел на графики и прозрел! Все же просто в этих ваших инвестициях, покупай на дне, продавай на пике! Изи же! 

Осталось понять, когда оно на дне, когда на пике.

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

Ну и как водится, истина где то там, в безбрежном океане информации и пока не попробуешь, не узнаешь. 
А пробовать то надо за деньги, а деньги жалко! 

И тут снова приходит великолепная идея, есть же данных о прошлых значениях, цен, объемов, мультипликаторов, осцилляторов, корреляций. Что если сформировать портфель в прошлом и посмотреть, как все было бы сейчас, если бы мы все купили/продали тогда?  

Это и есть backtest. Ответ на вопрос, что было бы, если бы мы в соответствии с подсказками, которую дает наша стратегия, купили / продали в прошлом. 
Такое тестирование можно делать смотря на графики, табличками в экселе используя специально предназначенные для этого инструменты. 

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

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

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

За такую подробность и гибкость приходится платить сложностью разработки. Например, сейчас мой код может посчитать доходность по стратегии «Купи и держи», для однократной покупки. При этом считает только итоговую доходность, коэффициент Шарпа, максимальную просадку и длительность этой просадки. 
А потратил я на это часов 30, 20 из которых я пытался понять, че там вообще написано и 10 исправлял то, что зачем то понаписал своими кривыми руками. В экселе такую задачу можно решить за 20 минут с открытием файла и чаем. 


Все, теперь и правда код. 
Основа событийно — ориентированной системы, ее сердце,  выглядит вот так: 
Что же такое бэктестинг и есть ли у него сердце?

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

Ниже, перевод с питонячего на русский. 

Внешний цикл
1.1. bars — это объект, который хранит в себе новые данные о цене открытия, закрытия, дате и времени котировок, объемах торговли. 
Если в объекте bars еще есть данные, делаем update_bars — кладем в очередь событий event первое событие, это будет рыночное событие под названием Market, событие о том, что появились новые данные о котировках.

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

2.2. если название следующего события не пустое значение идем дальше на шаг 2.3
если пустое возвращаемся на шаг 2.1

2.3. если название события равно Market то начинаем делать действия 2.3.1 — 2.3.3
если название другое идем дальше на шаг 2.4
2.3.1 port — это объект, который хранит данные о нашем портфеле. Инструменты, их стоимость с в каждый момент времени, свободная наличность,  общая стоимость и так далее. 
Для портфеля выполняем update_market — выполняем изменения в соответствии с датой (берем месячную комиссию, довносим деньги в соответствии с датой и т.д)
2.3.2 Для портфеля выполняем update_timeindex — берем свежие котировки и умножаем их на количество имеющихся у нас бумаг.
Получаем стоимость на текущую дату, пересчитываем общую стоимость портфеля
2.3.3 strategy — объект, в котором мы выполняем анализ свежих рыночных данных, данных из портфеля, прошлых рыночных данных, вообще чего угодно и на основе анализа создаем событие Signal и кладем его в очередь событий. Как раз в strategy мы и реализуем торговую стратегию. 

2.4 Если название события равно Signal, делаем для портфеля update_signal. 
Если не равно идем на шаг 2.5
Signal он и есть сигнал, в нем заложена сообщение от вашей торговой системы — надо, что то делать — покупать, продавать, шортить ну или там, как вы еще делаете?  Вот как раз update_signal — это метод, который на основании данных из сигнала делает событие Order несущее в себе приказ на исполнение брокеру и кладет его в очередь. 

2.5 Если название события равно Order то для объекта broker делаем execute_order.
Если нет идем на 2.6
Объект brocer, это объект в котором, как ни странное, реализовано взаимодействие с системой брокера. Для бэктеста в этом объекте можно например реализовать задержки, проскальзывания, комиссии и всякое такое. Для системы живой торговли в этом объекте будут все взаимодействия по API с реальной брокерской системой. В нашем случае, объект brocker формирует событие Fill, которое описывает результат исполнения приказа из события Order

2.6 Если название события — Fill делаем update_fill для портфеля, если нет уходим на 2.1 и берем следующее событие из очереди.
update_fill — это метод, который на основании результата выполнения приказа брокеру изменяет в портфеле количество бумаг, их стоимость, свободные средства и комиссии. Переводя портфель в следующее состояние. 

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

И про это уже в следующих сериях!
★4
11 комментариев
Сравнивать со строками для выбора события не очень хорошая практика — для подобных сравнений обычно используют перечисляемые типы:
docs.python.org/3/library/enum.html
avatar
Михаил, согласен полностью, но попытаться просто и наглядно объяснить логику множественного выбора, реализованного через словарь с собственным перечисляемым классом событий, мне не под силу.
avatar
Еще есть сердце у таблицы умножения.
avatar
Бэктест — это неодушевленный предмет, поэтому у него нет сердца.

if bars.continue_backtest == True

выдаёт так себе программиста.
avatar
_sk_, аллегория никому еще не мешала). По коду соглашусь,
If bars.continue_backtest:
гораздо более по питновски, но рефакторить эту штуку я буду еще не скоро. Так, что пока  этот код как в исходной статье, откуда я и взял эту идею.
https://habr.com/ru/company/iticapital/blog/263097/
avatar
Grin, ok.
avatar
Чем AmiBroker не устраивает?
avatar
Алексей А., Несоответствию с моими целями. Я хочу научиться писать на python и инвестициям, а не тестировать торговые стратегии.
Ну а если конкретно по AmiBroker, то скорее всего это узко специализированная программа с своим, узко специализированным языком, не используемым больше нигде. Потраченное время на обучение, можно будет использовать только в рамках решения одной конкретной прикладной задачи, в одной конкретной системе.
Потратив сопоставимое время на изучение python в приложении к инвестициям, получаешь доступ к куче инструментов, с отличной документацией  и огромным экспертным сообществом. Ну и плюс вполне себе востребованный навык в других сферах жизни.

Время мы тоже инвестируем, причем оно подороже денег будет. 
avatar
Удачи в написании тестера:) Сам читал статью на хабре очень понравилась и толково написано. Идея тоже витала в голове, что-то подобное написать, но на С++:)) Лайк к сожалению не могу поставить, рейтинга не хватает:)
avatar
zam, Спасибо! C++ думаю уже для живой торговли больше подойдет, все гораздо быстрее будет работать! 
avatar
Grin, да все верно… С++ я для живой торговли использую… С# тоже часто используют в бэктестинге и в торговле:) ну это уже на любителя, кому что нравиться.
avatar

теги блога Grin

....все тэги



UPDONW
Новый дизайн