基于Tushare与Flask构建板块轮动回溯分析工具
1. 为什么需要板块轮动回溯分析工具在股票投资中板块轮动是一个非常重要的现象。简单来说就是不同行业的股票会在不同时间段表现出不同的涨跌趋势。比如春节前后消费板块通常会表现较好而科技板块可能在年报季有不错的表现。如果能把握这种轮动规律对投资决策会有很大帮助。但问题是普通投资者很难直观地看到这种轮动规律。行情软件通常只显示当天的板块涨跌要查看历史数据往往需要付费。这就是为什么我们需要自己动手用Tushare和Flask搭建一个简单的回溯分析工具。这个工具可以让你输入任意时间段就能看到那段时间哪些板块涨得最好、哪些跌得最惨。我刚开始研究量化投资时就遇到过这个问题。当时想看看过去半年哪些板块表现最好结果发现免费工具根本做不到。后来发现Tushare这个宝藏数据接口配合Flask做个简单的Web界面问题就迎刃而解了。整个过程其实并不复杂即使你Python基础一般也能跟着做出来。2. 准备工作获取数据接口权限2.1 注册Tushare账号首先需要去Tushare官网注册账号。这个平台提供了丰富的金融数据接口包括股票、基金、期货等。注册是完全免费的但有些接口需要一定的积分才能调用。对于我们的板块数据需求基础权限就足够了。注册完成后在个人中心可以找到你的API token。这个token相当于你的身份凭证每次调用接口都需要带上它。建议把这个token保存好不要泄露给别人。2.2 安装必要的Python库我们需要三个主要的Python库tushare用于获取股票和板块数据flask用来构建Web应用pandas处理数据表格安装命令很简单pip install tushare flask pandas如果你用的是Anaconda也可以用conda安装。我建议单独创建一个虚拟环境来做这个项目避免和其他项目的依赖冲突。3. 核心代码实现3.1 获取板块列表数据Tushare提供了ths_index接口来获取同花顺板块指数列表。这个接口返回的数据包含板块代码、名称、交易所等信息。我们需要先获取所有A股的板块列表。import tushare as ts from flask import Flask, request, jsonify import time ts.set_token(你的token) # 替换成你的实际token pro ts.pro_api() # 获取板块列表 block_list pro.ths_index() block_dict {} for i in range(len(block_list)): if block_list.loc[i, exchange] A: # 只取A股板块 block_dict[block_list.loc[i, ts_code]] block_list.loc[i, name]这里有个小技巧因为板块数据量不大我们可以一次性全部获取然后过滤出A股的板块。得到的block_dict字典中键是板块代码值是板块名称。3.2 计算板块平均涨跌幅接下来是最关键的部分计算指定时间段内每个板块的平均涨跌幅。Tushare的ths_daily接口可以获取板块的日线行情数据。def calculate_sector_performance(start_date, end_date): results [] sector_codes list(block_dict.keys()) for i, code in enumerate(sector_codes): # 获取板块日线数据 df pro.ths_daily( ts_codecode, start_datestart_date, end_dateend_date, fieldsts_code,trade_date,pct_change ) # 计算平均涨幅和跌幅 up_days df[df[pct_change] 0] down_days df[df[pct_change] 0] avg_up round(up_days[pct_change].mean(), 2) if not up_days.empty else 0 avg_down round(down_days[pct_change].mean(), 2) if not down_days.empty else 0 results.append({ name: block_dict[code], code: code, avg_up: f{avg_up}%, avg_down: f{avg_down}%, up_days: len(up_days), total_days: len(df) }) # 遵守API调用频率限制 if (i 1) % 5 0: time.sleep(62) # 按平均涨幅排序 return sorted(results, keylambda x: float(x[avg_up][:-1]), reverseTrue)这里有几个需要注意的地方Tushare的API有调用频率限制每分钟最多5次所以每查询5个板块后需要暂停62秒我们分别计算了上涨日和下跌日的平均涨幅/跌幅结果按平均涨幅从高到低排序方便后续分析4. 用Flask构建Web界面4.1 创建基础Flask应用Flask是一个轻量级的Python Web框架非常适合这种小型工具的开发。我们先创建一个简单的Web服务app Flask(__name__) app.route(/) def index(): return form action/analyze methodget 开始日期: input typedate namestart_datebr 结束日期: input typedate nameend_datebr input typesubmit value分析 /form 这个简单的界面包含一个表单让用户输入开始和结束日期。提交后会跳转到/analyze接口。4.2 添加数据分析接口接下来创建处理数据分析的接口app.route(/analyze) def analyze(): start_date request.args.get(start_date).replace(-, ) end_date request.args.get(end_date).replace(-, ) results calculate_sector_performance(start_date, end_date) # 简单的HTML表格展示结果 html h2板块轮动分析结果/h2 html fp分析时段: {start_date} 至 {end_date}/p html table border1trth板块名称/thth平均涨幅/thth平均跌幅/thth上涨天数/thth总交易日/th/tr for item in results: html ftrtd{item[name]}/tdtd{item[avg_up]}/tdtd{item[avg_down]}/tdtd{item[up_days]}/tdtd{item[total_days]}/td/tr html /table return html if __name__ __main__: app.run(debugTrue)这个接口做了以下几件事获取用户输入的日期参数调用之前写的calculate_sector_performance函数将结果以HTML表格的形式返回给用户4.3 添加可视化功能纯数字可能不够直观我们可以用简单的柱状图来展示结果。这里使用matplotlib生成图表import matplotlib.pyplot as plt from io import BytesIO import base64 def create_plot(results): plt.figure(figsize(10, 6)) names [x[name] for x in results[:10]] # 只显示前10个 values [float(x[avg_up][:-1]) for x in results[:10]] plt.barh(names, values) plt.xlabel(平均涨幅(%)) plt.title(板块平均涨幅排名) plt.tight_layout() # 将图表转为base64编码的图片 buffer BytesIO() plt.savefig(buffer, formatpng) buffer.seek(0) return base64.b64encode(buffer.getvalue()).decode()然后在analyze接口中添加app.route(/analyze) def analyze(): # ...之前的代码... # 生成图表 plot_url create_plot(results) html fimg srcdata:image/png;base64,{plot_url} return html这样结果中就包含了直观的图表展示更容易看出哪些板块表现突出。5. 实际应用与优化建议5.1 典型使用场景这个工具在实际中有很多应用场景回溯特定事件如政策发布、节假日对板块的影响分析不同市场阶段牛市、熊市的板块轮动特征验证自己的板块轮动假设是否成立比如你可以比较春节前后消费板块的表现或者看看年报季期间哪些板块通常表现较好。5.2 性能优化建议原始版本有几个可以改进的地方缓存板块列表板块列表数据变化不频繁可以缓存起来避免重复查询from functools import lru_cache lru_cache(maxsize1) def get_sector_list(): return pro.ths_index()异步处理大量数据查询时可以改用异步方式避免阻塞Web请求from flask import Flask, jsonify import asyncio app Flask(__name__) async def fetch_sector_data(code, start_date, end_date): # 异步获取单个板块数据 pass app.route(/analyze_async) async def analyze_async(): # 异步处理逻辑 pass分页显示结果很多时可以添加分页功能from flask import request page int(request.args.get(page, 1)) per_page 20 paginated_results results[(page-1)*per_page : page*per_page]5.3 扩展功能思路这个基础工具还可以进一步扩展添加更多分析维度如波动率、最大回撤等支持多时间段对比分析加入基本面数据交叉验证开发更友好的前端界面我在实际使用中发现最简单的版本往往最实用。不必一开始就追求大而全先解决核心需求再逐步迭代完善。这个工具虽然代码量不大但已经能提供很有价值的板块轮动洞察。