跳到正文

研究指南

股票因子研究

股票因子评估实操:从每日因子值到扣费后的分组组合

股票因子评估需要分别重建统计分组和实际持仓。先从日期乘证券的因子面板出发,配对明确的未来收益,冻结每组成员,再把预定最高组转换成订单、费用和现金账。只有分层净值图,还不能回答账户究竟能投入多少钱、买到多少股以及扣费后剩多少。

本指南交付有效观察表、确定分组表和最小现金流水。文中全部数据都是合成示例,用于验证机制,不是历史业绩。每次研究只选一个股票市场和一种资金币种。CoTrading相关因子工作台仍属于规划或待核实能力,下面方法不依赖产品已经提供这些功能。

先冻结观察时点和成交时点

每行保留稳定证券标识、因子形成时间、实际可得时间、入选状态、建仓价格时间和退出价格时间。如果分数使用当日收盘价,收益标签应从之后可执行的价格开始,例如下一交易日开盘,不能从产生分数的同一收盘开始。把具体日期写下来,不要只使用含义不清的“明日收益”列。

配对前固定价格口径。包含分红的总回报标签,与使用未复权开盘价的成交账之间,需要有公司行动和现金分配的衔接。否则因子收益与组合收益的差别可能来自口径,而不是选股效果。缺价格、缺分数、不在冻结股票池等状态都要记录,不能把不知道的退出价格自动变成零收益。

本例规定,每天计算信息系数至少需要五只有效配对股票。这只是本次流程的最低运行门槛,不表示五只股票能提供可靠统计证据。若分数或收益全部相同,相关系数没有定义,应报告不可计算,而不是填写零。每日系数旁边同时保存样本数,让覆盖变化能被看见。

固定截面成员与排序方向

六只虚构股票甲至己,代码使用A至F,因子分数分别为一至六。对应的下一指定开盘到再下一指定开盘收益,依次为百分之一、二、三、四、五、六。先按分数升序,再按稳定证券标识排序,分成三组,每组两只。第一组A、B,第二组C、D,第三组E、F。

三组等权统计收益分别为百分之一点五、三点五、五点五。本例事先规定高分优先,因此做多目标为E和F。如果研究的是低值优先指标,分组与目标之间的映射必须提前反过来,不能看完收益才把表现最好的一组改称“优先组”。方向设定属于研究输入,不是事后解释。

信息系数使用分数秩与收益秩的相关。Python统计模块官方文档说明了样例使用的均值与相关计算工具。独立脚本先对并列值计算平均秩,再计算两列秩的普通相关。本例两列秩相同,得到一。这个刻意构造的完美排序,只证明样例计算一致,不能估计真实预测强度,更不能据此决定上线交易。

真实截面要额外固定容量规则。六只股票的每两只切片只是本例,不是任意样本的通用分组方法。需要说明余数分给哪些组、边界同分如何决胜、有效样本少于组数时怎样处理。输入行重新打乱后,组成员必须一致。统计收益旁保留完整成员,另一个实现者才能复算。

从最高组落到可买股数

为E和F另建一个初始资金一千的合成账户,两只建仓开盘价均为十。各买四十股,每张订单收取虚构佣金一。总买入名义金额八百,买入佣金合计二,现金剩一百九十八。这里有意留出现金,不假设统计篮子的全部权重都能无条件成交。

下一个指定开盘,E为十点五,F为十点六。卖出四十股E取得四百二十,扣佣金一后净入四百一十九;卖出四十股F取得四百二十四,扣佣金一后净入四百二十三。期末没有持仓,现金为一百九十八加四百一十九加四百二十三,等于一千零四十。账户净收益百分之四。

最高组的百分之五点五与账户百分之四并不矛盾。统计组假定两只各占满仓资金一半;账户实际只把初始资金的百分之八十投入股票,而且往返付出四个单位费用。账户毛收益四十四,净收益四十。把这个桥接过程展示出来,才可以解释统计收益与可执行结果的差异。

用独立脚本复算

仓库样例为docs/growth/research/round-5/examples/R561.py,只使用Python标准库。核心分组如下,完整文件还包含平均秩、缺样本状态和逐笔现金断言。

ordered = sorted(valid, key=lambda row: (row['score'], row['symbol']))
groups = [ordered[i:i + 2] for i in range(0, len(ordered), 2)]
group_returns = [mean(row['return'] for row in group) for group in groups]

在仓库根目录运行python docs/growth/research/round-5/examples/R561.py。程序断言固定成员、秩相关、最高组收益、最终现金以及样本不足状态,并输出四笔订单。读者可不依赖汇总数字,直接按数量乘价格复算现金。教学样例的浮点比较使用误差容忍;正式货币账需要固定精度与舍入规则。

反例是覆盖不足,而不是另一种费用假设

从配对数据中删除E和F,仅剩四只。程序返回跳过状态与样本数四,不再从不足门槛的截面输出日信息系数。这属于覆盖失败,与“样本有效,但成本侵蚀组合收益”的机制不同。不能为了让结果每天都有数,悄悄降低门槛或把缺失股票当零收益加入。

统计日期跳过后,已有账户怎么办,需要另一条明确规则。跳过一次信息系数不自动等于平掉全部仓位。可以规定维持旧持仓、暂停新增,或在后续可成交行情退出,但这些决定必须进入订单账。不能编造一个分组收益来保持曲线连续,也不能把未成交目标当已成交持仓。

扩展日期前先扩展对账

多日研究应保存上一期数量、卖出释放资金、买入需求、佣金、余款和估值。成员变化产生换手,成员不变通常不需要每天完整往返。拒单和目标未满足也属于结果。A股与美股应分别建模;港股研究需要另备相应面板,不能因方法通用就推断已经具备内置港股数据。

历史股票池是另一个独立输入。用当前成分股向过去回填,即使排序完全正确,仍保留幸存者偏差。保存名单来源及生效期,标明不能恢复的历史成员。验收时抽一个有效日期,贯穿原分数、标签、成员、订单和账户净值,再抽一个跳过日期检查状态流转。数据版本、股票池、成本或时间约定变化后,重跑整条链,同时保留旧工件,避免把两版不同口径的曲线直接拼接。

下载完整示例,保存为R561.py,使用Python 3.12及以上运行python R561.py。仅使用标准库与合成数据。

用版本差异解释成员与收益变化

研究重跑时,选一个日期,按证券标识连接新旧行,将差异分成输入修订、资格变化、分数变化与执行变化。下一期收益标签变了,可能只改变分组收益,不改变任何成员;建仓价变了,可能只改变可买数量和账户暴露,不改变因子排序。不要看到新版曲线提高,就自动写成选股能力提升。先把变动沿数据链定位,再解释经济含义。

检查人应分别用两只股票的收益标签重算最高组毛收益,用四条现金事件重算账户净盈利,并说明哪些事情尚未证明。本例没有多日期不确定性估计、退市股票历史和容量分析,这些要作为后续研究依赖保存。通过小样例算术验收,只能允许继续扩大研究,不能把六只股票推演成跨市场、跨行情和未来成本下都成立的因子证据。

另一个实用工件是“成员变动原因”表。每次新增列出分数进入、原成员失去资格或股票池变化;每次退出区分排名下降、数据失效和执行失败。执行失败不应倒写成未入选,数据失效也不应被当成因子主动看空。这样同样的目标与不同成交之间有明确桥梁,后续才有条件分析真实换手和费用,而不必从最终净值猜测过程。

在交接记录中写出两个独立结论:分组成员和标签算术是否正确,账户订单和现金是否正确。任何一个通过,都不替代另一个。若相关系数因常量向量无法定义,仍可保存成员,但不能给它补一个零系数来混入日均统计;脚本也检查了这条边界。

常见问题

信息系数为一是否表示因子能赚钱?

不能。它仅描述六条刻意构造观察的次序,账户结果还受投入比例、成交和费用影响。

分组收益能直接称为净业绩吗?

需要另有持仓、现金、费用和估值账能够闭合。本例已经展示两者为什么不同。

相关阅读