LynxCrypto 实战篇:用真实加密数据 6 步速通 pandas

不啃语法,用 ccxt 取真实 BTC 行情、pandas 处理、vectorbt 回测,6 步走完加密量化里 pandas 的全部核心用法——从读数据、重采样、手算 RSI/MACD,到多资产对齐和喂给回测引擎。

做加密量化绕不开 pandas。你的行情是表格,指标是列,回测引擎吃的就是带时间索引的 DataFrame——vectorbt、Freqtrade、你 strategy/ 里的策略类,全接这种数据结构。

但大多数人学 pandas 的方式不对:啃语法书、背 API,学完还是不会处理一根 K 线。

这篇是我给自己整理的 pandas 速成路线,思路就一条:不学语法,用真实加密数据驱动学。pandas 在量化里只干 4 件事——读数据进来、整理成时间序列表格、算技术指标、做统计分析。我把它拆成 6 步,每步一组概念 + 一段能在 JupyterLab 里直接跑的代码。走完,你能独立从 ccxt 取数 → pandas 处理 → vectorbt 回测走通全链路。

环境假设:你有一个装好 ccxt + pandas + vectorbt 的 Python 环境(我是 LynxCrypto 项目里的 .venv),JupyterLab 已开。没有的话,pip install ccxt pandas vectorbt jupyterlab 就齐了。

先打底(可选,但推荐过一遍)

如果 pandas 零基础,先花 30–60 分钟过一遍这几个 HTML 教程,都能直接复制代码:

  • Kaggle 免费课程 Pandashttps://www.kaggle.com/learn/pandas 浏览器里直接跑代码 + 练习题,免费。过一遍 Series / DataFrame / 索引 / 分组的概念最顺。
  • Pandas 官方 10 Minutes to pandashttps://pandas.pydata.org/docs/user_guide/10min.html 官方速览,代码全可复制,建立"pandas 能干什么"的全局印象。
  • 《Python for Data Analysis》(pandas 作者 Wes McKinney)第 5–9 章,有免费在线版,偏实战,可当字典查。

过完上面任一个再回来走下面的 6 步,会比纯啃语法快得多。

Step 1 — 把行情数据变成 DataFrame(读取 + 结构)

学到的概念: SeriesDataFrameindex(索引)、columnsdtypeshead/tailto_datetime

任务: 用 ccxt 从交易所拉 BTC/USDT 的 K 线(OHLCV),转成带时间索引的表格。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import ccxt
import pandas as pd

# 取 binance 的 BTC/USDT 1分钟线,公共数据不用 API key
# 连不上?确保代理在跑,或把 'binance' 换成 'okx'/'gate'
ex = ccxt.binance()
ohlcv = ex.fetch_ohlcv('BTC/USDT', '1m', limit=500)  # 500 根

# ccxt 返回的是 list of list:[时间戳, 开, 高, 低, 收, 量]
df = pd.DataFrame(ohlcv, columns=['ts', 'open', 'high', 'low', 'close', 'vol'])
df['ts'] = pd.to_datetime(df['ts'], unit='ms')   # 毫秒时间戳 → 时间
df = df.set_index('ts')                            # 时间当索引
df.head()                                          # 看前 5 行
df.dtypes                                          # 看每列数据类型

理解点: 表格里每一列是一个 Series,整张表是 DataFrame,最左边那列时间是 index。索引是 pandas 时间序列操作的地基,后面所有重采样、切片都靠它。

Step 2 — 时间序列整理与切片(索引、切片、重采样)

学到的概念: DatetimeIndexloc/iloc 切片、resample 重采样、时区

任务: 1 分钟线重采样成 4 小时线,取最近一段时间。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 切片:按时间取一段(用 loc + 字符串时间)
recent = df.loc['2026-09-05':]

# 重采样:1m → 4h 的 OHLC(金融标准聚合方式)
df_4h = df.resample('4h').agg({
    'open': 'first',   # 区间开盘价 = 第一根
    'high': 'max',      # 区间最高 = 每根最高的最大值
    'low': 'min',
    'close': 'last',   # 区间收盘 = 最后一根
    'vol': 'sum'       # 区间成交量 = 求和
})
df_4h.head()

# 按位置切片(iloc,第几行)
df.iloc[:10]      # 前 10 行
df.iloc[-5:]      # 最后 5 行

理解点: loc 用标签(时间字符串/索引值)切,iloc 用位置(第几个)切。resample 是把高频数据压缩成低频的核心工具——量化里 1m→4h、1h→1d 全靠它。

Step 3 — 手算技术指标(列运算、rolling、shift、ewm)

学到的概念: 列运算、rolling(滚动窗口)、shift(位移)、ewm(指数加权)、apply/lambda

任务: 不用现成指标库,自己手算一遍 MA、RSI、MACD,理解指标原理。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 移动平均线 MA(20):过去 20 根的均值滚动
df['ma20'] = df['close'].rolling(20).mean()

# RSI(14):先算涨跌幅,再用 ewm 平滑
delta = df['close'].diff()                     # diff = 当前减前一根
gain = delta.clip(lower=0)                      # 只留正的部分(涨)
loss = -delta.clip(upper=0)                     # 只留负的(跌),取绝对值
avg_gain = gain.ewm(alpha=1/14, adjust=False).mean()
avg_loss = loss.ewm(alpha=1/14, adjust=False).mean()
rs = avg_gain / avg_loss
df['rsi'] = 100 - 100 / (1 + rs)

# MACD:两条 EMA 的差
ema12 = df['close'].ewm(span=12, adjust=False).mean()
ema26 = df['close'].ewm(span=26, adjust=False).mean()
df['macd'] = ema12 - ema26
df['signal'] = df['macd'].ewm(span=9, adjust=False).mean()
df['hist'] = df['macd'] - df['signal']

df[['close', 'ma20', 'rsi']].tail()             # 看最近几行

理解点: rolling(20).mean() 是"开个 20 个元素的滑动窗口算均值",几乎所有趋势指标都从这来;shift(1) 能把数据往后挪一格,常用来"今天的值对比昨天的值";ewm 是带衰减权重的均值,RSI/MACD 都用它。手算一遍,你就明白 ft-pandas-ta 里那些现成函数底下在干什么。

Step 4 — 多资产对齐(concat、merge、相关性)

学到的概念: concatmerge/join、多资产时间对齐、fillnacorr(相关性)

任务: 把 BTC 和 ETH 的收盘价对齐到一张表,算它们的相关性。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 先分别取 ETH 的收盘价 series(同样套路)
eth = ex.fetch_ohlcv('ETH/USDT', '1m', limit=500)
eth_df = pd.DataFrame(eth, columns=['ts','o','h','l','c','v'])
eth_df['ts'] = pd.to_datetime(eth_df['ts'], unit='ms')
eth_close = eth_df.set_index('ts')['c']

# 横向拼:把 BTC 收盘和 ETH 收盘并成两列(axis=1 = 按列拼)
both = pd.concat({'BTC': df['close'], 'ETH': eth_close}, axis=1)
both = both.dropna()            # 丢掉没对齐上的行

both.corr()                     # 相关性矩阵
both['spread'] = both['BTC'] - both['ETH']   # 新列 = 两列相减
both.plot()                     # 直接画图(pandas 自带)

理解点: 多资产策略(配对交易、跨币种套利)的核心是"时间对齐"——两个币种时间戳对不齐就 fillnadropna,concat(axis=1) 是横向合并的主力。BTC 和 ETH 的高相关是加密市场的基本事实,配对交易和统计套利都建在它上面。

Step 5 — 统计与可视化(describe、groupby、绘图)

学到的概念: describepct_change(收益率)、groupby(分组)、agg(聚合)、plot

任务: 算收益率分布、按天/按小时分组看规律、画图。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
df['ret'] = df['close'].pct_change()          # 收益率 = (今-昨)/昨
df['ret'].describe()                          # 均值/标准差/分位数 速览

# 按小时分组:看哪个小时波动最大
df['hour'] = df.index.hour
df.groupby('hour')['ret'].agg(['mean', 'std', 'count'])

# 按天聚合日收益
df['day'] = df.index.date
daily_ret = df.groupby('day')['ret'].sum()

# 画图(在 notebook 里内联显示)
df[['close','ma20']].plot(title='BTC close + MA20')
df['ret'].hist(bins=50)                        # 收益率分布直方图

理解点: describe() 是最快的数据体检;groupby 是"按某列分组再分别算"——量化里按小时/星期/月份找规律全靠它;收益率的分布形状(是否正态、有没有肥尾)决定策略的风险假设。加密收益率有明显的肥尾,这是为什么马丁格尔长期必输(见我上篇的爆仓数学)。

Step 6 — 衔接 vectorbt(把 DataFrame 喂给回测引擎)

学到的概念: 这一步不学新 pandas,是理解"研究产物如何进回测"——pandas DataFrame 就是 vectorbt 的标准输入。

任务: 用 Step 3 算的 MA20 做一个穿越信号,喂给 vectorbt 回测。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import vectorbt as vbt

# 信号:收盘价上穿 MA20 买入,下穿卖出(布尔 Series)
entries = df['close'] > df['ma20']
exits   = df['close'] <= df['ma20']

# vectorbt 接收 close(Series)+ 进出场布尔信号
pf = vbt.Portfolio.from_signals(df['close'], entries, exits, init_cash=10000)
pf.stats()                  # 回测统计:总收益/胜率/最大回撤等
pf.plot()                   # 回测曲线

理解点: pandas 到这一步就是"成品数据"——vectorbt、你 strategy/ 里的策略类,吃的就是这种带时间索引的 DataFrame。研究阶段在 notebook 里试想法(这几步),定稿的逻辑提炼回 strategy/.py 模块。这就是 Jupyter 和工程代码的分工:notebook 是草稿纸,.py 是交付件。

学完后你能做什么

  • pandas 在量化里的 6 个核心动作(读 / 切 / 算指标 / 对齐 / 统计 / 喂回测)你都过了一遍真实加密数据
  • 能独立从 ccxt 取数 → pandas 处理 → vectorbt 回测走通全链路
  • 接下来:把这些手算的指标和信号,对照你 strategy/ 里已有的策略看一遍(我是对照 MacdCross),理解"notebook 探索版"和"工程模块版"的对应关系

四个反模式(我踩过,你别踩)

  • 别在一个 notebook 里塞十个想法 —— 一个 notebook 一个研究问题,否则三个月后你自己都看不懂。
  • notebook 顶部写清假设和结论 —— 回看时先看这两条,再看代码。
  • 确定下来的逻辑要提炼回 .py —— notebook 只留研究过程,别让 notebook 变成乱炖。
  • 别只看不跑 —— 每段代码都要自己敲一遍改参数,看输出变了什么,光看学不会。

这篇是 LynxCrypto 系列的实战入门。系列其他文章:研究蓝图 · 从网格马丁到 Alpha(上篇) · 证伪篇 · WFO 终审 · 工具篇