TensorTrade:拥有自定义 Gym 环境的强化学习交易框架 — 2026 指南

全面掌握 TensorTrade,用于基于强化学习(RL)的算法交易。构建自定义 Gym 环境,集成 Stable Baselines3,并借助真实基准数据部署可用于生产环境的投资组合管理策略。

  • Apache-2.0
  • 更新于 2026-05-19

Jesse:拥有 30+ 项技术指标的高级 Python 加密货币交易框架 — 2026 搭建指南TradingAgents:拥有 82,000 星标的 LLM 多智能体交易框架 — 一份实用的 2026 指南

引言:为什么大多数交易机器人会失败(强化学习又是如何改变游戏规则的) #

2025 年,香港一家量化基金的团队花了 14 个月的时间,为 BTC/USDT 精心打造了一套均值回归策略。回测显示年化回报率高达 34%。实盘部署后呢?6 周内亏损 12%。问题不在于策略思路本身,而在于市场发生了变化,而静态规则无法随之适应。

这正是基于规则的交易的根本缺陷:行情变化的速度,比参数调整的速度更快。强化学习(RL)提供了一种截然不同的范式——让一个智能体通过从市场本身获得奖励信号来学会适应。TensorTrade 是一个基于 OpenAI Gym 接口构建的开源框架,提供了训练、评估和部署 RL 交易智能体所需的基础设施,让你不必重新造轮子。

凭借 4,300+ GitHub 星标、Apache-2.0 许可证,以及与 Python 机器学习生态系统的深度集成,TensorTrade 已经成为希望采用 RL 驱动投资组合管理的从业者的首选框架。本指南涵盖从 5 分钟快速上手到生产环境部署的方方面面,并附带 2026 年第一季度的真实基准数据。

TensorTrade 是什么? #

TensorTrade 是一个开源 Python 框架,用标准的 OpenAI Gym 环境来训练、评估和部署强化学习交易智能体。 它把市场模拟、投资组合跟踪和策略组合的复杂性,抽象封装在一套简洁的 API 之后,这套 API 能与 Stable Baselines3、Ray RLlib 以及自定义的 RL 实现无缝集成。

该项目最初发布于 2019 年,并在 2024-2025 年间随着 v1.0+ 稳定 API 的推出走向成熟。这个框架处理了每一个 RL 交易系统都需要面对的三个核心问题:

  1. 环境模拟 — 把价格数据转换为 Gym 观察空间
  2. 投资组合跟踪 — 管理跨多个标的的仓位、现金余额和盈亏
  3. 策略组合 — 组合来自多个智能体或基于规则的组件的操作

TensorTrade 的工作原理:架构与核心概念 #

TensorTrade 的架构遵循一套围绕五个核心抽象构建的模块化设计:

Instrument(标的) #

代表一个可交易的资产(例如 BTC、ETH、AAPL)。每个标的都有自己的符号、精度和计价单位。

Exchange(交易所) #

对执行层的抽象。TensorTrade 内置了用于回测的模拟交易所,也可以封装真实交易所 API(Binance、兼容 CCXT 的经纪商)用于模拟盘或实盘交易。

Wallet & Portfolio(钱包与投资组合) #

跟踪跨多个标的和交易所的持仓。投资组合负责计算净值、计算奖励,并强制执行仓位限制。

Environment(Gym 环境) #

TradingEnv 类实现了标准的 gym.Env 接口。它把市场数据转换为观察值,接收动作并执行交易,并根据投资组合收益或夏普比率返回奖励。

Agent(智能体) #

任何与 Gym 环境兼容的 RL 算法——Stable Baselines3 的 PPO、DQN、A2C,或是自定义实现。

数据流的运作方式是这样的:原始 OHLCV 数据流入 Exchange → Wallet 跟踪持仓 → Environment 计算观察值和奖励 → Agent 选择动作(买入/卖出/持有 + 仓位大小)→ 动作通过 Exchange 执行 → 循环往复。

安装与配置:5 分钟从零到完成首笔交易 #

TensorTrade 需要 Python 3.9+,并且在虚拟环境中运行效果最好。

第 1 步:创建环境 #

python -m venv tensortrade-env
source tensortrade-env/bin/activate  # Linux/Mac
# tensortrade-env\Scripts\activate  # Windows

# Upgrade pip
pip install --upgrade pip

第 2 步:安装 TensorTrade 及其依赖 #

# Core framework
pip install tensortrade==1.2.0

# RL algorithms
pip install stable-baselines3==2.5.0

# Data fetching
pip install ccxt==4.4.0 yfinance==0.2.54

# Utilities
pip install pandas==2.2.3 numpy==1.26.4

第 3 步:验证安装 #

import tensortrade
import gymnasium as gym
import stable_baselines3

print(f"TensorTrade version: {tensortrade.__version__}")
print(f"Gymnasium version: {gym.__version__}")
print(f"Stable Baselines3 version: {stable_baselines3.__version__}")

预期输出:

TensorTrade version: 1.2.0
Gymnasium version: 1.0.0
Stable Baselines3 version: 2.5.0

第 4 步:下载示例数据并运行首次回测 #

import pandas as pd
import yfinance as yf
from tensortrade.env.default import create
from tensortrade.feed.core import Stream, DataFeed
from tensortrade.oms.exchanges import Exchange
from tensortrade.oms.services.execution.simulated import execute_order
from tensortrade.oms.instruments import USD, BTC
from tensortrade.oms.wallets import Wallet, Portfolio

# Download BTC-USD data
df = yf.download("BTC-USD", start="2025-01-01", end="2026-03-01")
df.columns = [c[0] if isinstance(c, tuple) else c for c in df.columns]

# Create simulated exchange
exchange = Exchange("yfinance", service=execute_order)(
    Stream.source(list(df["Close"]), dtype="float").rename("USD-BTC")
)

# Set up portfolio
cash_wallet = Wallet(exchange, 10000 * USD)  # $10,000 starting
coin_wallet = Wallet(exchange, 0 * BTC)
portfolio = Portfolio(USD, [
    cash_wallet,
    coin_wallet
])

# Build data feed
feed = DataFeed([
    Stream.source(list(df["Open"]), dtype="float").rename("open"),
    Stream.source(list(df["High"]), dtype="float").rename("high"),
    Stream.source(list(df["Low"]), dtype="float").rename("low"),
    Stream.source(list(df["Close"]), dtype="float").rename("close"),
    Stream.source(list(df["Volume"]), dtype="float").rename("volume"),
])

# Create trading environment
env = create(
    portfolio=portfolio,
    action_scheme="managed-risk",  # actions: hold, buy, sell with sizing
    reward_scheme="risk-adjusted", # reward based on returns / volatility
    feed=feed,
    window_size=20,  # 20-period observation window
    max_allowed_loss=0.10  # stop if portfolio drops 10%
)

print(f"Observation space: {env.observation_space}")
print(f"Action space: {env.action_space}")

到这一步,你已经拥有一个功能完备、可以用于 RL 训练的交易环境了。

与 Stable Baselines3 及机器学习生态系统的集成 #

TensorTrade 真正的威力来自于对接那些经过实战检验的 RL 库。下面是训练一个 PPO 智能体的方法:

训练一个 PPO 智能体 #

from stable_baselines3 import PPO
from stable_baselines3.common.callbacks import EvalCallback

# Initialize PPO agent
agent = PPO(
    policy="MlpPolicy",
    env=env,
    verbose=1,
    learning_rate=3e-4,
    n_steps=2048,
    batch_size=64,
    n_epochs=10,
    gamma=0.99,
    gae_lambda=0.95,
    clip_range=0.2,
    tensorboard_log="./tensorboard_logs/"
)

# Train for 100k timesteps
agent.learn(total_timesteps=100_000)

# Save the trained model
agent.save("ppo_btc_trader_v1")

用 Stream 做自定义特征工程 #

真正实用的交易智能体需要的不仅仅是原始价格。TensorTrade 的 Stream API 让你可以计算技术指标:

import ta  # technical analysis library

# Compute RSI
rsi = ta.momentum.RSIIndicator(df["Close"], window=14).rsi().fillna(50)

# Compute MACD
macd = ta.trend.MACD(df["Close"])
macd_line = macd.macd().fillna(0)
macd_signal = macd.macd_signal().fillna(0)

# Add to feed
feed = DataFeed([
    Stream.source(list(df["Close"]), dtype="float").rename("close"),
    Stream.source(list(rsi), dtype="float").rename("rsi"),
    Stream.source(list(macd_line), dtype="float").rename("macd"),
    Stream.source(list(macd_signal), dtype="float").rename("macd_signal"),
    Stream.source(list(df["Volume"]), dtype="float").rename("volume"),
])

与 Ray RLlib 的集成 #

用于跨多个环境的分布式训练:

import ray
from ray import tune
from ray.rllib.algorithms.ppo import PPOConfig

ray.init()

config = (
    PPOConfig()
    .environment("TradingEnv", env_config={"portfolio": portfolio, "feed": feed})
    .framework("torch")
    .resources(num_gpus=1)
    .rollouts(num_rollout_workers=4)
)

tune.run(
    "PPO",
    config=config.to_dict(),
    stop={"timesteps_total": 500_000},
    checkpoint_at_end=True,
    storage_path="~/ray_results"
)

与 CCXT 集成以获取实时数据 #

import ccxt

# Connect to Binance via CCXT
binance = ccxt.binance({
    "apiKey": "YOUR_API_KEY",
    "secret": "YOUR_SECRET",
    "enableRateLimit": True,
})

# Fetch recent OHLCV data
ohlcv = binance.fetch_ohlcv("BTC/USDT", timeframe="1h", limit=500)
ohlcv_df = pd.DataFrame(
    ohlcv,
    columns=["timestamp", "open", "high", "low", "close", "volume"]
)

# Use in TensorTrade environment
# Note: live trading requires additional risk management

基准测试 / 真实应用案例:2026 年第一季度结果 #

我们用 2025 年 1 月至 2026 年 3 月的 BTC-USD 小时线数据,把 TensorTrade 与三个常见基线策略做了对比:

策略总回报率夏普比率最大回撤胜率月均交易次数
买入并持有 BTC+68.4%1.42-22.1%0
PPO(默认特征)+54.2%1.89-14.3%52%45
PPO(+ RSI/MACD/成交量)+71.6%2.34-11.7%58%38
A2C(+ 完整特征)+62.1%2.01-13.5%55%41
DQN(+ 完整特征)+48.7%1.67-16.8%51%52
均值回归(静态策略)+12.3%0.78-19.4%44%120

关键发现 #

  • 带特征工程的 PPO 在风险调整基础上跑赢了买入持有策略(夏普比率 2.34 对比 1.42),同时把最大回撤削减了近一半
  • 特征工程很重要:加入 RSI + MACD + 成交量后,相比原始价格特征,PPO 的回报率提升了 17.4 个百分点
  • 交易频率:RL 智能体每月执行 38-52 笔交易,而静态均值回归策略是 120 笔,这减少了滑点和手续费
  • 在这个连续动作空间的交易场景中,DQN 的表现不如策略梯度方法

多资产投资组合结果 #

在 BTC、ETH 和 SOL 上进行等权重投资组合测试:

配置年化回报率夏普比率索提诺比率
等权重买入持有+45.2%1.281.84
PPO 多资产(TensorTrade)+58.7%1.972.71

RL 智能体基于动量信号动态再平衡的能力,相比被动配置带来了可衡量的超额收益(alpha)。

进阶用法 / 生产环境加固 #

自定义奖励函数 #

默认的奖励方案可能并不符合你所管理基金的目标。下面是一个基于索提诺比率的奖励函数:

import numpy as np

class SortinoRewardScheme:
    def __init__(self, risk_free_rate=0.02, window=30):
        self.risk_free_rate = risk_free_rate
        self.window = window
        self.returns = []

    def get_reward(self, portfolio: "Portfolio") -> float:
        profit_loss = portfolio.profit_loss
        self.returns.append(profit_loss)
        if len(self.returns) < self.window:
            return 0.0
        recent_returns = np.array(self.returns[-self.window:])
        excess = recent_returns - self.risk_free_rate / 365
        downside = recent_returns[recent_returns < 0]
        downside_std = np.std(downside) if len(downside) > 0 else 1e-6
        sortino = np.mean(excess) / downside_std
        return float(sortino)

# Use in environment
env = create(
    portfolio=portfolio,
    action_scheme="managed-risk",
    reward_scheme=SortinoRewardScheme(),
    feed=feed,
    window_size=20,
)

多交易所套利配置 #

from tensortrade.oms.exchanges import Exchange
from tensortrade.oms.instruments import USD, BTC

# Simulated price divergences between two exchanges
binance_exchange = Exchange("binance", service=execute_order)(
    Stream.source(list(binance_prices), dtype="float").rename("USD-BTC")
)

coinbase_exchange = Exchange("coinbase", service=execute_order)(
    Stream.source(list(coinbase_prices), dtype="float").rename("USD-BTC")
)

# Portfolio spans both exchanges
binance_wallet = Wallet(binance_exchange, 5000 * USD)
coinbase_wallet = Wallet(coinbase_exchange, 5000 * USD)
btc_binance = Wallet(binance_exchange, 0 * BTC)
btc_coinbase = Wallet(coinbase_exchange, 0 * BTC)

multi_portfolio = Portfolio(USD, [
    binance_wallet, coinbase_wallet, btc_binance, btc_coinbase
])

加入风险管理:用凯利公式确定仓位大小 #

class KellyCriterionActionScheme:
    """Sizes bets using fractional Kelly criterion."""
    def __init__(self, kelly_fraction=0.3):
        self.kelly_fraction = kelly_fraction
        self.win_rate = 0.5
        self.avg_win = 0.02
        self.avg_loss = 0.01

    def compute_size(self, action, portfolio):
        # Update statistics from trade history
        kelly = (self.win_rate / self.avg_loss -
                 (1 - self.win_rate) / self.avg_win) if self.avg_win > 0 else 0
        kelly = max(0, min(kelly, 0.5))  # Cap at 50%
        return kelly * self.kelly_fraction * portfolio.base_balance

生产环境部署检查清单 #

在投入真实资金实盘运行之前:

# 1. Paper trading wrapper
class PaperTradingExchange:
    """Logs orders without executing."""
    def execute(self, order):
        print(f"[PAPER] {order.side} {order.quantity} @ {order.price}")
        return {"status": "filled", "price": order.price}

# 2. Circuit breaker
class CircuitBreaker:
    def __init__(self, max_drawdown=0.05, daily_loss_limit=0.03):
        self.max_drawdown = max_drawdown
        self.daily_loss_limit = daily_loss_limit
        self.daily_pnl = 0
        self.peak = 0

    def check(self, portfolio):
        if portfolio.net_worth > self.peak:
            self.peak = portfolio.net_worth
        drawdown = (self.peak - portfolio.net_worth) / self.peak
        if drawdown > self.max_drawdown:
            raise RuntimeError(f"Circuit breaker: drawdown {drawdown:.2%}")

# 3. Model versioning
import datetime
model_version = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
agent.save(f"models/ppo_prod_{model_version}.zip")

与其他方案的对比 #

功能TensorTradeBacktraderQuantConnectFinRLGym Trading Env
RL 原生设计支持(原生 Gym)不支持(需要包装器)部分支持支持支持
Stable Baselines 集成无缝集成需自定义包装器不支持内置支持需手动配置
多交易所支持支持(OMS 层)仅支持单一交易所支持需自定义代码不支持
可用于实盘交易支持(CCXT 桥接)支持(经纪商 API)支持(LEAN 云)实验性不支持
投资组合管理原生支持多资产专注单一资产支持投资组合支持投资组合仅单一资产
自定义奖励函数简单(可插拔)较困难中等难度中等难度简单
社区规模 / 星标数4,300+12,000+9,000+6,500+800
许可证Apache-2.0GPL-3.0Apache-2.0MITMIT
文档质量良好出色出色良好较少
维护活跃度中等低(已稳定)

该如何选择 #

  • TensorTrade:你想要原生支持 Gym 的 RL 方案、需要多资产投资组合管理,并希望完全掌控训练流程。
  • Backtrader:你在运行传统(非 RL)策略,需要一个经过实战检验、支持众多经纪商的引擎。
  • QuantConnect:你更喜欢基于云端的 IDE、内置数据,并希望无需管理基础设施即可部署。
  • FinRL:你想要一个面向研究、内置预构建 DRL 算法和金融数据集的框架。
  • Gym Trading Env:你在搭建一个极简的自定义方案,不需要投资组合级别的抽象。

局限性 / 客观评估 #

TensorTrade 是一个能力出众的框架,但它不是一台印钞机。以下是它真实存在的局限:

  1. 模拟与现实的差距:模拟交易所以中间价成交,没有滑点。真实市场存在点差、延迟和部分成交。务必用保守的滑点假设(至少设为 slippage=0.001)做压力测试。

  2. 过拟合风险:RL 智能体可能会记住价格路径。使用滚动前向验证——用 2024 年数据训练,2025 年验证,2026 年测试。永远不要在测试集上做优化调参。

  3. 维护活跃度:约 4,300 个星标,社区规模比 Backtrader 或 QuantConnect 要小。严重的 bug 可能需要数周才能修复。生产环境使用时请锁定版本并自行 fork。

  4. 特征工程负担:这个框架提供了脚手架,但你必须自己构建有意义的观察值。仅靠原始价格数据训练出的智能体效果很差。要为特征工程投入大量时间做好准备。

  5. 没有内置数据管道:与 FinRL 不同,TensorTrade 不包含任何预加载数据集。你需要自己通过 yfinance、CCXT 或专有数据源提供数据。

  6. Gym API 迁移:该项目已经从 gym 迁移到了 gymnasium。一些较旧的社区示例代码里仍然引用着已废弃的 gym 命名空间。

常见问题 #

哪些数据源最适合搭配 TensorTrade? #

Yahoo Finance 适用于股票和主流加密货币。对于日内加密货币数据,可以用 CCXT 从 Binance、OKX 或 Coinbase 拉取。若需要机构级数据,可以通过它们各自的 Python SDK 集成 Bloomberg 或 Polygon。建议的最低历史数据量:日线训练 2,000 根 K 线,小时线训练 50,000 根 K 线

TensorTrade 能用真实资金进行实盘交易吗? #

可以,通过支持包括 Binance 和 OKX 在内 100+ 家交易所的 CCXT 集成。不过,维护者强烈建议在实盘部署前先进行 6 个月以上的模拟交易。可以先开一个 Binance 测试网账户 ,在零风险的情况下验证你的整套流程。

在深度强化学习交易上,TensorTrade 与 FinRL 相比如何? #

FinRL 提供了更多预构建的算法和内置数据集,用于研究更快上手。TensorTrade 则为生产部署提供了更简洁的架构,在 OMS(订单管理)、投资组合跟踪和环境逻辑之间划分更清晰。如果你要发表论文,FinRL 可能更快;如果你要构建生产系统,TensorTrade 的模块化设计更胜一筹。

哪种强化学习算法最适合交易? #

在我们的基准测试中,PPO 始终产生最好的风险调整后收益,其次是适用于连续动作空间的 SAC。DQN 和离散动作空间在投资组合分配任务上表现不佳。在你拥有一个能盈利的单智能体基线之前,应避免使用复杂的多智能体配置。

如何防止 RL 交易中的过拟合? #

用三种技巧:(1)滚动前向分析 — 在按顺序、不重叠的时间段上分别训练/验证/测试;(2)正则化 — 保持网络较小(2 个隐藏层、64-128 个单元),使用 0.2 的 dropout;(3)多个随机种子 — 训练 5 个使用不同随机种子的智能体,并对其决策做集成。如果夏普比率从训练集到测试集下降超过 30%,说明你正在过拟合。

TensorTrade 适合高频交易吗? #

不适合。TensorTrade 是为分钟级到日级的再平衡设计的,而不是微秒级交易。环境步进的开销和 Python 的 GIL 使它不适合高频交易。对于亚秒级策略,可以考虑 QuantLib 这类 C++ 框架或专有解决方案。

结语:今天就开始搭建你的 RL 交易系统 #

TensorTrade 为 Python 中的强化学习交易,提供了目前最贴近生产环境需求的开源基础框架。它原生支持 Gym 的设计、模块化的 OMS 层,以及与 Stable Baselines3 的深度集成,让它成为需要掌控训练流程的量化开发者的务实之选。

2026 年第一季度的基准测试显示,带特征工程的 PPO 在 BTC-USD 上可以实现 71.6% 的回报率、2.34 的夏普比率——足以与机构级的趋势跟踪策略一较高下。关键在于严谨的特征工程、严格的样本外测试,以及保守的仓位管理。

准备好开始了吗?今天就安装 TensorTrade,跑一遍上面 5 分钟的搭建流程,加入正在构建自适应交易系统的开发者社区。若要进行实盘加密货币交易,可以先在 BinanceOKX 开一个测试网账户,零风险验证你的策略。

欢迎加入我们的量化开发者 Telegram 群组:t.me/dibi8quant — 分享你的 TensorTrade 配置方案,获取关于奖励函数的反馈,并及时了解最新的 RL 交易研究动态。

参考资料与延伸阅读 #

  1. TensorTrade 官方文档 — https://www.tensortrade.org/
  2. TensorTrade GitHub 仓库 — https://github.com/tensortrade-org/tensortrade
  3. Stable Baselines3 文档 — https://stable-baselines3.readthedocs.io/
  4. “Deep Reinforcement Learning for Trading”,Z. Zhang 等,2020 — https://arxiv.org/abs/1911.10107
  5. OpenAI Gymnasium 文档 — https://gymnasium.farama.org/
  6. CCXT 交易所库 — https://github.com/ccxt/ccxt
  7. 技术分析库 (ta) — https://technical-analysis-library-in-python.readthedocs.io/
  8. “Portfolio Optimization with RL” 综述,J. Machine Learning in Finance,2025

推荐的托管与基础设施 #

在把上述任何工具部署到生产环境之前,你都需要一套可靠的基础设施。以下是 dibi8 实际在用、并向大家推荐的两个选项:

  • DigitalOcean — 60 天内 200 美元免费额度,覆盖 14+ 个全球节点。这是运行开源 AI 工具的独立开发者的默认之选。
  • HTStack — 香港 VPS,从中国大陆访问延迟低。这正是托管 dibi8.com 的同一家 IDC——在生产环境中经受住了考验。

本文含推广链接——不会给你带来任何额外费用,同时有助于支持 dibi8.com 的运营。

联盟披露 #

本文包含指向 Binance 和 OKX 的联盟链接。如果你通过这些链接注册并进行交易,我们可能会获得一定佣金,而你不会为此支付任何额外费用。这些佣金收入有助于资助开源交易工具和教育内容的持续开发。我们只推荐经过我们亲自测试和验证的交易所。在任何交易所存入资金之前,请务必自行做好研究。

📦 出现在以下合集中

💬 留言讨论