☰
ai_quant_trade 金融强化学习实战:基于 FinRL 复现 NeurIPS2018 股票交易 DRL 全流程(数据→训练→回测)
2026/10/10 1:15:59 网站建设 项目流程
  • 金融科技
  • 示例工程

【免费下载链接】ai_quant_trade

Stock AI Trader: 1-stop platform for learning, sim & live trading. Covers: stock basics, strategies, LLMs, factor mining, ML/DL/RL, graph nets, HFT, C++ deploy & JoinQuant code. 股票AI操盘手:一站式学习、模拟、实盘平台。涵盖:股票基础、策略、大模型、因子挖掘、机器学习/深度学习/强化学习、图网络、高频交易、C++部署及聚宽代码。

项目地址:https://gitcode.com/gh_mirrors/ai/ai_quant_trade
点击查看免费下载

本篇技术指南以 ai_quant_trade 仓库中 Stock_NeurIPS2018 样例 为核心,完整讲解如何基于 FinRL + Stable-Baselines3 复现论文《Practical Deep Reinforcement Learning Approach for Stock Trading》,在道琼斯 30 支成分股上完成 A2C / DDPG / PPO / TD3 / SAC 五类深度强化学习交易策略的环境构建、模型训练与回测评估。读者学完后,将掌握一套可复制到自有股票池上的 DRL 模拟交易研究流水线,并能对照本文规避数据格式、训练/测试不一致、依赖版本等高频踩坑点。

1. 样例背景与目录结构

该样例位于 egs_trade/rl/a002_finRL_tutorial/a01_Stock_NeurIPS2018/,其整体目标与仓库内其他 RL 样例(如 a001_proto_sb3)一致:把深度强化学习真正用于多股票组合的模拟交易。样例目录包含以下关键文件:

  • README.md:使用说明与踩坑记录(本文的主体骨架);
  • 1_Data.ipynb:数据获取与特征工程;
  • 2_Train.ipynb:环境构建与 DRL 模型训练;
  • 3_Backtest.ipynb:回测与基线对比;
  • 01_论文解读/:对复现论文的逐节解读(含 MDP 建模与 DDPG 原理);
  • requirements.txt:依赖清单;
  • RESULT.md:实验结果汇总;
  • run_e2e.py:finRL 0.3.7 与 gymnasium/SB3 的 API 契约冒烟测试。

复现的论文为Practical Deep Reinforcement Learning Approach for Stock Trading(NIPS 2018 Workshop,arxiv 1811.07522),策略代码参考 FinRL-Tutorials 的 1-Introduction 章节。相比原始 notebook,本样例做了两点本地化改造:加入了大量中文说明,并修复了部分无法跑通的 bug。

训练环境参考:单卡 GPU 下完成全部算法训练约需 15–30 分钟;CPU 因训练速度过慢未进行测试(本仓库 README 与训练 notebook 均明确标注)。

2. 环境安装与依赖清单

2.1 主要依赖

样例的运行依赖可分为三层:

  • 策略库:FinRL(AI4Finance 基金会开源的强化学习金融交易库);
  • 深度学习库:PyTorch(torch,对应 GPU 加速训练);
  • 强化学习库:Stable-Baselines3(提供 A2C / DDPG / PPO / TD3 / SAC 等成熟算法实现)。

此外还包括数据获取(yfinance)、特征工程(stockstats)、投资组合优化(pyportfolioopt)、回测可视化(pyfolio)、交易时段(exchange_calendars)、tensorboard 日志等辅助库。

2.2 安装步骤

pip install -r requirements.txt pip install git+https://github.com/AI4Finance-Foundation/FinRL.git

仓库内的 requirements.txt 给出了经过适配的依赖版本,关键项如下:

stable-baselines3==2.9.0 gymnasium==1.3.0 torch==2.14.0 setuptools>=83.0.0 pyportfolioopt pyfolio tensorboard yfinance stockstats

训练 notebook 顶部也保留了备用安装方式(!pip install -r requirements.txt、!pip install git+...FinRL.git),或说明“把 FinRL 仓中的 finrl 文件夹拷到根目录即可使用”,便于无法访问外网的离线环境。

2.3 ElegantRL 备选库与 Windows 编译环境

FinRL 除 Stable-Baselines3 外还支持 ElegantRL 与 Ray RLlib。README 提到 ElegantRL 比 stable-baselines3 更稳定,可替换尝试;但若在 Windows 上使用 ElegantRL,需要先安装Microsoft C++ Build Tools(约需 2.5G 空间):

  1. 打开 Visual Studio Build Tools 下载安装;
  2. 在“工作负荷”中勾选“使用 C++ 的桌面开发”;
  3. 在“单个组件/安装详细信息”中确保勾选两项:MSVC 生成工具、Windows SDK。

2.4 版本适配与 API 契约(源码佐证)

本仓库对“老 FinRL + 新 gymnasium/SB3”的兼容问题做了前置防御:run_e2e.py 是一个不真正调用 FinRL(避免其重量级原生依赖与 alpaca/wrds 拉取)的冒烟测试,它直接扫描finrl/meta/env_stock_trading/env_stocktrading.py源码并断言:

  • StockTradingEnv继承自gymnasium.Env(而非旧版 gym);
  • step()返回 5 元组(obs, reward, terminated, truncated, info);
  • reset()接受seed=参数并返回 2 元组(obs, info);
  • Stable-Baselines3 的DummyVecEnv能正常包裹该环境。

这些断言正好对应 gymnasium 与旧 gym 的关键差异,若 FinRL 版本回退到 gym,脚本会“快速失败”,避免用户在训练时才发现问题。

3. 策略设计与强化学习原理

3.1 交易标的与基线

  • 市场:道琼斯工业平均指数(DJIA)30 支成分股(DOW_30_TICKER),涵盖 AXP、AMGN、AAPL、BA、CAT、CSCO、CVX、GS、HD、IBM、JPM、KO、MSFT、V、WMT、DIS 等;
  • DRL 策略:A2C、DDPG、PPO、TD3、SAC 五种深度强化学习算法进行模拟交易;
  • 基线 1:传统投资组合管理——最大化均值方差(Mean-Variance Optimization);
  • 基线 2:道琼斯指数本身(论文中用于对照市场表现)。

3.2 强化学习核心概念

强化学习核心包含“智能体(机器人)”与“环境”,交互流程如下:

  1. 智能体观察当前条件,得到状态(state);
  2. 智能体执行动作(action);
  3. 环境进入新状态,并给智能体一个数字奖励(reward),反馈新状态的好坏;
  4. 不断重复交互,智能体追求最大化累计奖励。

更形式化地,股票交易可建模为马尔可夫决策过程(MDP)(见 论文解读):

  • 状态 s:状态空间表示智能体对环境的感知,例如人工交易员分析的各类信息。本实现中智能体从历史数据观察交易价格以及技术指标,通过回放历史数据与环境交互学习。论文中的状态定义为s = [p, h, b],即股票价格、持仓数量与账户余额;
  • 动作 a:动作空间编码智能体在每个状态可执行的动作。单支股票时a ∈ {−1, 0, 1}分别代表卖出、持仓、买入;多支股票时a ∈ {−k, ..., −1, 0, 1, ..., k},例如“买 10 股 AAPL”或“卖出 10 股 AAPL”即动作值 10 或 −10。所有买入动作不得导致账户余额为负;
  • 奖励函数 r(s, a, s′):用于激励智能体学习更好策略。典型设定为投资组合总市值的变动:r(s, a, s′) = v′ − v,其中v′、v分别为状态s′、s下的组合总市值(总市值 = 全部持仓市值pᵀh+ 账户余额);
  • 市场环境:DJIA 30 支成分股在回测时间段内的全部交易数据。

3.3 论文方法与 DDPG 原理

论文方法的核心是深度确定性策略梯度(DDPG),其三大组件:

  • Actor-Critic 架构:建模大的状态与动作空间;
  • 目标网络(Target Network):稳定训练过程(Q′ 与 μ′ 拷贝 Q 与 μ 的参数,提供时序差分备份,两个网络交替更新);
  • 经验回放(Experience Replay):降低样本相关性并提高数据利用率。

论文指出传统方法的两个缺陷:一是基于协方差矩阵的均值方差组合优化,投资经理若想在每个时间点调整策略会非常复杂;二是将交易视为 MDP 并用动态规划求解,会因股票状态空间巨大而可扩展性差。DQN 虽用神经网络近似价值函数,但离散动作空间会随股票数量指数增长,造成“维度灾难”,因此论文采用 DDPG 解决动作与状态的映射关系(见 01_论文解读)。

4. 三步实战流程

4.1 第一步:获取数据(1_Data.ipynb)

注意:数据获取依赖 YahooDownloader 从 Yahoo Finance 拉取美股数据,国内访问可能存在问题,因此可以跳过此步骤,直接使用数据集目录下提供的 train.csv / trade.csv。

若网络可用,流程如下:

  1. 安装 swig、wrds、pyportfolioopt,并安装 FinRL;
  2. 用yf.download(tickers="aapl", start=..., end=...)直接获取单只股票,或用 FinRL 封装好的YahooDownloader(start_date, end_date, ticker_list).fetch_data();
  3. 对 DJIA 30 全量标的拉取TRAIN_START_DATE='2009-01-01'至TRADE_END_DATE='2021-10-29'的 OHLCV 数据(样例输出Shape of DataFrame: (94301, 8),包含 date/open/high/low/close/volume/tic/day 共 8 列;close 使用复权收盘价,day 为星期几 0–4);
  4. 用FeatureEngineer做特征工程,加入技术指标与波动率指标:
    • 技术指标(INDICATORS默认 8 个):macd、boll_ub、boll_lb、rsi_30、cci_30、dx_30、close_30_sma、close_60_sma;
    • use_vix=True加入 VIX 指数;
    • use_turbulence=True加入动荡指数(Turbulence Index,衡量给定资产范围内异常行为程度的风险指标,用于金融危机等极端行情控制);
  5. 用data_split划分训练集与交易集,最终train.to_csv('train_data.csv')、trade.to_csv('trade_data.csv')。

训练与交易的时间窗口划分(论文口径见 论文解读):训练 2009-01-01 至 2020-07-01,交易(集外验证)2020-07-01 至 2021-10-29,样例输出训练集 83897 行、交易集 9715 行。

4.2 第二步:训练 DRL 模型(2_Train.ipynb)

4.2.1 构建 OpenAI Gym 风格的市场环境

训练环境使用 FinRL 的StockTradingEnv,其实现位于finrl/meta/env_stock_trading/env_stocktrading.py(README 明确给出依赖路径)。

状态空间维度计算:state_space = 1 + 2*stock_dimension + len(INDICATORS)*stock_dimension,其中 1 为账户余额、stock_dimension 个为股票价格、stock_dimension 个为持仓数量、len(INDICATORS)*stock_dimension个为每支股票的技术因子状态。样例输出Stock Dimension: 29, State Space: 291。

环境关键参数(env_kwargs,训练与回测共用):

参数值含义
hmax100单笔最大买入股数(动作先缩放到 0–1 再乘以 hmax)
initial_amount1000000初始资金
num_stock_shares[0]*29各股票初始持仓
buy_cost_pct/sell_cost_pct[0.001]*29买卖手续费比例(千分之一)
state_space291状态空间维度
stock_dim29股票数量
tech_indicator_listINDICATORS技术指标列表
action_space29动作空间维度
reward_scaling1e-4奖励缩放系数

随后通过e_train_gym.get_sb_env()得到 Stable-Baselines3 的DummyVecEnv向量化环境(训练 notebook 打印类型确认为stable_baselines3.common.vec_env.dummy_vec_env.DummyVecEnv)。

4.2.2 训练五种算法

通过开关变量选择算法:

if_using_a2c = True if_using_ddpg = False if_using_ppo = False if_using_td3 = False if_using_sac = True

五种算法统一采用DRLAgent(位于finrl/agents/stablebaselines3/models.py)训练,模型输出保存在TRAINED_MODEL_DIR下的a2c/ddpg/ppo/td3/sac子目录,保存为agent_*.zip。各算法超参数如下:

  • A2C:默认参数,total_timesteps=50000(训练日志显示n_steps=5, ent_coef=0.01, learning_rate=0.0007);
  • DDPG:默认参数,total_timesteps=50000;
  • PPO:PPO_PARAMS = {"n_steps": 2048, "ent_coef": 0.01, "learning_rate": 0.00025, "batch_size": 128},total_timesteps=200000;
  • TD3:TD3_PARAMS = {"batch_size": 100, "buffer_size": 1000000, "learning_rate": 0.001},total_timesteps=50000;
  • SAC:SAC_PARAMS = {"batch_size": 128, "buffer_size": 100000, "learning_rate": 0.0001, "learning_starts": 100, "ent_coef": "auto_0.1"},total_timesteps=70000。

训练前还会用configure(tmp_path, ["stdout", "csv", "tensorboard"])配置日志,使训练过程同时输出到终端、CSV 与 TensorBoard。SAC 训练日志中可以看到每若干 episode 打印一次begin_total_asset / end_total_asset / total_reward / total_cost / total_trades / Sharpe,便于观察训练期组合表现。

注意:强化学习比机器学习慢很多(本样例 CPU 训练约 2 分钟即可完成机器学习对比任务,而强化学习单卡 GPU 约需 30 分钟);且强化学习不稳定,每次收敛的 loss 不同、效果可能差异大,多跑几遍并调参是常态。

4.3 第三步:回测(3_Backtest.ipynb)

4.3.1 波动率阈值风控

回测阶段引入人工风控规则:StockTradingEnv(df=trade, turbulence_threshold=70, risk_indicator_col='vix', **env_kwargs)。当波动率指标(VIX)超过阈值时,判定市场波动剧烈,环境强制空仓以规避风险。阈值设定方法为取训练窗口内风险指标的 99.6% 分位数:

  • 样本内 VIX:insample_risk_indicator.vix.describe()显示均值约 16.47、最大 82.69,quantile(0.996)≈ 64.57;
  • 样本内动荡指数:均值约 40.86、最大 652.51,quantile(0.996)≈ 426.48。
4.3.2 加载模型并预测
trained_a2c = A2C.load(os.path.join(TRAINED_MODEL_DIR, 'a2c', "agent_a2c.zip")) # DDPG / PPO / TD3 / SAC 同理 df_account_value_a2c, df_actions_a2c = DRLAgent.DRL_prediction(model=trained_a2c, environment=e_trade_gym)
4.3.3 对比基线:最大化均值方差

均值方差(Mean-Variance Optimization)是经典投资组合管理策略。回测 notebook 实现了完整流程:

  1. process_df_for_mvo():把长表数据按交易日重排为“日期 × 29 支股票收盘价”的矩阵;
  2. StockReturnsComputing():按前后两天收盘价差值计算每日收益率;
  3. 计算平均收益meanReturns与收益的方差-协方差矩阵covReturns;
  4. 使用 PyPortfolioOpt 库的EfficientFrontier(meanReturns, covReturns, weight_bounds=(0, 0.5))求max_sharpe()有效前沿权重(马科维兹有效前沿:相同风险下选择最大收益、相同收益下选择最小风险的组合);
  5. 将 100 万初始资金按权重分配到各股,得到初始持仓Initial_Portfolio;
  6. 用TradeData @ Initial_Portfolio得到每个交易日的 MVO 组合资产序列。
4.3.4 对比基线:道琼斯指数

原 notebook 中道琼斯指数基线通过YahooDownloader(start_date, end_date, ticker_list=['dji'])下载,并以首日收盘价为基准归一化到 100 万(close.div(fst_day).mul(1000000))。因国内无法访问 YahooDownloader,本样例将该段代码注释,回测对比以 A2C/SAC 与均值方差为主。

4.3.5 性能对比与可视化

将各策略账户净值与 MVO 结果按日期 merge 成一张表(列名 A2C / DDPG / PPO / TD3 / SAC / Mean Var),再用result.plot()绘制资产变化曲线,并用 Quantopian pyfolio 工具(finrl.plot.backtest_stats等)计算详细回测指标。

5. 模型目录结构与实验结果

5.1 输出目录结构

训练与回测产物按如下结构组织(README 原图说明):

trained_models/ # 各算法 agent_*.zip 模型文件 results/ # 各算法训练日志(stdout/csv/tensorboard)与回测指标 csv tensorboard_log/ # tensorboard 日志

5.2 实验结果(仓库实测数据)

实验策略:均值方差基线 + DRL 策略 A2C 与 SAC;训练环境:单卡 GPU,约 15–30 分钟;账户初始资金 1000000。README 与 RESULT.md 记录:3 个策略均实现很高收益。

回测明细指标(pyfolio 计算):

a2c: Annual return 0.531267 Cumulative returns 0.761977 Annual volatility 0.207082 Sharpe ratio 2.168219 Calmar ratio 5.108832 Stability 0.913644 Max drawdown -0.103990 Omega ratio 1.434179 Sortino ratio 3.603966 Skew NaN Kurtosis NaN Tail ratio 1.140148 Daily value at risk -0.024308 sac: Annual return 0.229471 Cumulative returns 0.316038 Annual volatility 0.135545 Sharpe ratio 1.597028 Calmar ratio 2.503250 Stability 0.885632 Max drawdown -0.091669 Omega ratio 1.300750 Sortino ratio 2.291562 Skew NaN Kurtosis NaN Tail ratio 1.029162 Daily value at risk -0.016218

结合回测 notebook 的账户净值表可以看到,A2C 期末资产约 176 万(累计收益 76.2%)、SAC 约 131.6 万、均值方差约 153.5 万,A2C 在三者中表现最好。仓库总览 egs_trade/rl/README.md 也汇总了该样例:市场为美股道琼斯 30,年化收益 53.1%、最大回撤 -10.4%、夏普率 2.17。需注意:上述结果是特定数据窗口与随机种子下的单次复现,强化学习本身不稳定,不同运行可能差异明显,不能据此断言算法优劣。

6. 潜在问题与不足(仓库踩坑记录)

6.1 状态信息是否“看到了未来”?

问题:状态用到了收盘价/最高价/最低价,是否可能泄露未来信息?

解释:不存在。因为这不是机器学习的分类或预测问题,强化学习模型仅假设交易发生在收盘的最后一个时间点、使用该时刻的信息进行交易。当然,这种假设较简单,仅是一个原理演示级策略;更完善的股票环境可参考 FinRL-Meta 的 meta 目录实现。

6.2 训练与测试不一致:测试引入了波动率阈值

测试时加入了 VIX 阈值空仓规则,而训练环境中没有该规则。原因:模型无法完全学到风控策略,因为股市崩盘样本很少;因此需要加入人工策略,出现大波动时卖出所有股票。这也是“训练/测试环境不一致”的典型案例,实战中需权衡“模型自学习风控”与“人工规则兜底”的取舍。

6.3 stable-baselines3 在 GPU 下 batch size 调大不加速

README 记录:SB3 在 GPU 环境下训练,调大 batch size 也没有加速,可能 SB3 在 GPU 下优化不佳,可以尝试 ElegantRL 库。SAC 训练代码注释也提示“在单卡 GPU 下,batch 调大显存占用和利用率也上不去,不确定原因”。

6.4 PyTorch 远程恶意代码执行风险

存在 pytorch 远程恶意代码执行漏洞,建议使用>= 1.13.1版本以规避。

6.5 模拟环境的不足

模拟环境相对简单:没有考虑滑点(slippage);没有考虑股票停牌信息。因此在把策略迁移到实盘前,需在更逼真的环境中补充这些要素。

7. 常见问题 FAQ

7.1 无法复现论文结果

现象:论文中的结果无法复现,自己训练的模型比官方预训练模型性能差很多。原因:强化学习不稳定,建议调参,或者多训练几遍(同一个算法不同随机种子/不同训练轮次结果都可能显著不同)。

7.2'numpy.float64' object has no attribute 'values'

读取训练数据时,所有股票均混在一个 CSV 表里,格式必须保持如下:

索引 日期 股票 0 2009-01-02 苹果 0 2009-01-02 亚马逊 1 2009-01-05 苹果 1 2009-01-05 亚马逊

必须保持该格式:同样的索引下至少有 2 个数据,否则会报错。原因(源码级):

  1. finrl/meta/env_stock_trading/env_stocktrading.py的_initiate_state函数中self.data.close.values.tolist()(约 404 行)要求self.data.close必须是二维数组;
  2. 同文件__init__(约 64 行)中self.data = self.df.loc[self.day, :],如果索引顺序排成 0,1,2,...,会导致只取到一行、一维数据传入,从而触发第 1 点所述问题(因此若只有一支股票,需要把索引全部改成一样;这种情况几乎不存在,可暂时忽略)。

解决方法(三选一,推荐第 3 种):

  1. 降低 numpy 版本;
  2. 把数据改成二维的,即(10,)→(1,10)(改完是否存在回测不完整性,未详细验证);
  3. 保持上方所示的“索引-日期-股票”格式(推荐)。

7.3"zipline.assets" not found

现象:

anaconda3\lib\site-packages\pyfolio\pos.py:26: UserWarning: Module "zipline.assets" not found; mutltipliers will not be applied to position notionals. warnings.warn(

原因:pyfolio 报出的警告。Quantopian's Zipline 只支持 Python 3.7 以下版本,但 zipline 不是强制安装依赖,可忽略该警告。

8. 快速验证:API 契约冒烟测试

若只想快速验证“当前环境的 FinRL 与 gymnasium/SB3 版本是否兼容”,无需完整训练即可运行仓库自带的端到端冒烟测试:

python egs_trade/rl/a002_finRL_tutorial/a01_Stock_NeurIPS2018/run_e2e.py

脚本(run_e2e.py)会检查StockTradingEnv的父类是否为gymnasium.Env、step()是否返回 5 元组、reset()是否接受seed参数,并验证 SB3DummyVecEnv的包裹与 step/reset 往返,全部通过即输出E2E OK: a002_finRL_tutorial API contract holds for the upgraded stack.。该测试不依赖 FinRL 的本地安装路径时,可通过环境变量FINRL_ENV_PATH指定env_stocktrading.py的实际位置。

9. 小结与延伸

至此,一条完整的“数据获取与特征工程 → Gym 风格交易环境 → 五种 DRL 算法训练 → 波动率风控回测 → pyfolio 指标评估”流水线已跑通。本样例的核心价值在于:

  • 提供了一套最小可复现的多股票 DRL 交易研究模板,换掉DOW_30_TICKER与日期窗口即可迁移到其他股票池;
  • 明确揭示了 DRL 交易研究的常见坑:数据宽表格式、训练/测试环境不一致、SB3 GPU 利用率、RL 结果不稳定、版本兼容等;
  • 提供了源码级佐证(环境实现路径、run_e2e 契约测试)与仓库内实测回测数据,可直接作为后续策略迭代的基线参照。

在此基础上,可进一步探索仓库中更深入的主题:更逼真的交易环境(滑点/停牌)、FinRL-Meta 的完善环境、以及 egs_trade/rl/a001_proto_sb3 中更基础的原型实现,逐步把模拟交易能力延伸到实盘验证阶段。

  • 金融科技
  • 示例工程

【免费下载链接】ai_quant_trade

Stock AI Trader: 1-stop platform for learning, sim & live trading. Covers: stock basics, strategies, LLMs, factor mining, ML/DL/RL, graph nets, HFT, C++ deploy & JoinQuant code. 股票AI操盘手:一站式学习、模拟、实盘平台。涵盖:股票基础、策略、大模型、因子挖掘、机器学习/深度学习/强化学习、图网络、高频交易、C++部署及聚宽代码。

项目地址:https://gitcode.com/gh_mirrors/ai/ai_quant_trade
点击查看免费下载

相关推荐

上一篇:PHP面试问答项目使用教程
下一篇:3个魔法步骤:用Mermaid Live Editor从零到专业图表创作

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询