Начало здесь: Создание Трейдинг бота
Предыдущая статья: Трейдинг бот. Спустя год... ч4 Возвращение к боту.
Подготовка данных
Признаки
Они же фичи, они же колонки. За основу берем часовые свечи. Свечи это low high open close value quantity.
Но данных там увы мало поэтому для большего количества признаков (колонок, фич), упаковываем в строку данные за предыдущие таймфреймы. Также развернул в фичи - дату и время
Нейронным сетям и некоторым моделям машин лёрнинга в качестве таймфич плохо подходят категориальные данные (а это почти все атрибуты времени: час, день, месяц и прочее). Поэтому все подобные данные буду переводить в целочисленные а именно в тригонометрические функции от параметра периодичной. Например Час -> синус от часа по по модулю 24.
Ну и производные атрибуты от свечей это оконные функции я взял среднее от открытия за 24 таймфрейма (open_mean_24). Также этот атрибут имеет смысл корректирующего для выходных значений. Цена акции разных эмитентов может отличаться на несколько порядков (они продаются лотами). У нас информации по лотам нет. Например одна акция стоит 300р, а другая 0.009. В целом должен выправить скейлер. Но поскольку почти все атрибуты относительные (diff). абсолютный думаю лишним не будет.
Дальше пришлось бороться с пробелами в данных. Торговые сессии с 9 утра до 17 и у некоторых инструментов до 23 (расширенная торговая сессия). Для этого добавил признак Mask = 1 там где данные есть и Mask = 0 там где данных нет ( например с 23 ночи до 9 утра).
Целевые значения Y
Как я описывал ранее буду прогнозировать завтра 20й перцентиль по минимумам Low_q20 и 80й по максимумам Hi_q80.
В целом считается просто. Считаем перцентиль по завтрашнему дню и сдвигаем (DtaFrame.shift). И тут опять вмешались пробелы но уже пятница понедельник. Теоретически в пятницу совершать сделку с ожиданием продать в понедельник - более высокий риск. Поскольку за выходные могут случиться какие-то события выйти новости которые повлияют на котировки. Но это уже детали и надо статистику смотреть чтобы совершать сделки на покупку в пятницу или нет. Я оставил и сделал дополнительный сдвиг, если пятница то low_20 берём с понедельника. И подобная логика для hi_80.
Помним про масштабирование данных. Смотрел StandartScaler и MinMax. Остановился на StandartScaler.
Эксперименты
С данными
Пробовал разное количество таймфремов 20 ~1 день, 51 ~6 дней. В итоге остановился на 81.
С нейронными сетями
Вот тут пришлось попотеть. Пробовал разные структуры от простейших в 3 слоя, до сложных параллельных со свёрткой. Но результаты были не очень точные на проверочных данных. Минимальная ошибка получилась ~0,13 соответствует примерно 80% точности.
Формула вычисления точности
Если учесть что дневное колебание 3-5% ошибка больше чем значимая разница. Поэтому совершенно не подходит.
Также при обучении модель проходила максимум 30 эпох. Я не уверен что это плохо. Может и для нейронки в 3 слоя ~600 нейронов входящих и 2 на выходе Этого вполне достаточно.
Сетка параметров которые я менял. Примерно такая.
- Структура сети
- Количество слоёв, количество нейронов
- Свёртки, есть нет
- Max Avg pooling
- Структура сети
- Несколько линейных слоёв
- Количество слоёв
- Количество нейронов в каждом слое
- Функция активации
- Количество столбцов во входных данных (см выше количество таймфреймов)
- Весь рынок ( порядка 300к примеров - обучающая выборка и 25К тестовая)
- Количество данных в прошлое (3 месяца, пол года, 3 года)
Я конечно полный перебор не делал так как это бы заняло месяц или неделю чистого времени.
В итоге ошибка была 0.6 пока не нашёл и не исправил серьёзную ошибку !!О.о!! в подготовке данных =) Кудаж без них! Минимальная ошибка стала 0.17- 0.20. Целевой показатель для меня должен был быть порядка 0.01. Что в 15 раз меньше.
Но основной инструмент для проверки результата это график отображения где по одной оси прогнозное значение а во второй прогноз.
В идеале выглядит как график y=x
И вот он у меня всегда получался ну очень плохой.
Кривая обучения
Тут я остановил эксперименты и призадумался. Что ещё не так.... и сделал бенчмарк. Обычно я использую линейную регрессию чтоб понять ориентировочную точность. Но взгляд упал на GradientBoostingRegressor. И там сразу же точность 98% (ошибка ~0.013). То что нужно!
С другими моделями
Смотрим рядом
linear
RandomForestRegressor
Смотрим Xgboost
Здесь ещё поигрался с параметрами (GridsearchCV). Получилось чуть лучше чем GradientBoosting. Пока остановился на GB. Чтобы сильно не зависать на текущем шаге в ущерб MVP. Когда будут готовые рельсы накатить новую модель\данные будет проще.
Итоги
Данные Остановился на 81 таймфрейме + StandatrtScaler.
Модель GradientBoosting, точность 0.99 для low_20 и 0.98 для hi_80. Что логично т.к. послезавтра сложнее прогнозировать чем завтра.
Финмодель
В итоге получил достаточную точность для дальнейшей работы. Плюсом Посчитал фин. модель тоже в плюсе. НО! На эти показатели надо смотреть как оценку оочень сверху. Как потом оказалось реальные сильно другие но всё же годятся. Для точной оценки финмодели надо смотреть данные по дням и по каждому инструменту отдельно, лоты, скейлкеры и всё такое... Опишу в следующей части.
Нейронки Завести не удалось, хотя очень хотелось... Думаю тут можно поиграться ещё с learning rate. И попробовать оригинальный торч без обвязки superdruperdb, там контроля побольше. Данных должно хватать итого было 50 К в обучающей выборке...
За кадром осталось работа через superdruperdb + mongo. В целом я доволен SyperDruperDb оказалось очень удобно. В одном месте собираем данные и сохраняем в другом (докер контейнер) подгружаем и обучаем нейронку. Оставлю это для другой публикации. Планирую писать бота на этой архитектуре. Вопрос открыт. Надо поисследовать. А в целом на такой системе сделать гибко и расширяемо лично для меня привлекательно! Бонусом туда накатить поиск новых моделей.
Полезные ссылки
- Обучалки от Яндекса. Первое знакомство с нейросетями
Что дальше
Уточнение фин модели. финальный отбор инструментов. Апи для инвестиций. Реальные тесты. Написаание бота. Ну и тесты в проде....