恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
基于TuShare Pro的A股量化选股程序实战:从数据获取到策略落地
首页
资讯中心
/
基于TuShare Pro的A股量化选股程序实战:从数据获取到策略落地
基于TuShare Pro的A股量化选股程序实战:从数据获取到策略落地
发布时间:2026/9/8 13:46:56
简介面向量化投资初学者和Python开发者的A股自动选股项目基于TuShare金融数据接口实现了从行情获取、数据清洗到策略判断的完整流程适合用Python搭建选股框架或深入研究数据驱动投资策略。压缩包共25个文件、大小约1.95MB主体是17个Python源文件按模块分为数据拉取、主控工作流、策略计算与回测分析等另附README说明、依赖清单、配置文件和策略对比图表便于按图索骥。策略代码涵盖突破平台、250日均线回踩、海龟交易、低ATR、持续增长等常见思路并明确设置入场、出场边界可观察不同逻辑在历史行情下的表现。项目还提供数据库配置、通知与工作流脚本能直接体验每日自动扫描股票池并输出候选标的的完整过程。目前已有5963人学习或浏览目录结构清晰、模块耦合度低适合作为个人量化学习、策略实验及二次开发的参考起点。1. 为什么选TuShare做A股选股数据源我先说说背景这个项目的起点其实很朴素。每天收盘后我都要在几个炒股软件之间来回切换把当日涨幅、成交量、均线状态挨个翻一遍再手工记到表格里筛一遍。筛选条件少还好说一旦条件超过三个比如“20日均线在60日均线上方 当日放量1.2倍 排除ST 排除上市不满60天”手工操作就开始漏股票而且每天重复同样的动作效率极低。后来我想明白一件事选股这件事本质上就是一个数据过滤任务完全可以用程序替代。问题的核心只有一个——数据从哪来。市面上常见的免费A股数据源我也都试过。有的需要自己去爬网页解析起来麻烦不说网页结构一改代码就废了有的接口是收费的个人开发者扛不住还有的数据停留在日线层面财务指标、复权因子这些高级字段要另外找渠道。折腾了一圈最后落在TuShare上。TuShare Pro版也就是tushare pro提供一个稳定的接口日线行情、基础列表、财务指标、交易日历都能通过同一个token调用最关键的是数据字段比较规范省去了大量清洗工作。这篇文章我就完整记录一下我的选股程序是怎么搭起来的从环境准备、token接入到数据获取、策略编写再到限流规避和定时自动化。整个项目我已经在实际环境里跑了几个月期间踩过的坑都会写出来包括那些文档里没写明白的字段含义和容易翻车的细节。2. 环境准备与token接入先把数据门槛跨过去2.1 安装与验证项目整体使用Python 3.9依赖库不多核心就三个tushare、pandas、requests。安装命令如下pip install tushare pandas requests很多第一次接触TuShare的朋友会在这一步浪费大量时间。常见的情况是系统里装了好几个Python版本pip装完包之后代码跑起来却提示ModuleNotFoundError: No module named tushare。这多半是pip对应的Python版本和运行代码的Python版本不是同一个。我的建议是在项目目录下先建一个独立的虚拟环境再安装依赖。python -m venv venv source venv/bin/activate # Windows下是 venv\Scripts\activate pip install tushare pandas requests装完之后验证一下import tushare as ts print(ts.__version__)正常会输出版本号比如1.4.10。2.2 token的申请与使用逻辑TuShare Pro要求注册后才能在官网上获取token。这个token相当于你调用所有接口的通行证每个人的token绑定了对应的积分权限。注册后默认有100积分可以调一些基础接口如果你想调daily日线行情通常需要120积分调fina_indicator财务指标门槛会高一些需要2000积分以上。积分可以通过完善资料、留言等方式获得不是必须充钱。调用方式如下ts.set_token(你的token) pro ts.pro_api()这里有一个文档里不太强调的细节ts.set_token()设置一次token后TuShare会在本地生成一个缓存文件之后同一台机器上不再需要重复设置。但如果你在多台机器上跑脚本每台机器都要单独设置一次。我还建议把token放在环境变量里不要直接写死在代码中。尤其是后续要把脚本放到定时任务里运行的时候别人拿到你的脚本不会连带拿到tokenimport os TOKEN os.environ.get(TUSHARE_TOKEN, 你的默认token) ts.set_token(TOKEN) pro ts.pro_api()3. 核心数据流水线交易日历、股票列表、日线行情一个都不能少3.1 用交易日历解决“今天是不是交易日”的问题自动选股程序面临的第一个实际问题就是怎么知道今天是不是交易日你当然可以硬编码一个交易日清单但节假日调休安排每年都变硬编码维护成本太高。TuShare提供了交易日历接口trade_cal。我通常在每天开盘前先拉一次最近30天的日历数据df_cal pro.trade_cal(exchangeSSE, start_date20250101, end_date20251231) df_cal df_cal[df_cal[is_open] 1][cal_date].tolist()拿到这个列表后选股程序只在df_cal包含今天时才执行主逻辑否则直接退出。这样节假日、周末都不用额外处理。3.2 股票列表不只是拿个代码清单获取沪深两市的全部股票代码用的是stock_basic接口df_basic pro.stock_basic(exchange, list_statusL, fieldsts_code,symbol,name,area,industry,list_date)这里我建议一次性把字段拿全尤其是list_date和name。list_date用于计算上市时长name用于过滤ST、退市整理期等风险个股。还有一个容易忽略的点exchange参数填空字符串时返回沪深京三市所有股票如果只填SSE则只返回上交所。全市场扫描时一定要留空。3.3 日线数据优先按trade_date批量拉取日线行情是整个选股程序里数据量最大的部分。TuShare提供两种拉取方式按单只股票拉历史日线pro.daily(ts_code000001.SZ, start_date..., end_date...)按某一天拉全市场日线pro.daily(trade_date20250620)我在做全市场扫描时优先采用第二种方式。原因很简单一次调用就能拿到当天全市场5000多只股票的行情数据信息密度远高于挨个拉个股。等你把股票列表初步过滤到几十只或几百只之后再对候选池逐只补充历史均线数据整体效率会高很多。这里有个踩坑经验daily接口返回的pct_chg是涨跌幅百分比比如涨1.5%返回1.5不是0.015。数据处理时不要忘了这个量纲。另外所有金额字段的单位是千元不是元做市值、成交额计算时要自行换算。4. 选股策略落地从想法到能跑的规则4.1 基础过滤先排除掉“不能碰”的标的选股的第一步不是选好的而是排除坏的。我设置了五个基础过滤条件排除ST、*ST、退市整理期股票name字段包含ST或退排除上市未满60天的次新股排除当天停牌的股票daily数据里没有该股票的当天记录或vol为0排除上市状态不是L正常上市的股票排除北交所股票因为流动性差异较大且部分接口字段覆盖不全。第一个条件看似简单但要注意A股代码列表里有些股票的名字里天然含ST字样吗正常情况下不会但保险起见我会用name.str.contains(ST)和name.str.contains(退)两个条件同时判断。4.2 技术面策略RSI、均线、量能基础过滤完成后进入技术面策略层。我用的是三条件共振条件一20日均线在60日均线上方这代表中期趋势向上。计算时要注意复权问题。daily接口返回的是不复权价格如果股票中间有除权除息均线会失真。我的做法是使用pro.adj_factor接口获取复权因子再计算前复权价格df_adj pro.adj_factor(ts_codecode) # 合并后计算前复权收盘价复权价 不复权价 * 复权因子 / 最新复权因子不过考虑到选股池经过筛选后规模可控也可以直接用pro.daily接口单独拉取时指定adjqfq参数来获取前复权数据。只是要注意daily接口和pro.daily接口的传参方式略有不同pro.daily不支持adj参数需要使用ts.pro_bar。条件二RSI(14)处于50~75区间RSI大于50说明买方力量占优但超过75就进入超买区间追高风险大。50~75是一个比较舒服的强势区间。RSI的计算用pandas就能完成delta close.diff() gain delta.where(delta 0, 0.0) loss -delta.where(delta 0, 0.0) avg_gain gain.rolling(window14).mean() avg_loss loss.rolling(window14).mean() rs avg_gain / avg_loss rsi 100 - (100 / (1 rs))条件三当日成交量大于5日均量的1.2倍放量突破是资金进场的信号。注意这里的“5日均量”最好也基于前复权数据计算否则停牌复牌等异常情况会干扰计算结果。三个条件叠加后筛选结果基本能控制在几十只以内这时候再叠加财务面或人工复核。4.3 财务面策略有积分门槛的加分项TuShare的fina_indicator接口需要较高的积分权限如果积分不够代码要自动跳过财务筛选而不是抛异常终止整个程序。我建议把财务筛选设计成一个可配置选项USE_FINANCIAL True # 如果积分足够改为True财务筛选常用的核心指标包括ROE净资产收益率大于10%、毛利率大于30%、营收同比增长为正。这三个条件组在一起可以过滤掉大量基本面较弱的股票。积分不够的朋友也不用着急技术面策略单独跑也有参考价值。等积分上去了再开启财务过滤即可。5. 全市场扫描的实现细节分片拉取与限流避让5.1 按交易日批量拉取是性能关键全市场扫描时最忌讳的是循环5000次逐只拉日线。TuShare对调用频率有限制默认每分钟限制调用次数通常是每分钟500次左右但逐只拉取仍然会浪费大量时间和调用次数。我的做法是两步走第一步对最近一个交易日用pro.daily(trade_date...)一次性获取全市场当日行情。第二步经过基础过滤和当日行情初步筛选后候选池通常只剩几百只。此时再对候选池逐只获取历史日线用于计算均线和RSI。这样设计下来整个扫描过程调用次数可能在几百次左右完全在限流范围内跑完全市场大约只需要两三分钟。5.2 重试机制接口肯定会偶发失败TuShare接口在实际使用中偶尔会返回空数据或抛出网络异常这不是你代码的问题是服务端偶发状态。我在调用层封装了一个带重试的函数def safe_call(func, *args, retries3, **kwargs): for i in range(retries): try: return func(*args, **kwargs) except Exception as e: if i retries - 1: raise time.sleep(2 ** i) return None重试间隔用指数退避第一次失败等2秒第二次等4秒第三次等8秒。这比线性重试更合理既不会在接口短暂故障时频繁冲击服务端也不会让程序卡死太久。5.3 判断“今天该不该跑”还要考虑交易日数据延迟还有一个细节很容易被忽略交易日当天盘后当日的trade_cal已经显示为交易日但daily接口的当日数据可能还没完全更新。TuShare通常是收盘后过一段时间才更新当日数据。我的程序默认在每日下午6点后运行这时候当日数据基本已经齐了。如果你需要在盘中运行建议拉取最近一个已收盘的交易日数据而不是当天数据。可以这样判断latest_trade_date df_cal[-2] # 倒数第二个交易日即最近一个已收盘交易日6. 选股结果落盘与定时自动化程序要能自己跑起来6.1 输出结果CSV里塞足信息选股结果我会输出三个文件stock_pool.csv——当日选出的股票明细stock_pool_detail.csv——每只股票的技术指标明细包括收盘价、RSI、均线数值、量比等方便人工复核reject_reason.json——被排除的股票及排除原因。这个文件很有用它让你能随时回溯“为什么某只股票没被选中”尤其是当你的策略调整后可以对照历史排除原因验证新策略的合理性。股票明细表的字段设计如下字段含义ts_code股票代码name股票名称industry所属行业close收盘价pct_chg当日涨跌幅%rsi_14RSI(14)指标ma2020日均线ma6060日均线volume_ratio当日成交量 / 5日均量6.2 定时运行Windows与Linux都安排上程序写好后我用Windows任务计划程序设置了每日下午6点半自动运行一次。核心配置是程序路径python.exe的完整路径起始于项目目录运行条件只在计算机使用交流电源时运行避免笔记本睡眠导致任务错过。Linux服务器上更简单写进crontab30 18 * * 1-5 cd /path/to/project /usr/bin/python3 main.py logs/selection.log 21注意cron的1-5是指周一至周五交易日基本面是工作日但遇到节假日调休天然会多跑几次空脚本。不过由于程序内部有交易日历判断非交易日会自动退出不会产生脏数据。6.3 日志程序跑没跑、结果对不对全靠它日志是排障的第一抓手。我在项目中用Python标准库logging记录三类日志INFO级别的正常流程、WARNING级别的单只股票数据缺失、ERROR级别的程序级异常。比如每天筛选完成时日志会输出一行汇总2025-06-20 18:31:22 INFO - 扫描完成沪深京共5234只过滤后候选382只最终选中27只这行日志在复盘时非常有用——你可以快速看到当天的策略筛选率和市场状态辅助判断策略是否过于激进或过于保守。7. 回测验证选股结果到底能不能用先跑跑历史选股策略写完先别急着实盘参考。我的建议是先回测一段时间。不一定要用自带框架最简单的方式是把程序的“今天”参数改成历史某个日期让选股逻辑跑一遍然后检查被选中的股票在之后20个交易日内的表现。具体做法是给主函数加一个日期参数trade_date默认取最近已收盘交易日调试时传入任意历史日期。用历史某天的全市场数据跑完之后把选出来的股票保存下来再用TuShare拉这些股票后续20个交易日的日线统计平均涨幅、跑赢沪深300的比例。我自己的经验是如果策略在最近3个月的回测中都没有明显跑赢基准那就说明条件设置可能有问题需要回到第4章逐步调整。回测是检验策略逻辑最客观的手段这一步千万别跳。8. 几个实战中的坑最后统一说一遍我在跑这几个月的过程中遇到过几个比较隐蔽的坑统一记录在这里。接口权限与实际返回不一致。有些接口就算token积分看起来够了实际调用时还是会返回“抱歉您没有访问该接口的权限”。这种情况通常是积分和接口对应关系没对准。解决办法很朴实先写个test脚本拉一行数据试试确认权限没问题再写进主流程。复权和分红对均线的影响。前面提到过个股历史日线必须用前复权数据否则遇到大比例分红除权均线会被砸出一个大坑RSI也会失真。使用ts.pro_bar并指定adjqfq是最简单的方案。ST过滤的时间差。股票被ST是盘中公告而股票列表数据的更新存在延迟。也就是说某只股票当天刚被ST你的选股程序当天的日线数据里还是旧名称可能躲过过滤。这个问题目前没有完全的代码解法只能通过次日复核来弥补。我会每天把选中的股票再跑一遍当日行情检查如果发现名称变更就自动剔除。空数据不等于停牌。某些股票出现停牌时daily接口当天没有记录。但要注意新股上市首日也可能在部分接口里没有当日数据。所以停牌判断一定要放在上市时长过滤之后进行。这套程序我目前还保持每周至少复盘一次的频率主要看两个东西一是当日筛选结果是否合理二是回测指标有没有恶化。TuShare作为数据源整体稳定但策略本身不会一成不变市场风格切换后RSI区间、量比阈值这些参数都需要重新调。希望这个项目记录能帮你少走点弯路直接把数据流水线和策略框架搭起来然后把精力花在真正重要的策略迭代上。本文还有配套的精品资源点击获取