diff --git a/Makefile b/Makefile index dd21057..7511db3 100644 --- a/Makefile +++ b/Makefile @@ -23,8 +23,8 @@ RUN := docker compose run --rm --no-deps pms-web .PHONY: help deploy deploy-local build up down ps logs test stale initdb check health \ probe changes industry ws-status rebuild rebuild-accept \ - watch t-pool t-plan t-pre t-issue t-cmd t-cmds t-catalog t-plans t-mat \ - t-dry t-tick t-ins t-book t-gate reset-ledger shell + watch loop purge-dead-orders t-pool t-plan t-pre t-issue t-cmd t-cmds \ + t-catalog t-plans t-mat t-dry t-tick t-ins t-book t-gate reset-ledger shell help: ## 列出所有目标 @grep -hE '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \ @@ -142,6 +142,25 @@ sys.stdout.write(json.dumps(json.loads(d),ensure_ascii=False,indent=2)+"\n" if d watch: ## 【盯盘看这个】一屏看完整条链 (只读)。加 N=10 每 10 秒刷; 加 WIDE=1 连账本一起 $(RUN) python scripts/watch.py $(if $(N),-n $(N),) $(if $(WIDE),--wide,) +# beat 停着的时候, watch 只是"看", 不会推动任何事 —— 得有人跑 t-tick 才会评估与出手。 +# 这个目标把「跑一跳 + 看一眼」串起来, 手动联测期用它代替 beat。默认 20 秒一轮。 +# 一跳择时的**一行摘要** (curl 跑在宿主机, 与其它 t-* 目标同一条路) +TICKSUM := python3 -c 'import sys,json;\ +d=(json.loads(sys.stdin.read()) or {}).get("data") or {};\ +e=d.get("errors") or [];\ +print(" ▸ tick: 检查 %s · 出手 %s · 等待 %s · 拒绝 %s%s" % (d.get("checked"),\ +len(d.get("fired") or []), len(d.get("waited") or []), len(d.get("rejected") or []),\ +(" ⚠ 错误 " + json.dumps(e, ensure_ascii=False)) if e else ""))' + +loop: ## 手动联测循环: 每 N 秒跑一跳择时再刷监视 (beat 停着时用; Ctrl-C 退出) + @echo "每 $(or $(N),20) 秒跑一跳并刷新。Ctrl-C 退出。" + @while true; do \ + sum=$$(curl -s -X POST '$(A)/api/ops/exec-tick' | $(TICKSUM)); \ + $(MAKE) --no-print-directory watch; \ + echo "$$sum"; \ + sleep $(or $(N),20); \ + done + t-pool: ## A1 拉**候选池**(上游选股计划="能买哪些"; = 08:40 调度位) @curl -s -X POST '$(A)/api/ops/plan-refresh' | $(J) @@ -189,6 +208,16 @@ t-gate: ## 看评审账本: 规则闸/研判闸拒了什么、为什么 (联 @curl -s '$(A)/api/ledger?limit=50' | $(J) # ---------------------------------------------------------------- 危险操作 (要确认) +purge-dead-orders: ## 删掉出口表里**无成交的终态委托** (清账重来前跑; 必须 CONFIRM=1) + @test "$(CONFIRM)" = "1" || { echo "需要 CONFIRM=1。这会删 pms_qmt_order 里"; \ + echo "status 属于 EXPIRED/CANCELLED/REJECTED/ABORTED 且 cum_qty=0 的行。"; \ + echo "为什么要删: reset_ledger 默认保留通道两表, 于是旧子单号还占着唯一索引;"; \ + echo "重来后新指令很可能拿到同一个 seq → 同一个 _D01 子单号 → 撞唯一索引发不出去。"; \ + echo "只删无成交的终态行, 有成交的一律不动 (那是账的依据)。"; exit 1; } + $(RUN) python -c "from app.db.session import execute;\ +n=execute(\"DELETE FROM pms_qmt_order WHERE status IN ('EXPIRED','CANCELLED','REJECTED','ABORTED') AND cum_qty = 0\");\ +print('已删除 %s 行无成交的终态委托' % n)" + reset-ledger: ## 清空账本重来 (影子期专用; 必须 CONFIRM=1) @if [ "$(CONFIRM)" != "1" ]; then \ echo "这会清空 PMS 账本。确认请加 CONFIRM=1, 例如:"; \