如何利用akshare批量获取多只股票的历史数据?

企业微信

akshare批量获取股票历史数据的方法

akshare是一个基于Python的开源金融数据接口库,提供股票、期货、基金等多类金融数据。针对批量获取多只股票历史数据的需求,akshare提供了多种接口和灵活的处理方式。

一、选择合适的数据接口

akshare中获取股票历史数据的核心接口是stock_zh_a_hist,该接口用于获取A股个股的历史行情。其参数包括symbol(股票代码)、period(周期,如日、周、月)、start_dateend_date(日期范围)、adjust(复权类型)等。该接口返回DataFrame,包含日期、开盘、收盘、最高、最低、成交量等字段。

对于多只股票,常见的做法是循环调用该接口,并将结果合并。但需要注意接口的调用频率限制,避免触发反爬机制。

二、批量获取的两种主流方式

1. 循环请求与数据合并

手动编写循环遍历股票代码列表,每次调用stock_zh_a_hist获取单只股票数据,然后利用pandas的concat函数纵向合并。合并时,可以在数据中添加一个“股票代码”列以区分不同股票。

如何利用akshare批量获取多只股票的历史数据?


import akshare as ak

import pandas as pd

# 股票代码列表

stock_list = ['000001', '600000', '000002']

# 存储所有数据的列表

alldata = []

for code in stock_list:

    # 获取单只股票历史数据

    df = ak.stock_zh_a_hist(symbol=code, period='daily', start_date='20230101', end_date='20231231', adjust='qfq')

    # 添加股票代码列

    df['股票代码'] = code

    alldata.append(df)

    # 简单延迟,避免请求过快

    time.sleep(0.1)

# 合并所有数据

combined_df = pd.concat(alldata, ignore_index=True)

# 按日期和代码排序

combined_df.sort_values(['日期', '股票代码'], inplace=True)

这种方式简单直接,适用于股票数量较少(几十只)的情形。缺点是需要二次排序,且频繁请求可能被服务器拒绝。

2. 使用akshare的批量接口(如果存在)

akshare部分接口支持批量参数,比如stock_zh_a_hist本身不支持多代码同时获取,但其他接口如stock_zh_a_spot可以获取所有股票的实时快照,但历史数据则没有统一批量接口。因此,更高效的方式是使用异步请求或线程池来并发获取,但需注意akshare内部实现为同步请求,并发需自行实现。

三、高效批量获取的策略

对于大规模批量获取(数百只股票),建议采用以下策略:

  • 增加休眠时间:在每次请求后设置适当的time.sleep(0.5)左右,降低封IP风险。

  • 使用代理或更换IP:若需获取大量数据,可配置多个代理IP随机轮换。

  • 缓存机制:设计本地缓存(如pickle或parquet),避免重复请求相同数据。

  • 断点续传:记录已成功的股票,失败时重试,确保任务完成。

代码实现时,可以结合tqdm显示进度,便于监控。


from tqdm import tqdm

import time

# 增加进度条

for code in tqdm(stock_list):

    try:

        df = ak.stock_zh_a_hist(symbol=code, period='daily', start_date='20230101', end_date='20231231', adjust='qfq')

        df['股票代码'] = code

        alldata.append(df)

    except Exception as e:

        print(f"{code} 获取失败: {e}")

        continue

    time.sleep(0.2)  # 合理休眠

四、处理数据的一致性和完整性

批量获取的数据可能存在缺失日期或停牌问题。对于合并后的数据,可进行以下处理:

  • 检查缺失:每只股票的日期范围是否一致,可使用pd.date_range生成交易日历检查。

  • 去重:若重试导致重复,需去重。

  • 对齐:若需要面板数据(宽表),可使用pivot操作将数据透视为以日期为索引、股票代码为列的形式。


# 透视成宽表:每个变量一个宽表

close_pivot = combined_df.pivot(index='日期', columns='股票代码', values='收盘')

五、一次获取多只股票的简化函数

封装一个函数以简化调用,该函数接受股票列表和日期参数,返回合并后的DataFrame。


def fetch_stock_history(stock_list, start_date, end_date, period='daily', adjust='qfq'):

    data_list = []

    for code in stock_list:

        df = ak.stock_zh_a_hist(symbol=code, period=period, start_date=start_date, end_date=end_date, adjust=adjust)

        if not df.empty:

            df['股票代码'] = code

            data_list.append(df)

        time.sleep(0.1)

    if data_list:

        return pd.concat(data_list, ignore_index=True)

    else:

        return pd.DataFrame()

使用此函数,即可获取多只股票在指定时间段内的历史数据,后续可直接用于计算收益率、波动率等。

六、实际应用中的注意事项

  1. 数据源限制:akshare的数据源来自东方财富、新浪等,可能存在更新延迟或字段差异,需及时关注文档。

  2. 复权问题:使用前复权(qfq)更适合技术分析,后复权(hfq)用于收益计算,需根据需求选择。

  3. 频率限制:akshare没有官方QPS规定,但过快的请求可能被临时封禁,建议控制请求间隔。

  4. 内存占用:获取长期大规模数据时,注意合并后DataFrame所占内存,可使用dtype压缩或分块保存。

七、案例分析:获取沪深300成分股历史数据

假设需要获取沪深300成分股过去一年的日线数据。第一步,通过akshare获取成分股列表index_stock_cons,然后批量请求。


# 获取沪深300成分股代码

stock_cons = ak.index_stock_cons(symbol='000300')

code_list = stock_cons['品种代码'].tolist()[:10]  # 示例仅取前10只

data = fetch_stock_history(code_list, start_date='20230101', end_date='20231231', adjust='qfq')

运行后即可获得一个包含所有股票历史数据的大型DataFrame。

akshare库完全支持批量获取多只股票的历史数据,通过循环请求和pandas合并即可实现。关键在于控制请求频率、处理异常、优化合并方式。对于量化研究,此方法可快速构建个股历史数据库,为后续的分析奠定基础。

无论是个人投资者还是量化团队,利用akshare批量获取数据都能大幅提升数据准备效率。掌握该方法,即可轻松获取A股海量历史行情数据。

转载请注明出处:https://www.lianghuajiaoyi.top/wenzhang/akshare-piliang-huoqu-469.html