mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 16:44:15 +08:00
feat(ai): AI 生成自定义信号条件
- 新增 /api/signals/ai/generate 接口:自然语言描述 → 结构化信号条件 - 新增 custom_signals_ai 模块:组装提示词 + 解析校验 AI 返回的 JSON - 复用 custom_signals.validate() 白名单安全闸门 - 新增输出 token 上限和上下文窗口设置 - 实现 AI 请求 max_tokens 钳制和输入预算检查 - 自定义信号右值字段名容错处理 - 增强 JSON 解析容错(尾随逗号、垃圾字符) - 前端自定义信号对话框接入 AI 生成
This commit is contained in:
@@ -137,3 +137,59 @@ def test_save_strategy_code_updates_existing_source_file(tmp_path):
|
||||
assert custom_path.exists()
|
||||
assert not (tmp_path / "strategies" / "ai" / "custom_update.py").exists()
|
||||
assert '"name": "新名称"' in custom_path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_save_strategy_code_rejects_undefined_custom_signal(tmp_path):
|
||||
"""REQUIRED_FEATURES 引用未定义的自定义信号 → 拒绝保存并恢复文件。
|
||||
|
||||
回归: 之前保存不校验, 运行期才抛 polars 缺列错 (500)。
|
||||
"""
|
||||
request = _request(tmp_path)
|
||||
code = _code("custom_missing_sig") + (
|
||||
'\nREQUIRED_FEATURES = {"csg_oversold_macd_about_to_golden"}\n'
|
||||
)
|
||||
req = StrategyCodeSaveRequest(
|
||||
strategy_id="custom_missing_sig",
|
||||
target_source="custom",
|
||||
mode="create",
|
||||
code=code,
|
||||
name="引用不存在信号的策略",
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="csg_oversold_macd_about_to_golden"):
|
||||
_save_strategy_code(req, request)
|
||||
|
||||
# 校验失败不落盘
|
||||
assert not (tmp_path / "strategies" / "custom" / "custom_missing_sig.py").exists()
|
||||
|
||||
|
||||
def test_save_strategy_code_ok_when_custom_signal_defined(tmp_path):
|
||||
"""信号已定义时, 引用它的策略可以正常保存。"""
|
||||
from app.strategy import custom_signals
|
||||
|
||||
custom_signals.save_one(tmp_path, {
|
||||
"id": "oversold_macd_about_to_golden",
|
||||
"name": "超跌接近金叉",
|
||||
"kind": "entry",
|
||||
"conditions": [
|
||||
{"left": "momentum_60d", "op": "<=", "right": "-0.30",
|
||||
"leftDays": 0, "rightDays": 0},
|
||||
],
|
||||
"enabled": True,
|
||||
})
|
||||
request = _request(tmp_path)
|
||||
code = _code("custom_with_sig") + (
|
||||
'\nREQUIRED_FEATURES = {"csg_oversold_macd_about_to_golden"}\n'
|
||||
)
|
||||
req = StrategyCodeSaveRequest(
|
||||
strategy_id="custom_with_sig",
|
||||
target_source="custom",
|
||||
mode="create",
|
||||
code=code,
|
||||
name="引用已定义信号的策略",
|
||||
)
|
||||
|
||||
result = _save_strategy_code(req, request)
|
||||
assert result["ok"] is True
|
||||
loaded = request.app.state.strategy_engine.get("custom_with_sig")
|
||||
assert "csg_oversold_macd_about_to_golden" in loaded.required_features
|
||||
|
||||
Reference in New Issue
Block a user