"""策略管理路由:代码文件 CRUD + 实例 CRUD(spec §12 三层模型)。 鉴权说明:MVP 不挂 verify_token,便于本地联调与单测;敏感写操作(写文件) 已由 write_strategy_file 的 py_compile 语法门禁兜底。 """ from fastapi import APIRouter, HTTPException from pydantic import BaseModel from .strategy_registry import ( list_strategy_files, read_strategy_file, write_strategy_file, ) from . import instance_store router = APIRouter() class FileWriteRequest(BaseModel): code: str class InstancePayload(BaseModel): code_file: str = "" name: str = "" type: str = "cta" params: dict = {} symbol_or_pool: str = "" interval: str = "d" match_session: str = "next_open" @router.get("/strategy/files") def get_files(): """代码文件列表(不含 code 体)。""" return list_strategy_files() @router.post("/strategy/file/{name}") def post_file(name: str, req: FileWriteRequest): """保存策略代码(py_compile 校验,失败 400)。""" try: write_strategy_file(name, req.code) except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) return {"ok": True} @router.get("/strategy/instances") def get_instances(): return instance_store.list_instances() @router.post("/strategy/instances") def post_instance(req: InstancePayload): new_id = instance_store.create_instance(req.model_dump()) return {"id": new_id} @router.get("/strategy/instances/{inst_id}") def get_instance(inst_id: int): return instance_store.get_instance(inst_id) @router.put("/strategy/instances/{inst_id}") def put_instance(inst_id: int, req: InstancePayload): instance_store.update_instance(inst_id, req.model_dump()) return {"ok": True} @router.delete("/strategy/instances/{inst_id}") def del_instance(inst_id: int): ok = instance_store.delete_instance(inst_id) if not ok: raise HTTPException(status_code=404, detail="实例不存在") return {"ok": True}