TRADINGGYM · 强化学习交易环境

TradingGym 中文实验站:先看清哪个环境能跑,再谈回测结果

TradingGym 是受 OpenAI Gym 启发的强化学习交易环境工具包(tick 数据、双向持仓、自带账本)。它在 GitHub 上有 1919 star、MIT 许可,但 master HEAD 停在 2023-08-12,且 README 里的回测示例在当前 pandas 上跑不通。本站把 4 个环境逐个实测、把参数的真实语义摊开、把回测账本的口径对账,让你在花时间之前先知道会发生什么。

  • 实测环境:Python 3.11.9 + pandas 2.2.3 + numpy 2.4.6 + matplotlib 3.11.1(Windows)
  • 实测结论:4 个环境里 1 个能直接跑(training_v1),3 个在 reset() 就报错
  • 实测数字:5 个交易日、随机策略、max_position=1 下的账本与基准对照全部落盘可复跑

TradingGym 项目来源是什么?

1919 Star · 372 Fork · MIT · 47 次提交

Yvictor/TradingGym GitHub 仓库页面截图:仓库名、About 简介、顶层目录结构与 Star/Fork 数 查看源码 ↗
GitHub 公开仓库页面截图(2026-09-22 采集,1600×1100)。可读项包括仓库名与 Public 标记、About 简介原文、MIT 许可标签、顶层目录(dataset/、fig/、trading_env/、.travis.yml、setup.py)与 Star/Fork 数。仓库 master HEAD 提交为 08bb534(2023-08-12)、共 47 次提交,Star/Fork 数字会随社区变化。

TradingGym · 实测速览

TradingGym 现在能用吗?四个环境的实测结果先摆出来

下面每一项都是本机跑出来的,不是转述 README。环境版本、命令与产物都记在研究报告里,你可以自己复跑。

4 个环境

training_v0training_v1backtest_v0backtest_v1。两代实现并存,接口与账本形态都不一样,选错环境会让结果不可比。

1 个能直接跑

只有 training_v1 在当前 pandas 上 reset() 通过;它用的是 to_numpy(),是唯一被更新过的一支。

3 个在 reset() 报错

其余三个仍在调用 pandas 1.0 就已移除的 Series.as_matrix(),报 AttributeError。加两行兼容补丁即可继续。

0 个现成算法

README 里 simple dqn / policy gradient / actor-critic / A3C 全部标注 WIP,仓库内没有对应实现文件。算法要你自己带。

实测速览:本机一次性跑出来的结论(2026-09-22,Python 3.11.9 / pandas 2.2.3)
实测项结果怎么得到的对你的影响
环境注册清单4 个(v0/v1 各两支)调用 available_envs()文档里讲的「环境」其实有四个,别默认只有训练和回测各一个
training_v1.reset()通过,观测形状 (64,16)直接实例化并 reset想先摸接口,从这一支开始最快
其余三支 reset()失败:as_matrix 不存在同上,逐支跑照 README 搜到的老教程会卡在第一步
README 回测示例失败:没有 backtest() 方法按 README 原样调用回测得自己写日间循环,见「回测循环」页
官方 CI 命令-m trading_env/test 失败、-m trading_env.test 通过两条命令各跑一次.travis.yml 抄命令会报模块找不到
PyPI 包trading_env 等四个名字全部 404查询 PyPI JSON API没有 pip install 这条路,只能源码安装

证据:本机实测脚本与原始输出保存在研究报告 _verify\ 目录(as_is_result.txtrun_result.jsonpypi_check.txt)。TradingGym 与 EasyClaw 无已证实集成。

Tick / OHLC 数据你提供 DataFrame,四道列断言校验
training_v0 / v1 环境观测窗口 + 双向持仓
你的 Agent本项目不含算法(README 四项均 WIP)
env.info 账本逐 tick 持仓/成本/盈亏

依据 TradingGym 源码与本机实测绘制的链路示意(非官方流程图):数据 → 环境 → 自备 Agent → 账本。四段里只有中间两段是本项目提供的,算法与数据都在你这边。

TradingGym · 能力边界

TradingGym 能做什么、不能做什么:把边界说在前面

这类项目的坑不在「功能不够」,而在被当成别的东西:它不是数据源,不是策略库,也不是实盘通道。下面两栏按源码事实分开写。

它能做

  • 把一份带 serial_number 的 tick/OHLC 表切成交易日,做成 step / reward 风格的环境make(env_id=...))。
  • obs_data_len + step_len 控制观测窗口,双向持仓(max_position)与做空都支持。
  • 跑完整回测并给出逐 tick 账本env.info 里有 position、price_mean、reward、reward_fluctuant 等列。
  • 规则策略同样能用:只要实现一个 choice_action(state),不写 RL 也能做回测。

它不能做

  • 不带算法:仓库内没有 PPO/DQN 实现,README 里四个算法都是 WIP,训练要自己接。
  • 不带数据:没有行情下载接口;样例只是一份 SGX TW 的 tick 文件。
  • 不能实盘:README 说的实时交易与 Interactive Brokers 是「未来计划」,当前代码里没有。
  • 不是 gym.Env 子类:全仓库没有 import gym,接 Gymnasium / Stable-Baselines3 要自己写适配层。
把「能做什么」落成可核验的对照(源码为准)
你想要的现状源码/实测依据适用场景注意点
装好就能跑需先打 2 行兼容补丁3/4 环境 as_matrix 报错(实测)想重复老教程的流程补丁只解决取数,不改动项目行为
直接接 SB3 训练不行,需自写适配层类不是 gym.Env、空间声明与实际形状不一致做 RL 实验适配层要处理四元组→五元组
按天回测并取净值可以,但要自己重建净值env.info['reward'] 与增量盈亏一致(实测 -0.5 对 -0.5)规则策略验证不要用 reward_fluctuant 累加(同一天 +28.1)
控制成本可以,但 fee 语义特殊平仓按笔扣一次;另一列按每个持仓 tick 扣一次观察成本对策略的影响它不是你熟悉的「费率」,单位由使用者定义
换品种/换市场只要列齐就能用make() 有四个列断言A 股日线等自有数据索引必须是 0..N 整数,否则切片会错位
商用MIT 许可允许LICENSE + GitHub API spdx_id=MIT二次开发项目停止在 2023-08-12,需自行维护分支

TradingGym · 双代环境

TradingGym training_v0 与 training_v1、backtest_v0 与 backtest_v1 到底差在哪是什么?

这不是「新旧版本」,而是两套接口同时存在于同一个包:v0 系用扁平观测与单步 reward,v1 系用二维观测加窗口 reward。选错会让你的训练结果与别人不可比。

四个环境横向对照(源码逐行核对,本机实测标记)
环境取数实现观测形态step 返回的 reward日间推进本机实测
training_v0as_matrix()仅特征列(持仓特征被注释掉)单步 reward(reward_fluctuant/fluc_div随机抽日,另有 backtest() 方法reset() 失败
training_v1to_numpy()特征列 + 8 列持仓/成本/盈亏观测窗口内 reward 之和随机抽日,无 seed 参数reset() 通过
backtest_v0as_matrix()仅特征列单步 reward,含 gameover 提前终止随机抽日reset() 失败
backtest_v1as_matrix()特征列 + 8 列(return_transaction=True观测窗口内 reward 之和reset() 逐个交易日推进reset() 失败(打补丁后可跑)
四条实测结论里,最反直觉的是 backtest_v1:它名字带 v1,但取数代码仍是 v0 的写法(backtest_v1.py:91),所以在当前 pandas 上一样崩。想跑回测就得打补丁——这在任何中文教程里都还没人写过。

TradingGym · 快速开始

TradingGym 怎么 5 分钟跑通第一个交易环境?从 clone 到拿到观测

下面三步在本机实测通过(Python 3.11.9 + pandas 2.2.3)。第 0 步的两行补丁是为了让老代码在当前 pandas 上取数,不改变项目逻辑。

第 1 步 · 拿到源码并安装

git clone https://github.com/Yvictor/TradingGym.git
cd TradingGym
python setup.py install

官方只提供源码安装(PyPI 上没有 trading_env 这个包,实测 404)。装完 import trading_env 就应成功。

预期输出:无报错;trading_env.available_envs() 返回 ['training_v0','training_v1','backtest_v0','backtest_v1']

第 2 步 · 读样例数据建环境

import pandas as pd, trading_env
if not hasattr(pd.Series, "as_matrix"):      # 兼容补丁:pandas 1.0 起移除了 as_matrix
    pd.Series.as_matrix = lambda self: self.to_numpy()
    pd.DataFrame.as_matrix = lambda self: self.to_numpy()

df = pd.read_csv('trading_env/test/data/SGXTWsample.csv', index_col=0, parse_dates=['datetime'])
env = trading_env.make(env_id='training_v1', obs_data_len=256, step_len=128, df=df,
                       fee=0.1, max_position=5, deal_col_name='Price',
                       feature_names=['Price','Volume','Ask_price','Bid_price',
                                      'Ask_deal_vol','Bid_deal_vol','Bid/Ask_deal','Updown'])
obs = env.reset()

make() 会依次断言 env_id 合法、deal_col_name 在列、serial_number 必须在列、每个特征列存在(__init__.py:13-17)。

预期输出:obs.shape == (256, 16)——8 个特征列 + 8 列持仓/成本/盈亏。

第 3 步 · 走一步并看账本

obs, reward, done, info = env.step(1)     # 0=不动 1=做多 2=做空
print(reward, done, env.obs_price[:3])
print(env.obs_posi[:3])                    # 观测里的持仓列

step() 观测窗口前进 step_len 根 tick,撮合价取窗口之后的第一根 tick(backtest_v1.py:242);窗口走完一天即 done=True

预期输出:reward 为该观测窗口内 reward 数组之和(不是单步收益),done 在当日 tick 用尽时为 True。

以上代码全部照抄即可运行;training_v0backtest_v0backtest_v1 需要同一份补丁,否则会报 AttributeError: 'Series' object has no attribute 'as_matrix'(本站实测原文)。

TradingGym · 已验证实验

TradingGym 本站跑过哪些实验?5 个交易日、随机策略与基准的真实数字

实验口径统一为 backtest_v1 + obs_data_len=64 + step_len=32 + max_position=1,跑样例数据的前 5 个交易日。这样随机策略与「一直持有」才可比。

账本口径下的 5 日合计(单位:价格点;样例品种 SGX TW,价格量级约 277 点)
策略fee交易笔数账本收益(env.info['reward']Buy&Hold 对照怎么读这个数
do nothing(不动)000.000+1.100零成本基准,用来确认账本在无持仓时确实是 0
always long(一直持有)010+1.000+1.100与 Buy&Hold 差 0.1,差额来自进出场时点与撮合价位置
随机策略 seed 00802-9.300+1.100随机开平仓在这段数据上是亏的,说明样本本身没有「随便做都赚」
随机策略 seed 10830+3.800+1.100换种子由亏转盈——这正是「单次回测不可信」的直接证据
随机策略 seed 20812+1.700+1.100三个种子跨度 13 点,方差远大于策略差异
随机策略 seed 0(fee=0.1)0.1802-49.400+1.100同策略同数据,仅把 fee 从 0 改到 0.1,多出 -40.1(=0.1×401 笔平仓)

数字都能复跑

脚本 _verify\run_verify.py 与原始输出 run_result.json 已落盘;换机器只要版本一致就能复现同一组数字。

别只看收益率

同一策略在三个随机种子下从 -9.3 到 +3.8 点。只看一个种子的正收益,等于把噪声当策略。

成本口径要自己确认

fee 在源码里出现两次、含义不同:平仓按笔扣、另一列按每个持仓 tick 扣。用错一列,量级差几十倍。

TradingGym · SETUP AND ROUTE

TradingGym 有哪三条路线?官方源码跑、打完补丁跑、或者干脆不搭 Python 环境

TradingGym 是「环境 + 自备 Agent」的形态,用它的前提是你能接受 Python 环境与自写训练代码。如果你的真实目标只是取数、看指标或出图,那不必绕这一圈。

路线对照(前置条件与产物逐条写明)
路线前置条件你能得到适合谁不适合谁
官方源码安装(不推荐直接用)Python 环境、git;接受 3/4 环境报错可读的源码与 training_v1 基础接口只想读代码、做二次开发想立刻跑回测的人
源码 + 2 行兼容补丁(本站实测路径)同上,另加两行 patch四个环境都能实例化,可跑逐日回测与账本复现实验、做 RL 环境研究期望开箱即用、免维护的人
本机技能路线(不做同类替代)装 EasyClaw;部分技能需 Token/API Key一句话取数、算区间指标、出图、规则策略回测目标只是数据与指标,不做 RL 环境要做 Gym 风格环境与 step/reward 实验的人
必须说清楚的两件事:①TradingGym 与 EasyClaw 没有已证实集成,本机 29 个技能里也没有任何 RL 交易环境类技能;②本机技能解决的是「取数与指标」这类任务,不替代 TradingGym 的环境能力。

TradingGym · 免部署 demo

TradingGym 不搭 Python 环境时,同类任务在 EasyClaw 里长什么样

下面两张分别是 EasyClaw 处理「行情取数」与「规则策略回测」的对话示例。它们演示的是「一句话取数」与「一句话发起规则策略回测」,属于并列对比路线。

TradingGym · 选型

谁适合用 TradingGym,谁应该换条路是什么?

判断标准只有两条:你是否需要 Gym 风格的 step/reward 环境,以及你是否愿意自己写训练代码并维护一个 2023 年后没有更新的仓库。

适合:RL 环境研究者

要研究观测/动作/奖励设计本身,或要把 tick 数据做成可回放的实验环境。TradingGym 的结构简单、源码总量小(四个环境文件 + 一个包入口),改起来比大框架轻。

适合:带自研 Agent 的开发者

你已经有自己的模型或规则策略,只需要一个「能 step、能给账本」的执行壳。规则策略也能用:实现 choice_action(state) 即可,不写 RL 也能回测。

不适合:想开箱即用的人

没有数据下载、没有算法实现、没有实盘通道,还要先打兼容补丁。想要「一句话取数 + 指标 + 出图」,去看对比页的技能路线更省时间。

按目标选路(不要按项目热度选)
你的目标建议理由注意点
复现一篇 RL 交易论文的环境用 TradingGym + 补丁,并从 backtest_v1 入手它的 step/reward 与逐 tick 账本正好是这个用途观测里已含持仓信息,论文里若假设纯行情观测需自行裁剪
验证一条规则策略(如双均线)用 TradingGym 的 backtest_v1,或直接用 EasyClaw 的规则回测技能两条路都能出对照结果,后者不用搭环境两者账本口径不同,不要跨口径比较收益
只是想看行情与指标不必用 TradingGym它不提供数据下载能力数据技能需自备 Token 或按文档安装依赖
想做实盘本项目不适用实时交易与 IB 接入只是 README 的将来计划不要基于本项目做任何实盘改造预期
研究观测/奖励设计(如奖励塑形)用 TradingGym,从 training_v1它是唯一在当前 pandas 上可直接跑的 v1 环境改 reward 后要重建净值,见「奖励与基准」页
需要长期维护的生产环境谨慎:把本项目当参考实现HEAD 停在 2023-08-12,CI 仍指向已停服的 Travis自行 fork 维护,并补齐测试

TradingGym · FAQ

TradingGym 常见问题:免费吗、能实盘吗、要不要装 gym

TradingGym 免费吗?可以商用吗?

免费。仓库 LICENSE 为 MIT(GitHub API 的 license.spdx_id 也是 MIT),可商用与二次开发。但注意两点:项目 master HEAD 停在 2023-08-12,仓库既有 issue 与 CI 都是停服年代的产物,商用意味着你要自己维护分支;另外数据与依赖(pandas/numpy/matplotlib/colour)各有自己的许可,以各自官方为准。

TradingGym 能实盘交易吗?

当前不能。README 写的是「未来会实现带 Interactive Brokers API 的实时交易环境」,属于计划而非现状;仓库内没有任何下单、行情连接或风控代码。本站不对接实盘做任何承诺,以官方代码为准。

必须安装 gym 或 Gymnasium 吗?

不需要。全仓库没有 import gym,它只是「模仿 Gym 风格」:类里有 reset()step()render() 以及 action_spaceobservation_space 属性。反过来说,你想用 Stable-Baselines3 之类的库,必须自己写一层 gym.Env 适配——本站给了可复制的适配层写法。

为什么我照 README 跑回测会报错?

有两个独立原因。一是 README 用 env_id='backtest_v1' 却调用 env.backtest(),而 backtest() 方法只存在于 training_v0.py,本机实测报 AttributeError: 'trading_env' object has no attribute 'backtest';二是 backtest_v1 仍在用已移除的 as_matrix()。正确做法见「回测循环」页,并以官方源码为准。

它支持 A 股数据吗?

机制上支持——只要你的 DataFrame 满足四个断言(env_id 合法、deal_col_name 在列、有 serial_number 列、特征列齐全),并把索引整理成 0..N 的整数。但官方没有提供任何 A 股数据源或复权处理,serial_number(按交易日重置的连续编号)需要你自己生成;T+1、涨跌停、停复牌这些规则它完全不管,要自己在外层约束。以官方实现为准。

回测出的正收益能信吗?

单次结果不能。本站实测同一随机策略换三个随机种子,5 天结果从 -9.3 到 +3.8 点,跨度 13 点;同时段 Buy&Hold 只有 1.1 点。要看的是「多随机种子 + 基准对照 + 净值重建」三件套,而不是一个收益率数字。全部数字可在研究报告里复跑。

下一步该怎么做?先确认你的环境能不能跑

四个环境的实测结果、报错原文与最小兼容补丁都在这页;看完再去动参数,能省掉大半排错时间。