2.8 KiB
2.8 KiB
name: parse-signal-trader-and-price-pitfall description: "trader 解析 fallback + 价格格式化 (避免 18 位小数和"币种"误标)" version: 1.0.0 type: reference
⚠️ process_signal.py: trader 解析 + 价格格式化 实战教训
Bug 1: trader 字段错误 = "币种"
症状: 推送里显示 信号源: 币种 ? SKHY (价值$?) — trader 字段名是 "币种",不是真 trader。
根因: parse_signal L41 用 re.search(r'【([^】]+)】', text) 抓第一个方括号 — 第一个就是 【币种】...,导致 trader = "币种"。
真实 trader 通常不是 【X】 格式,而是 👉 跟单就选 X聚合社区(在信号末尾)。
修复方案 (3 层 fallback)
FIELD_NAMES = {'币种', '方向', '杠杆', '仓位大小', '仓位价值', '开仓价',
'当前价', '未实现盈亏', '收益额', '持仓量', '强平价', '数量'}
# 1. 优先: 【交易员】标签
m_trader = re.search(r'【交易员】\s*[::]?\s*([^【\n]{1,20})', text)
if m_trader:
fields['trader'] = m_trader.group(1).strip()
else:
# 2. Fallback: 👉 跟单就选 X (真实 trader 来源)
m_follow = re.search(r'👉\s*跟单就选\s*(\S+)', text)
if m_follow:
fields['trader'] = m_follow.group(1).strip()
else:
# 3. 最终 fallback: 第一个【xx】但跳过字段名
m_first = re.search(r'【([^】]{1,20})】', text)
if m_first and m_first.group(1) not in FIELD_NAMES:
fields['trader'] = m_first.group(1).strip()
else:
fields['trader'] = 'unknown'
测试用例
signal = """📈 注意
【币种】: SKHYUSDT|永续|5x
【方向】: 做空 🟥
【仓位】: 528.16 SKHY
【开仓价】: 161.90000
👉 跟单就选 X聚合社区"""
parse_signal(signal)['trader'] # ✅ "X聚合社区" (不再是 "币种")
Bug 2: 价格小数位溢出 (18 位)
症状: 入场: $161.01076124567473 — OKX 返回的浮点 × 比率算出 18 位小数。
根因: f-string 直接嵌入 float,没有 round。
修复: 通用 _fmt() helper
def _fmt(x, n=4):
"""格式化数字: 字符串保留原样, 数字 round 到 n 位."""
try:
return f"{float(x):.{n}f}"
except (ValueError, TypeError):
return str(x)
# 模板里全部用 _fmt()
msg = f"""⚡ 跟单建议 ...
入场: ${_fmt(entry_price)} | 当前: ${_fmt(current)}
• SL: ${_fmt(rec['sl_price'])} → 预亏 -{_fmt(rec.get('sl_pnl', 0))} USDT
"""
⚠️ value 缺失: OKX 信号有时价值字段空 (e.g. 价值 $?),_fmt 不能 float('?') 抛异常,保留 ? — 让推送显示 "?" 但不报错。
相关
process_signal.pyL36-67 (parse_signal)process_signal.pyL217-302 (format_message)- 测试:
python3 -c "import process_signal; process_signal.parse_signal(s)"