加 Telegram 通知,并修好一道死掉的闸
接 Telegram 时查出 Guard.realized() 定义了但全仓库没有调用点——pnl_day 恒为 0,MAX_DAY_LOSS 完全不生效。三条硬约束里最重要的一条是死的。 根因是止损与止盈都挂在交易所侧成交,本进程收不到通知,而 sweep 只在 48 分钟到点才查持仓。连带第二个后果:execs 条目不清,MAX_OPEN 把已出场的 仓位继续算在场,新信号被白挡到截止时刻。 补 watch() 循环(10s):持仓消失即判出场,去 history-position 取 netProfit(= pnl + 资金费 + 开平手续费)记回闸并释放名额。盈亏取交易所的 数而不自己按标记价估——估会漏掉费用且方向总偏乐观。历史未落库时留到下轮, 不会漏记。字段名按文档与官方 TS 类型的差异同时兼容 ctime/cTime。 Telegram(live/tg.py,stdlib + aiohttp):推开仓、平仓带已实现盈亏、被硬 约束挡住、报错、对账平仓、跨日结算、启动与停机。不推信号过期跳过(常态, 搬运重连会重放旧信号)与心跳,否则真事会被淹掉。启动那条兼作通道自检。 研究侧 tg_notify.send 改为复用生产的传输层,方向与 signal_bus 一致。 status.sh 增加一条判读:开过仓但 pnl 仍为 0 就是 watch() 出了问题。 实测:8 类消息渲染、_match_hist 的过早/方向不符/币不符/驼峰字段/取最近 五种情形、100 USDT 下 SOL 与 ADA 的端到端空跑(两腿等量,50/50 精确)。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -99,6 +99,26 @@ class Bitget:
|
||||
"marginCoin": MARGIN_COIN})
|
||||
return [p for p in (d or []) if float(p.get("total") or 0) != 0]
|
||||
|
||||
async def history_positions(self, start_ms: int | None = None,
|
||||
limit: int = 100) -> list:
|
||||
"""已平仓位,用来取**已实现盈亏**。
|
||||
|
||||
为什么必须问交易所而不是自己算:止损与止盈都挂在交易所侧成交,本进程
|
||||
看不到成交价;而且要算准还得含手续费与资金费。这个端点的 `netProfit`
|
||||
已经是 `pnl + totalFunding + openFee + closeFee`,正是日亏损上限该用
|
||||
的数。自己按标记价估会把费用漏掉,方向还总是偏乐观。
|
||||
|
||||
返回形状按文档是 `data.list`,但也见过直接给数组的写法,两种都收。
|
||||
时间字段文档写 `ctime/utime`,官方 TS 类型写 `cTime/uTime`,同样都读。
|
||||
"""
|
||||
p: dict = {"productType": PRODUCT, "limit": str(limit)}
|
||||
if start_ms:
|
||||
p["startTime"] = str(int(start_ms))
|
||||
d = await self._req("GET", "/api/v2/mix/position/history-position", p)
|
||||
if isinstance(d, dict):
|
||||
return list(d.get("list") or [])
|
||||
return list(d or [])
|
||||
|
||||
async def fee_rate(self, symbol: str) -> dict:
|
||||
"""账户在该合约上的**实际**费率档。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user