Обучение с подкреплением стало мощным методом разработки автоматизированных торговых стратегий. Использование принципов проб и ошибок позволяет алгоритмам изучать оптимальные политики принятия решений на основе наблюдаемой среды. В этой статье мы углубимся в обучение с подкреплением применительно к стратегиям торговли акциями, изучая альтернативный подход, использующий MaskablePPO (оптимизация проксимальной политики) и MultiInputPolicy. Кроме того, мы представим Процентный осциллятор цен (PPO) как средство для получения наблюдений для нашей торговой модели.
Иллюстрированное обучение с подкреплением — Акробатический дельфин
Чтобы получить интуитивное представление об обучении с подкреплением, давайте рассмотрим пример с участием дельфина, который учится выполнять акробатические трюки. Представьте себе дрессировщика, который хочет, чтобы дельфин прыгал через обручи. Сначала дельфин не знает, как выполнить желаемое поведение. Однако через серию испытаний и обратной связи дельфин учится приспосабливать свои движения, чтобы успешно проходить через обручи.
В этом сценарии дельфин играет роль «агента», а дрессировщик — «окружающей среды». Агент выполняет действия (например, плавает или прыгает), а среда обеспечивает обратную связь на основе результатов этих действий (например, поощряет успешные прыжки и наказывает за неудачи). Со временем дельфин учится оптимизировать свои действия, максимизируя совокупное вознаграждение, постепенно совершенствуя свою стратегию, пока не овладеет акробатикой.
Этот процесс отражает сущность обучения с подкреплением, когда агент взаимодействует с окружающей средой, получая обратную связь в виде вознаграждений или штрафов, чтобы изучить оптимальные политики принятия решений.
Представляем MaskablePPO — другой подход
В нашем исследовании обучения с подкреплением для стратегий торговли акциями мы будем использовать альтернативный подход, который использует MaskablePPO. Хотя обычно используются популярные алгоритмы обучения с подкреплением, такие как Deep Q-Network (DQN) и Proximal Policy Optimization (PPO), MaskablePPO предлагает явные преимущества в определенных сценариях.
MaskablePPO — это расширение PPO, алгоритма оптимизации политик, целью которого является максимизация вознаграждения при обеспечении стабильности обучения. «Маскируемый» аспект MaskablePPO относится к его способности выборочно применять ограничения к различным компонентам политики во время обучения. Таким образом, он позволяет гибко настраивать компромисс между разведкой и эксплуатацией, обеспечивая точную настройку поведения модели.
Далее мы представим концепцию MultiInputPolicy, которая играет решающую роль в реализации нашей торговой стратегии.
Политика MultiInputPolicy и создание словаря с последней операцией и наблюдением
Чтобы облегчить разработку нашей стратегии торговли акциями, мы будем использовать MultiInputPolicy. Эта политика позволяет нам создать словарь, включающий последнюю операцию и текущее наблюдение. Последняя операция предоставляет контекстную информацию о предыдущем предпринятом действии, а наблюдение фиксирует текущее состояние рынка.
Включая последнюю операцию и наблюдение в качестве входных данных, мы позволяем модели учиться на последовательности действий и наблюдений, фиксируя временные зависимости в процессе торговли. Эта временная информация расширяет возможности нашего алгоритма по принятию решений, что приводит к более эффективным торговым стратегиям.
Использование процентного ценового осциллятора для наблюдений
В нашем подходе мы будем использовать процентный осциллятор цен (PPO), версию индикатора MACD с процентным изменением, чтобы генерировать наблюдения для нашей торговой модели. PPO — это технический индикатор, обычно используемый в финансовом анализе для измерения импульса и определения потенциальных разворотов тренда.
PPO рассчитывает процентную разницу между двумя скользящими средними цены акции за определенный период, обычно 12 и 26 дней. Этот расчет дает представление об импульсе акций и помогает определить условия перекупленности или перепроданности. Используя PPO в качестве наблюдения в нашей системе обучения с подкреплением, мы снабжаем агента ценной информацией для принятия обоснованных торговых решений на основе ценовых тенденций и потенциальных разворотов.
TL;DR здесь — это полный исходный код, если вы опытный разработчик и разбираетесь в обучении с подкреплением.
Реализация среды Stop-Loss-Target
В статье Проверка стратегий торговли акциями с использованием Python (подготовка данных) мы узнали, как получить данные об акциях OIH из Интернета и как создать файл, содержащий данные за разные временные интервалы.
Теперь мы двинемся вперед и реализуем среду Stop-Loss-Target для обучения с подкреплением, используя 15-минутный файл данных акций OIH.
Импорт библиотек
Во-первых, нам нужно импортировать необходимые библиотеки для создания нашей среды. На этом этапе мы импортируем необходимые библиотеки, включая NumPy и библиотеку Gym.
import numpy as np import gym from gym import spaces
Определение констант, класса среды и конструктора класса
На этом шаге мы определяем константы и создаем класс среды с его конструктором. Константы представляют штрафы, точки выхода и операции. Класс среды с именем StopLossTargetEnv
является подклассом gym.Env
.
# Penalization NOOP_PENALIZATION = 0.01 # Exit Points STOP_LOSS = 0.01 TARGET = 0.015 # Operations HOLD = 0 BUY = 1 class StopLossTargetEnv(gym.Env): def __init__(self, observation_size, features, prices): # Data self.__features = features self.__prices = prices # Spaces self.observation_space = spaces.Dict({ 'last_action': spaces.Discrete(2), 'observation': spaces.Box(low=np.NINF, high=np.PINF, shape=(observation_size, features.shape[1]), dtype=np.float32)}) self.action_space = spaces.Discrete(2) # Episode Management self.__start_tick = observation_size self.__end_tick = len(self.__prices) self.__current_tick = self.__end_tick # Position Management self.__current_action = HOLD self.__current_profit = 0 self.__wins = 0 self.__losses = 0
Определение метода сброса
Метод reset
отвечает за сброс среды в исходное состояние. Он устанавливает текущее действие, текущую прибыль, выигрыши, проигрыши и текущий тик. Затем он возвращает новое наблюдение, используя метод __get_observation
.
def reset(self): # Reset the current action and current profit self.__current_action = HOLD self.__current_profit = 0 self.__wins = 0 self.__losses = 0 # Reset the current tick pointer and return a new observation self.__current_tick = self.__start_tick return self.__get_observation()
Определение пошагового метода
Метод step
отвечает за продвижение среды за один временной шаг. Он принимает действие в качестве входных данных и выполняет необходимые расчеты и обновления на основе текущего действия, цен и точек выхода. Он вычисляет вознаграждение за шаг, обновляет текущее действие и прибыль и проверяет, выполнена ли среда. Наконец, он возвращает наблюдение, вознаграждение за шаг, статус выполнения и пользовательскую информацию.
def step(self, action): # If current tick is over the last index in the feature array, the environment needs to be reset if self.__current_tick > self.__end_tick: raise Exception('The environment needs to be reset.') # Compute the step reward (Penalize the agent if it is stuck doing anything) step_reward = 0 if self.__current_action == HOLD and action == BUY: self.__open_price = self.__prices[self.__current_tick] self.__stop_loss = self.__open_price * (1 - STOP_LOSS) self.__target = self.__open_price * (1 + TARGET) self.__current_action = BUY elif self.__current_action == BUY: current_price = self.__prices[self.__current_tick] if current_price < self.__stop_loss or current_price > self.__target: step_reward = current_price - self.__open_price self.__current_profit += step_reward self.__current_action = HOLD if step_reward > 0: self.__wins += 1 else: self.__losses += 1 elif self.__current_action == HOLD: step_reward = -NOOP_PENALIZATION # Generate the custom info array with the real and predicted values info = { 'current_action': self.__current_action, 'current_profit': self.__current_profit, 'wins': self.__wins, 'losses': self.__losses } # Increase the current tick pointer, check if the environment is fully processed, and get a new observation self.__current_tick += 1 done = self.__current_tick >= self.__end_tick obs = self.__get_observation() # Returns the observation, the step reward, the status of the environment, and the custom information return obs, step_reward, done, info
Определение метода action_masks
Метод action_masks
используется MaskablePPO для фильтрации доступных действий. В этом случае мы разрешаем действие «КУПИТЬ» только в том случае, если текущая позиция «ДЕРЖАТЬ». Он возвращает массив масок, где True
представляет разрешенные действия.
def action_masks(self): # Allow to BUY only if the current position is HOLD mask = np.ones(self.action_space.n, dtype=bool) mask[BUY] = self.__current_action == HOLD return mask
Определение метода получения наблюдения
Метод __get_observation
— это частный вспомогательный метод, который возвращает текущее наблюдение. Он проверяет, выходит ли текущий тик за пределы последнего значения в массиве признаков, и возвращает None
, если это так. В противном случае он возвращает рассчитанное наблюдение, которое включает в себя последнее действие и фрагмент массива признаков.
def __get_observation(self): # If the current tick is over the last value in the feature array, the environment needs to be reset if self.__current_tick >= self.__end_tick: return None # Return the calculated observation return { 'last_action': self.__current_action, 'observation': self.__features[(self.__current_tick - self.__start_tick):self.__current_tick] }
С помощью этих шести шагов мы внедрили среду StopLossTargetEnv
, которая включает в себя подход стоп-лосс/цель для торговли акциями.
Использование среды Stop-Loss-Target для обучения и прогнозирования момента покупки и продажи актива
В этом разделе мы проведем вас через процесс настройки и запуска нашей модели для обучения и прогнозирования. Мы будем использовать Python и библиотеку Stable Baselines3 (версия ‹ 2.0) вместе с тренажерным залом OpenAI (не тренажерным залом) для запуска модели обучения с подкреплением. В частности, мы будем использовать алгоритм Maskable Proximal Policy Optimization (MaskablePPO). Чтобы упростить задачу, мы добавим фрагменты кода для каждого шага, которые помогут вам эффективно реализовать модель. Наша цель — обучить модель, используя 15-минутные данные фондового рынка OIH, и использовать ее для прогнозирования оптимальных точек покупки и продажи. Кроме того, мы покажем, как оценить производительность модели с помощью тестового набора данных.
Чтение данных и подготовка набора данных
Сначала мы считываем данные из CSV-файла и предварительно обрабатываем их для создания процентного ценового осциллятора (PPO). Мы разделяем данные на обучающие и тестовые наборы данных.
import math import numpy as np import pandas as pd import pandas_ta as ta from sb3_contrib import MaskablePPO from stable_baselines3.common.env_util import make_vec_env from stoploss_target_env import StopLossTargetEnv # Read the data, generate the Percentage Price Oscillator (PPO) and create the train and test dataset df = pd.read_csv('OIH_15T.csv.gz', compression='gzip') df.ta.ppo(close=df['close'], append=True) df.dropna(inplace=True) train = df[(df['date'] >= '2018-01-01') & (df['date'] <= '2022-01-01')] test = df[df['date'] > '2022-01-01']
Создание среды обучения
Затем мы создаем среду обучения, используя функцию make_vec_env
из Stable Baselines. Мы передаем класс StopLossTargetEnv
в качестве среды для создания экземпляра вместе с необходимыми параметрами, такими как размер наблюдения, функции и цены.
# Create 4 parallel train environments env = make_vec_env(StopLossTargetEnv, seed=42, n_envs=4, env_kwargs={'observation_size': 3, 'features': train[['PPOStopLossTargetEnv
26_9','PPOhStopLossTargetEnv
26_9','PPOsStopLossTargetEnv
26_9']].values, 'prices': train['close'].values})
Обучение модели
Мы инициализируем модель MaskablePPO
, передавая «MultiInputPolicy» в качестве политики для обработки нескольких входных данных, среды обучения и устанавливаем уровень детализации на 1. Затем мы обучаем модель для заданного общего количества шагов по времени.
# Train the model model = MaskablePPO("MultiInputPolicy", env, verbose=1) model.learn(total_timesteps=10_000_000)
Сохранение и загрузка модели
Мы сохраняем обученную модель в файл, удаляем ее из памяти, а затем перезагружаем, чтобы убедиться, что она работает должным образом.
# Save, remove, and reload the model (To be sure it works as expected) model.save("maskableppo_stoploss_target") del model model = MaskablePPO.load("maskableppo_stoploss_target")
Создание тестовой среды и прогнозирование
Мы создаем тестовую среду, используя класс StopLossTargetEnv
, предоставляя необходимые параметры. Мы инициализируем необходимые переменные и перебираем тестовые данные, делая прогнозы с помощью обученной модели. Выводим текущее действие и прибыль за каждый шаг.
# Create a test environment env = StopLossTargetEnv(observation_size=3, features=test[['PPOStopLossTargetEnv
26_9','PPOhStopLossTargetEnv
26_9','PPOsStopLossTargetEnv
26_9']].values, prices=test['close'].values) # Create the required variables for calculation done = False # Predict the test values with the trained model obs = env.reset() while not done: action, _states = model.predict(obs, deterministic=True) obs, rewards, done, info = env.step(action) print(f"Action: {info['current_action']} - Profit: {info['current_profit']:6.3f}")
Отображение результатов
Наконец, мы отображаем результаты, включая общую прибыль/убыток, количество выигрышей и проигрышей, а также процент выигрышей.
# Show results print(' RESULT '.center(56, '*')) print(f"* Profit/Loss: {info['current_profit']:6.3f}") print(f"* Wins: {info['wins']} - Losses: {info['losses']}") print(f"* Win Rate: {100 * (info['wins']/(info['wins'] + info['losses'])):6.2f}%")
Наконец, мы печатаем результаты прогноза. Печатаем текущую прибыль модели на тестовых данных.
После того, как мы сделали прогнозы, нам нужно оценить производительность нашей модели. Мы получим прибыль/убыток модели из custom_info
data.
Вот результат прибыли/убытка после исполнения
************************ RESULT ************************ * Profit/Loss: 62.554 * Wins: 29 - Losses: 22 * Win Rate: 56.86%
Примечание. Эти результаты оценки относятся к конфигурации, используемой в этом примере, и могут отличаться для разных моделей и наборов данных.
Заключение
В этой статье мы рассмотрели применение методов обучения с подкреплением в области стратегий торговли акциями. Мы начали с краткого объяснения обучения с подкреплением, используя аналогию с дельфином, обучающимся акробатике. Затем мы представили концепцию MaskablePPO, менее распространенного алгоритма, и объяснили, как он работает. Мы также обсудили использование MultiInputPolicy, которая позволяет нам создавать словарь с последней операцией и наблюдением, обеспечивая более богатое входное представление для нашей модели.
Чтобы построить торговую среду, мы реализовали класс StopLossTargetEnv, который следует подходу StopLoss/Target. Мы описали реализацию в пять шагов, предоставив фрагменты кода для каждого шага. Мы определили необходимые константы, класс окружения и конструктор класса. Мы также реализовали метод reset, метод step и метод action_masks, который фильтрует действия с помощью MaskablePPO. Кроме того, мы представили метод Get Observation, который использует подход MultiInputObservation для создания наблюдения.
В следующей части мы обсудили настройку и выполнение обучения и прогнозирования модели. Мы загрузили биржевые данные, предварительно обработали их и разделили на наборы данных для обучения и тестирования. Мы создали параллельные обучающие среды с помощью функции make_vec_env. Мы обучили нашу модель с помощью MaskablePPO и сохранили ее для использования в будущем. Затем мы создали тестовую среду и использовали обученную модель для прогнозирования тестовых данных, отображая действия и прибыль на каждом этапе.
В заключение, эта статья продемонстрировала, как обучение с подкреплением, в частности, с использованием алгоритма MaskablePPO и подхода StopLoss/Target, может применяться для разработки стратегий торговли акциями. Используя концепцию MultiInputPolicy и процентного ценового осциллятора (PPO), мы смогли создать надежную и адаптируемую торговую среду. Реализация и примеры, представленные в этой статье, предлагают отправную точку для дальнейших исследований и экспериментов в области алгоритмической торговли. Благодаря достижениям в обучении с подкреплением и доступности финансовых данных этот подход обещает разработку более эффективных и интеллектуальных торговых стратегий в будущем.
Если вам понравилась история, пожалуйста, не стесняйтесь потратить пару секунд, чтобы оставить комментарий и дать мне 10 хлопков. Это очень мотивирует меня продолжать писать. :)
Загрузите полный исходный код этой статьи здесь.
Twitter: https://twitter.com/diegodegese
LinkedIn: https://www.linkedin.com/in/ddegese
Github: https://github.com/crapher
Отказ от ответственности. Инвестирование на фондовом рынке сопряжено с риском и может не подходить для всех инвесторов. Информация, представленная в этой статье, предназначена только для образовательных целей и не должна рассматриваться как инвестиционный совет или рекомендация купить или продать какую-либо конкретную ценную бумагу. Всегда проводите собственное исследование и консультируйтесь с лицензированным финансовым консультантом, прежде чем принимать какие-либо инвестиционные решения. Прошлые результаты не являются показателем будущих результатов