跳到正文

研究指南

股票筛选与候选名单

选股结果为零怎么办:逐项定位卡住股票池的条件

选股结果为空,可能是确实没有股票同时满足条件,也可能是阈值单位写错,或者必须的观测根本没有取得。这三种情况需要不同处理。应保留原始筛选配置,先查输入,再做小范围诊断实验,最后决定是否修改研究要求。让名单出现更多股票,本身不是修复成功的标准。

本文使用三只虚构股票,把真实空交集、百分比单位错误和字段覆盖不足分开。脚本只对合成输入实际运行,不调用行情供应商,不评价历史收益,也不证明CoTrading已有对应故障诊断入口。不同市场可以参考流程,但必须独立核对字段定义与可用性。

先保存能够重复的零结果基线

保留股票池、数据快照、截止时间、规则版本、运算符和阈值,并记录第一次执行是否真正完成。接口失败后返回空数组,不能被写成“筛选成功,零只入选”。请求状态与股票数量是两个字段;只有输入被完整取得并执行后,候选数量才有确定含义。

本例确认的规则是市盈率严格小于20,年度收入增速至少10%。增速按比例存储,阈值为0.10。AAA的市盈率18、增速0.08;BBB为24、0.15;CCC为30、增速缺失。三只股票中只有两只具备两个必需字段。所有数据都是虚构数值,口径已在样例内约定,不代表真实公司的经营情况。

不改任何配置先跑基线。AAA被增速挡住,BBB被市盈率挡住,CCC既已不满足市盈率,又缺收入增速。完整观测中的确没有候选。缺失观测仍要进入覆盖报告,不能因为CCC反正不入选,就把它描述成已经测得增长不足。不同状态会决定下一步到底要补数据还是研究规则。

放宽前先检查单位和字段语义

把条件表与数据字典逐项比较。10%的收入增速可以存成百分数10,也可以存成比例0.10,只要字段与阈值一致就可以。对比例值使用阈值10,实际要求变成1000%,研究含义已经完全不同。只有先确认数据单位,才能判断配置有没有写错。

抽看原始行,保留原始字符串和转换后的数字。不要仅因为多数值很小,就推断供应商采用比例:某些公司可能确实增长很弱,百分数列也可能出现极端值。来源的单位声明比观察数值分布后猜测更可靠。遇到两种口径混杂的文件,应先隔离输入,而不是为得到结果寻找一个折中阈值。

SEC EDGAR官方接口说明展示了财务事实需要附带单位和期间上下文。它不是任意选股数据商的字段字典,实际任务仍须查对应来源及披露。把错误单位改回已确认要求叫实现修复;把原来确认的要求降低,叫研究范围调整。两者要分别留痕,不能都称为“优化筛选器”。

同时看单条件通过数与交集

诊断表应包含总行数、有值行数、单条件通过数和未知数。本例市盈率条件只有AAA通过;增速条件在两条有值记录中只有BBB通过。两个条件各自都有人通过,并不意味着它们的交集有人通过,因为通过的是不同股票。这种空交集可以完全没有程序错误。

实验市盈率规则增速规则通过股票
原始配置小于20至少0.10无
只放宽市盈率小于25至少0.10BBB
只放宽增长小于20至少0.05AAA

逐条件执行的剩余数量可以告诉我们在哪一步归零,但它受执行顺序影响。某条规则放在后面,可能因为前面已淘汰了相关股票而显得没有作用。因此还应对原始股票池计算各条件独立通过情况。顺序漏斗解释运行路径,独立统计解释每项要求的覆盖,两者不能互相替代。

一次只改一个条件做实验

原配置保持不变,另外建立命名清楚的候选方案。每个方案只改一个数值要求,固定股票池、数据及其他条件。这样恢复的候选才可以归因于这一处变化,研究者才能判断扩大后的范围是否还回答原问题。一次同时降低市盈率和增速门槛,会让原因难以分辨。

def screen(pe_limit=20, growth_floor=.10):
    return [r["symbol"] for r in rows
            if r["growth"] is not None
            and r["pe"] < pe_limit
            and r["growth"] >= growth_floor]

baseline = screen()
pe_proposal = screen(pe_limit=25)
growth_proposal = screen(growth_floor=.05)

完整标准库文件为docs/growth/research/round-5/examples/R522.py,可用Python直接执行。实际输出是原始结果空数组,只放宽市盈率得到BBB,只放宽增长得到AAA;增速覆盖为2/3。断言还验证错误比例阈值10产生零结果,以及实验后重新调用原函数仍得到原始空结果。本例数字远离舍入边界;若任务需要精确财务阈值,可参照Python Decimal文档采用明确的十进制表示。

下载完整示例。使用Python 3.12+,仅需标准库,全部为合成数据;下载后运行python R522.py。

代码的缺值检查只保证没有数据的行不会进入通过名单,并不是完整三态报告器。正式实现应分别列出已知失败和无法判断的行,保留每条不满足及缺失的条件。短样例验证的是单条件实验,不应被包装成已经覆盖全部供应商异常的选股系统。

分开记录修错、补数和政策选择

不同机制反例是比例单位写错。如果系统存了增长阈值10,而需求和数据字典确认是比例值10%,应改为0.10,并标记单位修复。这个样例修好后仍然零只入选,说明单位错误确实存在,却不是空交集的全部原因。不能因为候选数量没变,就否认实现有错误。

把增长门槛从确认的10%降到5%,则是主动放宽。它让增长8%的AAA入选,不证明原始10%写错。同理,把市盈率放宽到小于25,允许24倍的BBB进入,是改变研究范围。如果把这两项叫修复,会让使用者以为系统仍在执行原来的投资要求。

缺字段走第三条路径:取得定义匹配的观测、保留来源,再重算受影响股票。不能通过降低阈值绕开一个根本拿不到的字段。如果来源不支持该字段,应报告任务仅部分执行,并说明哪些股票或条件无法完成。模型凭常识补出一个增速,不属于数据修复。

用决策表结束诊断

交付未改变的基线、覆盖摘要、已定位的实现错误和彼此独立的放宽方案。每个方案写清改了哪条条件、恢复多少只及具体名单,以及仍有哪些数据未解决。研究范围变化经选择后才写进新的保存版本;原始零结果也可以是正确的最终结论。

后续重跑的触发条件包括确认的单位错误已修正、缺失观测已经取得,或用户明确改变要求。比较前后结果时使用相应标签,区分代码修复、数据更新与政策变化。该流程不把当前股票池变成历史成员池,也不证明更宽松的条件具有更高研究质量;它交付的是可以解释的诊断证据和可选择的下一步。

为诊断实验保留变更台账

每个实验保存父基线编号、改变参数、未改变输入引用和产生成员集。只放宽市盈率与只放宽增长两个方案,都应直接从原基线分支。不能先放宽市盈率,再在其上降低增长,却把第二次输出称为“只改增长”;那样实际同时测试了两次变化,因果解释已经失效。

选定修复后,重放最初失败样例及未受影响的其他样例。单位转换应修复表示,不改变原定运算符;补数应增加一条有来源观测,不顺手修改阈值。这样的小型重放能发现排障过程中意外引入的政策变更,避免一个故障修好、另一个问题被掩盖。

诊断也可以以“不改变任何研究要求”结束。此时保存带覆盖边界的零结果基线,并注明何时因新数据再次检查。没有候选是一种可交付结论,前提是系统能说清执行了什么、哪些输入仍未知,以及没有擅自为得到名字改变条件。

报告还应附上实验未覆盖范围。例如本例没有自动判断数据商字段是否正确映射,也没有验证整个市场是否存在其他合格股票;它只对冻结的三行输入负责。扩大股票池后重新检查覆盖,不能把小样例诊断结论直接套给全市场。每次排障最好保留一个原始失败输入,让之后的规则维护可以再次重现这次具体问题,而不是只留下“已修复”的状态。

常见问题

可以自动放宽到出现股票为止吗?

不应如此。可以生成可复跑方案,但未选择范围变化前应保留原始要求。

修好单位仍然零结果,是不是不用修?

不是。实现错误与最终候选数量是否变化是两件事。

相关阅读