feat(live): CTA实盘vt_symbol裸6位码自动补交易所后缀(6→SSE,0/3→SZSE);表单提示+单策略原因说明(实盘需A股适配,陆续扩展) [nas]
CI/CD / test (push) Successful in 15s
CI/CD / nas-deploy (push) Successful in 32s
CI/CD / nas-verify (push) Successful in 13s

This commit is contained in:
2026-08-14 08:30:56 +08:00
parent 5850a60561
commit 234b44e141
3 changed files with 31 additions and 3 deletions
+3 -3
View File
@@ -195,15 +195,15 @@ async function onSubmit(): Promise<void> {
:value="opt.value"
/>
</el-select>
<span class="muted form-hint">MVP 仅支持 AShareDoubleMaStrategy</span>
<span class="muted form-hint">实盘需 A 股适配(定寸/禁空/分钟合成),目前仅 DoubleMa 完成适配,其余策略陆续扩展</span>
</el-form-item>
<el-form-item label="策略实例名" required>
<el-input v-model="form.strategy_name" placeholder="AShareDoubleMa_600000" style="width: 320px" />
<span class="muted form-hint">engine 内唯一</span>
</el-form-item>
<el-form-item label="标的(vt_symbol)">
<el-input v-model="form.vt_symbol" placeholder="600000.SSE" style="width: 320px" />
<span class="muted form-hint">交易所代码 .SSE / .SZSE</span>
<el-input v-model="form.vt_symbol" placeholder="600000 或 600000.SSE" style="width: 320px" />
<span class="muted form-hint">可只写 6 位代码,自动补交易所后缀(.SSE / .SZSE)</span>
</el-form-item>
<el-form-item label="K 线周期">
<el-input v-model="form.interval" placeholder="15m" style="width: 160px" />
+15
View File
@@ -55,6 +55,18 @@ class LiveCreateRequest(BaseModel):
benchmark: str = ""
def _normalize_vt_symbol(code: str) -> str:
"""裸 6 位码自动补交易所后缀(与 jq_to_dbbardata 同规则):
6 开头→SSE,0/3 开头→SZSE。已带后缀或非 6 位码原样返回。"""
code = (code or "").strip()
if len(code) == 6 and code.isdigit():
if code.startswith("6"):
return f"{code}.SSE"
if code.startswith(("0", "3")):
return f"{code}.SZSE"
return code
@router.post("/live/create", dependencies=[Depends(verify_token)])
def create_live(req: LiveCreateRequest):
"""创建实盘实例(写 live_accounts,status=stopped)。需调 start 才会启动。"""
@@ -72,6 +84,9 @@ def create_live(req: LiveCreateRequest):
payload.setdefault("benchmark", "000300.XSHG")
payload["vt_symbol"] = payload["pool"]
payload["interval"] = "d"
else:
# CTA 实盘:标的允许只写 6 位码,后端自动补交易所后缀
payload["vt_symbol"] = _normalize_vt_symbol(payload.get("vt_symbol", ""))
# mini_path 兜底:req → env SANGUO_QMT_PATH → 内置默认(空值会导致 connect=-1)
if not payload.get("mini_path"):
payload["mini_path"] = (
+13
View File
@@ -141,3 +141,16 @@ def test_live_strategy_adapter_builds_all_strategies(monkeypatch):
monkeypatch.setenv("SANGUO_LIVE_STRATEGY", "nope")
with pytest.raises(ValueError):
live_strategy._build_live_strategy(_FakeProvider())
def test_normalize_vt_symbol_bare_code_gets_exchange_suffix():
"""CTA 实盘标的:裸 6 位码自动补交易所后缀(6→SSE,0/3→SZSE)。"""
from sanguo_api.routes_live import _normalize_vt_symbol
assert _normalize_vt_symbol("600000") == "600000.SSE"
assert _normalize_vt_symbol("000001") == "000001.SZSE"
assert _normalize_vt_symbol("300750") == "300750.SZSE"
# 已带后缀/非 6 位(池名等)原样
assert _normalize_vt_symbol("600000.SSE") == "600000.SSE"
assert _normalize_vt_symbol("hs300_subset") == "hs300_subset"
assert _normalize_vt_symbol("") == ""