金融数据获取:用Tushare和Akshare搞定A股日线数据

做量化选股,第一步就是搞数据。没有数据,再牛的模型也是空中楼阁。

我个人习惯把数据获取比作「做饭前的买菜」。菜买不好,厨艺再高也白搭。今天咱们就聊聊怎么用Python把A股的日线数据拿到手,洗干净,存起来。

数据源的选择:Tushare vs Akshare

国内做量化,绕不开这两个库。我两个都用过,说说我的感受。

对比项 Tushare Akshare
数据质量 高,经过校验 中等,部分数据需二次处理
获取门槛 需要注册,有积分限制 免费,无需注册
数据范围 全面,含财务、因子等 覆盖主流,更新快
稳定性 高,有付费保障 依赖源网站,偶尔波动
适合场景 正式回测、生产环境 快速原型、学习研究

我的建议是:学习阶段用Akshare,省心;正式项目用Tushare,靠谱。

实战:用Akshare获取日线数据

先来个最简单的。用Akshare拿贵州茅台的历史日线。

import akshare as ak
import pandas as pd

# 获取贵州茅台日线数据
df = ak.stock_zh_a_hist(symbol="600519", 
                        period="daily", 
                        start_date="20200101", 
                        end_date="20231231", 
                        adjust="qfq")

print(df.head())
print(df.info())

跑完你会发现,数据字段挺全的:开盘、收盘、最高、最低、成交量、成交额……

但注意,这里有个坑——日期列是字符串格式。我刚开始做回测时没注意,直接拿字符串去算时间差,结果全错了。

⚠️ 我曾经踩过的坑:

获取到的日期列是object类型,不是datetime。必须手动转换:

df['日期'] = pd.to_datetime(df['日期'])

否则后续的时间切片、滚动计算都会出问题。

数据清洗:脏数据比没数据更可怕

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

  1. 检查缺失值——停牌日、节假日会导致数据缺失
  2. 检查异常值——比如某天涨幅超过100%,大概率是复权问题
  3. 检查重复值——同一个交易日出现两条数据

我一般这样处理:

# 1. 删除重复行
df = df.drop_duplicates(subset=['日期'])

# 2. 填充缺失值(前向填充)
df = df.fillna(method='ffill')

# 3. 过滤异常值
df = df[df['收盘'] > 0]  # 剔除价格为0或负数的数据

# 4. 重置索引
df = df.reset_index(drop=True)
💡 一个小技巧:

对于停牌日的数据,我习惯用前一天的收盘价填充。但如果你做的是高频策略,最好标记出来,别让模型以为市场在「平稳运行」。

数据存储:SQLite还是CSV?

这个问题我纠结过很久。直接说结论:

  • CSV:简单粗暴,适合小规模数据、快速验证
  • SQLite:结构化查询,适合多股票、多周期、需要频繁读取的场景

我个人推荐SQLite。为什么?你想想看,如果你要查「2023年所有涨幅超过5%的股票」,用CSV你得遍历所有文件,用SQLite一句SQL就搞定。

存到SQLite的代码:

import sqlite3

# 创建数据库连接
conn = sqlite3.connect('stock_data.db')

# 将DataFrame写入表
df.to_sql('daily_600519', conn, if_exists='replace', index=False)

# 验证
query_df = pd.read_sql("SELECT * FROM daily_600519 WHERE 日期 >= '2023-01-01'", conn)
print(query_df.head())

conn.close()

存成CSV更简单:

df.to_csv('600519_daily.csv', index=False, encoding='utf-8-sig')
📌 我的经验:

如果你只做一两只股票的分析,CSV完全够用。但如果你要管理全A股5000多只股票的历史数据,一定要用数据库。我曾经用CSV存了3000只股票的数据,结果一个文件夹里3000个文件,找数据找到崩溃。

知识体系总览

下面这张图,概括了本章的核心逻辑:

金融数据获取与处理流程 数据源 Tushare / Akshare 数据获取 日线数据下载 数据清洗 去重/填充/过滤 数据存储 SQLite / CSV 关键步骤说明: 1. 数据源选择:Akshare免费快速,Tushare稳定全面 2. 数据获取:指定股票代码、时间范围、复权方式 3. 数据清洗:处理缺失值、异常值、重复值 4. 数据存储:小规模用CSV,大规模用SQLite 注意:日期格式转换是常见坑点,务必检查数据类型

完整代码示例:一条龙搞定

最后,给你一个可以直接跑的完整脚本。把股票代码、起止时间改一下就能用。

import akshare as ak
import pandas as pd
import sqlite3
from datetime import datetime

def fetch_and_store(symbol, start_date, end_date, db_path='stock_data.db'):
    """
    获取股票日线数据并存入SQLite
    """
    print(f"正在获取 {symbol} 的数据...")
    
    # 1. 获取数据
    df = ak.stock_zh_a_hist(symbol=symbol, 
                            period="daily", 
                            start_date=start_date, 
                            end_date=end_date, 
                            adjust="qfq")
    
    # 2. 数据清洗
    df['日期'] = pd.to_datetime(df['日期'])
    df = df.drop_duplicates(subset=['日期'])
    df = df.sort_values('日期')
    df = df.reset_index(drop=True)
    
    # 3. 存储到SQLite
    conn = sqlite3.connect(db_path)
    table_name = f"daily_{symbol}"
    df.to_sql(table_name, conn, if_exists='replace', index=False)
    conn.close()
    
    print(f"✅ {symbol} 数据已存入 {db_path} 的 {table_name} 表")
    print(f"   共 {len(df)} 条记录,时间范围:{df['日期'].min()} ~ {df['日期'].max()}")
    
    return df

# 使用示例
if __name__ == "__main__":
    df = fetch_and_store("600519", "20200101", "20231231")
    print(df.head())
🔧 我的建议:

第一次跑的时候,先拿一只股票试试。确认数据没问题了,再批量获取。我曾经一次性跑了500只股票,结果发现复权参数设错了,全部重来……那叫一个酸爽。

好了,数据到手,清洗干净,存好地方。下一步就是怎么用这些数据构建选股模型了。不过那是后面章节的事,咱们先把基础打牢。


专注资料整理