news 2026/9/1 12:41:08

用Python打造A股量化选股工具包:10大策略整合实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Python打造A股量化选股工具包:10大策略整合实践

简介:面向A股个人投资者与量化初学者的Python选股工具包,基于TuShare获取实时行情与基本面数据,内置10种常见技术选股逻辑,如250日均线突破、平台突破、回踩均线、停机坪形态、低ATR波动筛选、持续上涨趋势识别等,适合快速验证个人选股思路,同时也可作为初学者理解策略模块设计的参考。资源共27个文件,以17个Python脚本为主,配合图片(png/jpg)、依赖清单、配置文件及Markdown说明,压缩包仅1.96MB。脚本按职责独立封装:数据获取、SQLite本地存储、策略模块、回测统计、流程控制、买卖信号触发等,方便灵活组合与快速替换。目前已有103人学习下载,读者可获得从数据采集、本地存储、策略回测到交易信号生成的完整工具链,模块化设计便于二次开发扩展新策略,适合有一定Python基础的投资者快速搭建自己的选股系统。 搞了半年多的A股量化选股工具包,终于把10个策略脚本整合到一个项目里了。先说说这东西是干什么的:每天收盘后自动拉取全市场A股的行情、财务和交易数据,用10个不同的策略分别跑一遍筛选逻辑,输出符合各策略条件的股票清单和打分排名,第二天开盘前直接看结果就行。说白了,就是把我以前每天早上手忙脚乱翻十几个页面的人工选股流程,固化成一套可以重复执行的Python脚本。

这套工具包适合谁参考?如果你有一定Python基础,想用代码替代手工筛选;或者刚接触量化选股,想知道一个完整的选股工具包是怎么搭起来的,这篇内容应该对你有用。下面的内容会从策略逻辑、代码实现、回测验证到常见坑位,一点点拆开讲清楚。

需要先说明的是,这套工具包只负责选股信号和排名,不涉及自动下单,所有结果都需要你自己二次判断。我也不是荐股,文章里不会出现任何具体标的推荐,只会讨论方法和代码。

1. 为什么做这个工具包:从手工筛选到策略代码化

1.1 手工选股的痛点与策略固化的价值

以前每天选股的流程是这样的:先看涨幅榜、换手率,再逐个翻F10看财务数据、股东变化,遇到符合形态的还要切到K线图上确认一下均线结构。一轮下来少说大半个小时,而且很容易漏掉一些不在榜单里的票。最大的问题其实不在时间,而在"纪律"——连续跌几天之后再看什么票都觉得危险,连续涨几天之后又容易把"看得顺眼"当成买入理由。情绪一上来,所谓的选股规则全被抛到脑后了。

所以我想做的第一件事,不是把投资水平提升到多高,而是把"按规则选股"这件事固化下来。规则一旦写进代码,它就不会受情绪影响:市盈率超过某个阈值就剔除,不管这个票当天涨得多漂亮;均线死叉就标记风险,不因为它上一周涨得不错就选择忽略。代码化选股的核心价值,是让你的策略从"模糊的感觉"变成"明确的、可回测的、可复现的规则"。这一点在行情波动大的时候体会尤其明显,手动的筛选在恐慌行情里基本就是摆设,脚本反而能一丝不苟地执行预设逻辑。

1.2 工具包的整体架构与模块划分

这个工具包采用了一个很朴素的模块化结构,所有策略脚本放在strategies目录下,公共函数放在common模块里,数据缓存、日志、输出报告各归各的。结构如下:

quant_stock_selector/ ├── common/ │ ├── data_loader.py # 数据获取与缓存 │ ├── indicators.py # 技术指标计算 │ └── utils.py # 通用工具函数 ├── strategies/ │ ├── pe_low.py # 低市盈率策略 │ ├── dividend.py # 高股息率策略 │ ├── small_cap.py # 小市值策略 │ ├── momentum.py # 动量策略 │ ├── ma_cross.py # 均线突破策略 │ ├── rsi_reversal.py # RSI超跌反弹策略 │ ├── volume_surge.py # 成交量异动策略 │ ├── growth.py # 净利润增速策略 │ ├── capital_flow.py # 资金流向策略 │ └── multi_factor.py # 多因子打分策略 ├── main.py # 选股主流程 ├── report.py # 结果输出与汇总 └── config.yaml # 全局配置

模块化的好处很明显:新增一个策略只需要在strategies里加一个文件,实现一个统一接口,剩下的数据获取、结果输出、日志记录全部复用公共模块。后面想调整某个策略的阈值,也不需要动主流程,改配置或者改单个策略文件就行。这个设计后来帮我省了不少事,因为策略迭代的频率远比你想象得高,有时候一周就能冒出好几个想法要验证。

2. 10种策略的选股逻辑与Python实现要点

2.1 价值类策略:低市盈率与高股息率

低市盈率策略的逻辑很简单,就是找利润不差但市场给的价格相对便宜的股票。它的假设是市场短期会情绪化定价,但长期会回归基本面,所以买入估值洼地有机会获得估值修复的收益。实现上,先剔除亏损股(PE为负的),再对PE做升序排列取头部若干只。有一个容易被忽略的细节:PE用的是滚动市盈率(TTM)而不是静态市盈率,因为TTM用的是最近四个季度净利润之和,能更及时反映最新盈利状况,尤其是一季报或者中报刚出的时候,静态PE的数据往往是滞后的。

高股息率策略关注的是现金分红能力。代码里用过去12个月的每股累计分红除以最新股价来计算股息率,然后设定一个门槛值,比如股息率大于3%才进入候选池。这个策略的隐性要求是公司愿意且有能力持续分红,所以我会额外加一个条件:过去三年每年都实施了分红。这个条件的筛选能力比单纯的股息率门槛强很多,因为A股里不少公司一年分红一年不分的,稳定性没法保证,光看一年的股息率很容易踩雷。

2.2 趋势与动量类策略:均线突破与相对强弱

均线突破策略是技术派的老底子了。我实现的是双均线系统:短期均线上穿长期均线(金叉)时标记买入信号,下穿(死叉)时标记卖出信号。在选股场景里,我不会直接看信号当天是否金叉,而是看最近5天内是否发生过金叉,并且要求短期均线仍在长期均线上方。这么处理是为了避免信号刚生成就追高,给它一个缓冲窗口,兼容"回踩确认"的进场方式,实战中比单纯追当日金叉位要从容不少。

动量策略则完全不同,它不关心趋势是否刚转折,而是看谁涨得最凶。经典做法是取过去60个交易日的累计涨幅作为动量分数,然后排序选出动量最强的股票。这个策略在A股单独用效果不太好,因为市场风格切换很快,追高容易接盘,所以我把它和其他因子组合使用,很少单独作为选股依据。动量因子更适合用来做排序打分,而不是做硬性的入选条件。

2.3 反转与量能类策略:RSI超跌与成交量异动

RSI超跌反弹策略针对的是短期跌过头的情况。RSI小于30通常被视为超卖区,我会筛选出RSI进入超卖区但基本面没有明显恶化的股票,这类策略赚的是情绪修复的钱。实际操作中要格外注意一点:超跌的票有相当一部分是基本面出了问题的,所以这个策略必须叠加财务过滤条件。我一般要求净利润同比降幅不超过某一阈值,比如20%,不然很容易接住下落的刀。这是一条很重要的经验,光看技术指标做反转策略,在A股里会死得比较难看。

成交量异动策略关注的是量能变化。我定义了一个"量比"指标,用当日成交量除以过去5日平均成交量,量比大于1.5且股价上涨的股票,说明有资金在主动介入,会被标记为关注对象。这个策略单独看太敏感,任何突发事件都可能造成放量,所以我会在输出结果时把量比和涨幅、换手率放在一个表格里展示,让人工判断有足够的信息。这种策略的输出形态应该是"提示",而不是"结论"。

2.4 成长与资金类策略:净利润增速与资金流向

净利润增速策略是成长股筛选的经典方式。我用最新一期财报的净利润同比增长率作为核心指标,同时要求营收增速也保持为正,避免单靠非经常性损益造成利润虚高。还有一个我后来加的重要条件:剔除掉净利润绝对值规模太小的公司,因为基数太小的话,增速百分比没有意义,比如从1万元涨到2万元,增速100%但这个数字毫无参考价值。实际操作中,我会加上"归母净利润绝对值大于5000万"这样的门槛,把基数太小的直接过滤掉。

资金流向策略在A股语境下比较特殊,因为公开数据里并没有真正的"资金流向",各家平台计算的主动买入金额算法也不一样。我的做法是退而求其次:用大单成交净额作为代理指标,再叠加"近期主力净流入占比"这个复合条件。严格来说这不算精确的主力资金跟踪,但作为选股时的参考信号,聊胜于无,我通常把它和其他因子配合使用。注意不要迷信单一资金数据来源,不同平台给的净流入数字经常打架,这是数据口径本身的问题。

2.5 多因子打分与综合策略

单因子的有效性总是有周期的,所以我做了一个多因子打分策略作为压轴:将市盈率倒数、股息率、动量、波动率、ROE等5个因子做标准化处理后加权求和,得到每个股票的综合得分。权重的设置一开始我凭经验拍脑袋,后来改成用历史数据做因子IC分析,把IC值比较稳定的因子权重调高一些。这个策略的价值不是某个因子多厉害,而是通过分散因子来源降低单一因子失效带来的风险。

多因子策略的具体实现里,标准化这一步很容易出问题:有的因子是越大越好,比如ROE;有的因子是越小越好,比如市盈率。统一处理方式是对因子值做rank排序,再映射到0到1区间,这样所有因子的方向就一致了,后续加权求和也更有意义。实现时要注意每个因子的计算口径,尤其是波动率的计算要用对数收益率,不能用百分比收益率的简单标准差,否则结果会失真。

3. 核心脚本实现与每日自动运行

3.1 数据获取、清洗与本地缓存

数据是整个工具包的地基,我在数据获取上踩过不少坑。早期的方案是直接用第三方库的实时接口拉数据,结果经常遇到限流、字段缺失、编码错误等问题。后来改成了"盘中抓取+本地缓存"的方案:每个交易日收盘后拉一次全量数据,保存到本地SQLite数据库,选股脚本只读本地数据,不再实时请求网络。这样不仅速度快,也方便后续追溯历史结果,回测的时候直接查数据库就行。

清洗环节有三个必做的步骤:去重、去ST、剔除上市不足60个交易日的新股。ST股票在A股有特殊的涨跌幅限制,选股逻辑对它实际上是失真的,所以直接剔掉。上市不足60天的新股没有足够的历史数据,很多指标算不出来,也一并过滤掉。这三个过滤条件写在数据加载模块里,所有策略自动生效,不用每个脚本都重复写一遍。我见过不少新手把清洗逻辑散落在各个策略文件里,后面维护起来简直是一场灾难。

3.2 选股主流程与策略接口设计

主流程main.py的逻辑其实很薄,核心思想是"策略即函数",每个策略文件实现一个统一的process(df) -> df接口,传入清洗后的全市场数据,返回带标记和排序的结果。主流程做的事情就是遍历strategies目录下的所有策略文件,逐个执行,然后把结果汇总到一个总的Excel报告里。这样每个策略都是独立的,互不影响,改一个策略不会弄坏另一个。

我贴一段低市盈率策略的核心代码作为例子:

import pandas as pd def process(df: pd.DataFrame, cfg: dict) -> pd.DataFrame: # df: 全市场数据, 包含 code, name, pe_ttm, close 等字段 df = df[df['pe_ttm'] > 0] # 剔除亏损股 df = df[df['pe_ttm'] < cfg['pe_threshold']] # 市盈率上限 result = df.nsmallest(cfg['top_n'], 'pe_ttm') result = result[['code', 'name', 'pe_ttm', 'close']].copy() result['strategy'] = 'PE_LOW' result['rank'] = range(1, len(result) + 1) return result

这里有一个容易被新手忽略的点:cfg['pe_threshold']cfg['top_n']从config.yaml读取,而不是直接写死在代码里。参数和逻辑分离的好处是调参的时候不用改代码,改一下配置文件重新跑就行,后续做参数敏感性分析也方便得多。另外,nsmallest这个方法在处理全市场几千只股票时性能足够,但如果数据量再大一个量级,建议改成先排序再取前N行的写法,效率会更好。

3.3 每日自动运行与结果播报

自动运行部分用系统自带的任务计划程序就行(Windows下是任务计划,Linux下是crontab),不需要额外的调度框架。我自己的节奏是每个交易日晚上8点跑一次数据更新,8点10分跑选股主流程,生成报告后推送到手机。推送我用了一种特别简单的实现:生成报告后自动发送到钉钉机器人或者企业微信机器人,只需要一个webhook地址,代码里用requests.post就能搞定,不需要额外搭建消息服务。

每日报告的输出格式我建议固定为两层:第一层是汇总页,按策略分别列出当日选出的股票数量;第二层是明细页,每个策略一个sheet,包含代码、名称、关键指标和综合排名。这样每天早上扫一眼汇总页就能快速知道每个策略当天有没有选出标的,再按需看明细,效率会高很多。打印报告的时候我会把每个策略选出来的股票数量做一个统计,数量为零的策略会单独标红提示,防止脚本静默跑空数据。

4. 回测验证与过拟合防范

4.1 低成本回测方案与关键指标

选股脚本做出来以后,必须回答一个问题:这个策略是不是真的有效?如果不回测就直接实盘用,和闭着眼睛蒙没什么区别。我的做法是先做最朴素的回测:在历史数据上模拟每个策略的选股结果,假设持有20个交易日,计算收益率、最大回撤、胜率等统计指标。虽说这种简化回测不考虑滑点和冲击成本,但对于策略有效性的初步判断已经够用了。如果你想做更严格的回测,可以考虑把策略迁移到qlib这类开源的量化平台上,它提供了标准化的因子和回测基础设施,比自己在Excel里折腾高效得多。不过对于初版选股工具包来说,先把简化回测跑通更重要。

我建议用历史数据把每个策略都回测三年以上,时间太短的话,无法覆盖不同的市场阶段。A股的市场风格切换特别明显,一轮小盘行情、一轮白马行情、一轮震荡市下来,策略的短板和优势都会暴露得很充分。回测结果出来后,我会重点看两个指标:一是策略收益是否稳定,二是换手率是否过高。换手率太高的策略,实际交易成本会吃掉大部分理论收益,这是回测中最容易被忽视的陷阱。回测收益很漂亮但换手率一年十几倍的策略,实盘大概率是亏钱的。

4.2 参数敏感性分析与过拟合防范

参数过拟合是量化选股最容易犯的错误。比如RSI阈值,有人会把30改成29、31一个个试,最后挑出一个历史回测收益最好的数字,这个数字放在未来很可能完全不灵,因为它是专门针对历史数据调出来的。防范的方法有两个:一是做参数敏感性分析,把阈值在合理区间内变动,看策略表现是剧烈变化还是相对稳定;二是把数据分成样本内和样本外,用样本内数据调参,用样本外数据验证。

我的实操经验是:如果一个策略只在某个很窄的参数区间里表现好,换个参数就崩,这个策略基本可以放弃。真正有生命力的策略,参数变化时表现应该整体平滑,即使不是最优,也不会差太多。这个观察比纠结具体参数值重要得多。每次修改参数之后,我都要求自己在项目文档里记录改了什么、为什么改、回测结果如何,这样半年后回头看就知道当初的思路是什么,而不是面对一堆改了又改的代码无从下手。

5. 常见问题与排查技巧实录

5.1 数据质量与复权问题

量化选股脚本90%的Bug都出在数据上,而不是策略逻辑上。最常见的问题是复权处理不当。A股分红送股后,不除权和前复权的股价差异很大,如果直接在未复权数据上计算均线、涨幅、动量,结果会严重失真。我的做法是统一用前复权数据做指标计算,因为前复权保证了历史价格连续可比,选股回测时口径一致。后复权也能保证连续性,但当前价格会变得很大,看起来不直观,所以统一用前复权。

另一个经典问题是历史数据缺失。有些股票中途停牌几个月,复牌后的数据点和正常交易日的价格放在一起,会让各种移动平均计算产生巨大偏差。遇到这种情况,我建议在计算指标前先检查每个股票的有效交易天数,低于一定数量的直接跳过。还要注意财务数据有"发布延迟"的问题,一季报一般在4月底才披露,如果3月份就用一季报数据做回测,等于提前用了未来信息,属于典型的未来函数,这一点要特别小心。

5.2 未来函数与幸存者偏差

未来函数是我在回测和实盘对比中吃过亏的重灾区。最典型的就是财务报告延迟问题,还有一种是"当日收盘后选股、当日价格买入"的假设。真实操作中选股是收盘后跑的,最早也只能在下一个交易日开盘买入,回测如果假设当天就能以收盘价买入,收益会被放大,而且放大的幅度还不小。解决办法是把回测的买入时间点统一设成信号产生后的下一个交易日开盘,虽然这样会牺牲一点理论收益,但接近真实得多。

幸存者偏差则是另一个隐形的坑:如果股票池是用"当前还在上市的公司"数据构建的,那些退市的股票就不会出现在历史回测里,这会让回测结果系统性偏高。正确的做法是把历史上曾经存在过的股票都纳入数据范围,包括后来退市的。这个问题在大多数免费数据源上都存在,需要额外确认数据源的退市股票覆盖情况。我刚开始用免费数据跑回测的时候,收益漂亮得像股神,后来发现是幸存者偏差在作怪,修正之后数据就正常多了。

5.3 问题排查速查表

我在项目里维护了一个常见问题记录文档,把线上遇到的典型问题都记了下来,方便以后快速排查:

现象可能原因排查方向
策略结果为空过滤条件过严或数据字段异常先放宽阈值,再检查是否ST过滤误伤
指标出现NaN数据缺失或上市时间太短检查有效交易天数过滤逻辑
回测收益异常高存在未来函数或幸存者偏差核对财务数据时间戳、退市股覆盖
报告中的排名不稳定权重因子标准化方式不一致检查rank归一化方向是否统一
推送消息失败webhook地址失效重新生成webhook并更新配置

这张表是踩坑攒出来的,遇到新问题我会随时补进去,比翻代码排查省力不少。另外我还有一个习惯:每次跑完选股脚本,都会顺手把当天的全市场截面数据存一份快照,保留时间戳。这样如果某个策略在某个时间段突然失效,可以回溯到当时的市场环境去复现和分析,而不是只能看到当前的情形。

最后再分享一个我自己体会很深的东西:这套工具包的真正价值不在策略本身的胜率,而在于它把选股过程变成了一个可审计的流程。以前有人问我"你怎么选股的",我只能说个大概方向,现在我可以直接打开报告,说清楚每个策略在什么条件下选出了什么股票。如果哪个月账户跑输大盘,我还能翻出历史选股记录复盘,是市场风格问题还是策略失效问题,一目了然。这个能力,我觉得是所有想长期和量化打交道的人最应该先建立起来的。工具包本身还在持续迭代,下一个想加进去的方向是持仓组合的风险暴露分析,等做完再单独写一篇。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 12:40:51

智能体研发步骤证据工具:从输入校验到离线报告的完整实现

智能体研发步骤证据工具&#xff1a;从输入校验到离线报告的完整实现 项目编号&#xff1a;20260901-003。本文代码、测试、文档、示例数据和效果图均为独立编写&#xff0c;不包含热点产品或开源项目源码、品牌素材与官方截图。 问题与目标 关联需求、设计、实现、测试、评审…

作者头像 李华
网站建设 2026/9/1 12:38:02

清华大学C语言教程:198集系统学习与开发环境搭建指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/1 12:35:20

基于STM32的五种验证方式融合门禁系统设计与实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/1 12:33:22

Fluent UDF造波全解析:二阶Stokes波浪模拟从公式到调参

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/1 12:30:32

Unity 2D俯视角射击游戏源码实战解析:角色控制、敌人AI与血条UI

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/1 12:29:16

开源漏洞披露流程告急:从传闻到响应的主动安全防线

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华