美股内部人集群买入研究案例:从Form4公开披露到策略触发
内部人集群买入回测的第一步,是建立经过核对的购买事件表,而不是统计所有带P代码的Form 4记录。先明确证券、交易类型和独立买入人条件,冻结外部投资者何时能够公开使用这些信息,再安排股票订单。交易发生日说明内部人何时行动,不能直接当作研究者已经知道披露内容的日期。
本文使用一个合成集群和完整现金账户,输入是需要外部审阅的规范事件。CoTrading的Form 4采集、修订协调、内部人身份归并及实际执行能力仍属规划或待核实。这里没有取得真实内部人历史组合,也没有用一个机制案例宣称策略获得历史收益。
先定义能够进入研究的披露记录
SEC现行Form 4及填写说明把非衍生证券和衍生证券分到Table I与Table II。交易代码P覆盖公开市场或私人购买,也可能涉及非衍生或衍生证券。因此,看到P不能直接推出“公开市场普通股买入”。如果筛选器在这里放宽条件,后续回测再精确,也已经研究了不同的事件集合。
本例主动采用更窄的条件:Table I、普通股份、取得或处置栏为取得A、交易代码P、股数及价格均为有限正数,并且有单独审阅确认的公开市场购买标记。取得栏A与交易代码A是不同字段;后者在本例被排除。行权代码M、用于税款或行权价支付的F也被排除。脚注或证券描述尚不能确定时保持不合格,不能为了增加样本把未知默认为是。
每行还保存发行人、规范事件编号、独立人组、交易日期、首次可公开使用的时间和规范记录已审阅标记。代表同一受益人的不同报告实体不能制造“两个独立买家”。独立人组由外部身份核对后冻结,脚本并不实现姓名相似度归并。真实研究应同时保存申报编号、脚注依据和审阅版本,让其他研究者能够重建分类。
同一发行人和同一事件编号的完全重复记录只算一次。编号相同而内容冲突则抛出错误,要求上游先解决版本问题,不静默覆盖。本例没有声称自动处理所有Form 4修订。把后来修正过的记录直接放回早期时点,会让早期决策使用当时尚未公开的更正信息。
用公开可得时间组成十个自然日窗口
事件按公开可得时间、发行人和事件编号排序。对当前发行人,取截至当前时点向前二百四十小时(十个完整二十四小时日)的合格披露,两端包含,统计独立人组数量,不统计申报份数或交易行数。只有从不足两组进入至少两组时才生成一次触发;持续处于集群状态时,新来一行不会每天再次触发。
这是按信息公开时间定义的集群。它与按购买发生日聚合是不同研究规则。后者也可以另外设计,但无论采用哪一种,都不能在相关披露可得之前成交。报告延迟会改变两种窗口的成员,研究规格必须把选择写清楚,不能在结果出来之后选择较好的一种解释。
合成发行人ALFA的E1来自P1,于2026年1月5日美东16:30可用,随后有完全相同的E1副本和1月6日同属P1的E2。这些仍只代表一个独立买家。1月7日的E3来自P2,但被确认属于私人购买,不能进入。1月8日16:30公开的E4来自P2,满足公开市场普通股取得条件,此时才出现集群:独立组为P1和P2,参与事件为E1、E2、E4。
私人购买控制与重复申报控制针对不同机制:前者检验交易本身是否合格,后者检验事件身份。脚本还分别排除衍生表、授予、行权、支付代码和脚注尚未确认的记录。另一发行人BETA的P2事件不能替ALFA凑够人数。把P2的合格披露改到1月25日时,原P1披露已超过十日窗口,因此不能触发同一个集群。
按真实时刻排序,不按时间字符串排序
每个可得值先解析成带时区的datetime,再转换为UTC参与排序和窗口比较。缺少时区直接抛出timezone_required,不猜测电脑本地时区,也不无证据附上UTC。Python datetime文档区分明确时刻与有歧义的无时区值。触发保留原始时间写法供追溯,另给available_utc表示统一时刻。
混偏移控制让P1在1月5日22:00UTC可得,P2写成同日17:30、偏移负五小时,实际是22:30UTC。应在后一个时刻形成一次集群;按ISO文本字典序会先处理P2,可能漏触发。倒序输入或把两行都改为等价UTC,独立组、事件编号及统一触发时刻必须相同。同一时刻按发行人和事件编号稳定决胜。
这里十日窗口精确定义为二百四十个经过小时,两端包含,不是跨夏令时变化数本地日期标签。1月5日22:00UTC的P1,在1月15日22:00UTC仍合格,晚一微秒就过期。它与二十个交易所会话的持有期是不同计数。来源仍须在上游提供正确历史偏移;UTC转换不能修复来源本身写错的时区。
把触发映射到真实给定会话
集群在1月8日收盘后才知道,下一条给定正常开盘是1月9日美东09:30。会话表依据NYSE交易时间与休市日历冻结;其中没有1月19日的正常交易会话。不能简单加二十个工作日,也不能把有日期的每一天都当成可成交市场。
持有规则定义为二十个开盘到开盘间隔:列表索引4开仓,索引24退出,对应1月9日与2月9日。这不是把进入当天计为第一天后,在第二十行卖出。例子同时断言进入、到期索引和时间戳,防止文字仍写“二十期”,实际却因计数约定变化而提前一天。
长期研究应另外冻结完整交易所日历,处理提前收市、停牌及缺少可执行行情。本夹具提供两次订单的有效开盘,不把缺失bar变成成交。披露时间也不能预测实际集合竞价价格,更不证明券商在特定市场、账户或订单类型下接受该交易请求。
用亏损路径闭合现金、持仓与费用
账户初始一千、零持仓。1月9日开盘以10买入四十股,收取一单位费用,支出401,剩余现金599、持仓四十股、累计费用一。资金足够,无须借款。2月9日开盘以9.5卖出全部四十股,再收一单位费用,净收到379,最终现金978、零持仓、累计费用二。
现金桥是一千减401加379等于978。价格变化造成四十乘负0.5,即损失二十,费用再减少二。符合内部人集群条件也完全可以随后下跌。本例刻意保留亏损结果,说明事件识别正确与未来价格上涨是两个需要分别验证的问题,不能把“发现购买”写成盈利承诺。
脚本核对精确买卖记录、进入后的现金、结束现金、累计费用和清仓状态,防止仅凭末权益偶然相等就宣称执行一致。它把输入事件完全倒序后重跑,要求同样的规范触发,避免数据读取顺序替代真实信息时间。多发行人组合还需要资金分配、同时信号优先级、集中度上限和被阻止退出后的估值政策,不能把单账户演示默认为这些规则都已经存在。
下载样例并检查实际证据
下载完整示例,使用Python 3.12或更新版本执行python R591.py。脚本只依赖标准库,使用合成的已审阅事件与合成价格,不访问SEC、不抓取申报、不连接交易服务。输出先列出集群中的事件编号与独立人组,再列订单时间、最终现金、费用和持仓。
修改人数阈值之前,先检查分类控制。如果把私人购买确认改成真,E3可能让集群更早出现,这是输入分类发生变化,不能称为执行更及时。如果把同一个P1的两次购买算成两个人,集群也会提前,但违反的是独立性要求。如果用自然日安排持有到期,代码就不再实现声明的二十个交易间隔。
实际使用时,应归档原始申报、首次可得时间、独立人映射和修订处置。证券代码与公司行动另行核对,不与人员身份归并混为一谈。然后以冻结事件前缀重放,确认未来披露不能改变已经产生的历史触发。即使后来更正改变了对某次购买的认识,也能说明当时研究具体依据哪个版本作出决定。
事件到持仓的证据逐层保留
审阅表至少分开交易发生日、首次公开可得、发行人集群转态和实际开盘成交。E1与E2是两次事件但只有一个独立人组,E4提供第二组,它在收盘后公开,才把进入推到1月9日。随后按进入后二十个间隔退出,不能仅因为又有购买消息就悄悄延长当前交易。每一层有不同标识和失败理由,事件计数正确不等于日期正确,更不等于账户已经盈利。
如果真实申报无法确认公开市场属性,应列为未解决资料而不是失败交易;如果已确认事件但当天没有可执行bar,则是交易条件缺口。两者不能都记成无信号后直接删除,否则研究者会把来源覆盖不足和市场执行受阻混为策略选择。输出同时保留被排除记录和未成交请求,才能说明为何有些购买从未进入账户。资料后来补全应生成新版本,保存旧研究当时知道什么,而不是把最终确认反向写入早期样本。
另一个到期控制专门检验没有中间披露的空档:P1在1月5日,P2在1月8日,P1在1月17日重新出现。最后事件之前旧P1已过期而P2仍有效,因此新P1使人数重新跨到两组,必须再次触发。前态要在当前事件时点重新计算,不能只缓存上次事件的集群标记;时间流逝本身也会改变窗口成员。
常见问题
P代码能否证明公开市场普通股买入?
不能。本策略还要求表格、证券和公开市场属性经过独立核对,未知记录排除,并保留这些外部审阅依据。
978是否代表内部人策略的历史表现?
不是。它只是一次合成亏损交易在扣除两笔明确费用后的末现金。真实历史结论需要另行取得时点正确的事件档案并进行组合级研究。