grepan
grepan личный блог
17 июня 2021, 00:10

Быть или не быть нейросети?

Здесь периодически возникают статьи про применение нейронок в трейдинге.

Я решил поделиться примером того, как в одном пайплайне (единая структура программного кода) можно построить, обучить и протестировать нейронку в торговом алгоритме.

Статья будет более полезна и понятна тем, кто имеет хоть небольшой опыт работы с Python.

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

Чтобы в конце концов сделать вывод о перспективности применения нейронок, будем соревноваться с индексом РТС.

Сразу сделаю дисклеймер, все рассматриваемые и полученные в статье результаты являются лишь простым примером, и применять их на реальных деньгах не рекомендую. И я не буду давать теорию по нейронным сетям и работе с ними. Всё это находится/читается/выучивается.

Итак, приступим. Работать будем с фьючерсом РТС, торгуемым на Московской бирже.

Первый кусок кода с импортом библиотек и определением начальных переменных:
Быть или не быть нейросети?

Обратите внимание, переключение таймфрейма алгоритма (дневки/минутки) делается указанием соответствующих констант в переменных. Далее в программе нигде ничего менять не надо.

Данные будем забирать автоматически, возиться с CSV и прочими файлами не спортивно.

 Быть или не быть нейросети?
Данные получены. На выходе стандартный массив OHLCV. Проверяем:

Быть или не быть нейросети?

По горизонтальной шкале порядковый номер свечи, по вертикальной — цена закрытия.

Делаем небольшие, но важные манипуляции с данными: добавляем новые фичи, нарезаем данные скользящим окном, определяем целевую переменную, разделяем на обучающую и тестовую выборки, нормализуем. Тестовая выборка составляет долю [test_rate] от первичного набора данных. Здесь и далее в квадратных скобках приведены названия переменных, определенных в самом первом скриншоте программного кода.

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

В нашем случае целевая переменная такая: смотрим на данные за период [period_to_analize], и пытаемся предсказать, что через период [period_to_predict], цена будет либо расти, либо падать, либо оставаться во флэте. Чтобы система понимала, что такое тренд, мы вводим порог [treshold]:

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

Вот так у нас разбились данные на обучающую и тестовую выборки:
Быть или не быть нейросети?

Пора приступать к архитектуре нейронки. Делать будем с помощью библиотеки Keras. И самая главная причина этому – наличие open-source библиотеки Keras2cpp, которая позволяет «обернуть» готовую обученную нейронную сеть в виде dll-библиотеки, которую уже можно подтягивать из Lua, С++ или другого языка, на котором будет реализован конечный боевой робот.

Архитектура нейронной сети простая, жалких пол-ляма нейронов.

Быть или не быть нейросети?

На выходе сети конечный слой нейронки отвечает за классификацию входных данных на 3 возможных сценария развития на прогнозируемый горизонт: тренд вниз, флэт, или тренд вверх (вероятность для каждого сценария, в сумме 1).

Теперь обучаем сеть. В процессе сеть выдает нам статистику потерь и точности для каждой эпохи (итерации) обучения:

Быть или не быть нейросети?

Визуализируем результаты:
Быть или не быть нейросети?

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

Еще раз прогоняем обученную нейросеть на тестовых данных:
Быть или не быть нейросети?

Точность обучения сети 82.38%.

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

Быть или не быть нейросети?

Теперь пора приступать к бэктесту. Бэктест проводим с помощью open-source библиотеки Zipline (детище безвременно закрытого ресурса Quantopian). Библиотека была допилена до возможности работать с минутками, в отличие от оригинала, работающего на таймфреймах не ниже дней.

Задаем класс, эмулирующий обработку ордера. Класс возвращает цену исполнения ордера. Делаем по-простому, эмулируем мгновенное исполнение ордера по рынку без проскальзывания. При желании, в этом классе можно заложить любое, хоть самое пессимистичное проскальзывание (ухудшая цену исполнения ордера в зависимости от направления ордера) для дальнейшего тестирования.
Быть или не быть нейросети?

Делаем начальную инициализацию параметров бэктеста:

Быть или не быть нейросети?

Работаем одним ордером, комиссию устанавливаем в 70 копеек (можно указать точнее, но для простоты пойдет). За бэнчмарк для итогового сравнения принимаем сам индекс РТС, по которому будем работать с помощью алгоритма с использованием нейросети.

Теперь сам алгоритм:
Быть или не быть нейросети?

Суть проста: простой переворотный алгоритм, в зависимости от предсказанного направления тренда [signal] открывает, либо переворачивает, либо закрывает позицию, работая одним контрактом. Среда бэктеста позволяет реализовать практически любой торговый алгоритм.

Добавляем процедуру для анализа и отображения результатов.

Задаем начальный баланс capital_base = 100000 и стартуем наконец бэктест. При этом пропускаем данные, на которых нейронка тренировалась.  Это у нас форвардное тестирование.
Быть или не быть нейросети?

Смотрим на результаты теста:
Быть или не быть нейросети?
Над красной чертой самые ключевые результаты. Далее первый график – результат работы алгоритма (% возврата), второй график: изменение цены индекса, третий график – классификация трендов на разных периодах (пока не умею делать красиво, раскрашивая график цены актива в разные цвета в зависимости от тренда, может кто научит?).  

Далее для полноты анализа приводим полную статистику портфеля:

Быть или не быть нейросети?
Быть или не быть нейросети?
Быть или не быть нейросети?
Быть или не быть нейросети?
Быть или не быть нейросети?

Итак, что у нас получилось?

В одном пайплайне (структуре кода с последовательностью работ и процедур) мы:

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

В результате нейронная сеть обогнала индекс. Особенно если помнить, что для торговли одним контрактом фьючерса на индекс РТС можно использовать начальный депозит в 3 раза ниже заданного, что еще улучшит результат. Но, конечно, нейросеть не оптимальна. На это нам показывают:

  • всплески потерь и точности в процессе обучения,
  • снижающийся график 6-месячного скользящего коэффициента Шарпа,
  • структура просадок (drawdowns).

Как можно улучшить результаты:

  • Обогатить данные дополнительными атрибутами (features engineering). Здесь нет готовых советов, это искусство. Добавлять хоть фазы луны,
  • Реализовать другую архитектуру сети. Это тоже фактически творческий процесс,
  • Усложнить торговый алгоритм,
  • Переобучать периодически сеть на новых данных. Поскольку результат в виде сформированного файла автоматически подтянется в рабочий боевой алгоритм, то эта процедура не вызывает вопросов.

Для перехода к боевому роботу, остается сделать всего несколько вещей:

  • Научиться с помощью библиотеки Keras2cpp «оборачивать» обученную нейронку в виде DLL, и помимо нее, передавать в рабочий алгоритм робота параметры, необходимые для нормализации данных (при работе с боевыми данными строго необходимо повторить подход к нормализации тестовых данных).
  • Реализовать сам рабочий алгоритм робота (желательно на C++, хотя можно и в Lua с DLL).
40 Комментариев
  • Sarmatae
    17 июня 2021, 00:57

    Явно видно, что из-за одного «выброса» сделана практически вся доходность:

  • 3Qu
    17 июня 2021, 01:13
    1. Топик ничего не доказывает. Причем, независимо от результата эксперимента. Ни в плюс, ни в минус.
    2. Перспективы у ML, таки, есть.
    3. Вот так, в тупую, ML не работают.
  • sn1
    17 июня 2021, 08:06
    Дружище, можешь ли код текстом или ноуьуком выложить хотя-бы в облако?
    СПАСИБО
  • ves2010
    17 июня 2021, 08:17
    нее так делать нельзя... 

    через час удалю

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн