news 2026/9/29 3:12:18

TensorTrade 数据接入指南:用 tensortrade.data.cdd 的 CryptoDataDownload 拉取加密货币行情数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TensorTrade 数据接入指南:用 tensortrade.data.cdd 的 CryptoDataDownload 拉取加密货币行情数据
  • 人工智能
  • 金融科技
  • 机器学习

【免费下载链接】tensortrade

An open source reinforcement learning framework for training, evaluating, and deploying robust trading agents.

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

本篇技术指南围绕 TensorTrade 的tensortrade.data数据包及其核心子模块tensortrade.data.cdd展开,讲解如何通过CryptoDataDownload类从 CryptoDataDownload 免费数据源一键获取交易所历史行情(OHLCV),并将其清洗、对齐后无缝接入DataFeed、Exchange与强化学习训练环境。读完本文,你将掌握fetch/fetch_default/fetch_gemini三个方法的调用参数、返回数据的列结构与时间戳处理细节,并能在训练脚本与 Notebook 中复现完整的数据加载链路。

一、tensortrade.data 包:数据从何而来

在 TensorTrade 的模块体系中,tensortrade.data是负责外部数据采集的顶层包。它只有一个公开子模块tensortrade.data.cdd,该模块的定位非常明确:从数据源站点收集加密货币历史数据,并以pandas.DataFrame的形式返回给上层组件。

tensortrade.data.cdd的模块 docstring 直接写明了它的用途(见 tensortrade/data/cdd.py):

Contains methods and classes to collect data from cryptodatadownload.com.

也就是说,TensorTrade 本身不内置行情数据库,训练所需的 OHLCV 历史数据通过该模块按需拉取。拉取得到的 DataFrame 后续会进入 tensortrade/feed/core/feed.py 中的DataFeed/Stream,被包装成可迭代的特征流,再供给交易环境(env)的观察者(Observer)与动作方案使用。整条链路是:

CryptoDataDownload.fetch() → DataFrame(OHLCV) → Stream.source(list(df[col]), dtype="float") → DataFeed(features) → env.observer → 强化学习环境

在 docs 的 API 文档体系中,tensortrade.data.rst与tensortrade.data.cdd.rst分别通过automodule指令自动生成这两个模块的 API 参考页(见 docs/source/api/tensortrade.data.rst 与 docs/source/api/tensortrade.data.cdd.rst),本指南即基于cdd.py的真实实现与其在示例中的实际用法展开。

二、CryptoDataDownload 类总览

CryptoDataDownload是tensortrade.data.cdd中唯一的公开类,定义于 tensortrade/data/cdd.py#L13-L30。它的职责是:给定交易所名称、交易对符号与时间周期,拼出 CSV 文件的下载地址,读取后做统一的列重命名与时间解析,返回规整的 OHLCV DataFrame。

类的公开属性与方法如下:

成员类型说明
url属性(str)数据源根地址,__init__中固定为https://www.cryptodatadownload.com/cdd/
fetch_default(...)方法针对采用“标准命名与结构”的交易所数据文件进行下载与清洗
fetch_gemini(...)方法针对 Gemini 交易所的专属格式进行下载与清洗
fetch(...)方法统一入口,内部按交易所名自动分派到上述两个方法

模块顶部还做了一件值得注意的事(tensortrade/data/cdd.py#L10):

ssl._create_default_https_context = ssl._create_unverified_context

该语句全局放宽了 SSL 证书校验,是为了避免某些网络环境下下载数据文件时因证书问题而报错。它属于模块级副作用,在使用本模块时即生效,这一点在排查“为什么 import 后 TLS 校验变了”这类问题时需要留意。

2.1 fetch:统一的数据获取入口

fetch是日常使用最多的方法,签名与参数含义如下(tensortrade/data/cdd.py#L119-L149):

def fetch(self, exchange_name: str, base_symbol: str, quote_symbol: str, timeframe: str, include_all_volumes: bool = False) -> pd.DataFrame:
参数类型含义示例
exchange_namestr交易所名称(不区分大小写)"Bitfinex"、"Bitstamp"、"gemini"
base_symbolstr计价货币(Base Currency),即交易对中靠前的币种"USD"
quote_symbolstr标的货币(Quote Currency),即交易对中靠后的币种"BTC"
timeframestr时间周期,可选{"d", "h", "m"}(日线/小时线/分钟线),可带数字前缀"1h"、"1d"、"30m"
include_all_volumesbool是否同时保留 base 与 quote 两个成交量列,默认FalseFalse/True

返回值为pd.DataFrame,包含date、open、high、low、close、volume等列。fetch内部的分派逻辑是:

if exchange_name.lower() == "gemini": return self.fetch_gemini(base_symbol, quote_symbol, timeframe) return self.fetch_default(exchange_name, base_symbol, quote_symbol, timeframe, include_all_volumes=include_all_volumes)

即:交易所名(忽略大小写)为gemini时走 Gemini 专用分支,其余交易所一律走通用分支。

2.2 fetch_default:通用交易所的标准数据清洗

fetch_default针对绝大多数交易所的 CSV 文件结构做处理(tensortrade/data/cdd.py#L32-L84),其核心步骤可以拆解为:

  1. 拼接文件名:"{exchange}_{quote}{base}_{timeframe}.csv",例如Bitfinex_USDBTC_1h.csv;
  2. 读取并倒序:pd.read_csv(url + filename, skiprows=1)跳过首行表头说明,随后df[::-1]将数据按时间正序排列(源文件通常是时间倒序);
  3. 删除冗余列:df.drop(["symbol"], axis=1)去掉交易对标识列;
  4. 列名标准化:将"Volume BTC"→volume_base、"Volume USD"→volume_quote、"Date"→date;
  5. 时间戳归一化:unix列统一转int,若为 13 位毫秒级时间戳则除以 1000 转为秒级,再用pd.to_datetime(df["unix"], unit="s")解析为datetime并设为索引date;
  6. 统一小写列名:df.columns = [name.lower() ...],随后reset_index()把date恢复为普通列;
  7. 按需裁剪成交量列:当include_all_volumes=False(默认)时,丢弃volume_quote,并把volume_base重命名为volume,最终返回只含date/open/high/low/close/volume的紧凑 DataFrame;当include_all_volumes=True时,volume_base与volume_quote两列同时保留。

从源码结构看,默认返回的列顺序为date, open, high, low, close, volume,这与后续示例中data[['date', 'open', 'high', 'low', 'close', 'volume']]的选取方式完全吻合。

2.3 fetch_gemini:Gemini 交易所的专属分支

Gemini 的 CSV 格式与通用格式不同,因此单独处理(tensortrade/data/cdd.py#L86-L117)。该分支的差异点在于:

  • timeframe 转换:若 timeframe 以h结尾(如"1h"),会先转换为"1hr",以匹配 Gemini 文件名中的hr后缀;
  • 文件名模板:"gemini_{quote}{base}_{timeframe}.csv",不带交易所前缀重复;
  • 删除列不同:删除Symbol与Unix Timestamp两列;
  • 不做毫秒级时间戳换算:直接df[::-1]倒序、列名小写化、以date为索引后reset_index()返回。

需要说明的是,fetch_gemini不接受include_all_volumes参数,且该方法没有显式的时间戳归一化逻辑——这是与通用分支的显著差异,使用时建议确认源文件本身的date列格式。

三、实战一:单交易所单标的的基本拉取

仓库中几乎所有的训练脚本都采用同一套加载范式。以最简单的 examples/training/train_simple.py 为例:

from tensortrade.data.cdd import CryptoDataDownload cdd = CryptoDataDownload() data = cdd.fetch("Bitfinex", "USD", "BTC", "1h") data = data[['date', 'open', 'high', 'low', 'close', 'volume']] data = data.tail(200).reset_index(drop=True) print(f"Using {len(data)} rows | Price range: " f"${data['close'].min():,.0f} - ${data['close'].max():,.0f}")

这段代码做了三件事:

  1. 拉取:从 Bitfinex 获取 BTC/USD 的 1 小时 K 线,fetch内部已完成列标准化,所以data[['date', ...]]的列名可以直接命中;
  2. 截取:tail(200)只保留最近 200 根 K 线(约 8 天小时级数据),reset_index(drop=True)把行号重整为从 0 开始的连续整数——这保证了后续Stream.source(list(data["close"]))按行喂数据时不会携带原始索引;
  3. 输出诊断:打印数据规模与收盘价区间,用于快速校验数据是否正常。

在 docs/tutorials/01-foundations/03-your-first-run.md 中,这段代码被明确标注为“数据获取环节的核心代码”,说明该加载模式是 TensorTrade 入门教程的官方推荐路径。

拉取到的 DataFrame 随后会被包装成Stream并注册为交易所的价格流与环境的特征流:

from tensortrade.feed.core import Stream, DataFeed from tensortrade.oms.exchanges import Exchange, ExchangeOptions from tensortrade.oms.services.execution.simulated import execute_order price_data = list(data["close"]) price = Stream.source(price_data, dtype="float").rename("USD-BTC") exchange = Exchange("exchange", service=execute_order, options=ExchangeOptions(commission=0.001))(price) features = [Stream.source(list(data[c]), dtype="float").rename(c) for c in ['open', 'high', 'low', 'close', 'volume']] feed = DataFeed(features) feed.compile()

可见,CryptoDataDownload只是数据链路的起点,它产出的标准 OHLCV DataFrame 是后续所有Stream、Exchange与DataFeed组件的统一输入。

四、实战二:多交易所、多资产的数据融合

当需要在同一环境里同时使用多个交易所、多个币种的数据时,官方示例采用pd.concat(..., axis=1)按列拼接,再用add_prefix加前缀区分来源。docs/source/examples/setup_environment_tutorial.md 给出了完整范例:

import pandas as pd from tensortrade.data.cdd import CryptoDataDownload cdd = CryptoDataDownload() bitfinex_data = pd.concat([ cdd.fetch("Bitfinex", "USD", "BTC", "1h").add_prefix("BTC:"), cdd.fetch("Bitfinex", "USD", "ETH", "1h").add_prefix("ETH:") ], axis=1) bitstamp_data = pd.concat([ cdd.fetch("Bitstamp", "USD", "BTC", "1h").add_prefix("BTC:"), cdd.fetch("Bitstamp", "USD", "LTC", "1h").add_prefix("LTC:") ], axis=1)

这里的要点:

  • 同一交易所的多个币对用add_prefix("BTC:")/add_prefix("ETH:")打上币种标签,横向拼接后形成形如BTC:close、ETH:close的列;
  • 不同交易所的数据分开存放(bitfinex_data与bitstamp_data),随后各自注册为独立的Exchange实例,因为同一个交易所的价格流必须挂在同名的Exchange上(见同文件的 Exchange 定义段落);
  • fetch返回的date列在各币对间是相同的索引,因此concat(axis=1)可以自然对齐时间轴。

拼接完成后,价格流与特征流通过NameSpace划分命名空间,避免同名特征冲突:

with NameSpace("bitfinex"): bitfinex_streams = [ Stream.source(list(bitfinex_btc[c]), dtype="float").rename(c) for c in bitfinex_btc.columns ] ... feed = DataFeed(bitfinex_streams + bitstamp_streams)

feed.next()输出的每个键形如'bitfinex:/BTC:close'、'bitstamp:/LTC:volume',命名空间 + 币种前缀 + 特征名的三级结构,正是add_prefix与NameSpace共同作用的结果。这一模式同样出现在 examples/setup_environment_tutorial.ipynb 与 docs/source/examples/ledger_example.md 中,后者还演示了cdd.fetch("Bitfinex", "USD", "ETH", "1h")、cdd.fetch("Bitstamp", "USD", "LTC", "1h")等多币种拉取。

五、实战三:接入强化学习训练脚本

在 Ray RLlib 训练脚本中,CryptoDataDownload被用于加载训练与评估所需的完整历史数据。以 examples/training/train_advanced.py 为例:

print("\nLoading data...") cdd = CryptoDataDownload() data = cdd.fetch("Bitfinex", "USD", "BTC", "1h") data = data[['date', 'open', 'high', 'low', 'close', 'volume']] data['date'] = pd.to_datetime(data['date'])

随后数据会被切分为训练集与测试集,并分别构建价格流与特征流。类似地,examples/training/train_profit.py、examples/training/train_historical.py、examples/training/train_walkforward.py、examples/training/train_robust.py 等脚本都使用cdd.fetch("Bitfinex", "USD", "BTC", "1h")这一标准调用,说明它是仓库内所有训练入口共享的数据加载约定。

关于返回数据的进一步预处理,Notebook 示例 examples/train_and_evaluate.ipynb 中的prepare_data函数给出了常用的清洗步骤:

def prepare_data(df): df['volume'] = np.int64(df['volume']) # 成交量转整型,避免浮点精度问题 df['date'] = pd.to_datetime(df['date']) # 日期列显式解析 df.sort_values(by='date', ascending=True, inplace=True) # 确保按时间正序 df.reset_index(drop=True, inplace=True) df['date'] = df['date'].dt.strftime('%Y-%m-%d %I:%M %p') # 格式化时间供展示 return df

虽然fetch_default内部已经做过倒序与时间解析,但显式的sort_values与reset_index仍是训练前数据整理的稳妥做法,尤其当数据后续被多次切片、拼接时。

六、参数细节与边界说明

6.1 timeframe 的取值规则

fetch与fetch_default的 docstring 均将timeframe限定为{"d", "h", "m"}三档(见 tensortrade/data/cdd.py#L48-L49),即日线、小时线与分钟线。仓库示例中的实际取值包括:

  • "1h":1 小时 K 线,出现频率最高(几乎全部训练脚本与 Notebook 均使用);
  • "1d":日线,适用于较长周期策略;
  • 分钟级如"30m"在文档中未直接出现,但"m"后缀在源码层面是被接受的。

需要注意,fetch_default直接按"{exchange}_{quote}{base}_{timeframe}.csv"拼文件名,实际可用组合取决于 CryptoDataDownload 站点是否发布对应文件;若目标文件不存在,pd.read_csv会直接抛错。

6.2 时间戳的两种粒度

fetch_default中有一处容易被忽略的兼容逻辑(tensortrade/data/cdd.py#L71-L75):

df["unix"] = df["unix"].astype(int) df["unix"] = df["unix"].apply( lambda x: int(x / 1000) if len(str(x)) == 13 else x ) df["date"] = pd.to_datetime(df["unix"], unit="s")

它依据“13 位数字 = 毫秒级时间戳”的经验法则,把毫秒级unix列换算为秒级后统一解析。这意味着无论源文件提供的是秒级还是毫秒级时间戳,最终得到的date列都是规整的datetime对象——这是本模块“开箱即用”体验的关键实现细节。

6.3 include_all_volumes 的作用域

include_all_volumes参数只对fetch_default(即 Gemini 以外的交易所)生效:

  • False(默认):只返回volume(即 base 货币成交量),数据最紧凑;
  • True:同时返回volume_base与volume_quote,供需要双向成交量的研究使用。

从源码看,fetch_gemini不接收该参数,返回的列以源文件结构为准。因此,若你的策略需要volume_quote,应优先使用支持该参数的通用分支。

6.4 数据来源与适用前提

  • 本模块面向CryptoDataDownload 免费公开数据集,数据文件由该站点维护,文件命名与列结构需符合上述约定;
  • 模块在__init__中固定url,不支持自定义数据源地址;若需接入其他来源,可参考 examples/data/ 下已下载的 CSV(如Coinbase_BTCUSD_1h.csv、Coinbase_BTCUSD_d.csv)自行实现读取逻辑,或使用配置化方式加载(参见 examples/data/configuration.yaml);
  • 由于依赖网络下载,脚本运行前需保证目标站点可达;模块已通过ssl._create_default_https_context = ssl._create_unverified_context规避常见的证书校验问题。

七、测试与验证现状

关于tensortrade.data模块的自动化测试,仓库的测试目录 tests/tensortrade/unit/data/ 目前只有空的__init__.py,尚未包含针对CryptoDataDownload的单元测试文件。因此,对该模块的验证主要依赖两类间接证据:

  1. 示例运行输出:docs/tutorials/01-foundations/03-your-first-run.md 展示了运行train_simple.py时fetch成功返回 200 行数据并打印价格区间的真实输出;
  2. 集成测试:tests/tensortrade/integration/test_end_to_end.py 与 Ray 集成测试覆盖了环境构建与训练链路,数据加载作为链路起点被间接验证。

从源码结构可以推断,CryptoDataDownload的设计目标是把“下载 + 清洗 + 时间解析”封装为一个可复用的原子步骤,使上层训练脚本无需关心源文件格式差异。

八、完整速查

8.1 一行式拉取

from tensortrade.data.cdd import CryptoDataDownload df = CryptoDataDownload().fetch("Bitfinex", "USD", "BTC", "1h")

8.2 推荐的数据准备流程(结合训练脚本惯例)

import pandas as pd from tensortrade.data.cdd import CryptoDataDownload cdd = CryptoDataDownload() data = cdd.fetch("Bitfinex", "USD", "BTC", "1h") data = data[['date', 'open', 'high', 'low', 'close', 'volume']] data['date'] = pd.to_datetime(data['date']) data.sort_values(by='date', ascending=True, inplace=True) data = data.tail(200).reset_index(drop=True) # 截取最近 200 根 K 线

8.3 常用参考路径

用途路径
模块源码tensortrade/data/cdd.py
包入口tensortrade/data/init.py
最小训练示例examples/training/train_simple.py
多交易所融合示例docs/source/examples/setup_environment_tutorial.md
账本(Ledger)示例docs/source/examples/ledger_example.md
首次运行教程docs/tutorials/01-foundations/03-your-first-run.md
本地 CSV 示例数据examples/data/

九、小结

tensortrade.data.cdd是 TensorTrade 生态中承担“数据接入”职责的唯一模块,CryptoDataDownload类以极简的fetch(exchange, base, quote, timeframe)接口屏蔽了文件下载、倒序、列重命名、毫秒时间戳换算等全部细节,让 OHLCV 数据能够无缝进入Stream → DataFeed → 交易环境的后续链路。无论是最简单的单币种训练脚本,还是跨交易所、跨币种的特征融合,该模块都是官方示例中统一采用的数据入口。

  • 人工智能
  • 金融科技
  • 机器学习

【免费下载链接】tensortrade

An open source reinforcement learning framework for training, evaluating, and deploying robust trading agents.

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

相关推荐

上一篇:VueRouter 对象全解析:从构造函数到路由实例化的核心机制
下一篇:HashCalculator:3分钟掌握专业级文件完整性验证与重复文件查找

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 3:12:02

无电感升压电路:基于运放与电荷泵的极低功耗DC-DC设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 3:11:40

Model-Optimizer大模型推理优化:量化、算子融合与KV Cache实践

最近帮团队把一个7B模型的推理服务压进显存时,我把能试的优化手段几乎试了个遍。量化、剪枝、算子融合、KV Cache压缩,最后发现真正省心的不是自己拼凑脚本,而是用一套完整的Model-Optimizer把整个流程串起来。这篇文章就把我这几周折腾出来的…

作者头像 李华
网站建设 2026/9/29 3:10:32

ADS电磁联合仿真+OPTIM优化:版图一次成功实战指南

做射频微波电路设计的,谁没被“原理图仿真很理想,版图一测就翻车”戳过心。原理图里的连线是零阻抗无损的抽象节点,可到了实际版图,每段走线都变成带分布参数的传输结构,过孔、拐角、焊盘全是寄生。ADS里的EM-Cosimula…

作者头像 李华
网站建设 2026/9/29 3:09:28

OpenClaw部署为何强制要求Node.js?版本与报错全解析

最近好几个来问OpenClaw部署的朋友,都卡在同一行上:部署文档第一句写着“请先安装Node.js 18.20.4 LTS或更高版本”,他们看完就懵了——我要装的是一个智能体,跟JavaScript运行时有什么关系?这步能不能跳过&#xff1f…

作者头像 李华