第四节:数据获取——用Tushare和Akshare搞定行情数据

做量化交易,数据就是你的弹药。没有数据,再牛的策略也是纸上谈兵。

我个人习惯把数据获取分成两类:一类是离线批量拉取,存到本地数据库;另一类是实时在线调用,做盘中决策。今天咱们重点讲前者——怎么用Python把股票、期货、ETF的日线行情拿到手。

市面上免费的数据源不少,但我用得最多的就两个:TushareAkshare。前者老牌、稳定,后者新锐、覆盖面广。我建议你两个都装上,互补使用。

核心观点:数据获取不是简单的“调个API就完事”。你需要考虑频率限制、数据完整性、字段对齐、异常重试。这些坑,我当年都踩过。

4.1 环境准备与安装

先装包。没什么技术含量,但版本号要注意。

# 安装Tushare(建议用最新版)
pip install tushare==1.4.10

# 安装Akshare
pip install akshare==1.14.0

# 辅助库
pip install pandas numpy requests

嗯,这里要注意:Tushare从1.4.0版本开始,需要注册获取token。免费版有频率限制——每分钟最多200次请求,每天最多5000次。我个人觉得够用了,除非你跑全市场5000只股票。

小技巧:注册Tushare时,用我的邀请码能提高积分。当然,这不是必须的。免费版也能用。

4.2 用Tushare获取股票日线数据

先初始化。把token配置好,后面就简单了。

import tushare as ts

# 设置token(去官网注册获取)
ts.set_token('你的token')

# 初始化pro接口
pro = ts.pro_api()

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

print(df.head())

返回的字段包括:trade_dateopenhighlowclosepre_closechangepct_chgvolamount

这里有个细节:pct_chg是涨跌幅,单位是百分比。比如涨了5%,返回5.0。我刚开始做回测时,直接拿这个值当收益率用,结果发现和复利计算对不上。后来才意识到,它算的是单日简单收益率,不是对数收益率。

避坑指南:我曾经在回测中直接用pct_chg做复利计算,结果净值曲线偏差了0.3%。后来改成用close/shift(close)-1才对齐。记住:pct_chg是相对于前收盘价的百分比,不是连续复利收益率。

4.3 用Tushare获取期货主力连续合约

期货比股票麻烦。因为合约会到期,你需要主力连续合约。Tushare提供了fut_mapping接口,直接帮你映射好。

# 获取螺纹钢主力连续合约日线
df_fut = pro.fut_mapping(
    ts_code='RB.SHF',  # 螺纹钢,上海期货交易所
    start_date='20240101',
    end_date='20240131'
)

print(df_fut.head())

返回的字段多了oi(持仓量)和settle(结算价)。做跨品种套利时,我一般用结算价而不是收盘价,因为期货的收盘价容易被尾盘大单影响。

为什么会这样?因为期货市场最后3分钟是集合竞价,容易产生异常价格。我吃过这个亏——有一次做螺纹钢和热卷的套利,收盘价信号显示价差突破,结果第二天开盘就回归了。后来改用结算价,信号稳定多了。

4.4 用Akshare获取ETF行情数据

Akshare在ETF数据上做得比Tushare好。它直接抓取东方财富的数据,覆盖面广,更新及时。

import akshare as ak

# 获取沪深300ETF(510300)日线数据
df_etf = ak.fund_etf_hist_em(
    symbol="510300",
    period="daily",
    start_date="20240101",
    end_date="20240131",
    adjust="qfq"  # 前复权
)

print(df_etf.head())

返回字段包括:日期开盘最高最低收盘成交量成交额振幅涨跌幅涨跌额换手率

注意:Akshare返回的列名是中文。我建议你拿到数据后,统一转成英文列名,方便后续处理。

个人习惯:我会写一个统一的数据清洗函数,把Tushare和Akshare的字段名都映射成统一的格式。比如open、high、low、close、volume、amount。这样不管从哪个源拿数据,后面的代码都不用改。

4.5 多品种批量获取与存储

实战中,你不会只拿一只股票。我通常的做法是:先维护一个品种列表,然后循环拉取,最后存到本地CSV或数据库。

import pandas as pd
import time

# 品种列表
symbols = [
    '000001.SZ',  # 平安银行
    '600519.SH',  # 贵州茅台
    '510300.SH',  # 沪深300ETF
    'RB.SHF',     # 螺纹钢期货
    'CU.SHF',     # 铜期货
]

def fetch_all_data(symbols, start_date, end_date):
    data_dict = {}
    for sym in symbols:
        try:
            if sym.endswith('.SH') or sym.endswith('.SZ'):
                # 股票
                df = pro.daily(ts_code=sym, start_date=start_date, end_date=end_date)
            elif '.SHF' in sym:
                # 期货
                df = pro.fut_mapping(ts_code=sym, start_date=start_date, end_date=end_date)
            else:
                # ETF用Akshare
                df = ak.fund_etf_hist_em(symbol=sym[:6], period="daily", 
                                         start_date=start_date, end_date=end_date)
            
            data_dict[sym] = df
            print(f"成功获取: {sym}")
            time.sleep(0.5)  # 控制频率,别被封
        except Exception as e:
            print(f"获取 {sym} 失败: {e}")
    
    return data_dict

# 执行
all_data = fetch_all_data(symbols, '20240101', '20240131')

这里我加了time.sleep(0.5),就是为了避免触发Tushare的频率限制。你想想看,如果一次拉100个品种,不加延时的话,很可能第50个就被封了。

重要提醒:千万不要在生产环境中不加延时地批量请求。我曾经在回测框架里忘了加sleep,结果跑了10分钟就被Tushare封了24小时。那天下午的复盘会,我只能用本地缓存数据凑合。

4.6 数据质量检查

数据拿到手,别急着用。先做三件事:

  1. 检查缺失值——看看有没有NaN的行
  2. 检查日期连续性——交易日之间不能有跳空(除节假日外)
  3. 检查价格合理性——有没有0值或异常大值
def check_data_quality(df, symbol):
    issues = []
    
    # 1. 缺失值
    if df.isnull().any().any():
        issues.append(f"存在缺失值: {df.isnull().sum().to_dict()}")
    
    # 2. 日期连续性
    dates = pd.to_datetime(df['trade_date'])
    date_diff = dates.diff().dropna()
    if (date_diff > pd.Timedelta(days=5)).any():
        issues.append("存在超过5天的日期间隔")
    
    # 3. 价格合理性
    if (df['close'] <= 0).any():
        issues.append("存在非正收盘价")
    
    if issues:
        print(f"{symbol} 数据质量问题: {issues}")
    else:
        print(f"{symbol} 数据质量通过")
    
    return len(issues) == 0

这个检查函数,我每次拉完数据都会跑一遍。别嫌麻烦,数据质量决定了策略的生死。

4.7 知识体系总览

下面这张图,概括了本章的核心逻辑。你看一眼,就知道数据获取的全貌了。

数据获取知识体系 数据源 Tushare Pro Akshare 股票 期货 ETF 可转债 指数 批量拉取 → 频率控制 → 字段对齐 → 数据清洗 (sleep延时、列名映射、缺失值处理) 本地CSV / 数据库 数据质量检查:缺失值、日期连续性、价格合理性

4.8 实战中的几个建议

场景 推荐数据源 注意事项
股票日线 Tushare Pro 注意复权方式,默认不复权
期货主力连续 Tushare Pro 用结算价而非收盘价
ETF行情 Akshare 列名是中文,需转换
可转债 Akshare 注意转股溢价率字段
指数成分股 Tushare Pro 需要较高积分权限

最后说一句:数据获取是基本功,但很多人栽在这上面。别急着跑策略,先把数据管道搭稳了。我见过太多人,策略逻辑写得漂亮,结果数据源一换,回测结果天差地别。

嗯,今天就到这儿。代码都给你了,自己去跑一遍,感受一下。

核心要点回顾:
  • Tushare适合股票和期货,Akshare适合ETF和可转债
  • 批量拉取必须加延时,避免被封
  • 数据质量检查是必须步骤,不能跳过
  • 字段对齐能让你在切换数据源时少改代码
专注资料整理