尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Qbot 深度强化学习自动炒股实战:自定义 Gym 股票交易环境与 PPO 策略训练全流程

Qbot 深度强化学习自动炒股实战:自定义 Gym 股票交易环境与 PPO 策略训练全流程 Qbot 深度强化学习自动炒股实战自定义 Gym 股票交易环境与 PPO 策略训练全流程【免费下载链接】Qbot[updating ...] AI 自动量化交易机器人(完全本地部署) AI-powered Quantitative Investment Research Platform. online docs: https://ufund-me.github.io/Qbot ✨ :news: qbot-mini: https://github.com/Charmve/iQuant项目地址: https://gitcode.com/GitHub_Trending/qbot/Qbot本文基于 Qbot 仓库 docs/tutorials_code/15.rl_learning 目录下的教程文档与配套源码完整讲解如何用深度强化学习自动模拟炒股从监督学习与强化学习的本质区别讲起深入一个自定义 OpenAI Gym 股票交易环境的观测、动作、奖励函数设计再覆盖 PPO 策略梯度算法的训练超参、baostock 数据获取与 Celery 多股票并行的完整工程链路。读完后你可以复现一套「数据下载 → 环境构建 → PPO 训练 → 测试集验证 → 盈亏统计分析」的端到端强化学习量化交易实验流程。为什么要用强化学习自动炒股教程文档开篇给出了一个很朴素的问题起点人工「追跌加仓」式的抄底操作往往在连续下跌中被反复套牢。痛定思痛后作者提出的核心问题是如何用深度强化学习来自动模拟炒股并用实验验证它能否获得收益。在动手之前文档先厘清了一个关键的概念分野——监督学习与强化学习在交易场景中的角色差异监督学习如 LSTM基于历史数据预测未来股价的涨跌方向本质是「预测数值」最终仍需要人来根据预测结果做决策强化学习机器学习的另一个分支Agent 在决策时刻选择使最终奖励最大化的行动Action。它以当日状态开盘价、收盘价等为输入直接输出动作序列买进、持有、卖出以总收益最大化为目标从而实现自动交易无需人工介入。这条路线对应的学术工作方向是文档参考资料中列出的 Deng 等人 2017 年发表于 IEEE Transactions on Neural Networks and Learning Systems 的《Deep Direct Reinforcement Learning for Financial Signal Representation and Trading》vol. 28, no. 3, pp. 653-664以及 Huang 2018 年的《Financial trading as a game: A deep reinforcement learning approach》arXiv:1807.02787。核心实现StockTradingEnv 股票交易环境环境是整个项目的骨架实现位于 rlenv/StockTradingEnv0.py继承自gym.Env。文档对环境的三要素观测 Observation、动作 Action、奖励 Reward分别给出了设计说明下面逐一展开并结合源码核对实际实现。观测空间行情数据 账户状态共 19 维文档首先指出策略网络观测的是一只股票的各项参数如开盘价、收盘价、成交数量等。由于成交金额、成交量可能是百万乃至更大的数值为了训练收敛观测输入必须归一化。文档给出的观测参数完整定义如下17 个行情字段参数名称参数描述说明date交易所行情日期格式YYYY-MM-DDcode证券代码格式sh.600000。sh上海sz深圳open今开盘价格精度小数点后 4 位单位人民币元high最高价精度小数点后 4 位单位人民币元low最低价精度小数点后 4 位单位人民币元close今收盘价精度小数点后 4 位单位人民币元preclose昨日收盘价精度小数点后 4 位单位人民币元volume成交数量单位股amount成交金额精度小数点后 4 位单位人民币元adjustflag复权状态不复权、前复权、后复权turn换手率精度小数点后 6 位单位%tradestatus交易状态1正常交易 0停牌pctChg涨跌幅百分比精度小数点后 6 位peTTM滚动市盈率精度小数点后 6 位psTTM滚动市销率精度小数点后 6 位pcfNcfTTM滚动市现率精度小数点后 6 位pbMRQ市净率精度小数点后 6 位从源码结构看实际送入网络的观测向量比上表多了一层「账户自身状态」。observation_space定义为spaces.Box(low0, high1, shape(19,), dtypenp.float16)即19 维、取值范围 [0, 1]的连续向量StockTradingEnv0.py。_next_observation()方法L38-L60的构造逻辑是行情特征12 项open/high/low/close除以MAX_SHARE_PRICE5000volume除以MAX_VOLUME1000e8amount除以MAX_AMOUNT3e10pctChg除以 100 和 1e3 两次两次归一化尺度peTTM/pbMRQ/psTTM各自除以 1e4、100、100adjustflag除以 10tradestatus原值 0/1账户状态6 项现金余额balance、历史最大净资产max_net_worth、当前持股shares_held、持仓成本cost_basis、累计卖出股数total_shares_sold、累计卖出金额total_sales_value分别除以MAX_ACCOUNT_BALANCE、MAX_NUM_SHARES等上界常量压缩到 [0, 1]。这种设计的含义是Agent 不仅看行情还能「感知自己的持仓与账户健康度」——文档只强调了行情归一化源码补充的账户状态观测正是策略能够做出「该止盈就止盈」这类决策的信息来源。需要注意 date、code、preclose、turn、pcfNcfTTM 并未直接进入观测向量date 仅用于数据排序df.sort_values(date)。动作空间买入 / 卖出 / 保持文档将交易动作定义为长度为 2 的数组action[0]为操作类型action[1]为买入或卖出的百分比动作类型action[0]说明1买入action[1]2卖出action[1]3保持不买也不卖文档特别指出当action[0] 3保持时action[1]无实际意义网络在训练过程中会自行学到这一点。源码中的动作空间是连续区间spaces.Box(lownp.array([0, 0]), highnp.array([3, 1]), dtypenp.float16)L31-L32即操作类型输出 [0, 3] 的连续浮点数、比例输出 [0, 1]。_take_action()L62-L96通过区间判定的方式实现上表的离散语义action_type 1买入。按当日价格计算可买总股数int(balance / current_price)再乘以amount比例买入并同步更新现金余额与加权持仓成本cost_basisaction_type 2卖出。按int(shares_held * amount)卖出持仓比例更新余额、累计卖出量与卖出金额其余 2保持不做任何交易只刷新净资产。一个值得注意的实现细节成交价不是收盘价而是random.uniform(open, close)——在当日开、收盘价之间随机取价模拟盘中成交比固定收盘价更接近真实撮合的不确定性。每次动作后净资产更新为net_worth balance shares_held * current_price并记录历史峰值max_net_worth。奖励函数利润导向 亏损重罚文档强调「奖励函数的设计对强化学习的目标至关重要」股票交易环境中最应关心的是当前盈利情况因此用当前利润作为奖励——当前本金 股票价值 - 初始本金 利润初始本金INITIAL_ACCOUNT_BALANCE 10000。文档给出的奖励片段为# profits reward self.net_worth - INITIAL_ACCOUNT_BALANCE reward 1 if reward 0 else -100说明README 原文此处写成reward 1 if reward 0 else reward -100重复赋值不是合法 Python实际可运行实现见源码二者语义一致。对应源码 StockTradingEnv0.py# profits reward self.net_worth - INITIAL_ACCOUNT_BALANCE reward 1 if reward 0 else -100设计意图是不对称奖惩盈利时只给1亏损时给-100的大惩罚使网络更快学会「避免亏损」的策略。这个「利润符号」化的奖励并不直接等于收益率大小属于探索性设计后文会说明它带来的局限。环境生命周期reset / step / render从源码结构看该环境有三个针对「训练数据有限」问题的特殊处理resetL122-L141将现金、净资产、最大净资产全部重置为 10000持股、累计卖出等清零current_step固定从 0 开始代码中保留了从数据中随机起点的被注释版本随机起点可以增加训练多样性支持通过new_df参数热替换数据集训练/测试切换无需重建对象stepL98-L120执行动作后步数 1当步数越过数据集末尾时current_step回绕为 0# loop training注释表明这是循环训练策略——同一份历史数据被反复使用仅当net_worth 0总资产归零时才置done True提前终止 episoderenderL143-L153打印当前步数、现金、持股数、持仓成本、净资产、最大净资产与利润并返回当前利润值——main.py的测试循环正是靠env.render()的返回值逐日采集day_profits序列用于出图。环境常量MAX_SHARE_PRICE5000、MAX_STEPS20000等L8-L17决定了观测归一化的量级若换用不同市场的数据这些上界需要重新校准。PPO 策略梯度训练文档指出由于动作输出的数值是连续的类型是区间浮点数、比例是 [0,1] 连续值因此采用基于策略梯度的优化算法其中业界首选是PPOProximal Policy OptimizationPython 实现采用 stable-baselines 库的PPO2模块。单只股票的训练与验证入口训练主入口在 main.py核心流程如下L20-L42df pd.read_csv(stock_file) # 读取训练集 CSV df df.sort_values(date) # 按日期排序 env DummyVecEnv([lambda: StockTradingEnv(df)]) model PPO2(MlpPolicy, env, verbose0, tensorboard_log./log, gamma0.95, n_steps20, learning_rate2.5e-2) model.learn(total_timestepsint(1e5)) # 训练 10 万步策略网络使用MlpPolicy两层 MLPstable-baselines 要求传入向量化环境故用DummyVecEnv包装单环境tensorboard_log./log开启 TensorBoard 日志方便观察 loss 与回报曲线文件顶部还设置了os.environ[CUDA_VISIBLE_DEVICES] 1指定 GPU 卡训练完成后在同一模型上跑测试集把训练集路径中的train替换为test读取测试 CSVenv.reset()后逐日调用model.predict(obs)得到动作、env.step(action)推进环境、env.render()记录当日利润直到数据耗尽或done。main.py中使用的关键超参整理如下供复现时参考超参取值说明gamma0.95折扣因子权衡未来奖励n_steps20每个 rollout 收集的环境步数learning_rate2.5e-2PPO 学习率相对较高total_timesteps1e5单只股票训练总步数策略网络MlpPolicy连续动作空间的 MLP 策略多股票批量模式下见下文 tasks.pytotal_timesteps降为1e4以控制单只股票的训练成本体现「广度优先」的权衡。多只股票并行Celery Redis单只股票训练 10 万步耗时可观tasks.py 将批量训练改造成分布式任务BROKER_URL redis://127.0.0.1:6379/0 BACKEND_URL redis://127.0.0.1:6379/0 app Celery(rl, brokerBROKER_URL, backendBACKEND_URL) app.task def multi_stock_trade(code): stock_file find_file(./stockdata/train, str(code)) if stock_file: profits stock_trade(stock_file) with open(fresult/code-{code}.pkl, wb) as f: pickle.dump(profits, f)main.py 的__main__段会取训练集与测试集目录的文件名交集保证同一只股票两边都有数据对每只股票调用multi_stock_trade.apply_async(args(code,))异步派发代码注释标注「使用celery做并发」所有 worker 把逐日利润序列 pickled 到result/code-xxx.pkl后主进程遍历result/目录加载每个结果取每股最后一天的利润p[-1]做盈亏统计分析analysis_profits()L67-L104统计 Profit / Loss / 0 三类的数量绘制饼图保存为img/profits.png再用 150 个 bin 的密度直方图保存为img/profits_hist.png绘图使用 font/wqy-microhei.ttc 中文字体避免中文标签乱码。模拟实验环境与数据准备环境安装文档给出的安装步骤如下基于 Python 3.6 虚拟环境# 虚拟环境 virtualenv -p python3.6 venv source ./venv/bin/activate # 安装库依赖 pip install -r requirements.txtrequirements.txt 锁定了整套技术栈其中与核心链路直接相关的依赖版本为依赖版本用途stable-baselines2.10.0PPO2 算法与 MlpPolicytensorflow-gpu1.14PPO2 的底层训练框架gym0.17.1自定义交易环境的基类numpy / pandas1.18.2 / 1.0.3行情数据处理baostock0.8.8免费开源证券数据源matplotlib3.2.1盈亏统计绘图celery redis未锁版本多股票并行训练由于锁定了 TF 1.14 / Python 3.6 时代的版本该实验栈需要按原样搭建或自行升级到新版 stable-baselines3 并适配 API适用前提是具备 GPU 训练条件CUDA_VISIBLE_DEVICES已预留。股票数据获取baostock数据集来自免费开源的 baostock 证券数据平台文档给出的安装命令推荐通过国内镜像源加速pip install baostock数据下载脚本为 get_stock_data.pypython get_stock_data.py脚本内部结构Downloader类L14-L47先bs.login()登录用bs.query_all_stock(date)按指定日期拉取全市场股票列表再对每只股票调用bs.query_history_k_data_plus()按时间区间下载日 K 线落盘为stockdata/{code}.{股票名}.csv如sh.600036.招商银行.csv。下载字段与前述观测参数表一一对应self.fields date,code,open,high,low,close,volume,amount, \ adjustflag,turn,tradestatus,pctChg,peTTM, \ pbMRQ,psTTM,pcfNcfTTM,isST训练集/测试集划分文档的设计是把过去 20 多年的股票数据作为训练集末尾 1 个月作为测试集以验证策略在「训练时从未见过的时间段」上的有效性时间区间角色1990-01-01~2019-11-29训练集stockdata/train/2019-12-01~2019-12-31测试集stockdata/test/从源码看Downloader的构造参数date_start/date_end默认1990-01-01~2020-03-23决定了下载区间__main__中当前示例为两次调用分别落盘到stockdata/train与stockdata/test两个目录实际日期可按需修改——这与上面文档的划分方式一致都是「长历史训练 短窗口测试」。验证结果与结果分析单只股票文档给出的单股票实验配置与结果初始本金10000股票代码sh.600036招商银行训练集stockdata/train/sh.600036.招商银行.csv测试集stockdata/test/sh.600036.招商银行.csv模拟操作约20天最终盈利约400即 20 个交易日内约 4% 的测试期收益初始本金 10000、盈利约 400由test_a_stock_trade()main.py将逐日利润序列绘制为折线图保存为img/{code}.png。多只股票1002 只对 1002 只股票批量训练并跑测试集后按每股最后一天盈亏分类的统计结果为盈利44.5%不亏不赚46.5%亏损9.0%对应的盈亏分布饼图与直方图即文首引用的 img/profits.pngProfit/Loss/0 三类占比饼图Profit 占比 44.5%与 img/profits_hist.png每股最终利润的密度直方图150 bin。从直方图形态可以推断盈利与亏损的个股在最终利润量级上大体对称说明该奖励设计下策略学到的是「总体正期望」而非「大赚小亏」的极端分布。边界、局限与适用说明教程文档在结尾给出了明确声明复现时应一并理解Just For Fun数据和方法均来自公开资料作者自述「完全是股票没入门的新手难免存在错误」无法保证策略在真实市场中的有效性本文结果均为历史数据上的模拟环境是简化的成交价在开收盘价间随机取值、不含手续费/印花税/涨跌停约束、单步奖励被离散化为 1/-100丢失了利润幅值信息、step中循环复用训练数据done仅在净资产归零时触发——这些假设决定了该环境适合作为 RL 入门实验而非实盘决策依据股票 Gym 环境的参考来源主要参考了 Stock-Trading-Environment 项目本文实现对其观测状态、奖励函数和训练集划分做了修改工程依赖年代实验栈锁定 Python 3.6 TF 1.14 stable-baselines 2.10复现需按 requirements.txt 原样搭建环境main.py中find_file依赖stockdata/train与stockdata/test目录已就位由get_stock_data.py生成。目录结构与参考资料本教程的完整文件布局均为仓库相对路径文件作用rlenv/StockTradingEnv0.pyOpenAI Gym 股票交易环境观测/动作/奖励main.py单股票 PPO2 训练入口、测试回测、盈亏统计绘图tasks.pyCelery Redis 多股票并行训练任务get_stock_data.pybaostock 全市场日 K 线下载器train/test 两目录requirements.txt完整依赖锁定stable-baselines 2.10、TF 1.14、gym 0.17.1 等font/wqy-microhei.ttc图表中文绘图字体参考资料来自教程文档Y. Deng, F. Bao, Y. Kong, Z. Ren and Q. Dai, Deep Direct Reinforcement Learning for Financial Signal Representation and Trading, IEEE Transactions on Neural Networks and Learning Systems, vol. 28, no. 3, pp. 653-664, March 2017.Yuqin Dai, Chris Wang, Iris Wang, Yilun Xu, Reinforcement Learning for FX tradingStanford MSAND 448 课程报告。Chien Yi Huang. Financial trading as a game: A deep reinforcement learning approach. arXiv preprint arXiv:1807.02787, 2018.PPO 算法论文与 stable-baselines 库文档PPO2 模块。Stock-Trading-Environmentnotadamking 的自定义股票 Gym 环境项目。【免费下载链接】Qbot[updating ...] AI 自动量化交易机器人(完全本地部署) AI-powered Quantitative Investment Research Platform. online docs: https://ufund-me.github.io/Qbot ✨ :news: qbot-mini: https://github.com/Charmve/iQuant项目地址: https://gitcode.com/GitHub_Trending/qbot/Qbot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表