修改okx推送
This commit is contained in:
+113
-58
@@ -293,6 +293,22 @@ def send_wechat_msg(content):
|
|||||||
pass
|
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():
|
def _wechat_account_label():
|
||||||
return (os.getenv("OKX_ACCOUNT_LABEL") or "okx实盘子账户").strip()
|
return (os.getenv("OKX_ACCOUNT_LABEL") or "okx实盘子账户").strip()
|
||||||
|
|
||||||
@@ -308,15 +324,25 @@ def _wechat_trading_capital_text(fallback=None):
|
|||||||
except Exception:
|
except Exception:
|
||||||
trading_capital = None
|
trading_capital = None
|
||||||
if trading_capital is not 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:
|
if fallback is not None:
|
||||||
try:
|
try:
|
||||||
return f"{round(float(fallback), 4)}U"
|
return f"{round(float(fallback), 2)}U"
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return "-"
|
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(
|
def build_wechat_close_message(
|
||||||
symbol,
|
symbol,
|
||||||
direction,
|
direction,
|
||||||
@@ -332,29 +358,40 @@ def build_wechat_close_message(
|
|||||||
session_capital_fallback=None,
|
session_capital_fallback=None,
|
||||||
):
|
):
|
||||||
hold_txt = format_hold_minutes(calc_hold_minutes(hold_seconds)) if hold_seconds is not None else "-"
|
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 = [
|
lines = [
|
||||||
f"# ✅ {symbol} 实盘平仓记录",
|
f"📉 {symbol} 平仓完成",
|
||||||
f"**账户:{_wechat_account_label()}**",
|
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"开仓成交价:{ep}",
|
||||||
f"- 平仓结果:**{result or '-'}**",
|
f"离场参考价:{cp}",
|
||||||
f"- 交易所平仓ID:`{close_order_id or '-'}`",
|
f"止盈价位:{tp}",
|
||||||
f"- 持仓时长:`{hold_txt}`",
|
f"止损价位:{sl}",
|
||||||
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 '-'}`",
|
|
||||||
]
|
]
|
||||||
if extra_note:
|
if extra_note:
|
||||||
lines.extend(["", f"*备注:{extra_note}*"])
|
lines.extend(["", "📎 备注", extra_note])
|
||||||
return "\n".join(lines)
|
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"- 类型:**{arm_txt}**",
|
||||||
f"- 当前RR:`{round(float(now_rr), 2)}R`",
|
f"- 当前RR:`{round(float(now_rr), 2)}R`",
|
||||||
f"- 锁定RR:`{round(float(locked_r), 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:
|
if from_balance is not None and from_balance < needed:
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"INSERT INTO transfer_logs (transfer_type, transfer_day, amount, from_account, to_account, status, message) VALUES (?,?,?,?,?,?,?)",
|
"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.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
send_wechat_msg(
|
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()}"
|
f"账簿日(UTC):{transfer_day}|触发时刻(北京):{app_now_str()}"
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
@@ -2281,13 +2318,13 @@ def auto_transfer_once_per_day():
|
|||||||
conn.close()
|
conn.close()
|
||||||
if ok:
|
if ok:
|
||||||
send_wechat_msg(
|
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"{AUTO_TRANSFER_FROM}->{AUTO_TRANSFER_TO}\n"
|
||||||
f"账簿日(UTC):{transfer_day}|触发时刻(北京):{app_now_str()}"
|
f"账簿日(UTC):{transfer_day}|触发时刻(北京):{app_now_str()}"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
send_wechat_msg(
|
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()}"
|
f"账簿日(UTC):{transfer_day}|触发时刻(北京):{app_now_str()}"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -4301,7 +4338,7 @@ def _finalize_fib_key_fill(conn, row):
|
|||||||
base_amount,
|
base_amount,
|
||||||
oid,
|
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 = (
|
succ = (
|
||||||
f"# ✅ {symbol} 斐波限价成交\n"
|
f"# ✅ {symbol} 斐波限价成交\n"
|
||||||
f"**账户:{_wechat_account_label()}**\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"- 类型:{typ}|{_wechat_direction_text(direction)}\n"
|
||||||
f"- 订单 ID:**{new_order_id}**\n"
|
f"- 订单 ID:**{new_order_id}**\n"
|
||||||
f"- 成交价:{format_price_for_symbol(symbol, trigger_price)}\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"- 计划 RR:{rr_txt}:1\n"
|
||||||
f"- {'已挂交易所 TP/SL' if tpsl_attached else 'TP/SL 未挂上'}\n"
|
f"- {'已挂交易所 TP/SL' if tpsl_attached else 'TP/SL 未挂上'}\n"
|
||||||
)
|
)
|
||||||
@@ -4515,7 +4552,7 @@ def check_key_monitors():
|
|||||||
if plan_tuple:
|
if plan_tuple:
|
||||||
E, sl_raw, tp_raw, box_h = plan_tuple
|
E, sl_raw, tp_raw, box_h = plan_tuple
|
||||||
planned_rr = calc_rr_ratio(direction, E, sl_raw, tp_raw)
|
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 = [
|
op_lines = [
|
||||||
f"录入方案:{sl_tp_mode_label(sl_tp_mode)}|移动保本:{'开' if be_on else '关'}",
|
f"录入方案:{sl_tp_mode_label(sl_tp_mode)}|移动保本:{'开' if be_on else '关'}",
|
||||||
sl_tp_plan_summary_text(
|
sl_tp_plan_summary_text(
|
||||||
@@ -4523,7 +4560,7 @@ def check_key_monitors():
|
|||||||
outside_pct=KEY_STOP_OUTSIDE_BREAKOUT_PCT,
|
outside_pct=KEY_STOP_OUTSIDE_BREAKOUT_PCT,
|
||||||
trend_outside_pct=KEY_TREND_STOP_OUTSIDE_PCT,
|
trend_outside_pct=KEY_TREND_STOP_OUTSIDE_PCT,
|
||||||
),
|
),
|
||||||
f"计划 SL:`{round(sl_raw, 8)}`|计划 TP:`{round(tp_raw, 8)}`|计划 RR(E):{rr_txt}:1",
|
f"计划 SL:`{format_wechat_scalar_2dp(sl_raw)}`|计划 TP:`{format_price_for_symbol(sym, tp_raw)}`|计划 RR(E):{rr_txt}:1",
|
||||||
"说明:OKX 本实例为提醒模式,不自动市价开仓;请按方案自行下单。",
|
"说明:OKX 本实例为提醒模式,不自动市价开仓;请按方案自行下单。",
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
@@ -4560,6 +4597,7 @@ def check_key_monitors():
|
|||||||
"\n".join(
|
"\n".join(
|
||||||
[
|
[
|
||||||
f"# 🧾 {r['symbol']} 关键位监控结束",
|
f"# 🧾 {r['symbol']} 关键位监控结束",
|
||||||
|
f"**账户:{_wechat_account_label()}**",
|
||||||
"",
|
"",
|
||||||
f"- 原因:已满 {max_n} 次提醒",
|
f"- 原因:已满 {max_n} 次提醒",
|
||||||
"- 状态:已自动结束并记入历史",
|
"- 状态:已自动结束并记入历史",
|
||||||
@@ -4614,6 +4652,7 @@ def check_order_monitors():
|
|||||||
direction == "long" and new_sl > float(stop_loss)
|
direction == "long" and new_sl > float(stop_loss)
|
||||||
)
|
)
|
||||||
if should_move:
|
if should_move:
|
||||||
|
was_armed = breakeven_armed
|
||||||
ex_sym = resolve_monitor_exchange_symbol(r)
|
ex_sym = resolve_monitor_exchange_symbol(r)
|
||||||
new_sl = round_price_to_exchange(ex_sym, new_sl)
|
new_sl = round_price_to_exchange(ex_sym, new_sl)
|
||||||
tp_ex = float(take_profit or 0)
|
tp_ex = float(take_profit or 0)
|
||||||
@@ -4623,13 +4662,15 @@ def check_order_monitors():
|
|||||||
try:
|
try:
|
||||||
replace_active_monitor_tpsl_on_exchange(r, new_sl, tp_ex)
|
replace_active_monitor_tpsl_on_exchange(r, new_sl, tp_ex)
|
||||||
synced_ex = True
|
synced_ex = True
|
||||||
|
_clear_breakeven_exchange_warn(pid)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
print(
|
||||||
f"[breakeven] exchange tpsl replace failed order={pid} {sym}: {e}",
|
f"[breakeven] exchange tpsl replace failed order={pid} {sym}: {e}",
|
||||||
flush=True,
|
flush=True,
|
||||||
)
|
)
|
||||||
send_wechat_msg(
|
_send_breakeven_exchange_warn_once(
|
||||||
f"⚠️ {sym} 移动保本止损未同步交易所:{friendly_okx_error(e)}"
|
pid,
|
||||||
|
f"⚠️ {sym} 移动保本止损未同步交易所:{friendly_okx_error(e)}",
|
||||||
)
|
)
|
||||||
elif ok_live:
|
elif ok_live:
|
||||||
print(
|
print(
|
||||||
@@ -4642,18 +4683,20 @@ def check_order_monitors():
|
|||||||
(new_sl, new_sl, pid),
|
(new_sl, new_sl, pid),
|
||||||
)
|
)
|
||||||
stop_loss = new_sl
|
stop_loss = new_sl
|
||||||
arm_txt = "保本止盈" if not breakeven_armed else "移动止盈"
|
breakeven_armed = 1
|
||||||
be_msg = build_wechat_breakeven_message(
|
if not was_armed:
|
||||||
sym,
|
arm_txt = "保本止盈"
|
||||||
direction,
|
be_msg = build_wechat_breakeven_message(
|
||||||
arm_txt,
|
sym,
|
||||||
now_rr,
|
direction,
|
||||||
locked_r,
|
arm_txt,
|
||||||
new_sl,
|
now_rr,
|
||||||
)
|
locked_r,
|
||||||
if ok_live:
|
new_sl,
|
||||||
be_msg += "\n- 交易所:已先撤后挂止盈止损"
|
)
|
||||||
send_wechat_msg(be_msg)
|
if ok_live:
|
||||||
|
be_msg += "\n- 交易所:已先撤后挂止盈止损"
|
||||||
|
send_wechat_msg(be_msg)
|
||||||
|
|
||||||
res = None
|
res = None
|
||||||
# 做多
|
# 做多
|
||||||
@@ -6198,14 +6241,26 @@ def add_order():
|
|||||||
|
|
||||||
_, trading_capital_after = get_exchange_capitals(force=True)
|
_, trading_capital_after = get_exchange_capitals(force=True)
|
||||||
account_base_display = (
|
account_base_display = (
|
||||||
round(float(trading_capital_after), 4)
|
round(float(trading_capital_after), 2)
|
||||||
if trading_capital_after is not None
|
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)"
|
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 "-"
|
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 趋势"
|
style_zh = "Swing 波段" if trade_style == "swing" else "Trend 趋势"
|
||||||
wx_lines = [
|
wx_lines = [
|
||||||
f"📈 {symbol} 开仓成功",
|
f"📈 {symbol} 开仓成功",
|
||||||
@@ -6213,22 +6268,22 @@ def add_order():
|
|||||||
"🧾 订单基础信息",
|
"🧾 订单基础信息",
|
||||||
f"🔖 交易所订单 ID:{open_order_id}",
|
f"🔖 交易所订单 ID:{open_order_id}",
|
||||||
f"📈 交易风格:{style_zh}",
|
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"账户基数:{account_base_display} USDT",
|
||||||
f"合约杠杆:{leverage} 倍",
|
f"合约杠杆:{leverage} 倍",
|
||||||
f"名义仓位:{notional_value} USDT",
|
f"名义仓位:{format_wechat_scalar_2dp(notional_value)} USDT",
|
||||||
f"仓位占比:{position_ratio}%",
|
f"仓位占比:{position_ratio}%",
|
||||||
f"合约张数:{amount} 张",
|
f"合约张数:{format_wechat_scalar_2dp(amount)} 张",
|
||||||
f"折算标的:{base_amount} {journal_coin_from_symbol(symbol)}",
|
f"折算标的:{base_amount} {journal_coin_from_symbol(symbol)}",
|
||||||
"🎯 价位 & 盈亏比",
|
"🎯 价位 & 盈亏比",
|
||||||
f"开仓成交价:{trigger_price}",
|
f"开仓成交价:{ep_wx}",
|
||||||
f"止损价位:{stop_loss}",
|
f"止损价位:{sl_wx}",
|
||||||
f"止盈价位:{take_profit}",
|
f"止盈价位:{tp_wx}",
|
||||||
f"计划盈亏比:RR {rr_show} : 1",
|
f"计划盈亏比:{rr_line}",
|
||||||
f"移动保本位:{breakeven_rr_trigger}R → {breakeven_price}",
|
f"移动保本位:{breakeven_rr_trigger}R → {be_wx}",
|
||||||
"📌 状态统计",
|
"📌 状态统计",
|
||||||
f"✅ 止盈止损:{order_state_text}",
|
f"✅ 条件委托:{order_state_text}",
|
||||||
f"📅 当日开仓次数:{opens_today_after} / {DAILY_OPEN_ALERT_THRESHOLD} 次(风控阈值提醒)",
|
f"📅 当日开仓次数:{opens_today_after} / {DAILY_OPEN_ALERT_THRESHOLD} 次(风控阈值提醒)",
|
||||||
]
|
]
|
||||||
if chart_url:
|
if chart_url:
|
||||||
@@ -6236,8 +6291,8 @@ def add_order():
|
|||||||
send_wechat_msg("\n".join(wx_lines))
|
send_wechat_msg("\n".join(wx_lines))
|
||||||
|
|
||||||
flash_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"实盘开单成功:风格 {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 {planned_rr if planned_rr is not None else '-'};止盈止损已挂交易所",
|
f"计划RR {format_wechat_scalar_2dp(planned_rr) if planned_rr is not None else '-'};已在交易所挂条件止盈/止损委托(非仓位绑定型)",
|
||||||
f"本交易日累计开仓:{opens_today_after}",
|
f"本交易日累计开仓:{opens_today_after}",
|
||||||
]
|
]
|
||||||
if chart_url:
|
if chart_url:
|
||||||
|
|||||||
@@ -79,6 +79,13 @@
|
|||||||
- 手动强制同步:`GET /api/sync_exchange_pnl`(需登录)。
|
- 手动强制同步:`GET /api/sync_exchange_pnl`(需登录)。
|
||||||
- 可选 `.env`:`EXCHANGE_POSITION_SYNC_FROM_BJ`(北京时间起点)、`EXCHANGE_POSITION_HISTORY_LIMIT`(默认 200)。
|
- 可选 `.env`:`EXCHANGE_POSITION_SYNC_FROM_BJ`(北京时间起点)、`EXCHANGE_POSITION_HISTORY_LIMIT`(默认 200)。
|
||||||
|
|
||||||
|
## 企业微信推送(与 Gate 对齐)
|
||||||
|
|
||||||
|
- 平仓:`📉 … 平仓完成` 模板(盈亏 ±X.XX U、价位两位/按币价精度、账户资金 2 位小数)。
|
||||||
|
- 开仓成功:与 Gate 相同的 emoji 分段(条件委托状态文案、RR/张数/名义 2 位小数)。
|
||||||
|
- 移动保本:仅首次触发推送;交易所同步失败同一监控单只告警一次。
|
||||||
|
- 斐波/关键位/划转等推送数值格式与 Gate 一致(`format_wechat_scalar_2dp`)。
|
||||||
|
|
||||||
## 配置与部署
|
## 配置与部署
|
||||||
|
|
||||||
- 详见 `.env.example` 中 OKX(`OKX_*`)与通用风控项。
|
- 详见 `.env.example` 中 OKX(`OKX_*`)与通用风控项。
|
||||||
|
|||||||
Reference in New Issue
Block a user