ZVT 项目研究站 · 策略与界面

ZVT 怎么写策略、跑完又在哪里看:一个 on_time,三个入口

ZVT 的策略写法非常统一:继承 StockTrader,实现 on_time(timestamp),在事件循环里决定买什么、卖什么,调用 trade_the_targets(...) 下单。跑完之后的结果查看有三个入口——zvt 命令的 Dash 界面、zvt_server 的 REST 服务、以及独立仓库里的前端。它们在 README 里散落各处,本页集中对照。

策略基类:StockTrader入口:8050 / 8090 / 3000依据 README 与入口源码(2026-09-18)

三个入口,三种用途

zvtDash 界面 8050
zvt_serverFastAPI 8090
zvt_ui独立仓库前端 3000
zvt_export导出命令
setup.py 的 console_scripts 与入口源码自绘(非官方架构图);zvt_ui 前端不在本仓库,端口与路径取自 README。
Strategy

一个策略要写什么:on_time 与 trade_the_targets

README 给了一个完整的策略源码(跟着机构增持买的例子)。下表把它用到的每个关键点拆出来。

要素写法含义适用场景注意点
策略基类class XxxTrader(StockTrader):股票类策略基类,提供时间循环与交易记录个股与股票池策略基类会自动按交易日推进时间轴,你不需要自己写循环
时间回调def on_time(self, timestamp):每个时间点被调用一次,是策略仅有的事件入口所有策略官方示例里用一个 finish_date 属性避免同一报告期重复处理——这类幂等保护要自己写
选买卖集合long_selected=set(...) / short_selected=set(...)本时点要买 / 要卖的标的集合按条件选股后交易传的是实体 id 集合,不是代码字符串
下单调用self.trade_the_targets(due_timestamp=, happen_timestamp=, long_selected=, short_selected=)在指定时点按集合调仓回测与模拟两个时间参数分别表示「实际成交时点」与「信号发生时点」,做避免未来函数的检查时要盯住它们
运行参数start_timestamp / end_timestamp / entity_ids / provider / adjust_type / profit_threshold实例化时给出回测区间、标的、数据源、复权口径与止盈阈值所有回测adjust_type 要与取数时的口径一致;profit_threshold=None 表示不启用止盈逻辑
运行方式XxxTrader(...).run()启动回测,结果写入本地记录回测结果通过界面或记录表查看,不在控制台直接输出绩效
class FollowIITrader(StockTrader): finish_date = None def on_time(self, timestamp): recent_report_date = to_pd_timestamp(get_recent_report_date(timestamp)) if self.finish_date and is_same_date(recent_report_date, self.finish_date): return df = StockActorSummary.query_data(filters=[...]) long_df = df[df['change_ratio'] > 0.05] short_df = df[df['change_ratio'] < -0.5] self.trade_the_targets(due_timestamp=timestamp, happen_timestamp=timestamp, long_selected=set(long_df['entity_id']), short_selected=set(short_df['entity_id'])) FollowIITrader(start_timestamp='2002-01-01', end_timestamp='2021-01-01', entity_ids=['stock_sh_600519'], provider='em', adjust_type=AdjustType.qfq, profit_threshold=None).run()
读这段代码的三个要点:①策略逻辑就是「查数据 → 算条件 → 交集合」,没有隐藏的撮合细节;②同一份数据里既有 set(entity_id) 的选择也有 orchestrator 的买卖判定,你只负责选,成交规则由框架的交易日与价格口径决定;③示例本身是官方 README 的演示,不构成任何有效性或收益证据
Two modes

两种策略写法:solo 与 formal

README 明确区分了两种写法,很多人只看了第一种就以为 ZVT 只能这么写。

写法做法适合什么局限注意点
solo(自由式)on_time 里自己查数据、自己写条件,像写一段普通脚本事件驱动型策略(跟着公告、持仓变动、龙虎榜做)条件复杂后代码会变乱,复用性差README 自己也称这种例子「too simple, sometimes naive」——指的是逻辑简单,不是说框架简单
formal(形式化)用二维索引的因子与 selector:因子产出 result_df,selector 按时间切片选标的横截面选股、多因子组合要先有完整数据与因子,起步门槛更高这是 ZVT 区别于「单标的指标库」的核心能力;数据不全时结果会失真
选择建议:做「某个事件发生后买某只股票」这类研究用 solo 更快;做「每天从全市场选 20 只」用 formal。两者可以在同一个 trader 里混用,但建议先固定一种,避免口径混乱。
Entry points

三个入口到底能做什么(按源码现状,不按 README 印象)

README 的界面截图会让人以为装上就有完整系统。下表按 setup.py 与入口文件的实际代码说明现状。

入口启动方式地址与端口现状(据源码)适用场景与注意点
Dash 界面zvthttp://127.0.0.1:8050/入口文件用 dash-bootstrap-components 起服务(host 0.0.0.0、debug=True),当前 layout 只注册了一个 factor 标签页看因子与回测结果最直接;别期待 README 截图里的多模块界面,那可能是历史版本或商业化版本
REST 服务zvt_server(需先装 uvicorn)http://127.0.0.1:8090/docsFastAPI 应用,挂 data / factor / work / trading / misc 五个 router,CORS 允许所有来源,开发模式 reload=True二次开发与前后端分离时的接口层;api-tests/ 里有可直接导入的 .http 样例
独立前端另一个仓库 zvtvz/zvt_uihttp://127.0.0.1:3000/trade前端不在本仓库;需改 .envNEXT_PUBLIC_SERVER 指向 zvt_serverREADME 称其更适合实时行情与人工交互;要额外维护一个前端项目
导出命令zvt_export命令行setup.py 注册,对应 zvt.plugin:export批量导出数据时用;具体参数以源码为准
First result

跑出第一个结果:五步最小路径

下面是让「策略 + 界面」这条链路转起来的最短路径,顺序错了会卡在数据上。

  1. 先把数据准备好

    策略依赖本地库:至少要有标的清单、对应周期的 K 线,事件型策略还需要对应的事件表。预期:query_data 能查到连续数据;缺失时策略会静默跳过而不是报错。

  2. 确认复权口径与策略一致

    实例化 trader 时的 adjust_type 要和取数时的表一致(默认表 vs hfq 表)。预期:回测价格与你预想的口径吻合;口径混用会让结果整体偏移。

  3. 写最小 on_time,先不追求逻辑复杂

    第一版建议只做「固定选一只、固定买卖」这种可预期行为,确认框架跑通。预期:回测能跑完并在本地记录里看到交易记录。

  4. 打开 Dash 界面看结果

    zvt 命令起 8050,在 factor 标签页里查看标的、因子、信号与绩效。预期:能看到与你的交易记录一致的曲线;界面报错时先看 log_path 下的日志。

  5. 需要程序化消费时再上 REST

    pip install uvicornzvt_server 起 8090,用 /docs 试接口。预期:接口返回结构化数据;需要跨域时注意其 CORS 允许所有来源,生产环境要自己收口。

证据边界:本站没有在本机运行过 ZVT 的任何策略或界面,因此不提供运行截图、不提供任何绩效数字。上面的步骤是官方材料与源码给出的路径。
Pitfalls

策略与界面上的四个现实问题

这四条都来自源码与官方说明,官方文档没有集中提醒。

「回测」不等于「实盘」

Trader 记录的是研究口径下的调仓结果,官方材料里没有交易接口与报单能力的证据,实时行情还依赖 QMT 授权。把 ZVT 回测当作策略验证工具可以,当作实盘系统需要另找方案。

Dash 界面当前只有 factor 一个标签

入口源码里 dbc.Tabs 只注册了 factor 一个 tab,且应用以 debug=True 启动。生产使用要自己改入口文件;README 截图里的丰富界面与本仓库当前代码不完全对应。

REST 服务默认放开 CORS 且开自动重载

allow_origins=["*"]reload=True 是开发配置。要放在别人能访问的环境里,先改这两项,再加鉴权——框架本身没有提供账号体系。

版本升级可能破坏你的策略代码

README 的 Declaration 明确「当前不保证任何向后兼容」。策略里用到的类名、参数名与表结构都可能在升级后变化,回滚方案与版本锁定是必需的。

FAQ

策略与界面常见问题

以 README 与入口源码为准;涉及效果的问题本站不答。

ZVT 能做实盘吗?

官方材料里没有交易接口、也没有报单相关模块的证据,实时行情还依赖 QMT 授权(README 要求联系作者)。所以本站不宣称它能做实盘。它更准确的定位是研究、因子与回测框架。

回测结果在哪里看?

两个地方:一是 zvt 命令起的 Dash 界面(8050),二是框架写入本地的交易与绩效记录表,可用 query_data 查出来做二次分析。REST 服务(8090)则适合给外部程序消费。

为什么界面只有一个 factor 标签页?

因为当前入口文件(src/zvt/main.py)的 layout 里只注册了 factor 一个 tab,其余能力在 REST 服务与独立前端里。README 的界面截图可能来自更早版本或作者的另一套实现,以源码为准。

什么是 due_timestamp 与 happen_timestamp?

前者是期望成交的时点,后者是信号发生的时点。框架要求把两者分开传,作用是让「用哪天的数据决定哪天的交易」这件事显式化——这是避免未来函数的关键接口设计。具体撮合规则以源码为准。

profit_threshold 之类参数怎么设?

官方示例里 profit_threshold=None,表示不启用止盈逻辑。其余参数的取值需要在你的策略里自己定义,框架不提供默认策略。任何参数推荐都会涉及投资决策,本站不予提供。

和 EasyClaw 的 quant-analyst 技能相比呢?

技能提供的是方法论与代码片段层面的帮助(风险指标、组合优化、回测注意事项),不运行 ZVT 的 trader,也不产生 ZVT 的交易记录。ZVT 则提供可复现的框架执行。两者无已证实集成,对照见「对比」页。

策略跑通之后,可以做自动化与标签管理

ZVT 还带了股票池、标签体系和六个定时 runner。它们是把研究变成日常流程的那一层。