docs: expand strategy AI manual workflow
This commit is contained in:
@@ -5,6 +5,10 @@ pub struct StrategyAiManual {
|
||||
pub title: String,
|
||||
pub language: String,
|
||||
pub overview: Vec<String>,
|
||||
pub ai_workflows: Vec<ManualSection>,
|
||||
pub backtest_api: Vec<ManualSection>,
|
||||
pub result_presentation: Vec<ManualSection>,
|
||||
pub optimization_playbook: Vec<ManualSection>,
|
||||
pub statement_blocks: Vec<ManualSection>,
|
||||
pub runtime_field_groups: Vec<ManualFieldGroup>,
|
||||
pub functions: Vec<ManualFunction>,
|
||||
@@ -86,6 +90,82 @@ pub fn built_in_strategy_manual() -> StrategyAiManual {
|
||||
"支持数值型和字符串型数据库因子,字符串字段可用于行业、概念、标签、板块等分类过滤。".to_string(),
|
||||
"禁止自由 Python/JavaScript 命令式语句,最终必须输出平台 DSL。".to_string(),
|
||||
],
|
||||
ai_workflows: vec![
|
||||
ManualSection {
|
||||
title: "从用户提示词生成策略".to_string(),
|
||||
detail: "先抽取市场、基准、信号指数、调仓频率、持仓数量、选股条件、排序、仓位、止盈止损和排除条件;再生成完整 engine-script。代码必须包含 strategy(\"...\")、market、benchmark、signal、rebalance、selection、filter、ordering;动态参数必须写成 let 或 fn,不能硬编码成不可修改常量。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "生成后立即可回测".to_string(),
|
||||
detail: "AI 生成的策略代码应能转换成 strategy_spec,并用 POST /v1/backtests 提交。提交时 runtime 使用 start_date/end_date/source_table/signal_symbol/benchmark_symbol/initial_cash,strategy_source 保存原始 engine-script,strategy_spec 与 strategy_json 保存结构化配置。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "回测结果读取与复盘".to_string(),
|
||||
detail: "创建 run 后轮询 GET /v1/backtests/{run_id} 到 succeeded/failed;成功后读取 /result、/equity、/trades、/holdings。复盘必须同时看总收益、年化收益、最大回撤、夏普、基准收益、超额收益、交易次数、最后持仓和 diagnostics,避免只看单一收益指标。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "根据目标优化策略".to_string(),
|
||||
detail: "优化时输入当前策略代码、回测结果摘要、diagnostics 和用户目标。只修改与目标有关的少量参数或过滤条件,每次生成一份完整可运行策略,并重新回测对比。不要删除必要风控,也不要引入手册中不存在的字段或外部平台函数。".to_string(),
|
||||
},
|
||||
],
|
||||
backtest_api: vec![
|
||||
ManualSection {
|
||||
title: "POST /v1/backtests".to_string(),
|
||||
detail: "创建回测。请求 JSON 字段:strategy_id、strategy_version_id、user_id、runtime、execution、strategy_source、strategy_extract、strategy_spec、strategy_json。runtime 必填 start_date、end_date、source_table,建议 source_table 使用 fi_data_center.bt_daily_features_v1;signal_symbol 是信号指数,benchmark_symbol 是绩效基准,initial_cash 是初始资金。返回 run.runId 和 running 状态。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "GET /v1/backtests/{run_id}".to_string(),
|
||||
detail: "读取 run 状态和摘要。status 为 running/succeeded/failed;summary.metrics 中 total_return、annual_return、sharpe、max_drawdown、benchmark_cumulative_return、excess_cumulative_return 是展示和优化的核心字段。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "GET /v1/backtests/{run_id}/events".to_string(),
|
||||
detail: "SSE 事件流。用于实时展示快照导出、ClickHouse 查询、每日回测进度、交易日完成、失败原因等。Agent 自动化场景可不保持长连接,但前端应使用它展示进度。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "GET /v1/backtests/{run_id}/result|equity|trades|holdings".to_string(),
|
||||
detail: "/result 返回最终摘要;/equity 返回权益曲线;/trades 返回成交明细;/holdings 返回每日或指定日期持仓。美观展示时至少组合 summary 指标卡、权益/基准曲线、回撤、交易表、最终持仓表和 diagnostics。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "GET /v1/strategy-ai/manual.md|manual.json".to_string(),
|
||||
detail: "下载实时 AI 手册。manual 会合并当前数据库字段清单;Agent 在生成或优化前应先拉取 manual.md 或 manual.json,并优先使用其中列出的字段和函数。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "GET /v1/strategy-ai/skill|skill.tar".to_string(),
|
||||
detail: "查看或下载 OmniQuant Strategy Agent skill。skill 内含 SKILL.md、Agent 元数据、engine-script 手册、API 调用说明、结果呈现规范、优化方法和自动化脚本,其他 AI Agent 可下载后直接按用户提示词生成策略、提交回测、获取结果并输出报告。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "POST /v1/strategy-ai/generate|optimize".to_string(),
|
||||
detail: "/generate 输入 user_goal、constraints、market、benchmark_symbol、signal_symbol,返回 code;/optimize 输入 current_code、objective、result_summary、diagnostics,返回优化后的完整 code。返回代码仍需转换成 strategy_spec 后提交 /v1/backtests。".to_string(),
|
||||
},
|
||||
],
|
||||
result_presentation: vec![
|
||||
ManualSection {
|
||||
title: "指标卡".to_string(),
|
||||
detail: "用卡片展示总收益、年化收益、基准收益、超额收益、夏普、最大回撤、最终权益、交易次数、持仓数。总收益必须按 final_equity / initial_cash - 1 解释,年化收益必须标注按交易日折算。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "曲线与表格".to_string(),
|
||||
detail: "权益曲线至少展示策略净值、基准净值、超额净值;表格至少展示前后 20 条交易、最终持仓、异常 diagnostics。颜色不应只用红绿,需有文字标签,便于截图和复盘。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "诊断解释".to_string(),
|
||||
detail: "结果为空或收益异常时优先展示 diagnostics、选股数量、过滤原因、缺失字段、窗口不足、涨跌停/停牌拒单、快照缓存命中情况。不要只返回 JSON;要给用户自然语言结论和下一步优化建议。".to_string(),
|
||||
},
|
||||
],
|
||||
optimization_playbook: vec![
|
||||
ManualSection {
|
||||
title: "优化输入".to_string(),
|
||||
detail: "必须同时使用 current_code、result_summary、diagnostics、用户目标和手册。若目标是提高收益和夏普,应检查回撤、换手、持仓集中度、选股过滤过严/过松、买入仓位、调仓频率和止盈止损。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "优化原则".to_string(),
|
||||
detail: "一次优化只改变 1 到 3 类变量,保留可解释性。优先改可调参数:均线窗口、量能窗口、换手率阈值、市值带偏移、持仓数量、调仓频率、仓位表达式、止盈止损;不要因为单次回测结果过拟合具体日期。".to_string(),
|
||||
},
|
||||
ManualSection {
|
||||
title: "优化输出".to_string(),
|
||||
detail: "输出完整 engine-script,不输出片段。随后必须提交回测并和原 run 对比:总收益、年化、夏普、最大回撤、基准收益、交易次数、持仓集中度。若优化 run 失败,必须根据错误修复代码后重跑。".to_string(),
|
||||
},
|
||||
],
|
||||
statement_blocks: vec![
|
||||
ManualSection {
|
||||
title: "strategy(\"name\") { ... }".to_string(),
|
||||
@@ -323,6 +403,10 @@ pub fn render_manual_markdown(manual: &StrategyAiManual) -> String {
|
||||
}
|
||||
out.push('\n');
|
||||
}
|
||||
render_manual_sections(&mut out, "AI 工作流", &manual.ai_workflows);
|
||||
render_manual_sections(&mut out, "回测 API", &manual.backtest_api);
|
||||
render_manual_sections(&mut out, "结果呈现", &manual.result_presentation);
|
||||
render_manual_sections(&mut out, "策略优化闭环", &manual.optimization_playbook);
|
||||
out.push_str("## 语句块\n");
|
||||
for item in &manual.statement_blocks {
|
||||
out.push_str(&format!("- `{}`: {}\n", item.title, item.detail));
|
||||
@@ -369,6 +453,17 @@ pub fn render_manual_markdown(manual: &StrategyAiManual) -> String {
|
||||
out
|
||||
}
|
||||
|
||||
fn render_manual_sections(out: &mut String, title: &str, sections: &[ManualSection]) {
|
||||
if sections.is_empty() {
|
||||
return;
|
||||
}
|
||||
out.push_str(&format!("## {title}\n"));
|
||||
for item in sections {
|
||||
out.push_str(&format!("- `{}`: {}\n", item.title, item.detail));
|
||||
}
|
||||
out.push('\n');
|
||||
}
|
||||
|
||||
pub fn build_generation_prompt(
|
||||
manual_markdown: &str,
|
||||
request: &StrategyAiGenerateRequest,
|
||||
@@ -381,6 +476,8 @@ pub fn build_generation_prompt(
|
||||
prompt.push_str("- 必须使用 strategy(\"...\") { ... } 语法。\n");
|
||||
prompt.push_str("- 如需自定义参数,使用 let 和 fn。\n");
|
||||
prompt.push_str("- 优先使用数据库已存在字段和 factors[...]。\n\n");
|
||||
prompt.push_str("- 生成的代码必须能转换为 strategy_spec 并提交 POST /v1/backtests。\n");
|
||||
prompt.push_str("- 不要使用手册未列出的字段、函数或外部平台 API 名称。\n\n");
|
||||
prompt.push_str("用户目标:\n");
|
||||
prompt.push_str(&format!("- {}\n", request.user_goal));
|
||||
if !request.constraints.is_empty() {
|
||||
@@ -404,6 +501,7 @@ pub fn build_optimization_prompt(
|
||||
) -> String {
|
||||
let mut prompt = String::new();
|
||||
prompt.push_str("你是 OmniQuant 平台策略脚本优化器。必须输出完整、可运行的平台策略脚本,不要输出解释文本。\n");
|
||||
prompt.push_str("只修改与优化目标相关的少量参数或过滤条件,保留原策略的市场、基准、信号指数和核心风控;不要引入手册未列出的字段或外部平台 API 名称。\n");
|
||||
prompt.push_str("优化目标:\n");
|
||||
prompt.push_str(&format!("- {}\n\n", request.objective));
|
||||
prompt.push_str("当前策略代码:\n```txt\n");
|
||||
|
||||
Reference in New Issue
Block a user