setup_symbols 不再无条件报"已设好",失败要说出来

那行"已设 N 个币为逐仓 10x"原先无条件打印,20 次调用全失败也照样这么说。
日志里写假话比不写更糟。而且这段只在真跑模式执行,空跑从没碰过它,第一次
运行就是上实盘的那一刻。

杠杆设失败是有经济后果的:仓位大小由名义额算、与杠杆无关,但保证金要求会
变。若交易所侧实际是 1x,每笔需 100 USDT 保证金,第 2、3 笔必然失败,且
可能只成一条腿、静默变成半仓——收益结构从「50% 在 3 ATR + 50% 在 8 ATR」
变成别的东西。

现在按失败项数如实报告,并推一条 Telegram。不硬性阻止启动:真正的失败会在
下单时暴露,但日志必须诚实。

实测全部成功/一项失败/全部失败三种情形。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jack
2026-08-28 18:41:37 +08:00
co-authored by Cursor
parent 668ebe1e44
commit 5ffbadb0b2
+15
View File
@@ -331,6 +331,7 @@ class Exec:
杠杆若被人在 App 里改过,仓位大小就不是我们算的那个。设成幂等操作比 杠杆若被人在 App 里改过,仓位大小就不是我们算的那个。设成幂等操作比
读回来核对简单,且失败会直接暴露。 读回来核对简单,且失败会直接暴露。
""" """
bad: list[str] = []
for s in SYMS: for s in SYMS:
sym = f"{s}USDT" sym = f"{s}USDT"
for fn, arg in ((self.api.set_margin_mode, "isolated"), for fn, arg in ((self.api.set_margin_mode, "isolated"),
@@ -340,7 +341,21 @@ class Exec:
except Exception as e: except Exception as e:
print(f"{sym} 设置失败 {type(e).__name__}: {e}", print(f"{sym} 设置失败 {type(e).__name__}: {e}",
flush=True) flush=True)
bad.append(f"{sym}/{fn.__name__}")
if not bad:
print(f" 已设 {len(SYMS)} 个币为逐仓 {LEVERAGE}x", flush=True) print(f" 已设 {len(SYMS)} 个币为逐仓 {LEVERAGE}x", flush=True)
return
# 不能无条件报"已设好"。杠杆设失败是有经济后果的:仓位大小由名义额
# 算、与杠杆无关,但保证金要求会变。若交易所侧实际是 1x,每笔要 100
# USDT 保证金,第 2、3 笔必然失败,且可能只成一条腿变成半仓
print(f"{len(bad)} 项设置失败,交易所侧的逐仓/杠杆**不是** "
f"{LEVERAGE}x{bad[:6]}{'' if len(bad) > 6 else ''}",
flush=True)
print(" 后果不是不能交易,而是保证金要求与我们算的不一致——"
"可能只成一条腿、静默变成半仓。先在 App 里核一遍再跑",
flush=True)
await tg.error(f"{len(bad)} 项逐仓/杠杆设置失败",
f"交易所侧不是 {LEVERAGE}x{bad[:10]}")
async def reconcile(self) -> None: async def reconcile(self) -> None:
"""启动时把交易所的实际持仓对上。 """启动时把交易所的实际持仓对上。