feat(live): 引擎启动期行情腿自检quote_preflight——09-03行情事故定位件:momentum 9:30六笔卖单fail-closed忽略+18/22探针零单,引擎进程内取价失败但独立探针.SH格式全通(dev反证,我先前的「服务死」误判收回:get_full_tick须.SH后缀+subscribe须xtdata.run(),两个坑全踩);需进程内直接证据区分「引擎会话坏vs服务坏」:boot时broker交易腿连接后一笔get_full_tick(510500.SH)留痕OK/EMPTY/EXC,永不抛不阻断;今晚23:05轮换后新进程即出证据,明早9:30三灯(momentum重试/small_cap调仓/9:35探针)前置诊断;3新测+591绿 [vps]
This commit is contained in:
@@ -42,6 +42,32 @@ CONNECT_RETRY_ATTEMPTS = 5
|
||||
CONNECT_RETRY_WAIT_SEC = 10.0
|
||||
|
||||
|
||||
PREFLIGHT_QUOTE_CODE = "510500.SH" # QMT 后缀格式;聚宽 .XSHG 传入返回空(09-03 踩坑)
|
||||
|
||||
|
||||
def quote_preflight(_fetch: Any = None) -> str:
|
||||
"""启动期行情腿自检:进程内 get_full_tick 一笔,返回可读结论字符串。
|
||||
|
||||
2026-09-03 行情腿事故定位用:引擎进程内取价失败(momentum 6 笔卖单
|
||||
fail-closed 忽略)而独立探针 .SH 格式全通——需要**进程内**直接证据区分
|
||||
「引擎会话坏」vs「数据服务坏」。boot 时留痕一笔,轮换后即知新进程
|
||||
行情腿通不通;只记日志不阻断启动(自检失败不挡交易,留证据即可)。
|
||||
"""
|
||||
try:
|
||||
if _fetch is None:
|
||||
from xtquant import xtdata
|
||||
ticks = xtdata.get_full_tick([PREFLIGHT_QUOTE_CODE])
|
||||
else:
|
||||
ticks = _fetch()
|
||||
d = ticks.get(PREFLIGHT_QUOTE_CODE) if isinstance(ticks, dict) else None
|
||||
if d:
|
||||
price = d.get("lastPrice", d.get("last_price"))
|
||||
return "OK price=%s" % price
|
||||
return "EMPTY ticks=%s" % (str(ticks)[:60] if ticks else "{}")
|
||||
except Exception as e: # noqa: BLE001 - 自检不阻断引擎启动
|
||||
return "EXC: %s" % e
|
||||
|
||||
|
||||
def with_connect_retry(broker: Any,
|
||||
attempts: int = CONNECT_RETRY_ATTEMPTS,
|
||||
wait_sec: float = CONNECT_RETRY_WAIT_SEC,
|
||||
@@ -274,6 +300,8 @@ def run_live(provider_config: Dict[str, Any] | None = None) -> None:
|
||||
logger.info("QmtBroker 装配 account=%s data_path=%s(connect 失败退避重试 %d×%.0fs)",
|
||||
cfg["account"], cfg["mini_path"],
|
||||
CONNECT_RETRY_ATTEMPTS, CONNECT_RETRY_WAIT_SEC)
|
||||
logger.info("[quote-preflight] 行情腿自检 %s: %s",
|
||||
PREFLIGHT_QUOTE_CODE, quote_preflight())
|
||||
|
||||
# 实例虚拟账本(共享 QMT 账户的切片视图,2026-08-19 互卖/对账/收益率三问题同根):
|
||||
# 先建+恢复再起 engine——适配层 _setup 经 get_active() 注入 facade 通道
|
||||
|
||||
@@ -66,3 +66,31 @@ def test_live_config_carries_instance_strategy_name():
|
||||
from bullet_trade.core.live_engine import LiveConfig
|
||||
cfg = LiveConfig.load({"strategy_name": "live_17"})
|
||||
assert cfg.strategy_name == "live_17"
|
||||
|
||||
|
||||
# ---------------- quote_preflight:启动期行情腿自检(2026-09-03 事故定位) ----------------
|
||||
|
||||
def test_quote_preflight_ok_with_price():
|
||||
"""行情腿通:返回 OK+价格(进程内直接证据,boot 时一笔留痕)。"""
|
||||
from sanguo_portfolio.runner_live import quote_preflight
|
||||
out = quote_preflight(_fetch=lambda: {"510500.SH": {"lastPrice": 7.88}})
|
||||
assert out.startswith("OK")
|
||||
assert "7.88" in out
|
||||
|
||||
|
||||
def test_quote_preflight_empty_is_reported_not_raised():
|
||||
"""取到空(格式错/会话坏/盘后无数据):返回 EMPTY 摘要,绝不抛。"""
|
||||
from sanguo_portfolio.runner_live import quote_preflight
|
||||
assert quote_preflight(_fetch=lambda: {}).startswith("EMPTY")
|
||||
assert quote_preflight(_fetch=lambda: None).startswith("EMPTY")
|
||||
|
||||
|
||||
def test_quote_preflight_exception_is_swallowed():
|
||||
"""fetch 抛异常:返回 EXC 摘要——自检不阻断引擎启动。"""
|
||||
from sanguo_portfolio.runner_live import quote_preflight
|
||||
|
||||
def _boom():
|
||||
raise RuntimeError("xtdata down")
|
||||
out = quote_preflight(_fetch=_boom)
|
||||
assert out.startswith("EXC")
|
||||
assert "xtdata down" in out
|
||||
|
||||
Reference in New Issue
Block a user