第二章 金融数据基础:股票、期货、加密货币数据获取,pandas数据处理,OHLCV与K线图绘制
各位同学,欢迎来到第二章。这一章,我们要解决一个最实际的问题:数据从哪来?拿到手之后怎么处理?以及,怎么把枯燥的数字变成能一眼看懂的图表?
我个人习惯把数据获取比作「做饭前的买菜」。菜买不好,后面厨艺再好也白搭。量化投资更是如此——垃圾数据进,垃圾模型出。咱们今天就把「买菜」和「洗菜切菜」的功夫练扎实。
2.1 数据源:股票、期货、加密货币
金融数据源五花八门,我挑几个最常用的、且适合咱们强化学习场景的来说。
2.1.1 股票数据
国内股票数据,我个人最常用的是 Tushare 和 AKShare。Tushare 数据质量高,但部分接口需要积分;AKShare 完全免费,接口丰富,适合初学者上手。
核心要点: 对于强化学习,我们通常需要日线级别以上的数据。高频数据(分钟级)虽然信息量大,但噪声也大,初期不建议碰。
# 使用 AKShare 获取 A 股日线数据
import akshare as ak
# 获取贵州茅台(股票代码:600519)的历史日线数据
stock_zh_a_hist_df = ak.stock_zh_a_hist(symbol="600519", period="daily",
start_date="20200101", end_date="20231231",
adjust="qfq") # qfq 表示前复权
print(stock_zh_a_hist_df.head())
嗯,这里要注意:复权处理。股票有分红送股,不复权的话,K线图上会出现跳空缺口,影响技术指标计算。我建议初学者直接用前复权,这样历史价格是连续的。
2.1.2 期货数据
期货数据和股票有个很大的不同:合约有到期日。你拿到的螺纹钢主力合约,过几个月就换月了。如果不做处理,数据会出现断崖。
我曾经在项目中吃过这个亏——直接用主力连续合约训练模型,结果模型学会了「换月跳空」的规律,实盘一跑就崩。后来我改用 指数合约 或者自己写 换月拼接逻辑,才把问题解决。
# 使用 Tushare 获取期货日线数据(需要 token)
import tushare as ts
pro = ts.pro_api('your_token_here')
# 获取螺纹钢主力连续合约
df = pro.fut_daily(ts_code='RB9999.XSGE', start_date='20200101', end_date='20231231')
print(df.head())
避坑指南: 我曾经用「成交量最大」作为换月标准,但遇到节假日前后成交量异常时,换月点会漂移。后来我改用「持仓量最大+固定日期窗口」的双重判断,稳定多了。
2.1.3 加密货币数据
加密货币是 7×24 小时交易的,数据量巨大。我推荐用 CCXT 库,它统一了上百家交易所的 API 接口,写一套代码就能跑遍 Binance、OKX、Coinbase。
# 使用 CCXT 获取比特币现货数据
import ccxt
import pandas as pd
exchange = ccxt.binance()
# 获取 BTC/USDT 的 1 天 K 线,限制 500 根
ohlcv = exchange.fetch_ohlcv('BTC/USDT', timeframe='1d', limit=500)
# 转换成 DataFrame
columns = ['timestamp', 'open', 'high', 'low', 'close', 'volume']
df = pd.DataFrame(ohlcv, columns=columns)
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
print(df.head())
你想想看,加密货币数据有个特点:数据频率可以很高。对于强化学习,我个人建议先从 1 小时或 4 小时级别开始,别一上来就搞 1 分钟 tick 数据,那会让你的智能体「只见树木不见森林」。
2.2 pandas 数据处理:从原始数据到干净特征
数据拿到手,十有八九是脏的。缺失值、异常值、时间戳不对齐……这些都是家常便饭。pandas 就是咱们的「瑞士军刀」。
2.2.1 数据清洗三板斧
- 检查缺失值:
df.isnull().sum()一眼看出哪些列有空洞。 - 处理异常值:比如某天收盘价突然变成 0,那肯定是数据错误。
- 对齐时间索引:把 timestamp 设为 index,确保数据按时间排序。
# 数据清洗示例
# 假设 df 是上一步获取的 BTC 数据
# 1. 检查缺失
print(df.isnull().sum())
# 2. 删除收盘价为 0 或负数的异常行
df = df[df['close'] > 0]
# 3. 设置时间索引并排序
df.set_index('timestamp', inplace=True)
df.sort_index(inplace=True)
# 4. 向前填充缺失值(比如周末无交易)
df.fillna(method='ffill', inplace=True)
注意: 向前填充(ffill)在金融数据中很常用,但要注意边界情况。比如停牌期间用 ffill,复牌后第一个数据点会失真。我一般会在 ffill 之后,再检查一下连续填充的长度,超过 5 天的就标记为「待处理」。
2.2.2 计算常用技术指标
强化学习需要状态特征,原始 OHLCV 往往不够。咱们得加工一下。下面是我常用的几个指标:
| 指标名称 | 计算公式 | 用途 |
|---|---|---|
| 收益率 | (close - close.shift(1)) / close.shift(1) | 衡量价格变化幅度 |
| 对数收益率 | log(close / close.shift(1)) | 更符合正态分布假设 |
| 波动率 | 收益率滚动 20 日标准差 | 衡量风险 |
| RSI | 14 日相对强弱指标 | 判断超买超卖 |
| ATR | 平均真实波幅 | 衡量市场波动 |
# 计算特征
import numpy as np
# 收益率
df['return'] = df['close'].pct_change()
# 对数收益率
df['log_return'] = np.log(df['close'] / df['close'].shift(1))
# 20 日滚动波动率
df['volatility'] = df['return'].rolling(window=20).std()
# RSI(14 日)
def compute_rsi(data, window=14):
delta = data.diff()
gain = (delta.where(delta > 0, 0)).rolling(window=window).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=window).mean()
rs = gain / loss
rsi = 100 - (100 / (1 + rs))
return rsi
df['rsi'] = compute_rsi(df['close'], 14)
# 删除前 20 行 NaN
df.dropna(inplace=True)
print(df.tail())
说白了,这些特征就是强化学习智能体的「眼睛」。特征选得好,模型学得快;特征选得烂,模型就是在瞎猜。
2.3 OHLCV 与 K 线图绘制
数据处理好之后,画个 K 线图看看,是最直观的验证方式。我习惯用 mplfinance 库,它是 matplotlib 的金融专用扩展,画 K 线图非常方便。
2.3.1 使用 mplfinance 绘制 K 线图
import mplfinance as mpf
# 确保数据格式正确:索引为 DatetimeIndex,包含 OHLCV 列
# 这里用我们清洗后的 BTC 数据
mpf.plot(df, type='candle', volume=True, style='charles',
title='BTC/USDT K-line Chart',
ylabel='Price (USDT)', ylabel_lower='Volume')
运行这段代码,你会看到一张标准的 K 线图:红色阳线、绿色阴线、下方成交量柱状图。嗯,看到这个图,你心里就有底了——数据没问题。
2.3.2 自定义 K 线图:加入均线
我个人习惯在 K 线图上叠加均线,这样能快速判断趋势。
# 计算均线
df['ma5'] = df['close'].rolling(window=5).mean()
df['ma20'] = df['close'].rolling(window=20).mean()
# 绘制带均线的 K 线图
ap = [mpf.make_addplot(df['ma5'], color='blue', width=0.8),
mpf.make_addplot(df['ma20'], color='orange', width=0.8)]
mpf.plot(df, type='candle', volume=True, style='charles',
addplot=ap,
title='BTC/USDT with MA5 & MA20',
ylabel='Price (USDT)')
小技巧: 如果你觉得 mplfinance 的默认样式不好看,可以试试 style='binance' 或者自己定义颜色。我经常用 style='yahoo',那个配色比较经典。
2.4 本章知识体系总览
下面这张 SVG 图,把本章的核心逻辑串起来了。从数据获取到清洗,再到特征工程和可视化,每一步都是为后续的强化学习模型打基础。
这张图里,从数据源到最终的可视化,每一步都环环相扣。你可能会问:「为什么要把可视化放在最后?」其实,可视化不仅是验证数据的手段,更是你理解市场行为的窗口。我每次拿到新数据,第一件事就是画 K 线图,看看有没有异常跳空、有没有数据断层——眼睛比代码更容易发现问题。
好了,这一章的内容就到这里。数据基础打牢了,后面咱们才能放心地搭建强化学习环境、训练智能体。记住:数据质量决定模型上限,别在这个环节偷懒。