Install
openclaw skills install @listolany/quant-strategy-assistantopenclaw skills install @listolany/quant-strategy-assistant兼容说明:本文档既是 OpenClaw Skill,也可作为任意 AI Agent 的操作手册。只要 Agent 能读取文件、执行命令、生成代码,即可按下方协议使用。YAML 头部的
metadata.openclaw为 OpenClaw 平台专用字段,其他 Agent 忽略即可。
回测三轮交互闭环 → 用户按需选择参数优化 / 模拟实盘。
| 能力 | 引擎 | 依赖 | 说明 |
|---|---|---|---|
| CTA回测 | vnpy_ctastrategy | python3 + qgdata | 单标的择时策略,任意平台 |
| Portfolio回测 | vnpy_portfoliostrategy | python3 + qgdata | 多标的组合/轮动策略,任意平台 |
| 参数优化 | vnpy OptimizationSetting | 同回测 | 回测后由用户触发,穷举/遗传算法 |
| 模拟/实盘 | miniQMT + vnpy CTA引擎 | QMT 交易端 | qmt-check 检测 → trade 启动自动交易,含探针单验证 |
回测是核心能力,不依赖 QMT。用户请求模拟/实盘时才运行 qmt-check。
| 条件 | 模式 | 策略基类 |
|---|---|---|
| 单一标的 + 无组合关键词 | cta | CtaTemplate |
| 以下任一条件满足 | portfolio | StrategyTemplate(vnpy_portfoliostrategy) |
portfolio 判定规则(分层,LLM 和 parse_requirement() 均遵循):
轮动/组合/多标的/全市场/等权/仓位分配/前N名排序/筛选/选股/调仓/排列/持仓周期 需同时存在多标的上下文(板块/成分股/指数/行业/概念/股票池)--symbols 含 2 只以上自动 portfolio注意:"多头排列"中的"排列"、"均线排序"在单标的场景不触发 portfolio。
路由由 parse_requirement() 自动判定并写入 parsed["mode"],agent 生成策略代码时必须使用对应基类。
Portfolio 引擎驱动约束:Portfolio 回测引擎仅支持 DAILY 和分钟级驱动。周级策略用 --interval DAILY,在 on_bars(bars) 中按 list(bars.values())[0].datetime.weekday()==0(周一)判断调仓日;周线指标直接用 pro.weekly() 获取,无需从日线合成。
股票池所有权契约(强制):股票池由 --symbols 参数唯一定义 → 引擎加载数据 → 策略通过 self.vt_symbols 接收。策略代码 __init__ 中禁止覆盖 vt_symbols,必须使用引擎传入的列表。所有标的代码使用 vnpy 格式(600519.SSE/000858.SZSE),不可使用 qgdata 格式(.SH/.SZ)。选股逻辑在 on_bars(bars) 中基于 self.vt_symbols 遍历和筛选。
板块/指数成分股由引擎自动解析(强制):用户说"人工智能板块"/"沪深300成分股"/"银行行业"等时,引擎会自动解析出完整成分股列表到 --symbols。策略代码中禁止自行调用 pro.ths_member()/pro.ths_index()/pro.dc_member() 等板块 API。
回测日期约束(强制):用户的回测日期意图必须由你转换为标准 --start YYYYMMDD --end YYYYMMDD 参数。例如用户说"最近1年"则根据当天日期计算 today-365 输出对应日期。用户未提及任何日期时,不传 --start/--end(引擎默认最近1年,即 today-365 ~ today)。第1轮确认摘要中日期栏必须写"引擎默认最近1年"而非自行编造"近2年"等。禁止编造与用户意图不符的固定日期。
用户提及 模拟/实盘/模拟交易/开始交易/QMT 时触发。前提:至少有一次成功的回测(status=completed)。
第 1 步:环境检测(自动发现 QMT 路径,无需用户手动配置路径)
"${PYTHON_BIN}" "${QUANTCLAW_ROOT}/backtests/pipeline_orchestrator.py" qmt-check
输出 JSON 含 ready(布尔)和 hint(状态说明):
platform != Windows → 提示用户在 Windows + QMT 环境运行--account-id 或 QMT_ACCOUNT_ID 提供ready=true → 进入第 2 步第 2 步:启动交易(内含自动探针验证:100股跌停价挂单→确认→撤单,可选单独跑 probe --symbol {代码} --account-id {账号})
"${PYTHON_BIN}" "${QUANTCLAW_ROOT}/backtests/pipeline_orchestrator.py" trade \
--run-id "{最近成功回测的 run_id}"
返回 JSON 分流:
status=trading_started → 告知用户:✅ 交易已启动,附带日志路径status=platform_redirect → 告知用户:需在 Windows + QMT 环境运行,给出命令status=error → 告知具体错误第 3 步:停止交易(用户说「停止交易」时)
"${PYTHON_BIN}" "${QUANTCLAW_ROOT}/backtests/pipeline_orchestrator.py" trade-stop --run-id "{run_id}"
仅需用户提供 资金账号(--account-id 或 QMT_ACCOUNT_ID);QMT 路径自动扫描各盘符下 userdata_mini 目录(可通过 QMT_PATH 覆盖)。
| 项目 | 值 |
|---|---|
| 项目根目录 | QUANTCLAW_ROOT(兼容 QMT_PROJECT_ROOT) |
| vnpy_qmt源码 | $QUANTCLAW_ROOT/vnpy_qmt |
| 策略输出 | $QUANTCLAW_ROOT/strategies/ |
| 回测输出 | $QUANTCLAW_ROOT/backtests/ |
| 回测数据源 | qgdata(建议预先配置 QGDATA_TOKEN) |
| 实盘交易 | miniQMT (xt_gateway.py),需 QMT 交易端已启动 |
| Python解释器 | PYTHON_BIN(默认 python3) |
回测默认参数:capital=1000000 / rate=0.0003 / slippage=0.01 / size=1 / pricetick=0.01
配置指南: https://gitee.com/GuojinQuant/quant-claw#第四步配置环境变量 (仓库自带 .env.example)
关键变量(优先从 .env / 环境变量自动推导,不需要写死):
QUANTCLAW_ROOT:项目根目录(兼容 QMT_PROJECT_ROOT)MONITOR_PUBLIC_BASE:监控公网基址(可留空;OpenClaw 环境下可由 OPENCLAW_CONTROL_URL 自动推导)ORCH_MONITOR_PORT_CANDIDATES:白名单端口(默认 8767,必须在防火墙放通)QGDATA_TOKEN:数据 Token(可选;未配置时自动使用内置共享试用Token,有每日额度限制)Token 自动提取规则(强制):若用户对话中出现 60~70 位连续字母数字串(如"我的token是 Mj9mN2xP..."),自动提取并通过 --token 参数传给 submit 命令。日志和回复中只显示前 6 位+***,绝不回显完整 Token。提取到个人 Token 后提示用户:已使用您的个人Token,不消耗共享试用额度。
"${QUANTCLAW_ROOT}/backtests/pipeline_orchestrator.py"。.html/.png/.json),只使用 orchestrator 的 status 命令输出获取结果。${QUANTCLAW_ROOT}/strategies/ 目录。status + error + next_action,禁止只说"失败了"不给下一步。qmt-check 检测。回测、策略、自动编排、均线、上穿、下穿、买入、卖出 → 进入三轮交互协议开始生成、生成策略、好、开始、继续、1(或任何第1轮确认后的用户消息);若同条消息同时包含完整需求+第2轮触发词,直接视为已确认并进入第2轮优化、调参、参数优化、网格搜索 → 执行 optimize(回测完成后触发)模拟、模拟盘、模拟交易、开始交易、实盘、实盘交易、QMT → 执行 qmt-check + trade(独立流程,不走三轮协议)运行 Skill 内置预检脚本(scripts/preflight.py,相对于本 Skill 目录)。脚本内部使用 sys.executable 自适应解释器,直接调用即可:
Linux/macOS:
python3 "<本Skill目录>/scripts/preflight.py"
Windows PowerShell:
python "<本Skill目录>\scripts\preflight.py"
输出 JSON,按字段消费:
ready=true → 取 engine_root 作为 QUANTCLAW_ROOT,进入第 1 轮ready=false + engine_found=true → 依赖缺失,向用户展示 blockers 和 fix_cmdready=false + engine_found=false → 引擎未找到,返回 status=config_missing + 配置指南链接。禁止降级为手动脚本。hints 非空 → 非阻塞提示(如 Token 状态),向用户如实展示doctor_cmd 做深度配置诊断(端口/Token/公网等)退出码:0=就绪 1=引擎未找到 2=依赖缺失可修复
编排器脚本内置路径回退(Path(__file__).parents[1]),即使环境变量未设置,只要找到脚本就能正常运行。
目标:理解用户意图,确认关键参数,引导进入代码生成轮。
"${PYTHON_BIN}" "${QUANTCLAW_ROOT}/backtests/data_capability_guard.py" \
--requirement "{用户原始需求}"
data_capability_guard 输出含 token_hint(非空字符串),必须在确认摘要之后、引导词之前如实告知用户。这表示检测到 Portfolio 策略 +(未传 Token 将回退共享试用 Token / 正在使用共享试用 Token)的组合,数据调用量大可能触发频率限制。直接呈现 token_hint 内容即可,不要包装为广告需求已确认:{标的} / {模式cta或portfolio} / {日线/分钟线} / {做多/做空} / {回测区间或"引擎默认最近1年"}
{若有token_hint则在此呈现,无则省略此行}
请回复「开始生成」,我来为你生成策略代码并提交回测。
第 1 轮禁止:不做代码生成、不调用 submit、不创建文件。
第 1 轮最多命令:data_capability_guard.py(1条)。
触发:第 1 轮确认后,用户发送任意消息(开始生成/好/1 等);若同条消息同时包含完整需求+第2轮触发词,也可直通第2轮。
直通首响(强制):直通第2轮时先立即回复一句 已收到,开始生成中...,再执行代码生成与提交,避免长时间无反馈。
第 2 轮速度约束(强制):
data_capability_guard(第 1 轮已检查)py_compile(submit 内部已含编译+静态检查+冒烟测试)status: "accepted" + monitor_url(回测已在后台运行)status: "lint_error"/"compile_error"/"dryrun_error" + error + strategy_file(不返回 monitor_url)error + strategy_file → 修复代码 → 重新 submitaccepted 后若回测运行时/超时/数据失败 → 已有 monitor_url,在第 3 轮处理parsed["mode"] 选择正确模板:
cta → 继承 CtaTemplate,on_bar(self, bar),self.buy(price, vol) / self.sell(price, vol),self.pos,初始化用 self.load_bar(N)(单数,N=bar 数量)portfolio → 继承 StrategyTemplate(vnpy_portfoliostrategy),on_bars(self, bars: dict),self.buy(vt_symbol, price, vol) / self.sell(vt_symbol, price, vol),self.get_pos(vt_symbol),初始化用 self.load_bars(days)(复数,days=天数)load_bars,Portfolio 策略禁止用 load_barself.available_cash 动态计算最大可买手数)fixed_size = 100 或任何硬编码固定股数作为默认仓位(这是 vnpy 教程示例值,不是真实交易逻辑)vol = int(self.available_cash / (bar.close_price * 1.0003)) // 100 * 100 # 主板100股整数倍
if vol >= 100:
self.buy(bar.close_price, vol)
per_capital = self.available_cash / max(len(target_symbols), 1)
vol = int(per_capital / (bar.close_price * 1.0003)) // 100 * 100
if vol >= 100:
self.buy(vt_symbol, bar.close_price, vol)
self.available_cash — 可用现金(买入扣减,卖出回款)self.total_value — 账户总值(现金+持仓市值)self.closable_pos — CTA可卖数量(T+1 自动扣减当日买入)self.closable_positions — Portfolio per-symbol可卖量dict(self.closable_positions.get(vt_symbol, 0))self.capital — 等于 available_cash(兼容)self.trade_calendar — 交易日历(set of "YYYYMMDD"),可用 date_str in self.trade_calendar 判断交易日self.last_order_status — 最近一次下单结果({"ok":True/False,"reason":"...","symbol":"..."})self.order_reject_log — 最近200条被拒订单记录(停牌/涨跌停/资金不足等)buy()/sell() 返回值(空列表=被拒),而非假设一定成功am.sma(),禁止用 am.ma()(vnpy 不存在此方法)on_bar 开头调用 am.update_bar(bar):否则 ArrayManager 永远不会 inited,导致全程 0 交易。引擎有运行时兜底但不能依赖${QUANTCLAW_ROOT}/strategies/{module_name}.pyPortfolio 轮动策略速查(减少生成思考时间):
on_bars(self, bars) 中 list(bars.values())[0].datetime.weekday()==0 判断周一调仓self.vt_symbols 计算因子 → sorted() → 取前N名self.available_cash / N,按交易所规则取整手pro.weekly(ts_code=code, start_date=..., end_date=...) 直取,无需从日线合成"${PYTHON_BIN}" "${QUANTCLAW_ROOT}/backtests/pipeline_orchestrator.py" submit \
--requirement "{用户原始需求}" \
--strategy-file "${QUANTCLAW_ROOT}/strategies/{module_name}.py" \
--strategy-module "{module_name}" \
--strategy-class "{class_name}" \
--symbols "{策略中所有vt_symbol逗号分隔}" \
--monitor-public-base "${MONITOR_PUBLIC_BASE:-}" \
--monitor-port-candidates "${ORCH_MONITOR_PORT_CANDIDATES:-8767}" \
--timeout-sec 1200
status: "accepted" + monitor_urlstatus: "<error_type>" + error + strategy_file,不启动回测、不返回 monitor_urlstatus == "accepted" → 进入步骤 3(回复用户)status 为 compile_error/lint_error/dryrun_error → 先输出一句话告知用户(如"检测到 xxx 错误,正在修复第 N/6 次...")→ 读 error + strategy_file → 修复代码 → 重新 submit(最多 6 轮)accepted 后):
run_id + monitor_url + 当前状态触发词:查看结果、结果、status、重新生成
"${PYTHON_BIN}" "${QUANTCLAW_ROOT}/backtests/pipeline_orchestrator.py" status --run-id "{run_id}"
| status | 处理 |
|---|---|
running | 告知当前进度,提示继续等待 |
completed | 输出摘要 + 强制输出 report_url,不用 monitor_url 表述完整报告 |
failed | 根据 last_error.error_type 分流处理(见下方错误分流表) |
| error_type | 含义 | agent 策略 |
|---|---|---|
compile_error | py_compile 失败 | 读 strategy_file + traceback → LLM 修复代码 → 重新提交 |
lint_error | 静态检查 blocker(如 am.ma()、vnpy.trading 导入) | 同 compile_error 处理 |
dryrun_error | 冒烟测试失败(50根K线采样回放运行时异常) | 同 compile_error 处理:读 strategy_file + traceback → LLM 修复 → 重新提交 |
runtime_error | 回测运行时异常 | 读 strategy_file + traceback → LLM 分析修复 → 重新提交 |
compat_error | 引擎兼容性(如 portfolio+WEEKLY 未降级) | 提示用户调整参数,通常不应出现(parse_requirement 已自动降级) |
data_error | 数据加载失败/为空 | 提示用户检查标的代码/日期范围/token |
config_error | 环境/配置问题 | 提示用户检查配置 |
timeout_error | 超时 | 建议缩短日期范围或标的数量 |
compile_error、lint_error、dryrun_error 和 runtime_error 尝试自动修复,其余直接报告用户。3.5 结果校验告警(status=completed 时优先检查):
status 输出中若包含 result_warnings 字段(非空列表),说明回测结果校验发现语义异常:
result_warnings + strategy_file → LLM 分析是否为策略 bug
常见告警类型:零交易、单边信号(有买无卖/有卖无买)、胜率极端值(100%/0%)。
回测已完成,{摘要}。您可以:
1. 回复「优化参数」对策略参数进行网格搜索
2. 回复「模拟交易」在 QMT 中启动自动交易(需 Windows + QMT 环境)
触发词:优化、调参、参数优化、网格搜索
前提:已完成至少一次回测(数据已缓存在数据库中)。
确认优化方案:agent 分析当前策略的可调参数,向用户确认:
sharpe_ratio,可选 total_return/annual_return/max_ddpercent)[起始, 终止, 步长])执行优化:
"${PYTHON_BIN}" "${QUANTCLAW_ROOT}/backtests/pipeline_orchestrator.py" optimize \
--strategy-file "${QUANTCLAW_ROOT}/strategies/{module_name}.py" \
--strategy-class "{class_name}" \
--symbols "{vt_symbol}" \
--start "{YYYYMMDD}" --end "{YYYYMMDD}" \
--optimize-params '{"target":"sharpe_ratio","params":{"fast_window":[5,30,5],"slow_window":[10,60,10]}}'
支持 "algorithm":"ga" 使用遗传算法(大参数空间时推荐)。
展示结果:输出 JSON 含 best(最优参数+指标)和 results(Top N),agent 以表格形式呈现。
后续选择:用户可选择用最优参数重新回测验证,或继续调整参数范围。
.html 报告文件reports/ 目录下的历史文件backtest_runner.py、monitor_server.py、/api/codepython -m http.server 或任何临时 HTTP 服务[run_id][N/M][状态]QUANTCLAW_ROOT)strategies/ 目录之外