Биткойн-торговый бот, часть 3: руководство по разработке биткойн-торгового бота с использованием обучения с подкреплением.

Самые продвинутые планы развития науки о данных, которые вы когда-либо видели! Поставляется с тысячами бесплатных учебных ресурсов и интеграцией ChatGPT! https://aigents.co/learn/roadmaps/intro

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

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

Хотя я не буду создавать что-то столь впечатляющее, как это сделали инженеры OpenAI, по-прежнему непросто торговать биткойнами с прибылью изо дня в день и делать это с прибылью!

Планируйте до этого момента

Прежде чем двигаться дальше, мы рассмотрим, что мы должны сделать для достижения нашей цели:

Если вы еще не знакомы с моими предыдущими руководствами, создайте собственную торговую среду с нуля — пример бота для торговли биткойнами и Визуализируйте элегантную диаграмму торгового агента Bitcoin RL с помощью Matplotlib. Не так давно я написал туториалы по обеим этим темам. Не стесняйтесь остановиться здесь и прочитать любой из них, прежде чем продолжить этот (третий) урок.

Выполнение

В этом уроке я буду использовать те же данные истории рынка, что и в предыдущем уроке. Если вы пропустили откуда я это взял, то вот ссылка https://bitcoincharts.com/. Файл .csv также будет доступен в моем репозитории GitHub вместе с этим полным кодом руководства. Если вы хотите проверить это перед тестированием, я рекомендую прочитать этот учебник. Хорошо, давайте начнем.

При написании кода для этого урока я подумал, что для новичков в Python могут быть сложности с необходимыми библиотеками, поэтому я решил добавить файл requirements.txt в свой репозиторий GitHub, чтобы люди знали, какие пакеты им нужно установить. Итак, если вы клонируете мой код, перед его тестированием обязательно запустите команду pip install -r ./requirements.txt, которая установит все необходимые пакеты для этого урока:

Я хочу сказать, что эта (Третья) часть туториала потребует небольшого творчества в программировании. Я уже запрограммировал все, что нам нужно в прошлом. Мне нужно объединить два разных кода с небольшими изменениями. Если вы следили за мной, я уже написал и протестировал агент обучения с подкреплением Proximal Policy Optimization (PPO) для среды Gym LunarLander-v2. Итак, мне нужно будет выбрать этот код и объединить его с моим предыдущим учебным кодом.

Если вы не знакомы с PPO, я рекомендую прочитать мой предыдущий учебник по LunarLander-v2. Это поможет вам составить представление о том, чем мы здесь занимаемся. В отличие от моего предыдущего урока, я буду определять архитектуру моей модели в другом файле с именем model.py. Поэтому я копирую классы Actor_Model и Critic_Model в следующий файл и в начале файла добавляю все необходимые импорты для сборки нашего кода:

Как я уже сказал, я не буду объяснять, как работает модель PPO, потому что об этом уже говорилось. Но вы можете заметить одно отличие в коде: вместо ввода X = Dense(512, activation=”relu”)(X_input) я использую X = Flatten(input_shape=input_shape)(X_input). Я делаю это потому, что входная форма нашей модели имеет трехмерную форму (1, 50, 10), а наш первый плотный слой этого не понимает, поэтому я использую слой Flatten, который дает мне конкатенированный массив формы (1, 500). ) — это значение, из которого наша модель будет пытаться извлечь уроки.

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

TensorboardX будет использоваться для наших журналов Tensorboard, вы можете использовать его или нет, решать вам, но иногда это полезно. Затем я импортирую оптимизаторы Adam и RMSprop для наших экспериментов, чтобы изменить и поэкспериментировать с разными оптимизаторами из основного скрипта. И, наконец, я импортирую наши только что созданные классы Actor и Critic.

В основном скрипте в часть инициализации нашего класса CustomEnv я добавляю следующий код:

Здесь я определяю скорость обучения, эпохи обучения и выбираю оптимизатор для нашей нейронной сети. Кроме того, здесь я определяю значение нормализации/масштабирования, которое обычно рекомендуется, а иногда очень важно. Особенно для нейронных сетей нормализация может быть очень важной, потому что, когда мы вводим ненормализованные входные данные для функций активации, мы можем застрять в очень плоской области предметной области и вообще не учиться. Или, что еще хуже, мы в конечном итоге с числовыми проблемами. Позже мне нужно будет углубиться в этот материал по нормализации, но сейчас я буду использовать значение 100000, потому что знаю, что в моем наборе данных нет большего числа. В лучшем случае мы должны использовать значения нормализации между минимумом и максимумом, но что, если наши будущие рыночные максимумы станут больше, чем в нашей истории? Собственно, с нормализацией у меня больше вопросов, чем ответов, на которые мне нужно будет ответить в будущем. Теперь я буду использовать эту жестко закодированную нормализацию.

Хотя мы создаем наши классы Actor и Critic в этом месте, это сделает всю сложную работу за нас! Счетчик повторов и запись используются для ведения журнала Tensorboard; ничего такого важного.

Затем я скопировал функции replay, act, save и load. Все они не изменились. За исключением replay, я добавил три строки, используемые для моего автора Tensorboard, чтобы регистрировать потери наших актеров и критиков в конце. Также забыл упомянуть, что в функцию reset я добавил параметр self.episode_orders, который использую в функции шага. Каждый раз, когда наш Агент продает или покупает ордера, я увеличиваю self.episode_orders на единицу; Я использую этот параметр, чтобы отслеживать, сколько заказов агент выполняет за один эпизод.

Обучение агента

Как мы обучаем этого агента совершать прибыльные сделки на рынке? Считаю эту часть одной из самых ожидаемых. Обычно каждый новичок в обучении с подкреплением не знает, как подготовить своего агента к решению своей проблемы в конкретной среде, поэтому я рекомендую начинать с простых задач и делать небольшие шаги, пробуя более сложные среды, получая лучшие результаты. Вот почему я реализовал случайную торговлю в своем первом уроке. Теперь мы можем использовать его для надстройки над ним, чтобы дать нашему Агенту разумные действия. Итак, вот наш код для обучения агента:

Кроме того, я не буду пошагово объяснять тренировочную часть. Если вы хотите понять все шаги здесь, ознакомьтесь с моими учебниками по обучению с подкреплением. Но я дам короткие уведомления. Я использую следующие строки, чтобы отобразить нашу среднюю чистую стоимость и количество заказов, которые наш агент выполняет в течение эпизода:

env.writer.add_scalar('Data/average net_worth', average, episode)

env.writer.add_scalar('Data/episode_orders', env.episode_orders, episode)

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

Тестирование агента

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

Отличий всего два:

  • В начале функции мы загружаем веса нашей обученной модели;
  • Во-вторых, вместо случайных действий (action = np.random.randint(3, size=1)[0]) мы используем обученную модель для прогнозирования действия (action, prediction = env.act(state));

Начинается самое интересное — обучающая часть:

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

Например, одна из распространенных форм перекрестной проверки называется k-кратной проверкой. Данные разбиваются на k равных групп и поочередно выделяют группу в качестве тестовой, а остальную информацию используют в качестве обучающей группы. Однако данные временных рядов сильно зависят от времени, а это означает, что более поздние данные сильно зависят от предыдущих данных. Таким образом, k-fold не будет работать, потому что наш агент будет учиться на будущих данных, прежде чем торговать ими; это несправедливое преимущество.

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

Поскольку наша среда настроена только для обработки одного фрейма данных, мы создаем две среды: одну для обучающих данных и одну для тестовых данных:

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

Я не уверен, как долго я должен тренироваться, но я решил тренироваться на 20 тысяч шагов. Давайте посмотрим, как выглядит наш процесс обучения в Tensorboard, написав в терминале следующую команду: tensorboard --logdir runs и открыв http://localhost:6006/ в нашем браузере.

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

Приведенные выше графики говорят нам о том, что наш агент учится, и, как вы можете видеть, агент подумал, что лучше делать меньше заказов, чем больше. В один из обучающих моментов событие агента принесло, что лучшая торговая стратегия держится, но мы не хотим этого делать. Из приведенной выше таблицы я пытался ответить, может ли наш агент чему-то научиться? Ответ был — ДА! Я на 100% уверен, что мы можем сказать ДА; наш Агент чему-то учится, но довольно сложно сказать чему.

Тест с невидимыми данными

Во-первых, давайте посмотрим, как агент работает с данными, которых он никогда раньше не видел:

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

Хорошо, давайте оценим нашего агента и проверим, сможем ли мы победить случайного агента за 1000 шагов эпизода с помощью следующих двух команд:

А вот результаты нашего обученного агента:

average 1000 episodes agent net_worth: 1043.4012850463675

И вот результаты нашего случайного агента:

average 1000 episodes random net_worth: 1024.3194149765457

Единственная причина, по которой наш случайный агент также получил хорошую прибыль, заключается в том, что наш рыночный тренд был восходящим. Учитывая, что эта средняя прибыль нашего Агента была получена за один месяц, 4% звучит довольно неплохо. Но также, увидев гифку с моим торговым агентом выше, его поведение довольно странное; агент не любит держать нулевой заказ. Однако я заметил, что Агент, сразу после продажи всех открытых позиций, быстро открывает еще одну покупку. Это никогда не приведет нас к хорошей прибыли, поэтому нам нужно проанализировать и решить эту проблему.

Заключение:

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

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

Спасибо за прочтение! Увидимся в следующей части, где мы постараемся использовать больше техник для улучшения нашего Агента! Как всегда, весь код, приведенный в этом руководстве, можно найти на моей странице GitHub и использовать его можно бесплатно!

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

Первоначально опубликовано на https://pylessons.com/RL-BTC-BOT-NN

Больше контента на plainenglish.io