选股器遇到缺失数据:把未知股票放进单独队列
选股字段缺失,应影响实际执行,而不只是出现在候选表下方的一条备注。先把每个条件判为真、假或未知,再分开通过、已知失败和未解决股票,生成具体字段补数任务。接受替换输入后重跑对应依赖,输出前后迁移。这样交付的是可以继续执行的恢复流程,而不是一组缺值标签。
本文用四只虚构股票和两条固定数值条件,实际建立补数队列、补齐一个观测并检查状态变化。它不取得真实披露、不重试实际供应商,也不证明CoTrading已有数据质量服务。各市场与来源的字段覆盖仍需分别核实,模型不能凭常识填一个合理数来让任务看起来完整。
把数值与可用状态分开
字段记录应包含数值及状态,并保留判断可用性所需的来源和日期。过期观测可能是完全合法的数字;接口错误可能没有数字,但公司在其他地方已经披露;确实未披露又需要另一种调查。不能让三种原因都退化成一个没有解释的空单元格。
样例用(value, status)表示字段。只有状态为observed且值不缺失,才进入数值比较;stale、provider_error和not_disclosed在条件层面为未知。这些是明确给定的合成状态,不是脚本根据空数组自动推断。真实取得层必须结合请求结果与披露证据判断原因,尤其不能把一次失败就称为公司没有披露。
Python表达式参考说明None、零和空值在普通布尔判断中都可能表现为假。因此不能靠if value判断字段是否取得。已测得增长为零,与没有增长观测,是不同事实;先查状态与缺失,再比较数字,才能保留这一区别。
明确三态合取规则
本例要求正市盈率低于20,以及收入增长至少10%,按比例存0.10。两条强制条件合取时,只要一个已观察条件为假,整体就失败;没有假但至少一个未知,则整体未知;两个都为真才通过。这允许保留明确淘汰原因,即使另一个字段仍未补齐。
def evaluate(row):
checks = []
for field, predicate in [("pe", lambda v: 0 < v < 20),
("growth", lambda v: v >= .10)]:
value, state = row[field]
checks.append(predicate(value)
if state == "observed" and value is not None else None)
return "fail" if False in checks else "unknown" if None in checks else "pass"
不要把这个合取逻辑直接套到任意OR树。替代路线中,一条已知通过分支有时足以支持整体通过,即使另一条未知;那需要单独定义。本恢复样例只用两条必需条件,便于观察补数依赖与迁移,不声称已经实现完整三态查询语言。
对不完整输入实际执行
AAA市盈率18,增长0.12已观察;BBB市盈率25,增长状态未披露;CCC市盈率16,但增长请求失败;DDD市盈率17,存有0.15增长却已过期。故意给DDD放一个看起来能通过的数字,检查系统会不会为了提高覆盖率忽略有效性要求。
| 股票 | 市盈率 | 增长值 | 增长状态 | 筛选状态 |
|---|---|---|---|---|
| AAA | 18 | 0.12 | 已观察 | 通过 |
| BBB | 25 | 缺失 | 未披露 | 失败 |
| CCC | 16 | 缺失 | 来源请求错误 | 未知 |
| DDD | 17 | 0.15 | 过期 | 未知 |
BBB已经因为强制市盈率条件失败,其披露缺口仍进入数据维护队列,但优先级可以低于候选资格尚不确定的CCC。筛选状态与补数优先级是两个字段,不能为了安排工作方便,把所有不完整记录统一改成未知,也不能把BBB的缺增长写成已经测得不满足。
按失败机制生成具体动作
样例产生三个任务:确认BBB披露情况,重试CCC来源,刷新DDD过期观测。脚本不执行这些外部动作,但每项都包含股票、字段、原因和下一步,使数据负责人知道要解除哪个依赖。任务只写“检查数据”会丢失分流价值,也难以验收到底修好了什么。
真实重试要保留尝试次数和原请求;过期要按照约定新鲜度检查,不是只要时间戳更新就接受;未披露则确认真的不可得,还是选定来源没有覆盖。没有取得来源时继续保留未知,不能让语言模型猜一个数字填满必需列。若某个字段本来就不适用,修改的是规则或适用范围,不是普通数值修复。
队列包括已失败股票的缺口,有利于完整数据维护;资源有限时可以优先处理未知候选,但应把优先级另外记录。暂缓BBB不意味着缺值已经变成观察失败,也不意味着可以从总输入数里删除它。每个状态都应有清楚语义,不能随工作安排任意改名。
补一项观测并重跑对应依赖
下载完整示例。使用Python 3.12+与标准库,全部合成输入,运行python R521.py。作者文件为docs/growth/research/round-5/examples/R521.py。
脚本建立独立输入副本,给CCC补增长0.20并标记已观察,只重新评估CCC。实际输出CCC从未知变通过,AAA保持通过,BBB保持失败,DDD保持未知。断言核对前后均四只,唯一改变股票为CCC,并验证原始CCC记录仍为空且状态为来源错误,没有被新值覆盖。
Python复制模块参考说明变量赋值与独立复制不同。本例包含嵌套可变对象,因此使用深复制。若“之前”和“之后”实际上指向同一被修改对象,审阅者无法重建补数过程,所谓差异表也可能错误显示没有变化。
这里能只重跑一股,是因为阈值固定且各行独立。若该字段贡献行业中位数或横截面排名,受影响范围要扩到依赖共享统计的其他股票。应从实际规则计算重跑集合,不能把单行重算当作适用于所有筛选器的优化承诺。前后依赖范围也要写进执行记录。
用过期数值反例挑战放行逻辑
DDD的0.15在数值上满足增速门槛,但由于过期,样例继续阻挡。没有新证据,只把状态从过期改成已观察,就会靠元数据错误让未知变通过,不是真正补数。需要新的有效观测,或经过明确选择的新鲜度政策变更;后者应有新规则版本,不能伪装成来源更新。
CCC来源错误则可能通过再次取得数据解决;BBB未披露可能需要确认,而不是反复请求。同样一个空值,不能统一安排重试。更新原因也要保留依据,不能因为任务被处理过就把它标成成功。错误分流与数值比较同时成立,补数才有可以检查的闭环。
修复接受前还应核对证券、字段、期间和单位。拿到CCC别的年度增长,不等于补齐指定年度;取得利润增长也不能填收入增长。缺口是否解除取决于字段约定,不取决于新增单元格是否能转成数字。这个检查防止恢复任务在最后一步改变原始研究问题。
用迁移报告结束恢复任务
交付初始状态、补数队列、接受替换输入、实际重跑名单和前后变化。真实数据替换时保存新来源与日期。如果补得增长低于门槛,正确迁移是未知到失败;修复成功表示条件终于可以判断,不表示必须增加候选股票。用入选数量评价补数人员,会鼓励不当放行。
最后确认无关行未变、输入未丢失、未知没有被替零。未成功修复项继续保留最新证据,不能因为队列每项都尝试过,就把整批宣布完成。来源更正、新鲜度到期或新增披露覆盖后重新打开相应字段,再按依赖执行。这样缺失数据处理成为有边界、可复跑的筛选操作,而不是长期堆积的备注清单。
接受修复证据,而不是只看新增单元格
替换前比较证券、字段、期间、单位和可获得日期是否匹配被挡住的依赖。另一财年的新数字不能补齐指定观测,利润率也不能替代收入增长,除非研究规则明确修改。来源更新很快,不等于来源回答了同一个问题;字段约定应在恢复步骤继续生效,不能只在首次执行时检查。
记录哪一步取得或哪位负责人接受替换,以及什么来源支持状态变为已观察。小型文件流程也值得保留这些信息,才能区分真实取得与误手工改状态。修复记录同时连接旧值旧状态与新值新状态,审阅者才可以看到变化本身,不必从最终表猜原来出了什么问题。
定向重跑后,股票数和补数项数分别对账。一只股票可能有多项不可用字段,完成一项后仍未知;也可能一个已知失败条件已经决定结果,但数据维护尚未结束。筛选完成、数据维护完成与外部请求尝试完成是不同层级,不应合并成一个成功标签。这样有限资源可以明确安排,同时不改变事实判断。
若替换输入被拒绝,保留拒绝原因并继续原状态。不能因为取得流程结束,就把数据质量队列自动关闭。下一次处理者应能接着看已有证据和待补内容,避免重新猜测缺口含义,或把已经确认不适用的来源再次无效重试。
常见问题
任一字段缺失都应让股票未知吗?
本AND政策下,若另一强制条件已经为假,整体仍失败;同时保留数据缺口。
补数成功必须让股票入选吗?
不必,也可能确认不合格。目标是有证据的判断,不是名单更大。