企业微信

获取多支股票数据的必要性

在量化交易和数据分析中,常常需要同时获取多支股票的历史交易数据,以便进行组合分析、回测或监控。tushare作为国内流行的金融数据接口,提供了多种方式来满足这一需求。

使用pro_bar接口获取多支股票数据

pro_bar是tushare提供的一个便捷函数,专用于获取股票日线数据,它支持单个股票代码,但通过循环或自定义函数可以轻松扩展到多支股票。

初始化接口

确保已安装并导入tushare,并设置token(需在tushare官网注册获取)。


import tushare as ts

import pandas as pd

ts.set_token('你的token')

pro = ts.pro_api()

定义多股票代码列表

创建一个包含所需股票代码的列表,例如沪深300成分股中的部分股票。

tushare如何同时获取多支股票的交易数据?


stock_list = ['000001.SZ', '600000.SH', '000002.SZ', '600036.SH']  # 平安银行、浦发银行、万科A、招商银行

逐一获取并合并数据

使用循环迭代每个股票代码,调用pro_bar获取数据,并将结果存储在一个字典中,最后使用pd.concat合并。


def get_multi_stock_data(stock_list, start_date='20200101', end_date='20231231'):

    data_dict = {}

    for code in stock_list:

        df = ts.pro_bar(ts_code=code, start_date=start_date, end_date=end_date)

        if df is not None and not df.empty:

            df['stock'] = code  # 添加股票代码列

            data_dict[code] = df

    # 将所有数据纵向合并

    if data_dict:

        all_data = pd.concat(data_dict.values(), ignore_index=True)

        return all_data

    else:

        return pd.DataFrame()

all_data = get_multi_stock_data(stock_list)

print(all_data.head())

注意:pro_bar返回的日期是字符串格式,若要按日期排序,需转换。由于pro_bar默认返回未复权数据,可通过adj参数调整复权方式。

使用query接口批量获取

tushare的query接口(如daily)也支持传入多支股票代码,但需要利用循环或线程池。query接口更适合获取单只股票的多天数据,对于多股票,通常通过循环调用。

使用daily接口


def get_daily_data(stock_list, start_date='20200101', end_date='20231231'):

    all_data = []

    for code in stock_list:

        # 每次插入sleep以规避频率限制

        time.sleep(0.2)

        df = pro.daily(ts_code=code, start_date=start_date, end_date=end_date)

        if df is not None and not df.empty:

            df['stock'] = code

            all_data.append(df)

    if all_data:

        return pd.concat(all_data, ignore_index=True)

    else:

        return pd.DataFrame()

import time

all_data = get_daily_data(stock_list)

注意循环中的time.sleep用于避免触发tushare的访问频率限制(每分钟最多200次,根据积分)。积分越高限制越宽。

高效批量获取技巧

对于数量较多的股票(如几百上千),循环可能效率低下,且易受频率限制。可以采用以下策略:

使用线程池并发请求

利用concurrent.futures.ThreadPoolExecutor并发请求,但注意tushare的限速,需要控制并发数。


from concurrent.futures import ThreadPoolExecutor, as_completed

def fetch_single(code):

    df = pro.daily(ts_code=code, start_date='20200101', end_date='20231231')

    if df is not None and not df.empty:

        df['stock'] = code

        return df

    return None

with ThreadPoolExecutor(max_workers=5) as executor:

    future_map = {executor.submit(fetch_single, code): code for code in stock_list}

    all_data = []

    for future in as_completed(future_map):

        result = future.result()

        if result is not None:

            all_data.append(result)

final_data = pd.concat(all_data, ignore_index=True)

但注意,过度并发可能导致封IP,建议根据自身积分设置合理并发数。

利用历史行情接口(如pro_bar)的批量支持

tushare的某些接口,例如pro_bar,并不直接支持多股票代码,但ts.pro_bar内部可能调用的是query,因此同样需要循环。

数据格式与存储

合并后的数据包含多支股票的交易数据,每一行对应某一天某股票的OHLCV等指标。建议将日期转换为datetime格式,便于时间序列分析。


all_data['trade_date'] = pd.to_datetime(all_data['trade_date'])

all_data = all_data.sort_values(['stock', 'trade_date'])

可将数据存储为CSV或Parquet格式,便于后续复用。


all_data.to_csv('multi_stock_data.csv', index=False)

实际应用注意事项

  • 数据完整性:部分股票可能有停牌或退市,数据可能缺失,需处理缺失值。

  • 财务数据与其他数据:若需同时获取财务指标,可调用财务接口,同样采用循环。

  • 接口权限:tushare积分2000以上可获取更多数据,否则部分接口不可用。积分可通过社区贡献或付费获得。

  • 频率控制:tushare根据积分限制每分钟访问次数,需查阅文档合理规划请求间隔。

tushare同时获取多支股票的交易数据主要依靠循环或并发调用单股票接口,避免直接传参多个代码。通过构建函数封装,可以灵活控制数据范围与输出格式。在实际操作中,要根据数据量、频率限制和积分情况选择合适的方法。