修改okx推送

This commit is contained in:
dekun
2026-05-27 06:49:12 +08:00
parent b26647060e
commit 3c461a8068
2 changed files with 120 additions and 58 deletions
+113 -58
View File
@@ -293,6 +293,22 @@ def send_wechat_msg(content):
pass
_BREAKEVEN_EXCHANGE_WARNED_IDS = set()
def _send_breakeven_exchange_warn_once(order_id, message):
"""移动保本同步交易所失败:同一笔监控单只推送一次,避免轮询刷屏。"""
oid = int(order_id)
if oid in _BREAKEVEN_EXCHANGE_WARNED_IDS:
return
_BREAKEVEN_EXCHANGE_WARNED_IDS.add(oid)
send_wechat_msg(message)
def _clear_breakeven_exchange_warn(order_id):
_BREAKEVEN_EXCHANGE_WARNED_IDS.discard(int(order_id))
def _wechat_account_label():
return (os.getenv("OKX_ACCOUNT_LABEL") or "okx实盘子账户").strip()
@@ -308,15 +324,25 @@ def _wechat_trading_capital_text(fallback=None):
except Exception:
trading_capital = None
if trading_capital is not None:
return f"{round(float(trading_capital), 4)}U"
return f"{round(float(trading_capital), 2)}U"
if fallback is not None:
try:
return f"{round(float(fallback), 4)}U"
return f"{round(float(fallback), 2)}U"
except Exception:
pass
return "-"
def format_wechat_scalar_2dp(value):
"""企业微信推送:数值统一两位小数(与交易所 tick 无关)。"""
if value in (None, ""):
return "-"
try:
return f"{float(value):.2f}"
except (TypeError, ValueError):
return str(value)
def build_wechat_close_message(
symbol,
direction,
@@ -332,29 +358,40 @@ def build_wechat_close_message(
session_capital_fallback=None,
):
hold_txt = format_hold_minutes(calc_hold_minutes(hold_seconds)) if hold_seconds is not None else "-"
ep = format_price_for_symbol(symbol, trigger_price)
cp = format_price_for_symbol(symbol, current_price)
tp = format_price_for_symbol(symbol, take_profit)
sl = format_wechat_scalar_2dp(stop_loss)
cap_txt = _wechat_trading_capital_text(session_capital_fallback)
try:
if pnl_amount is not None:
pv = float(pnl_amount)
pnl_disp = f"{'+' if pv > 0 else ''}{round(pv, 2)} U"
else:
pnl_disp = "-"
except (TypeError, ValueError):
pnl_disp = "-"
lines = [
f"# ✅ {symbol} 实盘平仓记录",
f"**账户:{_wechat_account_label()}**",
f"📉 {symbol} 平仓完成",
f"💼 账户:{_wechat_account_label()}",
"",
"---",
"🧾 平仓概要",
f"🔖 平仓单号:{close_order_id or '-'}",
f"📌 方向:{_wechat_direction_text(direction)}",
f"📌 平仓结果:{result or '-'}",
f"💰 本单盈亏:{pnl_disp}",
f"⏱ 持仓时长:{hold_txt}",
f"💵 交易账户资金:{cap_txt}",
"",
"### 平仓基础信息",
f"- 方向:**{_wechat_direction_text(direction)}**",
f"- 平仓结果:**{result or '-'}**",
f"- 交易所平仓ID`{close_order_id or '-'}`",
f"- 持仓时长:`{hold_txt}`",
f"- 本单盈亏:`{round(float(pnl_amount), 4) if pnl_amount is not None else '-'}U`",
f"- 交易账户资金:`{_wechat_trading_capital_text(session_capital_fallback)}`",
"",
"---",
"",
"### 价格信息",
f"- 入场价:`{trigger_price if trigger_price is not None else '-'}`",
f"- 平仓参考价:`{current_price if current_price is not None else '-'}`",
f"- 止盈/止损:`{take_profit if take_profit is not None else '-'}` / `{stop_loss if stop_loss is not None else '-'}`",
"🎯 价位(计划)",
f"开仓成交价:{ep}",
f"离场参考价:{cp}",
f"止盈价位:{tp}",
f"止损价位:{sl}",
]
if extra_note:
lines.extend(["", f"*备注:{extra_note}*"])
lines.extend(["", "📎 备注", extra_note])
return "\n".join(lines)
@@ -371,7 +408,7 @@ def build_wechat_breakeven_message(symbol, direction, arm_txt, now_rr, locked_r,
f"- 类型:**{arm_txt}**",
f"- 当前RR`{round(float(now_rr), 2)}R`",
f"- 锁定RR`{round(float(locked_r), 2)}R`",
f"- 新保护位:`{new_sl}`",
f"- 新保护位:`{format_wechat_scalar_2dp(new_sl)}`",
]
)
@@ -2262,12 +2299,12 @@ def auto_transfer_once_per_day():
if from_balance is not None and from_balance < needed:
conn.execute(
"INSERT INTO transfer_logs (transfer_type, transfer_day, amount, from_account, to_account, status, message) VALUES (?,?,?,?,?,?,?)",
("auto_daily", transfer_day, needed, AUTO_TRANSFER_FROM, AUTO_TRANSFER_TO, "failed", f"{AUTO_TRANSFER_FROM}账户USDT不足,需{needed}U,当前{round(from_balance,4)}U")
("auto_daily", transfer_day, needed, AUTO_TRANSFER_FROM, AUTO_TRANSFER_TO, "failed", f"{AUTO_TRANSFER_FROM}账户USDT不足,需{round(needed, 2)}U,当前{round(from_balance, 2)}U")
)
conn.commit()
conn.close()
send_wechat_msg(
f"自动划转失败:{AUTO_TRANSFER_FROM}余额不足,需{needed}U,当前{round(from_balance,4)}U\n"
f"自动划转失败:{AUTO_TRANSFER_FROM}余额不足,需{round(needed, 2)}U,当前{round(from_balance, 2)}U\n"
f"账簿日(UTC){transfer_day}|触发时刻(北京){app_now_str()}"
)
return
@@ -2281,13 +2318,13 @@ def auto_transfer_once_per_day():
conn.close()
if ok:
send_wechat_msg(
f"自动划转成功:补足到{target_amount}U,实际划转{needed}U "
f"自动划转成功:补足到{round(float(target_amount), 2)}U,实际划转{round(needed, 2)}U "
f"{AUTO_TRANSFER_FROM}->{AUTO_TRANSFER_TO}\n"
f"账簿日(UTC){transfer_day}|触发时刻(北京){app_now_str()}"
)
else:
send_wechat_msg(
f"自动划转失败:计划补足到{target_amount}U,需划转{needed}U\n原因:{msg}\n"
f"自动划转失败:计划补足到{round(float(target_amount), 2)}U,需划转{round(needed, 2)}U\n原因:{msg}\n"
f"账簿日(UTC){transfer_day}|触发时刻(北京){app_now_str()}"
)
@@ -4301,7 +4338,7 @@ def _finalize_fib_key_fill(conn, row):
base_amount,
oid,
)
rr_txt = f"{planned_rr:.4f}" if planned_rr is not None else "-"
rr_txt = format_wechat_scalar_2dp(planned_rr) if planned_rr is not None else "-"
succ = (
f"# ✅ {symbol} 斐波限价成交\n"
f"**账户:{_wechat_account_label()}**\n"
@@ -4309,7 +4346,7 @@ def _finalize_fib_key_fill(conn, row):
f"- 类型:{typ}{_wechat_direction_text(direction)}\n"
f"- 订单 ID**{new_order_id}**\n"
f"- 成交价:{format_price_for_symbol(symbol, trigger_price)}\n"
f"- 止损:{sl}|止盈:{format_price_for_symbol(symbol, tp)}\n"
f"- 止损:{format_wechat_scalar_2dp(sl)}|止盈:{format_price_for_symbol(symbol, tp)}\n"
f"- 计划 RR{rr_txt}:1\n"
f"- {'已挂交易所 TP/SL' if tpsl_attached else 'TP/SL 未挂上'}\n"
)
@@ -4515,7 +4552,7 @@ def check_key_monitors():
if plan_tuple:
E, sl_raw, tp_raw, box_h = plan_tuple
planned_rr = calc_rr_ratio(direction, E, sl_raw, tp_raw)
rr_txt = f"{planned_rr:.4f}" if planned_rr is not None else "-"
rr_txt = format_wechat_scalar_2dp(planned_rr) if planned_rr is not None else "-"
op_lines = [
f"录入方案:{sl_tp_mode_label(sl_tp_mode)}|移动保本:{'' if be_on else ''}",
sl_tp_plan_summary_text(
@@ -4523,7 +4560,7 @@ def check_key_monitors():
outside_pct=KEY_STOP_OUTSIDE_BREAKOUT_PCT,
trend_outside_pct=KEY_TREND_STOP_OUTSIDE_PCT,
),
f"计划 SL`{round(sl_raw, 8)}`|计划 TP`{round(tp_raw, 8)}`|计划 RRE):{rr_txt}:1",
f"计划 SL`{format_wechat_scalar_2dp(sl_raw)}`|计划 TP`{format_price_for_symbol(sym, tp_raw)}`|计划 RRE):{rr_txt}:1",
"说明:OKX 本实例为提醒模式,不自动市价开仓;请按方案自行下单。",
]
else:
@@ -4560,6 +4597,7 @@ def check_key_monitors():
"\n".join(
[
f"# 🧾 {r['symbol']} 关键位监控结束",
f"**账户:{_wechat_account_label()}**",
"",
f"- 原因:已满 {max_n} 次提醒",
"- 状态:已自动结束并记入历史",
@@ -4614,6 +4652,7 @@ def check_order_monitors():
direction == "long" and new_sl > float(stop_loss)
)
if should_move:
was_armed = breakeven_armed
ex_sym = resolve_monitor_exchange_symbol(r)
new_sl = round_price_to_exchange(ex_sym, new_sl)
tp_ex = float(take_profit or 0)
@@ -4623,13 +4662,15 @@ def check_order_monitors():
try:
replace_active_monitor_tpsl_on_exchange(r, new_sl, tp_ex)
synced_ex = True
_clear_breakeven_exchange_warn(pid)
except Exception as e:
print(
f"[breakeven] exchange tpsl replace failed order={pid} {sym}: {e}",
flush=True,
)
send_wechat_msg(
f"⚠️ {sym} 移动保本止损未同步交易所:{friendly_okx_error(e)}"
_send_breakeven_exchange_warn_once(
pid,
f"⚠️ {sym} 移动保本止损未同步交易所:{friendly_okx_error(e)}",
)
elif ok_live:
print(
@@ -4642,18 +4683,20 @@ def check_order_monitors():
(new_sl, new_sl, pid),
)
stop_loss = new_sl
arm_txt = "保本止盈" if not breakeven_armed else "移动止盈"
be_msg = build_wechat_breakeven_message(
sym,
direction,
arm_txt,
now_rr,
locked_r,
new_sl,
)
if ok_live:
be_msg += "\n- 交易所:已先撤后挂止盈止损"
send_wechat_msg(be_msg)
breakeven_armed = 1
if not was_armed:
arm_txt = "保本止盈"
be_msg = build_wechat_breakeven_message(
sym,
direction,
arm_txt,
now_rr,
locked_r,
new_sl,
)
if ok_live:
be_msg += "\n- 交易所:已先撤后挂止盈止损"
send_wechat_msg(be_msg)
res = None
# 做多
@@ -6198,14 +6241,26 @@ def add_order():
_, trading_capital_after = get_exchange_capitals(force=True)
account_base_display = (
round(float(trading_capital_after), 4)
round(float(trading_capital_after), 2)
if trading_capital_after is not None
else round(float(capital_base), 4)
else round(float(capital_base), 2)
)
account_name = (os.getenv("OKX_ACCOUNT_LABEL") or "okx实盘子账户").strip()
dir_text = "多头(long" if direction == "long" else "空头(short"
order_state_text = "交易所止盈止损已挂单" if tpsl_attached else "未挂单(已拦截)"
order_state_text = (
"已在交易所挂条件委托(止盈、止损各一张触发单)"
if tpsl_attached
else "条件委托未挂上(已拦截)"
)
rr_show = planned_rr if planned_rr is not None else "-"
try:
rr_show_fmt = f"{float(planned_rr):.2f}" if planned_rr is not None else None
except (TypeError, ValueError):
rr_show_fmt = None
rr_line = f"RR {rr_show_fmt} : 1" if rr_show_fmt is not None else f"RR {rr_show} : 1"
ep_wx = format_price_for_symbol(symbol, trigger_price)
sl_wx = format_wechat_scalar_2dp(stop_loss)
tp_wx = format_price_for_symbol(symbol, take_profit)
be_wx = format_price_for_symbol(symbol, breakeven_price)
style_zh = "Swing 波段" if trade_style == "swing" else "Trend 趋势"
wx_lines = [
f"📈 {symbol} 开仓成功",
@@ -6213,22 +6268,22 @@ def add_order():
"🧾 订单基础信息",
f"🔖 交易所订单 ID{open_order_id}",
f"📈 交易风格:{style_zh}",
f"⚠️ 单笔风控风险:{risk_percent}% ≈ {round(float(risk_amount_final), 4)} U",
f"⚠️ 单笔风控风险:{risk_percent}% ≈ {round(float(risk_amount_final), 2)} U",
"📊 仓位配置详情",
f"账户基数:{account_base_display} USDT",
f"合约杠杆:{leverage}",
f"名义仓位:{notional_value} USDT",
f"名义仓位:{format_wechat_scalar_2dp(notional_value)} USDT",
f"仓位占比:{position_ratio}%",
f"合约张数:{amount}",
f"合约张数:{format_wechat_scalar_2dp(amount)}",
f"折算标的:{base_amount} {journal_coin_from_symbol(symbol)}",
"🎯 价位 & 盈亏比",
f"开仓成交价:{trigger_price}",
f"止损价位:{stop_loss}",
f"止盈价位:{take_profit}",
f"计划盈亏比:RR {rr_show} : 1",
f"移动保本位:{breakeven_rr_trigger}R → {breakeven_price}",
f"开仓成交价:{ep_wx}",
f"止损价位:{sl_wx}",
f"止盈价位:{tp_wx}",
f"计划盈亏比:{rr_line}",
f"移动保本位:{breakeven_rr_trigger}R → {be_wx}",
"📌 状态统计",
f"止盈止损{order_state_text}",
f"条件委托{order_state_text}",
f"📅 当日开仓次数:{opens_today_after} / {DAILY_OPEN_ALERT_THRESHOLD} 次(风控阈值提醒)",
]
if chart_url:
@@ -6236,8 +6291,8 @@ def add_order():
send_wechat_msg("\n".join(wx_lines))
flash_lines = [
f"实盘开单成功:风格 {trade_style};风险 {risk_percent}%≈{risk_amount_final}U;基数 {margin_capital}U,杠杆 {leverage}x,名义仓位 {notional_value}U,仓位占比 {position_ratio}%,合约张数 {amount}(折算标的 {base_amount}),"
f"计划RR {planned_rr if planned_rr is not None else '-'};止盈止损已挂交易所",
f"实盘开单成功:风格 {trade_style};风险 {risk_percent}%≈{round(float(risk_amount_final), 2)}U;基数 {round(float(margin_capital), 2)}U,杠杆 {leverage}x,名义仓位 {format_wechat_scalar_2dp(notional_value)}U,仓位占比 {position_ratio}%,合约张数 {format_wechat_scalar_2dp(amount)}(折算标的 {base_amount}),"
f"计划RR {format_wechat_scalar_2dp(planned_rr) if planned_rr is not None else '-'}已在交易所挂条件止盈/止损委托(非仓位绑定型)",
f"本交易日累计开仓:{opens_today_after}",
]
if chart_url: