第二章:数据获取与处理——金融数据源的实战选择

做量化交易,第一步就是搞数据。没有数据,再牛的策略也是空中楼阁。今天咱们聊聊金融数据源怎么选、数据怎么洗、存到哪儿最合适。

我个人习惯把数据获取分成两个阶段:研究阶段实盘阶段。研究阶段追求免费、方便、数据全;实盘阶段追求稳定、低延迟、合规。今天主要讲研究阶段,因为这是大家入门最关心的。

2.1 金融数据源介绍

国内做量化,绕不开两个库:TushareAKShare。我两个都用过,各有千秋。

2.1.1 Tushare

Tushare 是老牌数据源了。我2018年刚开始做量化时就在用。它最大的特点是数据规范、文档清晰。但有个门槛——需要积分。免费用户能拿到的数据有限,想拿全得充值。

举个例子,获取股票日线数据:

import tushare as ts

# 设置token(需要去官网注册获取)
ts.set_token('你的token')
pro = ts.pro_api()

# 获取平安银行2024年1月日线数据
df = pro.daily(ts_code='000001.SZ', start_date='20240101', end_date='20240131')
print(df.head())

输出结果长这样:

ts_codetrade_dateopenhighlowclosevol
000001.SZ202401319.129.359.089.221234567
000001.SZ202401309.309.389.109.15987654
小提示:Tushare 的 pro 接口返回的是 pandas DataFrame,直接就能用。我个人建议研究阶段至少充个200块,拿到2000积分,基本够用。

2.1.2 AKShare

AKShare 是后起之秀,完全免费。它的数据源来自各大财经网站,覆盖面很广。但有个问题——数据格式不太统一,不同接口返回的列名可能不一样。

我去年做一个期货策略时,AKShare 帮了大忙。它连南华期货指数这种冷门数据都有:

import akshare as ak

# 获取南华商品指数
index_df = ak.futures_nh_index(symbol="南华商品指数", start_date="20240101", end_date="20240131")
print(index_df.head())
注意:AKShare 的接口名经常变。我遇到过好几次,昨天还能跑的代码,今天报错了。原因是网站改版,接口名变了。所以用 AKShare 时,建议固定版本号。

2.1.3 怎么选?

我的建议很简单:

  • 做股票策略:优先 Tushare,数据规范,省心
  • 做期货/期权:AKShare 免费且数据全
  • 做回测:两个都备着,互相校验

为什么会这样?因为股票数据对复权、除权处理要求高,Tushare 做得更专业。期货数据嘛,AKShare 的覆盖面确实广。

2.2 数据清洗与预处理

拿到原始数据后,千万别直接扔进策略。我见过太多人,数据没洗干净,策略跑出来漂亮得很,实盘一跑就亏。为什么?前视偏差幸存者偏差在作怪。

2.2.1 常见问题

金融数据常见的坑,我列几个:

  • 缺失值:停牌日、节假日,数据是空的
  • 异常值:比如某天涨幅1000%,明显是数据错误
  • 复权问题:不处理复权,回测结果全是错的
  • 未来数据:用当天的数据预测当天,这是作弊

2.2.2 清洗实战

拿 Tushare 的日线数据举例,我一般这么洗:

import pandas as pd
import numpy as np

# 假设 df 是原始数据
def clean_stock_data(df):
    # 1. 排序:按时间升序
    df = df.sort_values('trade_date')
    
    # 2. 处理缺失值:前向填充
    df = df.fillna(method='ffill')
    
    # 3. 处理异常值:涨跌幅超过20%的,用前一日数据替换
    df['pct_chg'] = df['close'].pct_change()
    abnormal = df['pct_chg'].abs() > 0.2
    df.loc[abnormal, 'close'] = df['close'].shift(1)
    
    # 4. 复权处理(这里用后复权)
    df['adj_close'] = df['close'] * df['adj_factor']
    
    return df

# 使用
df_clean = clean_stock_data(df)
核心要点:数据清洗的顺序很重要。先排序,再填充,最后处理异常。顺序错了,结果可能完全不一样。

2.2.3 避坑指南

我曾经犯过一个低级错误:用当天的收盘价计算均线,然后预测当天的涨跌。回测结果年化收益50%,实盘直接腰斩。后来才发现,回测时用了未来数据

正确的做法是:计算技术指标时,只用历史数据。比如计算5日均线,只能用前5天的数据,不能用当天。

2.3 数据存储

数据洗好了,存哪儿?我试过三种方式:CSV、SQLite、MySQL。各有适用场景。

2.3.1 CSV 存储

最简单的方式。研究阶段,数据量不大,CSV 完全够用。

# 保存
df_clean.to_csv('stock_data.csv', index=False)

# 读取
df = pd.read_csv('stock_data.csv', parse_dates=['trade_date'])

但 CSV 有个问题:不支持增量更新。每次更新数据,都得全量重写。数据量大了之后,效率很低。

2.3.2 数据库存储

我建议用 SQLite 做研究阶段的数据存储。它不需要安装服务器,一个文件搞定,而且支持 SQL 查询。

import sqlite3

# 连接数据库(文件不存在会自动创建)
conn = sqlite3.connect('quant_data.db')

# 写入数据
df_clean.to_sql('stock_daily', conn, if_exists='replace', index=False)

# 查询数据
query = "SELECT * FROM stock_daily WHERE trade_date >= '2024-01-01'"
df = pd.read_sql(query, conn)

conn.close()
小技巧:用 SQLite 时,给 trade_date 和 ts_code 建索引,查询速度能快10倍以上。

如果数据量特别大(比如全市场分钟级数据),可以考虑 MySQL 或 PostgreSQL。但说实话,个人研究阶段,SQLite 完全够用。

2.3.3 存储方案对比

存储方式优点缺点适用场景
CSV简单、通用不支持增量、查询慢小数据量、一次性分析
SQLite轻量、支持SQL并发差个人研究、中小规模
MySQL并发好、功能强需要安装维护团队协作、生产环境

2.4 本章知识体系

说了这么多,咱们用一张图总结一下数据获取与处理的完整流程:

数据获取与处理流程 数据源 Tushare / AKShare 数据清洗 缺失值 / 异常值 / 复权 数据存储 CSV / SQLite / MySQL 数据源选择 • 股票:Tushare(规范) • 期货:AKShare(免费) • 回测:两者互验 • 注意:接口版本固定 清洗要点 • 先排序再填充 • 异常值用前值替换 • 必须处理复权 • 警惕未来数据 存储建议 • 研究用SQLite • 小数据用CSV • 生产用MySQL • 记得建索引

嗯,数据这块就聊到这儿。记住一句话:数据质量决定策略上限。数据没处理好,后面再牛的模型也白搭。我见过太多人花90%时间写策略,10%时间搞数据,结果策略一跑就崩。反过来,花70%时间搞数据,30%时间写策略,反而更容易出成果。

你想想看,是不是这个理?


专注资料整理