用错复权口径,因子会整体偏移
ZVT 的因子建立在 K 线表上,而默认表与后复权表的价格量级不同(README 示例中同一日期差异接近一个数量级)。技术指标对价格绝对量级敏感,混用口径会让因子值失去可比性。
ZVT 项目研究站 · 因子与选股
大多数框架里,算 3000 只股票的指标要么写循环、要么写向量化技巧;ZVT 把这件事放进了数据结构本身:因子层的 DataFrame 以 (entity_id, timestamp) 为二维索引,多标的与单标的是同一个写法。理解 data_df → factor_df → result_df 这三层,就理解了它的因子设计。
官方 README 用一次会话演示了这三层,但没有汇总成表。下表按输出整理。
| 层 | 来源 | 索引与形态 | 关键列 | 怎么用 / 注意点 |
|---|---|---|---|---|
data_df | 由因子对象从 schema 读入(query_data 的结果) | 二维索引 (entity_id, timestamp) | open / close / high / low / volume / level / id | 只读检查:确认标的数与时间范围符合预期,再往下算 |
factor_df | 对 data_df 施加 Transformer(如 MacdTransformer(count_live_dead=True)) | 同样二维索引,列被扩充 | MACD 例:diff / dea / macd | 中间层:想复用中间量(例如只用 DIF)时直接取这一层,避免重算 |
result_df | 由 factor_df(或 data_df)按规则计算 | 二维索引,通常单列或多列布尔/评分 | filter_result(True/False)或 score_result(0 到 1) | 两种结局二选一:筛选型给布尔,评分型给 0–1 分数;文档未统一,按具体因子的实现为准 |
TargetSelector | 消费 result_df | 按时间切片选取标的 | —— | 把「哪些标的在哪些时点命中」变成每期选股集合;README 的选股与回测流程图就停在这里 |
官方文档没有因子清单。下表按 src/zvt/factors/ 的实际目录结构归类(共 29 个 .py,分在 ma / macd / zen / fundamental 四个子包与根目录),方便你判断有没有现成可用的东西。
| 类别 | 文件 | 作用 | 什么时候直接用它 | 注意点 |
|---|---|---|---|---|
| 基础设施 | base_factor、factor_models、factor_service、common | 因子基类、数据模型与服务封装 | 写自定义因子时继承基类 | 扩展前先读基类对 data_df / factor_df / result_df 的约定 |
| 技术指标 | technical_factor、macd_factor、ma_factor、ma_stats_factor、shape | MACD 类、均线类、均线统计类与形态类因子 | 做常见技术面选股 | 参数含义以源码为准,文档未逐一说明 |
| 基本面 | finance_factor | 基于财务指标构造因子 | ROE、增长率一类的基本面筛选 | 要处理财报的时间轴口径,见 K 线页的时间对齐提醒 |
| 特定标的因子 | stock_1d_ma_factor、stock_1d_ma_stats_factor、stock_1d_zen_factor、stock_1wk_zen_factor、index_1d_zen_factor、zen_factor | 已绑定到具体标的类型与周期的成品种子因子 | 想要「开箱可用」的日线/周线因子时 | 绑定死周期与标的类型,换场景要自己改 |
| 选股与排序 | target_selector、top_stocks、top_bottom_factor | 把因子结果变成标的集合或头部/尾部标的 | 构造股票池、做多空分组 | 与 result_df 的两种形态配合使用,注意哪一类因子给的是评分 |
| 变换器 | transformers | 把 data_df 变成 factor_df 的计算器集合 | 只想加一个附加列而不建完整因子时 | 示例里 MACD 变换器带 count_live_dead 参数(统计金叉死叉) |
| 算法 | algorithm | 横向算法类因子 | 需要跨标的排序类因子时 | 依赖全市场数据,数据不全时结果会失真 |
下面用 README 的 MACD 示例串一次完整链路,每一步都写清输入、输出与判断点。
ZVT 的因子层不会替你取数:先按取数页的步骤把标的清单与对应周期的 K 线写进本地。预期:查询能返回连续序列;缺数据时因子计算结果里会出现大片空值。
from zvt.factors import BullFactor
factor = BullFactor(codes=['000338', '601318'],
start_timestamp='2019-01-01',
end_timestamp='2019-06-10',
transformer=MacdTransformer(count_live_dead=True))说明:codes 决定标的范围,时间范围决定计算窗口。预期:对象内部完成 data_df 的读取。
先看 factor.data_df 的行数是否等于「标的数 × 交易日数」,再看 factor.factor_df 是否多出指标列(MACD 例为 diff / dea / macd)。预期:前几行指标列为 NaN(窗口不足),这是正常现象。
示例里 factor.result_df 只有一列 filter_result,取值 True/False。若使用评分型因子,则会看到 0 到 1 的 score_result。预期:布尔列里 True 的占比决定选出多少标的。
选股场景把 result_df 交给 selector 得到每期标的集合;回测场景在 StockTrader.on_time 里调用 trade_the_targets。预期:得到可复现的选股记录,而不是手工挑出来的名单。
BullFactor 与两个代码都来自 ZVT 官方 README 的示例,不是收益证明。本站不提供任何因子有效性、胜率或绩效数字(见证据台账 X-01)。框架给了成品种子因子,但它们的绑定很具体,先看表再决定要不要自己写。
| 你的需求 | 建议做法 | 理由 | 注意点 |
|---|---|---|---|
| 快速验证一条技术面选股逻辑 | 用 technical_factor 一族 | 已有 MACD、均线、形态类实现,省去重复造轮子 | 参数与阈值以源码为准,先用小样本跑通 |
| 标准基本面筛选 | 用 finance_factor + query_data 条件 | 财务表的 important_cols 能直接拼出常用口径 | 注意财报时间轴选择(公告日 vs 报告期) |
| 自定义因子(举例:量价背离) | 继承 ZVT 的因子基类,自己实现 Transformer 与 result_df | ZVT 的扩展点在 factors/base_factor.py | 保持二维索引结构,不要退回 pandas 单标的口径 |
| 只想加一个中间列 | 直接用 transformers 里的计算器 | 比建完整因子对象轻 | 注意变换器是否接收并保留 count_live_dead 这类参数 |
| 需要横截面排序类因子 | 用 algorithm 或自行按时间分组排序 | 横截面因子必须依赖全市场数据 | 数据不全时排序结果会系统性失真 |
这四条都能从 README 的示例输出里看出来,但官方没有集中提示。
ZVT 的因子建立在 K 线表上,而默认表与后复权表的价格量级不同(README 示例中同一日期差异接近一个数量级)。技术指标对价格绝对量级敏感,混用口径会让因子值失去可比性。
MACD 这类指标需要预热窗口,示例输出里前五个交易日的 diff / dea / macd 都是 NaN。把 NaN 当作「数据没取到」而重复写库,是常见的无效劳动。
README 说明 filter_result 是 True/False,score_result 是 0 到 1。写下游代码前先打印一列看一眼形态,否则拿布尔列当评分排序会得到无意义的结果。
做排序类因子时如果只取了几十只标的,排名几乎没有统计意义。官方示例本身只用两三只标的做演示——那是为了说明写法,不是推荐的研究规模。
src/zvt/factors/ 的文件清单;本站未运行因子计算,不提供任何数值结果。答案以 README 与因子源码为准;涉及效果的问题本站一律不答。
因为它要一次处理多个标的:以 (entity_id, timestamp) 为索引后,「一只股票的一段行情」和「三千只股票的同一段行情」在结构上没有区别,选股与回测可以直接在这张表上做切片。代价是内存占用随规模增长。
两者都有。README 明确写 filter_result 为 True 或 False,score_result 为 0 到 1。具体某个因子给哪一种取决于它的实现;写下游逻辑前先打印一列确认。
ZVT 自带 transformers 与一组技术因子,但没有把 ta-lib 列为依赖(19 项依赖里没有它)。想引入外部指标库需要自己在 transformer 层做适配,并保持二维索引的输出结构。
README 的流程是:result_df 交给 TargetSelector 得到标的集合,再由策略按其交易。TargetSelector 的职责就是「按时间切片把命中的标的选出来」,这也是它和普通 DataFrame 操作的区别。
可以算,但排序类因子的意义不大:排名需要足够宽的横截面才有统计意义。官方示例用两三只标的只是演示写法。做真实研究时先确认样本范围,再决定用时序因子还是横截面因子。
没有已证实集成。本机的 quant-analyst 技能提供的是量化研究方法论与风险指标口径(夏普、最大回撤、组合优化等),它不实现 ZVT 的三层结构,也不能调用 ZVT 的因子类。两者是并列路线,取舍见「对比」页。