多条件选股怎么写:验证AND、OR和分组规则
多条件选股首先要回答哪些要求同时成立、哪些路线可以互相替代,以及哪些排除条件约束所有路线。应先画逻辑树,再写表达式,最后用能区分分支的股票验证。每个比较都算对,并不代表整体规则正确;括号的位置可能决定一只本来应排除的股票能否绕过共同门槛。
本文对合成股票的已声明布尔规则树实际执行,不解析任意自然语言,也不证明CoTrading已有可视化规则编辑器。对应产品承接仍属规划或待核实。交付是分组规则、可执行求值函数、逐股真值表,以及错误分组会改变哪只股票的对照,不是只有一句提示词建议。
先定义两条路线与共同门槛
假设研究者接受价值成长路线A,或盈利质量路线B。一个经过确认的定义可以是:A要求正市盈率低于15且年度收入增长至少5%;B要求净资产收益率至少15%且指定债务比例不高于40%。真实筛选前,这些比较仍需取得有日期、单位和期间的数据,不能从路线名称直接推断已满足。
为了单独检验分组,样例假设字段比较已产生路线真假值。route_a表示A的所有数值条件通过,route_b表示B的所有条件通过。共同的suspended标志用于排除股票,不论通过哪条路线。这里是明确的合成资格标志,不代表任意行情源都提供所有市场的停牌信息,也不替代真实交易资格核对。
意图写为(route_a OR route_b) AND NOT suspended。外层AND拥有共同排除条件,内层OR拥有替代路线。树里的内部节点是逻辑运算,叶节点是已经求值的条件。把关系表示出来,比让读者从长句中的“而且”“或者”“同时”自行猜测更加可复核。
转换时保持条件归属不变
树根是AND,两个子节点分别为A与B组成的OR,以及包含停牌标志的NOT。数据结构中的树与实际执行使用同一个对象,可以减少展示树与手写查询各改一半的漂移。若另外生成可读表达式,也应从这个已确认结构派生,并用相同真值表检查。
tree = {"op": "and", "children": [
{"op": "or", "children": [{"leaf": "route_a"}, {"leaf": "route_b"}]},
{"op": "not", "children": [{"leaf": "suspended"}]}]}
运算符采用小型白名单,并检查子节点数量。NOT只能有一个子节点,AND和OR至少一个;未知运算显式报错。不要为省去解释器,就把用户原文送进任意代码求值。本例只支持声明的树格式,不是完整查询语言,也不能执行其他Python程序。
Python表达式官方参考说明布尔操作和优先级。在Python中AND比OR结合得更紧,但研究规格仍应明确括号,不能要求所有审阅者记住语言优先级。表达式能被程序接受,与它符合研究者意图,是两个需要分别检查的问题。
构造真正能区分分支的真值表
有用样例不应全是容易通过的股票。至少包括仅A、仅B、两者都通过、两者都不通过,以及本来符合路线却触发共同排除的一只。本例五只虚构股票分别承担这些角色,人工预期在执行前写好。
| 股票 | 路线A | 路线B | 停牌 | 正确结果 |
|---|---|---|---|---|
| AAA | 真 | 假 | 假 | 通过 |
| BBB | 假 | 真 | 假 | 通过 |
| CCC | 真 | 真 | 假 | 通过 |
| DDD | 真 | 假 | 真 | 不通过 |
| EEE | 假 | 假 | 假 | 不通过 |
DDD是关键区分样例。如果表里只有未停牌股票,错误分组也可能通过全部可见检查。刻意挑一个挑战共同门槛的输入,比增加很多相似通过记录更有价值。以后新增排除条件,也要补一个能单独触发它的样例,避免该条件从未真正影响任何验收结果。
人工预期与解释器输出分开保存。若预期结果也从同一棵写错的树计算,只是把同一个错误重复两次。本例用明确括号表达式和逐股预期作为参照,让树的执行接受外部检查,而不是自证正确。
实际执行并查看结果
解释器递归取得每个子节点结果,再执行对应逻辑。叶值必须是真正布尔值,None和数字不会被隐式当作真假。这里有意不实现缺失数据三态逻辑;字段尚未知时,应先处理或另行设计三态规则,不能把未知转成假来凑出路线标志。
下载完整示例。使用Python 3.12+,只需标准库,全部为合成数据;下载后运行python R519.py。作者源文件为docs/growth/research/round-5/examples/R519.py。
实际输出通过AAA、BBB、CCC,拒绝DDD、EEE,并指出错误分组改变的是DDD。脚本还枚举A、B、停牌三个布尔量全部八种组合,将树结果与(a or b) and not suspended比较。额外注入xor运算必须抛出invalid_node,分别覆盖分组、完整布尔组合与未知运算拒绝。
CCC虽然同时符合两条路线,候选名单只出现一次。路线明细用于解释,不应变成两次研究机会,也不能在总候选数中重复计数。若系统按路线分别输出,最终合流必须按确认的证券标识去重,同时保留两条支持路径。
重现共同排除被绕过的反例
错误表达式为route_a OR (route_b AND NOT suspended),停牌排除只归B所有。DDD通过A,因此不再经过共同门槛就入选。A和B内部的数值定义完全没有变,股票集合却改变了。这是逻辑归属错误,不是数据缺失、阈值太宽或数值精度问题。
样例把错误表达式作为独立诊断实验运行,再比较差异集合,不会静默替换正确规则。把差异名单附在规则审阅旁,研究者能够看到括号对实际股票的影响,不必只接受一条抽象语法提醒。若差异为空,也要检查样例是否真的覆盖到可能绕过的分支。
多个共同排除条件应放在共同层级;确实只约束某条路线的条件才挂在该路线内部,并构造区分两种归属的输入。条件位置取决于已经确认的政策,不能为了界面看起来对称而挪动。移动节点属于规则修改,应保留版本与原因。
规则演进时保持可执行规格
把树版本、叶定义、数据截止日和真值表版本一起保存。A增加条件时重放仅A和两条都通过样例,共同排除改变时重放两条路线的排除情景。输入约定改变后补缺叶测试,在三态政策明确前继续停止,而不是自动用默认值填上。
真实数据中,每片叶都要连接原字段、单位、期间及来源。分组验收不能验证上游财务比较是否计算正确,因此先核字段,再执行树,再给原股票池每只股票一个明确状态。输出数量与输入数量核对,不能只保留成功路径而丢失配置错误或无法求值对象。
交接包包括逻辑树、可读表达式、真值表、去重候选表和拒绝配置。另一位研究者应能不依赖AI叙述,直接还原DDD为何被挡住。每条替代路线正常工作,每个共同排除在预期位置生效,语法改变的成员后果在扩大运行前可见,才算完成这个具体选股任务。
按受影响路径审阅规则修改
建立变更表,写旧节点、新节点、预期政策变化及应受影响样例。若研究者把停牌门槛移动到B内部,表中必须明确A现在可以绕过它。未来可视化编辑器里一次误拖动,不能因为树仍可解析就变成合法投资政策。配置语法有效与政策经过确认需要分别验收,二者都通过才能形成新规则版本。
真实输入还要同时保留路线层结果和底层字段比较。路线真假足以检验本例分组,却不足以说明原财务条件怎样测量。两层分别验证并连接版本,字段更正时才可以重新打开相应路线,而不用猜整体树是否也变了。反过来,树的归属改变也不应偷偷重写原始市盈率或增长观测。
交付修订候选表前,比较旧新成员,给每个差异附对应规则变化。没有输入或批准规则变化,却出现不同成员,应先查执行缺陷。真值表因此不仅是首次设计插图,而是持续维护可以重放的约定。以后新增第三条路线,也应保留原有共享排除反例,确保复杂度增加没有让旧门槛失效。
还要让非编程审阅者能够从可读表达式重算一个样例。若必须依赖作者解释才能知道括号范围,交付仍不够清晰。可以按节点编号逐步记录子结果,再合流到根结果;这份记录比只打印最终通过布尔值更容易定位第一个偏离预期的位置。
常见问题
同时通过两条路线会得到两只候选吗?
不会。同一股票保留两个支持路径,研究名单按确认证券标识去重。
缺字段可以直接当假吗?
本例不可以。叶值必须为布尔值,未知语义应另外设计和检验。