从Tushare到Excel:一份给量化新手的股票数据获取与清洗实战指南

张开发
2026/4/19 12:06:16 15 分钟阅读

分享文章

从Tushare到Excel:一份给量化新手的股票数据获取与清洗实战指南
从Tushare到Excel量化新手的股票数据处理全流程实战刚接触量化分析时最令人头疼的往往不是复杂的算法而是如何把原始数据变成能直接使用的格式。记得我第一次从Tushare获取股票数据时面对密密麻麻的字段和混乱的日期格式完全无从下手——数据有了但根本没法用。这篇文章就是为解决这个问题而生我会带你完整走一遍从数据获取到清洗再到Excel导出的全流程重点解决那些没人告诉你的脏活累活。1. 环境准备与数据获取工欲善其事必先利其器。在开始前我们需要准备好Python环境和必要的库。推荐使用Anaconda创建专属的量化分析环境conda create -n quant python3.8 conda activate quant pip install tushare pandas openpyxlTushare的接口分为免费版和Pro版对于初学者免费版已经能满足大部分需求。注册后获取token的方式很简单import tushare as ts ts.set_token(你的token) # 在Tushare官网注册后获取 pro ts.pro_api()获取单只股票历史数据的典型代码如下以贵州茅台(600519.SH)为例df pro.daily(ts_code600519.SH, start_date20200101, end_date20221231)初次拿到数据时你可能会看到这样的结构ts_codetrade_dateopenhighlowclosepre_closechangepct_chgvolamount600519.SH202212301720.01728.01705.01719.01720.18-1.18-0.0733826.61580902.3提示Tushare返回的DataFrame默认索引是无序数字trade_date是字符串格式这些都需要后续处理2. 数据清洗的核心操作原始数据往往存在各种问题日期格式混乱、缺失值、需要计算的衍生字段等。下面这些操作能帮你把生数据变成熟数据。2.1 基础清洗步骤首先处理最棘手的日期问题。Tushare返回的trade_date是YYYYMMDD格式的字符串我们需要转换为Pandas的datetime类型df[trade_date] pd.to_datetime(df[trade_date], format%Y%m%d) df df.sort_values(trade_date) # 按日期排序接下来处理字段命名。Tushare的原始字段名对中国人不够友好我们可以建立映射关系进行重命名column_mapping { ts_code: 股票代码, trade_date: 交易日期, open: 开盘价, high: 最高价, low: 最低价, close: 收盘价, pre_close: 前收盘价, change: 涨跌额, pct_chg: 涨跌幅(%), vol: 成交量(手), amount: 成交额(千元) } df df.rename(columnscolumn_mapping)2.2 处理缺失值与异常值股票数据中常见的缺失情况包括停牌日数据全为NaN极端行情导致的部分字段缺失早期数据某些字段可能不存在处理方案需要根据具体情况选择# 简单删除缺失值适用于停牌日 df df.dropna(subset[开盘价,收盘价]) # 向前填充适用于部分字段缺失 df[成交量(手)] df[成交量(手)].fillna(methodffill) # 设置默认值适用于早期数据 df[成交额(千元)] df[成交额(千元)].fillna(0)2.3 计算衍生指标原始数据只提供基础字段实际分析中我们还需要计算各种技术指标。以下是几个常用指标的计算方法# 计算5日均线 df[5日均线] df[收盘价].rolling(5).mean() # 计算每日振幅最高价-最低价/前收盘价 df[日振幅(%)] (df[最高价] - df[最低价]) / df[前收盘价] * 100 # 计算换手率需要知道总股本 total_share 12.56 # 贵州茅台总股本(亿股) df[换手率(%)] df[成交量(手)] * 100 / (total_share * 1e4)3. 数据可视化与探索性分析清洗后的数据需要先进行可视化检查确保数据质量。Pandas内置的plot方法能快速生成基础图表import matplotlib.pyplot as plt # 设置中文显示 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 绘制价格走势图 df.set_index(交易日期)[[收盘价,5日均线]].plot( figsize(12,6), title贵州茅台2020-2022年股价走势, gridTrue ) plt.ylabel(价格(元)) plt.show()常见的探索性分析还包括收益率分布检查成交量与价格变动关系波动率聚类现象观察周内效应分析4. 导出为结构化Excel文件最终我们需要把处理好的数据导出为Excel方便与他人协作或存档。Pandas的Excel导出功能非常强大可以支持多sheet、格式设置等高级功能。4.1 基础导出方法最简单的单sheet导出df.to_excel(茅台股票数据.xlsx, indexFalse)但实际项目中我们通常需要更结构化的输出with pd.ExcelWriter(茅台股票分析报告.xlsx) as writer: # Sheet1原始数据 df.to_excel(writer, sheet_name日线数据, indexFalse) # Sheet2月度统计 monthly df.resample(M, on交易日期).agg({ 开盘价:first, 最高价:max, 最低价:min, 收盘价:last, 成交量(手):sum }) monthly.to_excel(writer, sheet_name月度统计) # Sheet3技术指标 tech_indicator df[[交易日期,5日均线,日振幅(%),换手率(%)]] tech_indicator.to_excel(writer, sheet_name技术指标, indexFalse)4.2 添加Excel格式使用openpyxl引擎可以进一步美化输出with pd.ExcelWriter(茅台股票分析报告(美化版).xlsx, engineopenpyxl) as writer: df.to_excel(writer, sheet_name日线数据, indexFalse) # 获取workbook和worksheet对象 workbook writer.book worksheet writer.sheets[日线数据] # 设置列宽 for col in worksheet.columns: max_length max(len(str(cell.value)) for cell in col) worksheet.column_dimensions[col[0].column_letter].width max_length 2 # 添加条件格式 from openpyxl.formatting.rule import ColorScaleRule rule ColorScaleRule(start_typepercentile, start_value10, start_colorFF0000, mid_typepercentile, mid_value50, mid_colorFFFFFF, end_typepercentile, end_value90, end_color00FF00) worksheet.conditional_formatting.add(H2:H1000, rule)5. 实战中的常见问题与解决方案在实际操作中你可能会遇到以下典型问题问题1数据量太大导致内存不足解决方案分时间段获取数据date_ranges [(2020-01-01,2020-06-30), (2020-07-01,2020-12-31)] dfs [] for start, end in date_ranges: dfs.append(pro.daily(ts_code600519.SH, start_datestart.replace(-,), end_dateend.replace(-,))) df pd.concat(dfs)问题2需要处理多只股票数据解决方案构建股票池批量处理stock_list [600519.SH, 000858.SZ, 600036.SH] all_data {} for code in stock_list: try: all_data[code] pro.daily(ts_codecode, start_date20200101, end_date20221231) print(f{code} 数据获取成功) except Exception as e: print(f{code} 获取失败: {str(e)})问题3自动更新数据解决方案记录最后更新时间增量获取import os if os.path.exists(last_update.txt): with open(last_update.txt,r) as f: last_date f.read() else: last_date 20200101 new_data pro.daily(ts_code600519.SH, start_datelast_date, end_datepd.Timestamp.now().strftime(%Y%m%d)) # 更新记录文件 with open(last_update.txt,w) as f: f.write(pd.Timestamp.now().strftime(%Y%m%d))处理股票数据最考验的不是编程技巧而是对金融业务的理解。比如复权处理就有多种方式前复权以当前价格为基准调整历史数据后复权以历史价格为基准调整当前数据定点复权以特定时点为基准# 简单的前复权处理示例 df[复权因子] df[收盘价] / df[前收盘价].cumprod() df[前复权收盘价] df[收盘价] / df[复权因子]记住好的数据清洗流程应该是可复现的。建议把所有处理步骤封装成函数甚至类方便下次直接调用class StockDataProcessor: def __init__(self, token): ts.set_token(token) self.pro ts.pro_api() def get_clean_data(self, ts_code, start_date, end_date): raw self.pro.daily(ts_codets_code, start_datestart_date, end_dateend_date) # 这里放入之前所有的清洗步骤 return cleaned_data最后分享一个实际项目中的经验处理金融数据时一定要保留原始数据的备份所有转换步骤都应该记录在代码中而非手动操作。我曾因为直接修改原始数据而丢失了重要信息不得不重新获取浪费了大量时间。

更多文章