第 10 章 · 06 强化学习交易 Agent DQN


文档摘要

第 10 章 · 06 强化学习交易 Agent DQN 本节摘要:本节是全章的收官,把深度学习与强化学习合二为一——训练一个深度 Q 网络(DQN)交易 Agent。Agent 不靠「预测收益再下单」,而是通过「试错」学习在什么市场状态下做什么动作(做空/持有/做多)能最大化长期奖励。本节讲清四件事:马尔可夫决策过程(MDP)与 Q-learning 的基本框架;DQN 三大创新(经验回放、目标网络、Double DQN)如何让 Q-learning 在连续状态下收敛;原项目 如何用三个类( / / )构造一个 OpenAI Gym 兼容的交易环境;以及奖励设计、动作空间、episode 长度等关键决策的含义。

第 10 章 · 06 强化学习交易 Agent DQN

本节摘要:本节是全章的收官,把深度学习与强化学习合二为一——训练一个深度 Q 网络(DQN)交易 Agent。Agent 不靠「预测收益再下单」,而是通过「试错」学习在什么市场状态下做什么动作(做空/持有/做多)能最大化长期奖励。本节讲清四件事:马尔可夫决策过程(MDP)与 Q-learning 的基本框架;DQN 三大创新(经验回放、目标网络、Double DQN)如何让 Q-learning 在连续状态下收敛;原项目 trading_env.py 如何用三个类(DataSource/TradingSimulator/TradingEnvironment)构造一个 OpenAI Gym 兼容的交易环境;以及奖励设计、动作空间、episode 长度等关键决策的含义。读完本节,你能理解强化学习在交易中的完整建模思路,并跑通一个最简的 DQN 交易 Agent。

内容来源:原项目 22_deep_reinforcement_learning/02_gridworld_q_learning.ipynb03_lunar_lander_deep_q_learning.ipynb04_q_learning_for_trading.ipynbtrading_env.py,汉化并套用体系化模板。

⚠️ 学习提示:强化学习交易 Agent 是出了名的「难收敛」——奖励稀疏、市场非平稳、样本相关性强。本节的 Agent 在单只 AAPL 上能学会一些模式,但离实盘有巨大鸿沟,把它当作「RL 建模流程的入门示例」。

学习目标

阅读完本节,你应当能够:

  1. 列举 MDP 的五要素与强化学习的目标。
  2. 解释 Q-learning 的更新规则与 ε-greedy 策略。
  3. 说清 DQN 三大创新如何解决连续状态下的收敛难题。
  4. 读懂 trading_env.py三类协作step()/reset() 接口。
  5. 理解奖励设计、动作空间、episode 长度对训练的影响。

一、强化学习的框架:MDP

强化学习把「交易」建模成一个马尔可夫决策过程(MDP),五要素:

要素 含义 交易映射
状态 S 环境的描述 收益、波动、技术指标
动作 A Agent 可选的行为 做空 / 持有 / 做多
转移 P 动作后的状态分布 市场本身的演化
奖励 R 即时反馈 当日持仓收益 - 成本
折扣 \gamma 未来奖励的权重 平衡眼前与长远

目标:学一个策略 \pi(状态→动作的映射),使累计折扣奖励最大化。与监督学习不同,这里没有「正确答案」标签,只有环境给的奖励信号——Agent 必须自己探索试错。

💡 核心心法:强化学习的本质是「用试错学决策」。监督学习告诉模型「这根 K 线该买」,强化学习只告诉模型「你做了这个动作,赚了多少」,让模型自己推断什么状态做什么动作最好。这套范式特别适合「没有标准答案,只有好结果与坏结果」的交易场景。

二、Q-learning:学动作价值

Q-learning 直接优化动作价值函数 Q(s, a)——在状态 s 做动作 a,之后按某策略走,期望能拿到的累计折扣奖励。更新规则:

Q(s, a) \leftarrow Q(s, a) + \alpha [r + \gamma \max_{a'} Q(s', a') - Q(s, a)]

直觉:用「实际拿到的奖励 r + 对下一步最优价值的估计 \gamma \max Q(s', a')」去修正旧的 Q(s,a)\alpha 是学习率。

ε-greedy 策略

Q-learning 是离策略(off-policy)——它学的是最优 Q,但实际行为可以用任意策略。为兼顾「探索未知」与「利用已知」,常用 ε-greedy:以 ε 概率随机选动作(探索),否则选 Q 最大的动作(利用)。ε 通常随训练线性衰减,从「多探索」过渡到「多利用」。

notebook 02_gridworld_q_learning.ipynb 在 3×4 网格上实现了表格式 Q-learning——状态离散有限,直接用一个二维数组存 Q(s, a),是理解算法的最佳起点。

三、DQN:让 Q-learning 在连续状态下收敛

网格世界的状态是离散的,可以用表存。但交易的状态(收益、指标)是连续的,无法穷举。深度 Q 网络(DQN)(DeepMind, 2013)用神经网络近似 Q(s, a),把状态映射到各动作的价值。但「直接套神经网络到 Q-learning」会发散,三大创新让它稳定下来:

创新 解决的问题
经验回放 样本相关性高、分布非平稳
目标网络 训练目标自身在变,形成反馈循环
Double DQN \max 操作系统性高估动作价值

经验回放

把每一步的 (s, a, r, s') 存进回放缓冲区,训练时从缓冲区随机采样小批量——打破样本时序相关性,提升样本效率,避免当前权重产生的训练样本导致局部最优。

目标网络

用两个结构相同的网络:主网络(在线学习)与目标网络(缓慢更新)。训练目标里的 Q(s', a') 用目标网络算,主网络只负责预测当前 Q(s, a)。目标网络权重每隔若干步从主网络硬拷贝一次,这样训练目标不会随每次更新剧烈变化,反馈循环被削弱。

Double DQN

原 DQN 用同一个网络既选最优动作又估其价值,会系统性地高估(因为 \max 偏向噪声中的高估)。Double DQN 解耦:用主网络选最优动作,用目标网络估其价值,显著降低高估偏差。

notebook 03_lunar_lander_deep_q_learning.ipynb 在 OpenAI Gym 的 Lunar Lander 上实现了一个 DDQN,本节交易 Agent 复用同一架构。

四、自定义交易环境:trading_env.py

OpenAI Gym 规定环境必须实现 step(action)reset() 两个接口。原项目 trading_env.py 用三个协作类实现:

DataSource:喂市场数据

class DataSource: def __init__(self, trading_days=252, ticker='AAPL', normalize=True): ... self.data['returns'] = self.data.close.pct_change() self.data['rsi'] = talib.STOCHRSI(self.data.close)[1] self.data['macd'] = talib.MACD(self.data.close)[1] self.data['atr'] = talib.ATR(...) # ... 多种 TA-Lib 指标

每个 episode 从历史数据里随机起点抽 252 个交易日,逐日推进。返回当天特征作为 observation。

TradingSimulator:持仓与奖励

class TradingSimulator: def take_step(self, action, market_return): start_position = self.positions[max(0, self.step - 1)] end_position = action - 1 # 动作 0/1/2 → -1/0/+1 n_trades = end_position - start_position trade_costs = abs(n_trades) * self.trading_cost_bps time_cost = 0 if n_trades else self.time_cost_bps # 不交易也有成本 reward = start_position * market_return - (trade_costs + time_cost) ...

关键设计:

  • 动作空间:Discrete(3),0=做空,1=持有,2=做多;action - 1 映射到 -1/0/+1 持仓;
  • 奖励:当日持仓 × 市场收益 - 交易成本 - 时间成本;
  • 交易成本:每次换仓按 bps 计;
  • 时间成本:不交易也扣一点点,鼓励 Agent 别干等——这是「机会成本」的代理。

TradingEnvironment:Gym 接口

class TradingEnvironment(gym.Env): def step(self, action): observation, done = self.data_source.take_step() reward, info = self.simulator.take_step(action=action, market_return=observation[0]) return observation, reward, done, info def reset(self): self.data_source.reset() self.simulator.reset() return self.data_source.take_step()[0]

NAV 从 1 开始,降到 0 算输,升到 2.0 算赢——这是 episode 的终止条件之一。同时记录了 buy-and-hold 基准做对比。

五、训练与挑战

notebook 04_q_learning_for_trading.ipynb 复用 Lunar Lander 的 DDQN,在 AAPL 上训练。配置:探索 500000 步(约 2000 个 1 年 episode),ε 线性衰减到 0.1,之后指数衰减(因子 0.9999)。关键代码骨架:

import tensorflow as tf from tensorflow.keras import Sequential from tensorflow.keras.layers import Dense, Dropout # 主网络与目标网络同结构 def build_model(state_dim, action_dim): return Sequential([ Dense(64, activation='relu', input_dim=state_dim), Dropout(0.2), Dense(64, activation='relu'), Dense(action_dim) ]) # 训练循环(简化) for step in range(total_steps): action = epsilon_greedy(state, eps) next_state, reward, done, _ = env.step(action) replay_buffer.append((state, action, reward, next_state, done)) batch = sample(replay_buffer, batch_size) train_step(batch, main_net, target_net) # 经验回放训练 if step % update_every == 0: target_net.set_weights(main_net.get_weights()) # 周期性硬更新

⚠️ 强化学习交易的三大难:

  1. 奖励稀疏:单日收益噪声大,真实信号被淹没,Agent 很难从噪声里学到稳定模式;
  2. 市场非平稳:训练期学到的模式,测试期可能已失效,「分布漂移」是 RL 的天敌;
  3. 样本相关性强:连续交易日的状态高度相似,经验回放虽能缓解但无法根除。

务实态度:把 RL 交易 Agent 当「研究范式」而非「印钞机」。它能跑通、能学会简单模式,但稳定盈利需要更精细的奖励工程、更稳的算法(如 PPO/SAC)、更稳健的市场建模——这些都远超本节范围。

本节要点回顾

  1. MDP 五要素:状态、动作、转移、奖励、折扣;目标是最大化累计折扣奖励,没有标签靠试错。
  2. Q-learning:用 r + \gamma \max Q(s', a') 修正 Q(s,a),ε-greedy 平衡探索与利用,off-policy。
  3. DQN 三大创新:经验回放(打破相关性)、目标网络(削弱反馈循环)、Double DQN(消除高估)。
  4. trading_env.py 三类:DataSource(数据+特征)、TradingSimulator(持仓+奖励)、TradingEnvironment(Gym 接口)。
  5. 动作与奖励:动作 0/1/2 → -1/0/+1 持仓;奖励 = 持仓 × 市场收益 - 交易成本 - 时间成本。
  6. RL 交易三难:奖励稀疏、市场非平稳、样本相关——本节是入门范式,稳定盈利需 PPO/SAC 等更稳算法与更精的奖励工程。

至此,第 10 章结束。从 PCA 提取隐性因子,到 HRP 稳健配置,到 FNN/LSTM 做收益预测,再到 DQN 训练交易 Agent——我们走过了金融机器学习的高阶全景。后续可进一步深入自编码器、GAN 合成数据、CNN 处理金融图表,以及 PPO/SAC 等更稳定的强化学习算法。


发布者: 作者: 灏天文库 转发
评论区 (0)
U