From e462c63b451a39f79ed7c52203b2d2e5cff8b04d Mon Sep 17 00:00:00 2001 From: shy3130 <415333856@qq.com> Date: Sat, 18 Jul 2026 18:31:02 +0800 Subject: [PATCH] fix: align AI strategy prompt constraints --- .../strategy/prompts/strategy-builder-step2.md | 12 ++++++------ .../strategy/prompts/strategy-guide-compact.md | 17 +++++++++-------- backend/app/strategy/prompts/strategy-guide.md | 8 +++++++- backend/tests/test_ai_generator_prompt.py | 12 +++++++++++- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/backend/app/strategy/prompts/strategy-builder-step2.md b/backend/app/strategy/prompts/strategy-builder-step2.md index b330e90..05d5e67 100644 --- a/backend/app/strategy/prompts/strategy-builder-step2.md +++ b/backend/app/strategy/prompts/strategy-builder-step2.md @@ -20,19 +20,19 @@ ## 你应该做的事 -- 增/删/改参数 → 更新 META["params"],同步修改 filter() +- 增/删/改参数 → 更新 META["params"],同步修改当前执行后端对应的 `filter()`、`filter_history()` 或 `MATRIX_STRATEGY` - 调整信号 → 更新 ENTRY_SIGNALS / EXIT_SIGNALS - 修改止损/持有 → 更新 STOP_LOSS / MAX_HOLD_DAYS - 增减告警 → 更新 ALERTS -- 调整评分 → 更新 META["scoring"],权重总和保持 100 +- 调整评分 → 更新 META["scoring"];只使用真实数值字段或受控虚拟字段 `ma20_bias`,权重总和保持 1.0 - 修改筛选逻辑 → 更新唯一公式;新增历史回溯时切换为 `python_history_legacy` + `filter_history()`,移除回溯时切回 `polars_expr` + `filter()`,不得同时保留两套公式 ## 规则 -1. 保持策略文件结构完整,不丢失任何已有字段(包括 RULES) -2. 删除参数后 filter() 中用原 default 值代替 -3. 新增参数要有 type、label、default、min、max、step -4. 删除信号时 ENTRY_SIGNALS / EXIT_SIGNALS 至少保留一个 +1. 保持策略文件结构完整,不丢失任何已有字段(包括 RULES);`META` 必须保持为模块顶层字面量字典 `META = {...}` 或 `META: dict = {...}` +2. 删除参数后,在当前执行入口中用原 default 值代替 +3. 新增参数必须有 id、type、label、default;float/int 增加 min、max、step,select 增加 options +4. ENTRY_SIGNALS / EXIT_SIGNALS 只保留与策略逻辑直接相关的信号;没有匹配信号时允许为空,不得凑数 5. 如果修改了筛选逻辑,同步更新 RULES 中的对应条目 6. 用户可能调节的阈值才需要放入 META["params"];公式常数、固定窗口边界不必强行参数化 7. 优先使用 Polars 表达式、窗口函数、聚合和 join,不要默认改成逐行/逐股 Python 循环 diff --git a/backend/app/strategy/prompts/strategy-guide-compact.md b/backend/app/strategy/prompts/strategy-guide-compact.md index d02fdff..27b2e68 100644 --- a/backend/app/strategy/prompts/strategy-guide-compact.md +++ b/backend/app/strategy/prompts/strategy-guide-compact.md @@ -4,14 +4,15 @@ ## 必须遵守 -1. Polars/历史策略允许 `polars`、`datetime`;矩阵策略允许 `numpy`、`app.backtest.matrix`。 -2. AI 策略只属于 `data/strategies/ai/`,`META.id` 使用用户给定的 `ai_` ID。 -3. 不要读写文件,不要使用 `open/exec/eval/compile/__import__/globals/locals/vars/dir/getattr/setattr/delattr/type/input`。 -4. `META.params` 每项使用 `id/label/type/default/min/max/step`,只放可调阈值。 -5. `META.scoring` 仅使用真实数值字段或 `ma20_bias`,权重和为 1.0。 -6. `ENTRY_SIGNALS` / `EXIT_SIGNALS` 只选和策略逻辑直接相关的信号,不要凑数。 -7. `RULES` 用中文逐条列出核心逻辑,至少 3 条。 -8. 优先 Polars 表达式、`with_columns`、`over("symbol")`、`group_by`、`join`、`filter`,避免逐行循环。 +1. Polars/历史策略限用 `polars/datetime`;矩阵策略限用 `numpy/app.backtest.matrix`。 +2. AI 策略位于 `data/strategies/ai/`,`META.id` 用指定的 `ai_` ID。 +3. 禁止文件读写和 `open/exec/eval/compile/__import__/globals/locals/vars/dir/getattr/setattr/delattr/type/input`。 +4. `META.params` 只放可调项:必填 `id/label/type/default`;数值项加 `min/max/step`,select 加 `options`。 +5. `META.scoring` 只用真实数值字段或 `ma20_bias`,权重和为 1.0。 +6. `ENTRY_SIGNALS/EXIT_SIGNALS` 只选相关信号,无匹配项可为空。 +7. `RULES` 用中文列出至少 3 条核心逻辑。 +8. 优先 Polars 向量化,避免逐行循环。 +9. `META` 须为顶层字面量字典(可用 `META: dict = {...}`),禁止改名或动态构造。 ## 文件结构 diff --git a/backend/app/strategy/prompts/strategy-guide.md b/backend/app/strategy/prompts/strategy-guide.md index b1583e4..069711b 100644 --- a/backend/app/strategy/prompts/strategy-guide.md +++ b/backend/app/strategy/prompts/strategy-guide.md @@ -220,6 +220,12 @@ REQUIRED_FEATURES = {"ma20", "momentum_20d", "vol_ratio_5d"} | annual_vol_20d | 20日年化波动率 | | high_60d, low_60d | 60日最高/最低价 | +### 受控虚拟评分字段 + +| 列名 | 说明 | +|------|------| +| ma20_bias | `close / ma20 - 1`,仅在内存中计算,不写入数据表 | + ### 涨跌停 | 列名 | 说明 | @@ -281,7 +287,7 @@ REQUIRED_FEATURES = {"ma20", "momentum_20d", "vol_ratio_5d"} 1. `filter()` 必须返回 `pl.Expr` (用 `&` `|` 组合布尔表达式);`filter_history()` 返回筛选后的 `DataFrame` 2. 信号列使用 `.fill_null(False)` 处理空值 3. 用户可能调节的数值阈值通过 `params` 暴露;公式常数、固定窗口边界、一次性内部变量不必强行参数化 -4. `scoring` 权重总和必须为 1.0 +4. `scoring` 只能使用上述真实数值字段或受控虚拟字段 `ma20_bias`,权重总和必须为 1.0;不要使用条件名称或信号列作为评分字段 5. 遵循 A 股 T+1 规则 (当日买入次日才能卖出) 6. Polars 策略允许 `import polars as pl` 和 `from datetime import date/datetime`;矩阵策略只允许 NumPy 和 `app.backtest.matrix` 协议/算子 7. 禁止使用 `open()`, `exec()`, `eval()`, `os`, `sys`, `subprocess` diff --git a/backend/tests/test_ai_generator_prompt.py b/backend/tests/test_ai_generator_prompt.py index 9f86a42..8443100 100644 --- a/backend/tests/test_ai_generator_prompt.py +++ b/backend/tests/test_ai_generator_prompt.py @@ -3,7 +3,7 @@ from __future__ import annotations import pytest from app.strategy.ai_generator import GUIDE_PATH, AIStrategyGenerator -from app.strategy.prompt_builder import build_step1 +from app.strategy.prompt_builder import build_step1, build_step2 def test_ai_strategy_generator_uses_compact_guide(): @@ -31,6 +31,16 @@ def test_build_step1_keeps_user_prompt_compact(): assert len(prompt) < 1000 +def test_build_step2_uses_runtime_meta_constraints(): + prompt = build_step2("META = {}", "调整参数和评分") + + assert "权重总和保持 1.0" in prompt + assert "权重总和保持 100" not in prompt + assert "filter()`、`filter_history()` 或 `MATRIX_STRATEGY" in prompt + assert "没有匹配信号时允许为空" in prompt + assert "模块顶层字面量字典" in prompt + + def test_matrix_backend_prompt_and_imports_are_supported(): prompt = build_step1( "矩阵策略",