为了将 Q 学习方法迁移至金融领域,本节展示了一个模拟 OpenAI Gym 环境的类,但其仅 适用于以金融时间序列数据为代表的金融市场。这里的思路是,类似于 CartPole 环境, 4 个历史价格代表金融市场的状态,当给定一个状态时,智能体可以决定是做多还是做空。 在这种情况下,两个环境是可比较的,因为每一个状态都是由 4 个参数给出,并且智能体 可以采取两种不同的动作。 为了模仿 OpenAI Gym API,需要两个辅助类,一个用于观察空间,一个用于动作空间。 In [52]: class observation_space: def __init__(self, n): self.shape = (n,) In [53]: class action_space: def __init__(self, n): self.n = n强化学习 | 217 def seed(self, seed): pass def sample(self): return random.randint(0, self.n - 1) 以下 Python 代码定义了 Finance 类,该类提取了许多交易品种的日终历史价格。该类的 主要方法是 .reset() 和 .step(),其中,.step() 方法会检查是否采取了正确的动作,相 应地定义奖励,并检查成功或失败。当智能体能够通过整个数据集正确交易时,就取得了 成功。当然,这可以有不同的定义(例如,定义当智能体成功交易 1000 步时就取得了成 功)。失败被定义为准确率小于 50%(总奖励除以总步数)。然而,这仅在一定数量的步骤 之后进行检查,以避免该指标的初始方差过高。 In [54]: class Finance: url = 'http://hilpisch.com/aiif_eikon_eod_data.csv' def __init__(self, symbol, features): self.symbol = symbol self.features = features self.observation_space = observation_space(4) self.osn = self.observation_space.shape[0] self.action_space = action_space(2) self.min_accuracy = 0.475 ➊ self._get_data() self._prepare_data() def _get_data(self): self.raw = pd.read_csv(self.url, index_col=0, parse_dates=True).dropna() def _prepare_data(self): self.data = pd.DataFrame(self.raw[self.symbol]) self.data['r'] = np.log(self.data / self.data.shift(1)) self.data.dropna(inplace=True) self.data = (self.data - self.data.mean()) / self.data.std() self.data['d'] = np.where(self.data['r'] > 0, 1, 0) def _get_state(self): return self.data[self.features].iloc[ self.bar - self.osn:self.bar].values ➋ def seed(self, seed=None): pass def reset(self): ➌ self.treward = 0 self.accuracy = 0 self.bar = self.osn state = self.data[self.features].iloc[ self.bar - self.osn:self.bar] return state.values def step(self, action): correct = action == self.data['d'].iloc[self.bar] ➍ reward = 1 if correct else 0 ➎ self.treward += reward ➏ self.bar += 1 ➐ self.accuracy = self.treward / (self.bar - self.osn) ➑ if self.bar >= len(self.data): ➒ done = True 图灵社区会员 cxc_3612(17665373813) 专享 尊重版权218 | 第 9 章 elif reward == 1: ➓ done = False elif (self.accuracy < self.min_accuracy and self.bar > self.osn + 10): done = True else: done = False state = self._get_state() info = {} return state, reward, done, info ➊ 定义所需的最低准确率。 ➋ 选择用于定义金融市场状态的数据。 ➌ 将环境重置为其初始值。 ➍ 检查智能体是否选择了正确的动作(成功交易)。 ➎ 定义智能体收到的奖励。 ➏ 将奖励添加到总奖励中。 ➐ 使环境向前运行一步。 ➑ 计算给定所有步骤(交易)的成功的动作(交易)的准确率。 ➒ 如果智能体到达数据集的末尾,则成功。 ➓ 如果智能体采取了正确的动作,那么它可以继续前进。 如果在一些初始步骤之后,准确率下降到最低水平以下,则该回合结束(失败)。 对于其余情况,智能体可以继续前进。 Finance 类的实例表现得很像 OpenAI Gym 的环境。特别是,在这种基本情况下,该实例 表现得与 CartPole 环境完全一样。 In [55]: env = Finance('EUR=', 'EUR=') ➊ In [56]: env.reset() Out[56]: array([1.819 , 1.8579, 1.7749, 1.8579]) In [57]: a = env.action_space.sample() a Out[57]: 0 In [58]: env.step(a) Out[58]: (array([1.8579, 1.7749, 1.8579, 1.947 ]), 0, False, {}) ➊ 指定用于定义代表状态数据的交易标的代号和特征类型(交易标的代号或对数收益率)。 为 CartPole 游戏开发的 DQLAgent 能否学习在金融市场中进行交易?是的,它能,如下面 的代码所示。然而,尽管智能体在训练回合中提高了其交易技能(平均而言),但结果并 不“惊艳”(参见图 9-3)。 图灵社区会员 cxc_3612(17665373813) 专享 尊重版权强化学习 | 219 In [59]: set_seeds(100) agent = DQLAgent(gamma=0.5, opt=RMSprop) In [60]: episodes = 1000 In [61]: agent.learn(episodes) episode: 1000/1000 | treward: 2511 | av: 1012.7 | max: 2511 In [62]: agent.test(3) episode: 3/3 | treward: 2511 Out[62]: [2511, 2511, 2511] In [63]: plt.figure(figsize=(10, 6)) x = range(len(agent.averages)) y = np.polyval(np.polyfit(x, agent.averages, deg=3), x) plt.plot(agent.averages, label='moving average') plt.plot(x, y, 'r--', label='regression') plt.xlabel('episodes') plt.ylabel('total reward') plt.legend(); 移动平均线 回归线 回合 总 奖 励 图 9-3:运行于 Finance 环境的 DQLAgent 的平均总奖励 通用 RL 智能体 本节为金融市场环境提供了一个类,该类模拟了 OpenAI Gym 环境的 API。 它还可以将 DQL 智能体应用于新的金融市场环境,无须对智能体本身进 行任何更改。尽管智能体在这种新环境中的表现可能并不“惊艳”,但它 说明了本章介绍的强化学习方法是相当通用的。RL 智能体通常可以从与 它们交互的不同环境中学习,这在一定程度上解释了为什么第 2 章所述的 DeepMind 的 AlphaZero 不仅能够掌握围棋,还能够掌握国际象棋和将棋。
简单的金融沙箱
最新推荐文章于 2024-08-29 10:04:09 发布