- 金融科技
- 示例工程
【免费下载链接】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++部署及聚宽代码。
本篇技术指南以 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 空间):
- 打开 Visual Studio Build Tools 下载安装;
- 在“工作负荷”中勾选“使用 C++ 的桌面开发”;
- 在“单个组件/安装详细信息”中确保勾选两项: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 强化学习核心概念
强化学习核心包含“智能体(机器人)”与“环境”,交互流程如下:
- 智能体观察当前条件,得到状态(state);
- 智能体执行动作(action);
- 环境进入新状态,并给智能体一个数字奖励(reward),反馈新状态的好坏;
- 不断重复交互,智能体追求最大化累计奖励。
更形式化地,股票交易可建模为马尔可夫决策过程(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。
若网络可用,流程如下:
- 安装 swig、wrds、pyportfolioopt,并安装 FinRL;
- 用
yf.download(tickers="aapl", start=..., end=...)直接获取单只股票,或用 FinRL 封装好的YahooDownloader(start_date, end_date, ticker_list).fetch_data(); - 对 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); - 用
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,衡量给定资产范围内异常行为程度的风险指标,用于金融危机等极端行情控制);
- 技术指标(
- 用
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,训练与回测共用):
| 参数 | 值 | 含义 |
|---|---|---|
hmax | 100 | 单笔最大买入股数(动作先缩放到 0–1 再乘以 hmax) |
initial_amount | 1000000 | 初始资金 |
num_stock_shares | [0]*29 | 各股票初始持仓 |
buy_cost_pct/sell_cost_pct | [0.001]*29 | 买卖手续费比例(千分之一) |
state_space | 291 | 状态空间维度 |
stock_dim | 29 | 股票数量 |
tech_indicator_list | INDICATORS | 技术指标列表 |
action_space | 29 | 动作空间维度 |
reward_scaling | 1e-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 实现了完整流程:
process_df_for_mvo():把长表数据按交易日重排为“日期 × 29 支股票收盘价”的矩阵;StockReturnsComputing():按前后两天收盘价差值计算每日收益率;- 计算平均收益
meanReturns与收益的方差-协方差矩阵covReturns; - 使用 PyPortfolioOpt 库的
EfficientFrontier(meanReturns, covReturns, weight_bounds=(0, 0.5))求max_sharpe()有效前沿权重(马科维兹有效前沿:相同风险下选择最大收益、相同收益下选择最小风险的组合); - 将 100 万初始资金按权重分配到各股,得到初始持仓
Initial_Portfolio; - 用
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 个数据,否则会报错。原因(源码级):
finrl/meta/env_stock_trading/env_stocktrading.py的_initiate_state函数中self.data.close.values.tolist()(约 404 行)要求self.data.close必须是二维数组;- 同文件
__init__(约 64 行)中self.data = self.df.loc[self.day, :],如果索引顺序排成 0,1,2,...,会导致只取到一行、一维数据传入,从而触发第 1 点所述问题(因此若只有一支股票,需要把索引全部改成一样;这种情况几乎不存在,可暂时忽略)。
解决方法(三选一,推荐第 3 种):
- 降低 numpy 版本;
- 把数据改成二维的,即
(10,)→(1,10)(改完是否存在回测不完整性,未详细验证); - 保持上方所示的“索引-日期-股票”格式(推荐)。
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++部署及聚宽代码。
相关推荐
FinRL 快速入门指南:用 NeurIPS2018 股票交易系列走通"数据 → 训练 → 回测"DRL 全流程
FinRL 快速入门指南:用 NeurIPS2018 股票交易系列走通"数据 → 训练 → 回测"DRL 全流程 本文是 FinRL 官方文档 First Gl
金融科技强化学习人工智能Momentum Firmware 的 JS Widget 视图:组合式界面元素与按钮事件实战指南
Momentum Firmware 的 JS Widget 视图:组合式界面元素与按钮事件实战指南 Widget 视图是 Momentum Firmware J
金融科技示例工程FinRL 多股票强化学习交易实战指南:基于 Dow 30 从数据、环境到 DDPG 训练与回测
FinRL 多股票强化学习交易实战指南:基于 Dow 30 从数据、环境到 DDPG 训练与回测 导读 本指南以 FinRL 官方教程《Multiple Sto
金融科技强化学习人工智能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考