fix(live/shadow): 实例锁第二层——按账户复制策略适配文件(live_3/live_5共用QMT账号被误判重复实例拒启);bullet_trade实例锁判重键=主机+strategy_path+broker+account_identity,同账号多策略是合法场景须路径互异 [vps]
CI/CD / test (push) Successful in 18s
CI/CD / nas-deploy (push) Successful in 26s
CI/CD / nas-verify (push) Successful in 13s

This commit is contained in:
2026-08-14 20:28:14 +08:00
parent e1cafac451
commit b27c3b479c
2 changed files with 39 additions and 2 deletions
+19 -1
View File
@@ -121,6 +121,24 @@ def _snapshot_loop(broker: Any, db: str, account_id: int,
logger.warning("[shadow-snapshot] 落库失败 (account=%s): %s", account_id, exc)
def _instance_adapter(account_id: str) -> Path:
"""按账户复制一份策略适配文件(同 runner_live._instance_adapter)。
bullet_trade 实例锁按 strategy_path+broker_type+account_identity 判重;
多影子账户共用 ShadowBroker(同 identity)时须路径互异才不被判重复实例。
"""
if not account_id:
return ADAPTER_FILE
dst = (Path(__file__).resolve().parents[2] / "runtime"
/ f"shadow_{account_id}" / ADAPTER_FILE.name)
dst.parent.mkdir(parents=True, exist_ok=True)
if not dst.exists() or dst.read_text(encoding="utf-8") != \
ADAPTER_FILE.read_text(encoding="utf-8"):
import shutil
shutil.copyfile(ADAPTER_FILE, dst)
return dst
def run_shadow(provider_config: Optional[Dict[str, Any]] = None) -> None:
"""装配 LiveEngine(影子 broker)并 run(阻塞)。"""
from bullet_trade.core.live_engine import LiveEngine # type: ignore
@@ -153,7 +171,7 @@ def run_shadow(provider_config: Optional[Dict[str, Any]] = None) -> None:
)
engine = LiveEngine(
ADAPTER_FILE,
_instance_adapter(cfg["account_id"]),
broker_factory=lambda: broker,
# 独立 runtime 目录:bullet_trade 单实例锁默认 ./runtime,
# 影子与实盘并行(双轨§8)会互抢锁,按账户分目录隔离