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

Существуют библиотеки алгоритмической торговли / разработки стратегий на основе Python с открытым исходным кодом, но нет интеграции с пошаговым анализом. Без понимания нестандартной производительности вашей стратегии вы можете так легко переоснастить свои параметры и обмануть себя, построив алгоритм, который дает безумную отдачу. Черт возьми, на самом деле вы можете получить безумную прибыль от почти любой идеи стратегии, если вы переобучитесь и потерпите неудачу в реальной торговле.

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

Попутно обсудим

  1. Резюме backtrader
  2. Как справиться с проблемой точки разделения в оптимизации Walkforward.
  3. Использование динамических индикаторов для управления параметрами
  4. Оптимизация BlackBox
  5. Диверсификация параметров

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

Краткий обзор стратегии обратного трейдера

Backtrader использует объект стратегии для представления торгового алгоритма и объект cerebro для управления торговлей.

Давайте рассмотрим в качестве примера простую длинную стратегию. Идея состоит в том, чтобы предсказать следующий минимум, используя 'n' минимумов из прошлого с линейной регрессией. Мы покупаем, если следующее закрытие ниже нашего прогноза, и продаем, если оно выше. (Я упростил код здесь, чтобы передать идею стратегии, продолжайте читать, чтобы увидеть рабочий класс стратегии)

class MyStrategy(bt.Strategy):
    params = (
        ('linear_reg_length', 20),
    )
       
    def __init__(self):
        self.dataclose = self.datas[0].close
        self.datalow = self.datas[0].low
        self.LR_low_trend = LinearRegression(self.datalow, len=self.params['linear_reg_length'])
    def next(self):
        if self.LR_low_trend < self.data.close and (not self.long):
            self.size_to_buy = self.broker.getvalue()/  self.dataclose[0]
            self.order = self.buy(exectype=bt.Order.Market, size=self.size_to_buy)
        elif self.LR_low_trend > self.data.close and self.long:
            self.order = self.sell(exectype=bt.Order.Market, size=self.size_to_buy)

Когда рынок растет, все становятся гениями. Именно это произошло в 2017 году с криптовалютой. Итак, давайте посмотрим на результаты ETH на Coinbase для 4-часовых баров с 20 января 2018 г. по 10 марта 2019 г., когда рынок снижался.

Мы пробуем некоторые параметры и устанавливаем для параметра linear_reg_length значение 300. Результат тестирования на истории: PnL: 10,64%. Вау, похоже, когда рынок упал на ~ 80%, мы получили 10% прибыли. Выглядит потрясающе. Может, мы взломали рынок. Посмотрим, так ли это на самом деле.

Идя вперед

Основная проблема, с которой нам нужно справиться в нашей пошаговой оптимизации, - это проблема точки разделения.

Допустим, у нас есть 2 месяца в выборке и 1 месяц вне периода выборки. Примером может быть оптимизация для января / 01/2018 - марта / 01/2018 (в период выборки), а затем торговля с найденными нами параметрами для марта / 01/2018 - апрель / 01/2018 (вне периода выборки)

Мы, конечно, продолжаем это делать:

  • оптимизировать для февраля и марта, торговать на апрель
  • оптимизировать для марта и апреля, торговать на май….

Затем, в конце, мы объединим результаты за период выборки, чтобы оценить эффективность нашей стратегии.

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

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

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

Для этого воспользуемся динамическими индикаторами бэктрейдера. И нам нужно будет написать небольшую оболочку вокруг объекта стратегии.

Во-первых, вот наш динамический индикатор для расчета линейной регрессии.

Мы вычисляем значение Индикатора в функции next (). Кроме того, у нас есть функция changeLen () для динамического управления параметром len из самой стратегии.

Модифицированная стратегия выглядит так:

Идея состоит в том, чтобы использовать функцию get_params_for_time (), чтобы получить соответствующие параметры для периода, в котором мы находимся, когда время повторяется. Мы можем манипулировать параметрами для разных временных интервалов как таковые:

Оптимизация

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

Для оптимизации мы используем открытую библиотеку blackbox. Хорошо написано, прямолинейно, использует несколько ядер, что отлично для этого простого рабочего листа.

Что нам нужно предоставить в черный ящик, так это функцию, которую нужно минимизировать. Библиотека будет многократно вызывать эту функцию. Самый простой пример - вызвать нашу оболочку для заданного периода и вернуть отрицательное значение PnL.

Само собой разумеется, что мы можем оптимизировать другую меру риска, такую ​​как Calmar или Sharpe. Рабочий лист также вычисляет их. Пожалуйста, не стесняйтесь их использовать.

Хорошо, теперь мы можем оптимизировать и идти вперед. Нам нужно еще кое-что.

Как выбрать периоды в выборке и вне ее?

У нас может возникнуть соблазн попробовать метод поиска по сетке, чтобы найти лучшие в выборке и вне ее. Однако мы должны быть осторожны, потому что этот подход также может быть переоснащен. По сути, если мы будем делать это слишком много, мы будем делать именно то, что пытаемся избежать: пробовать разные параметры, глядя в прошлое без перекрестной проверки и ожидая, что эти параметры будут работать в будущем. И здесь нам снова может повезти со странным сплитом вроде (1090 дней, 51 день). Я попытаюсь обратиться к этому в другом сообщении, но для целей этого рабочего листа общая идея состоит в том, чтобы иметь значимый размер выборки (количество сделок) как в вашем периоде выборки, так и вне его. I Важно помнить, что мы выбираем только несколько периодов выборки - выходов, которые имеют для нас смысл и не пытаются чрезмерно оптимизировать. Если стратегия в них не работает, мы возвращаемся к разработке нашего алгоритма и пробуем снова.

Как мы действительно уверены, что набор параметров, который мы нашли в нашем периоде выборки, является лучшим для периода вне выборки?

Допустим, мы разрабатываем описанный выше алгоритм. Мы оптимизировали для января и февраля и обнаружили, что

  • для linear_reg_length = 10, PnL =% 1,4
  • для linear_reg_length = 20, PnL =% 1,2
  • для linear_reg_length = 23, PnL =% 1.13
  • для linear_reg_length = 12, PnL =% 1.0
  • для linear_reg_length = 13, PnL =% 9.3

Действительно ли мы уверены, что linear_reg_length = 10 превзойдет linear_reg_length = 20 в марте (вне периода выборки)? Все эти результаты довольно близки друг к другу. Вполне возможно, что linear_reg_length = 23 будет лучшим из этих 5 за период вне периода выборки. Так что же нам делать? Мы все диверсифицируем и торгуем. Таким образом, наши результаты вне выборки будут усреднены по плохим и удачным случаям.

Собираем все вместе

Мы говорили о динамической настройке параметров, оптимизации, выборе периодов выборки и многопараметрической торговле. Рабочий лист выполняет все это и рассматривает другие второстепенные, но важные вопросы, такие как буферный период для горячего старта индикатора. Не стесняйтесь использовать его для написания собственных алгоритмов, изменив «MyStrategy» и обновив имена параметров при вызове пошаговой оптимизации и в функции оптимизации.

Вернемся к нашему простому алгоритму, который превзошел рынок более чем на 500%. Вот как это выглядит за тот же период с оптимизацией Walk forward:

В среднем мы теряем 72% нашего капитала. В лучшем случае мы потеряли 67%. Не так уж и круто, да :)?

Это хорошо, мы немного более объективны и еще на один шаг ближе к созданию стратегии, которая может работать.

Стратегия, которая выживает, идя вперед

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

Надеюсь, вам понравится, и, пожалуйста, дайте мне знать, если вы обнаружите ошибки / проблемы.