84 lines
2.8 KiB
Python
84 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""value 双轨重锚工序(2026-09-11 夜,用户拍板A)。
|
|
stop(live_21+shadow_62) -> 等停死 -> 备份+删 live_state.json 的 strategy_start_date -> start。
|
|
安全闸: 引擎未停死拒绝改档。用法: python -X utf8 C:\\sanguo_bigqmt\\reanchor_value.py [edit-only]
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import datetime
|
|
import json
|
|
import shutil
|
|
import sqlite3
|
|
import sys
|
|
import time
|
|
|
|
DB = r"C:\sanguo_vnpy_v2\data\backtest_results.db"
|
|
RUNTIMES = [r"C:\sanguo_vnpy_v2\runtime\live_21\live_state.json",
|
|
r"C:\sanguo_vnpy_v2\runtime\shadow_62\live_state.json"]
|
|
|
|
|
|
def _children_alive():
|
|
"""返回 (live_21存活, shadow_62存活)。"""
|
|
import psutil
|
|
live21 = shadow62 = False
|
|
for p in psutil.process_iter(["pid", "name", "cmdline"]):
|
|
if "python" not in (p.info["name"] or "").lower():
|
|
continue
|
|
cmd = p.info["cmdline"] or []
|
|
joined = " ".join(cmd)
|
|
if "runner_live" in joined and "21" in cmd:
|
|
live21 = True
|
|
if "sanguo_trader.shadow" in joined and "62" in cmd and "--auto" not in joined:
|
|
shadow62 = True
|
|
return live21, shadow62
|
|
|
|
|
|
def _set_status(value):
|
|
with sqlite3.connect(DB, timeout=15) as c:
|
|
c.execute("UPDATE live_accounts SET status=? WHERE id=21", (value,))
|
|
c.execute("UPDATE paper_accounts SET status=? WHERE id=62 "
|
|
"AND mode='shadow' AND strategy_type='portfolio'", (value,))
|
|
c.commit()
|
|
print("STATUS ->", value)
|
|
|
|
|
|
def main():
|
|
edit_only = len(sys.argv) > 1 and sys.argv[1] == "edit-only"
|
|
if not edit_only:
|
|
# 1. stop
|
|
_set_status("stopped")
|
|
t0 = time.time()
|
|
while time.time() - t0 < 150:
|
|
l, s = _children_alive()
|
|
if not l and not s:
|
|
print("HARVEST_DONE %.0fs" % (time.time() - t0))
|
|
break
|
|
time.sleep(10)
|
|
else:
|
|
print("HARVEST_TIMEOUT live21=%s shadow62=%s" % _children_alive())
|
|
raise SystemExit(1)
|
|
# 2. 安全闸 + 备份 + 删字段
|
|
l, s = _children_alive()
|
|
if l or s:
|
|
print("SAFETY_ABORT engines still alive", l, s)
|
|
raise SystemExit(1)
|
|
stamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
for path in RUNTIMES:
|
|
bak = path + ".bak_reanchor_" + stamp
|
|
shutil.copy2(path, bak)
|
|
st = json.load(open(path, encoding="utf-8"))
|
|
strat = st.get("strategy") or {}
|
|
old = strat.pop("strategy_start_date", None)
|
|
st["strategy"] = strat
|
|
json.dump(st, open(path, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
|
|
print("EDIT", path, "old_start=", old, "bak=", bak.split("\\")[-1])
|
|
if edit_only:
|
|
return
|
|
# 3. start
|
|
_set_status("running")
|
|
print("STARTED — 等 boot 后读新锚(post 锚=首个交易日事件日)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|