Initial standalone crypto_okx with one-click deploy.
Add deploy/manage.sh bootstrap for git.bz121.com/dekun/crypto_okx and point docs at this repo. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
"""对冲计划企业微信推送(起止必发,幂等落库标记)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
from lib.hedge_plan.hedge_plan_db import update_plan
|
||||
|
||||
|
||||
def _fmt(v: Any, d: int = 2) -> str:
|
||||
try:
|
||||
if v is None or v == "":
|
||||
return "—"
|
||||
return f"{float(v):.{d}f}"
|
||||
except (TypeError, ValueError):
|
||||
return str(v)
|
||||
|
||||
|
||||
def _type_label(plan_type: str) -> str:
|
||||
return "永期对冲" if (plan_type or "") == "perp_options" else "期期对冲"
|
||||
|
||||
|
||||
def _dir_label(direction: str) -> str:
|
||||
d = (direction or "").lower()
|
||||
if d == "long":
|
||||
return "做多"
|
||||
if d == "short":
|
||||
return "做空"
|
||||
return "—"
|
||||
|
||||
|
||||
def build_hedge_start_message(plan: dict[str, Any], *, legs: Optional[list[dict[str, Any]]] = None) -> str:
|
||||
pt = plan.get("plan_type") or ""
|
||||
lines = [
|
||||
f"🟢 对冲计划启动 #{plan.get('id')}",
|
||||
f"📌 类型:{_type_label(pt)}",
|
||||
f"🪙 标的:{plan.get('underlying') or '—'}",
|
||||
]
|
||||
if pt == "perp_options":
|
||||
lines.extend(
|
||||
[
|
||||
f"📈 方向:{_dir_label(plan.get('direction') or '')}",
|
||||
f"💵 开仓参考:{_fmt(plan.get('entry_mark'))}",
|
||||
f"🎯 止盈:{_fmt(plan.get('tp'))}|止损:{_fmt(plan.get('sl'))}",
|
||||
f"📦 永续张数:{_fmt(plan.get('perp_size'), 4)}|杠杆:{_fmt(plan.get('leverage'), 0)}x",
|
||||
f"💎 期权保费合计:{_fmt(plan.get('premium_total'), 4)} USDC",
|
||||
]
|
||||
)
|
||||
else:
|
||||
rr = plan.get("profit_rr")
|
||||
if rr not in (None, ""):
|
||||
lines.extend(
|
||||
[
|
||||
f"🎯 盈亏比:{_fmt(rr)} (盈利金额/总权利金)",
|
||||
f"💎 期权保费合计:{_fmt(plan.get('premium_total'), 4)} USDC",
|
||||
]
|
||||
)
|
||||
else:
|
||||
lines.extend(
|
||||
[
|
||||
f"🎯 上破:{_fmt(plan.get('target_price_up') or plan.get('target_price'))}"
|
||||
f"|下破:{_fmt(plan.get('target_price_down') or plan.get('target_price'))}",
|
||||
f"💎 期权保费合计:{_fmt(plan.get('premium_total'), 4)} USDC",
|
||||
]
|
||||
)
|
||||
if legs:
|
||||
for leg in legs:
|
||||
role = leg.get("leg_role") or ""
|
||||
if role == "perp":
|
||||
lines.append(f"· 永续腿 {leg.get('symbol') or ''} ×{_fmt(leg.get('size'), 4)}")
|
||||
else:
|
||||
lines.append(
|
||||
f"· {role} {(leg.get('opt_type') or '')} K{_fmt(leg.get('strike'), 0)} "
|
||||
f"×{_fmt(leg.get('size'), 0)}张 {leg.get('inst_id') or ''}"
|
||||
)
|
||||
lines.append("📎 独立模块推送,不进普通交易复盘")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def build_hedge_end_message(plan: dict[str, Any]) -> str:
|
||||
reason = plan.get("close_reason") or "—"
|
||||
total = plan.get("realized_pnl_total")
|
||||
try:
|
||||
tv = float(total) if total is not None else None
|
||||
except (TypeError, ValueError):
|
||||
tv = None
|
||||
head = "🔴" if (tv is not None and tv < 0) else "🟢"
|
||||
reason_map = {
|
||||
"perp_tp": "永续止盈(期权默认不平)",
|
||||
"perp_sl": "永续止损(期权强制平)",
|
||||
"target_win_leg": "期期已平盈利腿(中间态)",
|
||||
"target_up_win_leg": "期期上破·已平盈利腿",
|
||||
"target_down_win_leg": "期期下破·已平盈利腿",
|
||||
"profit_rr_win_leg": "期期盈亏比达标·已平盈利腿",
|
||||
"oo_rest_closing": "期期残值平·清亏损腿中",
|
||||
"oo_rest_closed": "期期残值平·两腿已平",
|
||||
"oo_expiry_loss": "期期到期无盈利·总亏损",
|
||||
"oo_expiry_win": "期期到期仍盈利",
|
||||
"expiry": "到期收口",
|
||||
"manual": "人工结束",
|
||||
"partial_fail": "半腿失败收尾",
|
||||
"cancelled": "已取消",
|
||||
}
|
||||
lines = [
|
||||
f"{head} 对冲计划结束 #{plan.get('id')}",
|
||||
f"📌 类型:{_type_label(plan.get('plan_type') or '')}",
|
||||
f"🪙 标的:{plan.get('underlying') or '—'}",
|
||||
f"📎 原因:{reason_map.get(reason, reason)}",
|
||||
f"💰 合计≈U:{_fmt(total)}",
|
||||
f"· 永续分项:{_fmt(plan.get('realized_pnl_perp'))} USDT",
|
||||
f"· 期权分项:{_fmt(plan.get('realized_pnl_options'))} USDC(≈U 1:1)",
|
||||
f"⏱ 开仓:{plan.get('opened_at') or '—'}|结束:{plan.get('closed_at') or '—'}",
|
||||
]
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def build_hedge_alert_message(
|
||||
*,
|
||||
title: str,
|
||||
plan_id: Any = None,
|
||||
detail: str = "",
|
||||
) -> str:
|
||||
lines = [f"⚠️ 对冲计划告警{(' #' + str(plan_id)) if plan_id else ''}", f"📌 {title}"]
|
||||
if detail:
|
||||
lines.append(str(detail)[:800])
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def notify_hedge(
|
||||
cfg: dict[str, Any],
|
||||
content: str,
|
||||
) -> bool:
|
||||
send: Optional[Callable[[str], Any]] = cfg.get("send_wechat")
|
||||
if not callable(send):
|
||||
return False
|
||||
try:
|
||||
send(content)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def notify_plan_start(
|
||||
cfg: dict[str, Any],
|
||||
conn: Any,
|
||||
plan: dict[str, Any],
|
||||
legs: Optional[list[dict[str, Any]]] = None,
|
||||
) -> bool:
|
||||
if int(plan.get("wechat_start_sent") or 0):
|
||||
return False
|
||||
ok = notify_hedge(cfg, build_hedge_start_message(plan, legs=legs))
|
||||
if ok and plan.get("id") is not None:
|
||||
update_plan(conn, int(plan["id"]), wechat_start_sent=1)
|
||||
plan["wechat_start_sent"] = 1
|
||||
return ok
|
||||
|
||||
|
||||
def notify_plan_end(cfg: dict[str, Any], conn: Any, plan: dict[str, Any]) -> bool:
|
||||
if int(plan.get("wechat_end_sent") or 0):
|
||||
return False
|
||||
# 中间态 target_win_leg 不算正式结束推送(用告警)
|
||||
if (plan.get("close_reason") or "") in (
|
||||
"target_win_leg",
|
||||
"target_up_win_leg",
|
||||
"target_down_win_leg",
|
||||
"profit_rr_win_leg",
|
||||
"oo_rest_closing",
|
||||
) and (plan.get("status") or "") != "closed":
|
||||
cr = str(plan.get("close_reason") or "")
|
||||
if "profit_rr" in cr:
|
||||
side = "盈亏比达标"
|
||||
elif "up" in cr:
|
||||
side = "上破"
|
||||
elif "down" in cr:
|
||||
side = "下破"
|
||||
else:
|
||||
side = "目标"
|
||||
mode = (plan.get("oo_close_mode") or "").strip().lower()
|
||||
if mode in ("close_all", "全平", "残值平"):
|
||||
rest_txt = "另一腿残值平(本合约权利金≤20%且有买一,失败重试)"
|
||||
else:
|
||||
rest_txt = "另一腿到期平(持有至到期结算)"
|
||||
rr = plan.get("profit_rr")
|
||||
if rr not in (None, ""):
|
||||
detail = f"盈亏比 {_fmt(rr)} (盈利金额/总权利金)"
|
||||
else:
|
||||
detail = (
|
||||
f"上破 {_fmt(plan.get('target_price_up') or plan.get('target_price'))}"
|
||||
f"|下破 {_fmt(plan.get('target_price_down') or plan.get('target_price'))}"
|
||||
)
|
||||
notify_hedge(
|
||||
cfg,
|
||||
build_hedge_alert_message(
|
||||
title=f"期期{side}已平盈利腿 · {rest_txt}",
|
||||
plan_id=plan.get("id"),
|
||||
detail=detail,
|
||||
),
|
||||
)
|
||||
return True
|
||||
ok = notify_hedge(cfg, build_hedge_end_message(plan))
|
||||
if ok and plan.get("id") is not None:
|
||||
update_plan(conn, int(plan["id"]), wechat_end_sent=1)
|
||||
plan["wechat_end_sent"] = 1
|
||||
return ok
|
||||
|
||||
|
||||
def notify_partial_fail(cfg: dict[str, Any], *, plan_type: str, msg: str, results: Any = None) -> bool:
|
||||
detail = msg
|
||||
if results:
|
||||
try:
|
||||
detail = f"{msg}\n路径结果:{results}"[:800]
|
||||
except Exception:
|
||||
pass
|
||||
return notify_hedge(
|
||||
cfg,
|
||||
build_hedge_alert_message(title=f"{_type_label(plan_type)}半腿失败", detail=detail),
|
||||
)
|
||||
Reference in New Issue
Block a user