diff --git a/app/scheduler.py b/app/scheduler.py index da6f997..ed8e705 100644 --- a/app/scheduler.py +++ b/app/scheduler.py @@ -157,6 +157,10 @@ def intraday_exec(): r = {"materialized": executor.materialize_plans()} r["proposals"] = proposal_service.scan_and_route() r["strategies"] = strategy_runner.tick() # 个股交易方案: 触发即发短窗口指令, 由下面 run_tick 执行 + # 过期收口改为每分钟一次 (原来只在 15:10 日结跑) —— 让过了窗口/deadline 的单当即作废, + # 不再多活一整天堵在「今日在办」、也不会隔天还替它试单 (2026-08-12 用户定的"实时"口径)。 + # 先收口再 run_tick: 确保 run_tick 不会再去撮合一张本该已作废的单。 + r["swept"] = executor.sweep_windows() r.update(executor.run_tick()) return r diff --git a/app/web/main.py b/app/web/main.py index 32ebc69..23fd0cb 100644 --- a/app/web/main.py +++ b/app/web/main.py @@ -301,12 +301,15 @@ def api_decide(proposal_id: str, payload: dict = Body(default={})): "instruction_id": rr.get("instruction_id"), "strategy": True} instruction_id = cs.make_instruction_id(td.ymd(), p["ts_code"], p["action"], 1) side = "sell" if p["action"] in ("TRIM", "EXIT") else "buy" + _win = param_store.get_int("PMS_EXEC_WINDOW_TDAYS", 3) pms_repo.insert_instruction( instruction_id=instruction_id, origin_type="proposal", origin_id=proposal_id, ts_code=p["ts_code"], action=p["action"], side=side, qty=int(p["qty"] or 0), limit_price=hn.get("price"), - window_tdays=param_store.get_int("PMS_EXEC_WINDOW_TDAYS", 3), - status="PROPOSED", progress={"from_proposal": proposal_id}) + window_tdays=_win, + status="PROPOSED", + progress={"from_proposal": proposal_id, "is_command": False, "children": [], + "deadline": str(td.window_deadline(None, _win))}) # 与自主执行同一口径: 采纳即算「做过一次」, 计数器要跟着走 # (否则页面采纳的那条动作绕开了 §6 的一次性约束) from app.services import proposal_service