加 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:
@@ -111,6 +111,11 @@ journalctl -u chan-live-ship -f # 搬运日志
|
||||
重连次数。管道死了但进程还活着是这里最危险的状态——`ServerAliveInterval=15`
|
||||
负责让它变成一次可见的断开。
|
||||
|
||||
**Telegram** 在 `live.env` 里填 `TG_TOKEN` / `TG_CHAT` 就开。启动时会推一条
|
||||
"执行器启动",兼作通道自检——配错了当场就知道,而不是等几小时后第一个真信号
|
||||
来时才发现。推开仓、平仓(带已实现盈亏)、被硬约束挡住、报错、对账平仓、跨日
|
||||
结算;不推信号过期跳过(常态)和心跳。约 30 条/天上限。
|
||||
|
||||
## 停机与回滚
|
||||
|
||||
```bash
|
||||
@@ -153,3 +158,9 @@ cd /opt/chan && sudo git reset --hard <sha> && sudo systemctl restart chan-live-
|
||||
staleness 闸挡掉。这是对的——参考成交价是次根开盘价,过了就不是回测那个价。
|
||||
- **重启时会平掉交易所上已有的仓位**(`reconcile`)。接管要重建入场价、ATR、
|
||||
剩余半仓状态和已过根数,任一项猜错就跑成另一个收益结构,所以选择平掉。
|
||||
- **日亏损上限依赖 `watch()` 循环**。止损与止盈在交易所侧成交,本进程收不到
|
||||
通知,所以有个 10s 轮询去 `history-position` 取 `netProfit`(含手续费与资金
|
||||
费)记回闸。这个循环停了,`pnl_day` 会恒为 0,`MAX_DAY_LOSS` 静默失效。
|
||||
心跳里会打 `当日 PnL x/-20`,值一直是 0.00 而又确实有平仓,就是它出了问题。
|
||||
- **平仓后 `MAX_OPEN` 名额由 `watch()` 释放**,不是立刻。最坏延迟 10s。若
|
||||
历史记录还没落库,会等下一轮,日志里打"历史未就绪,下轮再结算"。
|
||||
|
||||
@@ -48,3 +48,21 @@ LIVE_STALE_S=20
|
||||
|
||||
# 交易的币池。要与采集机一致,否则会收到不做的币的信号(会被忽略但徒增噪声)
|
||||
SYMS=BTC,ETH,SOL,BNB,XRP,DOGE,ADA,AVAX,LINK,LTC
|
||||
|
||||
# 盯交易所侧出场的轮询间隔(秒)。**别关掉这个循环**:止损与止盈在交易所侧
|
||||
# 成交,本进程收不到通知,缺了它 pnl_day 恒为 0,MAX_DAY_LOSS 就是死的
|
||||
LIVE_WATCH_S=10
|
||||
|
||||
# ── Telegram 通知 ─────────────────────────────────────────────────
|
||||
# 拿 token:Telegram 里找 @BotFather → /newbot
|
||||
# 拿 chat id:给 bot 随便发一句,再开
|
||||
# https://api.telegram.org/bot<TOKEN>/getUpdates 看 result[0].message.chat.id
|
||||
#
|
||||
# 留空则完全不推(不报错)。推的内容:开仓、平仓(带已实现盈亏)、被硬约束
|
||||
# 挡住、报错、对账平仓、跨日结算、启动与停机。
|
||||
# **不推**信号过期跳过(常态,搬运重连会重放旧信号)和心跳(日志里有)。
|
||||
# 量级约 30 条/天上限。
|
||||
TG_TOKEN=
|
||||
TG_CHAT=
|
||||
# 前缀,用来和采集机推的手工信号区分开——两边可以共用同一个 bot 和对话
|
||||
TG_TAG=实盘
|
||||
|
||||
@@ -54,7 +54,10 @@ today = time.strftime("%Y-%m-%d")
|
||||
day = d.get("day", "?")
|
||||
stale = "" if day == today else f" ⚠ 是 {day} 的,跨日后首次开仓时才归零"
|
||||
print(f" 当日 {day}{stale}")
|
||||
print(f" 已开 {d.get('n_day', 0)} 笔 · 盈亏 {d.get('pnl_day', 0.0):+.2f} USDT")
|
||||
pnl, n = d.get("pnl_day", 0.0), d.get("n_day", 0)
|
||||
# pnl 恒为 0 而又确实开过仓,说明 watch() 没在记账 → MAX_DAY_LOSS 是死的
|
||||
warn = " ⚠ 开过仓但盈亏仍为 0,查 watch() 是否在跑" if n and pnl == 0 else ""
|
||||
print(f" 已开 {n} 笔 · 盈亏 {pnl:+.2f} USDT{warn}")
|
||||
print(f" 已处理信号键 {len(d.get('done', []))} 个(幂等去重用,留最近 5000)")
|
||||
PY
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user