币本位期权开仓/翻倍提醒/翻倍平仓/目标平仓/手动平仓微信推送:按ETH/BTC计价并补齐全平必发
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -378,6 +378,8 @@ def open_coin_option_buy_full(
|
||||
open_quote=float(ask),
|
||||
target_index=target_index,
|
||||
signal_note=signal_note,
|
||||
premium_ccy=premium_ccy,
|
||||
margin_mode="coin",
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -30,16 +30,23 @@ def build_profit_alert_message(
|
||||
upl: float,
|
||||
upl_ratio: float | None,
|
||||
bid: float | None,
|
||||
premium_ccy: str | None = None,
|
||||
) -> str:
|
||||
from lib.options.options_notify_lib import resolve_options_premium_ccy
|
||||
|
||||
ccy = resolve_options_premium_ccy(inst_id=inst_id, premium_ccy=premium_ccy)
|
||||
d = 6 if ccy in ("ETH", "BTC") else 4
|
||||
pct = f"{upl_ratio * 100:.1f}%" if upl_ratio is not None else "—"
|
||||
bid_txt = f"{bid:.4f}" if bid is not None else "—"
|
||||
bid_txt = f"{bid:.{d}f}" if bid is not None else "—"
|
||||
mode = "币本位" if ccy != "USDC" else "USDC"
|
||||
return "\n".join(
|
||||
[
|
||||
"【OKX期权·翻倍提醒】",
|
||||
f"账户:{account_label}",
|
||||
f"本位:{mode}",
|
||||
f"合约:{inst_id}",
|
||||
f"已付权利金:{premium_paid:.4f} USDC",
|
||||
f"未实现盈亏:{upl:+.4f} USDC({pct})",
|
||||
f"已付权利金:{premium_paid:.{d}f} {ccy}",
|
||||
f"未实现盈亏:{upl:+.{d}f} {ccy}({pct})",
|
||||
f"当前买一:{bid_txt}(可考虑限价平仓锁利)",
|
||||
]
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""OKX 期权开仓/平仓企业微信推送(必发,幂等落库标记)."""
|
||||
"""OKX 期权开仓/平仓企业微信推送(必发,幂等落库标记).支持 USDC / 币本位(ETH/BTC)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
@@ -23,6 +23,63 @@ def _opt_type_label(opt_type: Any) -> str:
|
||||
return t or "—"
|
||||
|
||||
|
||||
def resolve_options_premium_ccy(
|
||||
*,
|
||||
inst_id: str = "",
|
||||
underlying: str = "",
|
||||
premium_ccy: Any = None,
|
||||
margin_mode: Any = None,
|
||||
row: dict[str, Any] | None = None,
|
||||
) -> str:
|
||||
"""权利金计价币种:USDC 或 ETH/BTC."""
|
||||
raw = premium_ccy
|
||||
if (raw is None or str(raw).strip() == "") and row:
|
||||
raw = row.get("premium_ccy")
|
||||
ccy = str(raw or "").strip().upper()
|
||||
if ccy:
|
||||
return ccy
|
||||
try:
|
||||
from lib.options.options_margin_mode_lib import margin_mode_from_inst_id, premium_ccy_for_mode
|
||||
|
||||
mid = str(inst_id or (row or {}).get("inst_id") or "").strip()
|
||||
mode = margin_mode if margin_mode is not None else (row or {}).get("margin_mode")
|
||||
if mode is None and mid:
|
||||
mode = margin_mode_from_inst_id(mid)
|
||||
u = str(
|
||||
underlying
|
||||
or (row or {}).get("underlying")
|
||||
or (mid.split("-")[0] if mid else "ETH")
|
||||
or "ETH"
|
||||
).strip().upper() or "ETH"
|
||||
return premium_ccy_for_mode(str(mode or "usdc"), u)
|
||||
except Exception:
|
||||
return "USDC"
|
||||
|
||||
|
||||
def _amount_decimals(ccy: str) -> int:
|
||||
c = (ccy or "USDC").strip().upper()
|
||||
if c in ("ETH", "BTC"):
|
||||
return 6
|
||||
return 4
|
||||
|
||||
|
||||
def _mode_tag(*, inst_id: str = "", premium_ccy: str = "", margin_mode: Any = None) -> str:
|
||||
ccy = (premium_ccy or "").strip().upper()
|
||||
if ccy and ccy != "USDC":
|
||||
return "币本位"
|
||||
try:
|
||||
from lib.options.options_margin_mode_lib import is_coin_margin_mode, margin_mode_from_inst_id
|
||||
|
||||
mode = margin_mode
|
||||
if mode is None and inst_id:
|
||||
mode = margin_mode_from_inst_id(inst_id)
|
||||
if is_coin_margin_mode(mode):
|
||||
return "币本位"
|
||||
except Exception:
|
||||
pass
|
||||
return "USDC"
|
||||
|
||||
|
||||
def ensure_options_notify_columns(conn: sqlite3.Connection) -> None:
|
||||
for ddl in (
|
||||
"ALTER TABLE options_trades ADD COLUMN wechat_open_sent INTEGER DEFAULT 0",
|
||||
@@ -57,10 +114,21 @@ def build_options_open_message(
|
||||
target_index: Any = None,
|
||||
signal_note: str = "",
|
||||
trade_id: Any = None,
|
||||
premium_ccy: Any = None,
|
||||
margin_mode: Any = None,
|
||||
) -> str:
|
||||
ccy = resolve_options_premium_ccy(
|
||||
inst_id=inst_id,
|
||||
underlying=underlying,
|
||||
premium_ccy=premium_ccy,
|
||||
margin_mode=margin_mode,
|
||||
)
|
||||
d = _amount_decimals(ccy)
|
||||
mode = _mode_tag(inst_id=inst_id, premium_ccy=ccy, margin_mode=margin_mode)
|
||||
lines = [
|
||||
"【OKX期权·开仓】",
|
||||
f"账户:{account_label or 'OKX期权'}",
|
||||
f"本位:{mode}",
|
||||
]
|
||||
if trade_id is not None:
|
||||
lines.append(f"本地单号:#{trade_id}")
|
||||
@@ -69,8 +137,8 @@ def build_options_open_message(
|
||||
f"合约:{inst_id}",
|
||||
f"标的:{(underlying or '—')} · {_opt_type_label(opt_type)}",
|
||||
f"张数:{sheets if sheets is not None else '—'}",
|
||||
f"开仓报价:{_fmt(open_quote)} USDC",
|
||||
f"权利金:{_fmt(premium_paid)} USDC",
|
||||
f"开仓报价:{_fmt(open_quote, d)} {ccy}",
|
||||
f"权利金:{_fmt(premium_paid, d)} {ccy}",
|
||||
]
|
||||
)
|
||||
if target_index is not None and str(target_index).strip() != "":
|
||||
@@ -98,10 +166,21 @@ def build_options_close_message(
|
||||
target_index: Any = None,
|
||||
trigger_idx: Any = None,
|
||||
trade_id: Any = None,
|
||||
premium_ccy: Any = None,
|
||||
margin_mode: Any = None,
|
||||
) -> str:
|
||||
ccy = resolve_options_premium_ccy(
|
||||
inst_id=inst_id,
|
||||
underlying=underlying,
|
||||
premium_ccy=premium_ccy,
|
||||
margin_mode=margin_mode,
|
||||
)
|
||||
d = _amount_decimals(ccy)
|
||||
mode = _mode_tag(inst_id=inst_id, premium_ccy=ccy, margin_mode=margin_mode)
|
||||
lines = [
|
||||
"【OKX期权·平仓】",
|
||||
f"账户:{account_label or 'OKX期权'}",
|
||||
f"本位:{mode}",
|
||||
]
|
||||
if trade_id is not None:
|
||||
lines.append(f"本地单号:#{trade_id}")
|
||||
@@ -111,9 +190,9 @@ def build_options_close_message(
|
||||
f"标的:{(underlying or '—')} · {_opt_type_label(opt_type)}",
|
||||
f"原因:{(reason or '平仓').strip()}",
|
||||
f"张数:{sheets if sheets is not None else '—'}",
|
||||
f"平仓报价:{_fmt(close_quote)} USDC",
|
||||
f"已付/收回:{_fmt(premium_paid)} / {_fmt(premium_received)} USDC",
|
||||
f"实现盈亏:{_fmt(realized_pnl, 4)} USDC",
|
||||
f"平仓报价:{_fmt(close_quote, d)} {ccy}",
|
||||
f"已付/收回:{_fmt(premium_paid, d)} / {_fmt(premium_received, d)} {ccy}",
|
||||
f"实现盈亏:{_fmt(realized_pnl, d)} {ccy}",
|
||||
]
|
||||
)
|
||||
if target_index is not None and str(target_index).strip() != "":
|
||||
@@ -142,15 +221,26 @@ def notify_options_open(
|
||||
open_quote: Any = None,
|
||||
target_index: Any = None,
|
||||
signal_note: str = "",
|
||||
premium_ccy: Any = None,
|
||||
margin_mode: Any = None,
|
||||
) -> bool:
|
||||
ensure_options_notify_columns(conn) if conn is not None else None
|
||||
row_ccy = premium_ccy
|
||||
row_mode = margin_mode
|
||||
if conn is not None and trade_id is not None:
|
||||
row = conn.execute(
|
||||
"SELECT wechat_open_sent FROM options_trades WHERE id=?",
|
||||
"SELECT wechat_open_sent, premium_ccy, margin_mode, underlying FROM options_trades WHERE id=?",
|
||||
(int(trade_id),),
|
||||
).fetchone()
|
||||
if row and int(row["wechat_open_sent"] or 0):
|
||||
return False
|
||||
if row:
|
||||
if row_ccy is None:
|
||||
row_ccy = row["premium_ccy"] if "premium_ccy" in row.keys() else None
|
||||
if row_mode is None:
|
||||
row_mode = row["margin_mode"] if "margin_mode" in row.keys() else None
|
||||
if not underlying:
|
||||
underlying = str(row["underlying"] or "") if "underlying" in row.keys() else underlying
|
||||
msg = build_options_open_message(
|
||||
account_label=str(cfg.get("account_label") or "OKX期权"),
|
||||
inst_id=inst_id,
|
||||
@@ -162,6 +252,8 @@ def notify_options_open(
|
||||
target_index=target_index,
|
||||
signal_note=signal_note,
|
||||
trade_id=trade_id,
|
||||
premium_ccy=row_ccy,
|
||||
margin_mode=row_mode,
|
||||
)
|
||||
ok = notify_options_send(cfg, msg)
|
||||
if ok and conn is not None and trade_id is not None:
|
||||
@@ -197,6 +289,8 @@ def notify_options_close(
|
||||
close_quote: Any = None,
|
||||
target_index: Any = None,
|
||||
trigger_idx: Any = None,
|
||||
premium_ccy: Any = None,
|
||||
margin_mode: Any = None,
|
||||
force: bool = False,
|
||||
) -> bool:
|
||||
"""平仓必发.默认按 trade_id / 同合约未标记行幂等."""
|
||||
@@ -230,6 +324,18 @@ def notify_options_close(
|
||||
).fetchone()
|
||||
if q2:
|
||||
rows = [dict(q2)]
|
||||
if not rows:
|
||||
# 已有平仓记录且均已推送:幂等跳过,避免再走「无库行」重复推
|
||||
exists = conn.execute(
|
||||
"""
|
||||
SELECT 1 FROM options_trades
|
||||
WHERE inst_id=? AND status='closed'
|
||||
LIMIT 1
|
||||
""",
|
||||
(inst_id,),
|
||||
).fetchone()
|
||||
if exists:
|
||||
return False
|
||||
|
||||
if rows:
|
||||
# 同次平仓可能多腿:合并一条推送,逐条标记
|
||||
@@ -259,6 +365,8 @@ def notify_options_close(
|
||||
target_index=target_index,
|
||||
trigger_idx=trigger_idx,
|
||||
trade_id=head.get("id") if len(rows) == 1 else None,
|
||||
premium_ccy=premium_ccy or head.get("premium_ccy"),
|
||||
margin_mode=margin_mode or head.get("margin_mode"),
|
||||
)
|
||||
ok = notify_options_send(cfg, msg)
|
||||
if ok and conn is not None:
|
||||
@@ -288,6 +396,8 @@ def notify_options_close(
|
||||
target_index=target_index,
|
||||
trigger_idx=trigger_idx,
|
||||
trade_id=trade_id,
|
||||
premium_ccy=premium_ccy,
|
||||
margin_mode=margin_mode,
|
||||
)
|
||||
return notify_options_send(cfg, msg)
|
||||
|
||||
@@ -327,4 +437,6 @@ def notify_options_close_trade_ids(
|
||||
premium_received=sum(float(r["premium_received"] or 0) for r in rows if r["premium_received"] is not None),
|
||||
realized_pnl=sum(float(r["realized_pnl"]) for r in rows if r["realized_pnl"] is not None),
|
||||
close_quote=first.get("close_quote"),
|
||||
premium_ccy=first.get("premium_ccy"),
|
||||
margin_mode=first.get("margin_mode"),
|
||||
)
|
||||
|
||||
@@ -233,6 +233,12 @@ def _notify_profit_exit_close(
|
||||
result: dict[str, Any],
|
||||
conn: Any = None,
|
||||
) -> None:
|
||||
from lib.options.options_notify_lib import resolve_options_premium_ccy
|
||||
|
||||
ccy = resolve_options_premium_ccy(inst_id=inst_id)
|
||||
d = 6 if ccy in ("ETH", "BTC") else 4
|
||||
mode = "币本位" if ccy != "USDC" else "USDC"
|
||||
reason = f"翻倍出场({mult:g}倍)"
|
||||
if result.get("fully_closed") or result.get("already_flat"):
|
||||
if cfg is not None:
|
||||
try:
|
||||
@@ -242,26 +248,31 @@ def _notify_profit_exit_close(
|
||||
cfg,
|
||||
conn,
|
||||
inst_id=inst_id,
|
||||
reason=f"翻倍出场({mult:g}倍)",
|
||||
reason=reason,
|
||||
sheets=result.get("submitted_sheets"),
|
||||
premium_received=result.get("premium_received"),
|
||||
close_quote=result.get("locked_bid_px") or result.get("bid"),
|
||||
premium_ccy=ccy,
|
||||
)
|
||||
# 无论首次/幂等跳过,全平路径不再走下方 fallback,避免重复推
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
if not send_wechat:
|
||||
return
|
||||
try:
|
||||
prem_txt = f"{float(premium_paid):.{d}f}" if premium_paid is not None else "—"
|
||||
recv_txt = f"{float(recycle):.{d}f}" if recycle is not None else "—"
|
||||
send_wechat(
|
||||
"\n".join(
|
||||
[
|
||||
"【OKX期权·翻倍出场】",
|
||||
f"账户:{account_label}",
|
||||
f"本位:{mode}",
|
||||
f"合约:{inst_id}",
|
||||
f"倍数:{mult:g}(1倍=盈利=权利金)",
|
||||
f"权利金:{premium_paid if premium_paid is not None else '—'}",
|
||||
f"可回收:{recycle if recycle is not None else '—'}",
|
||||
f"权利金:{prem_txt} {ccy}",
|
||||
f"可回收:{recv_txt} {ccy}",
|
||||
f"提交张数:{result.get('submitted_sheets') or '—'}",
|
||||
f"状态:{'已全平' if (result.get('fully_closed') or result.get('already_flat')) else '挂单中/部分'}",
|
||||
]
|
||||
@@ -330,6 +341,17 @@ def run_options_profit_exits(
|
||||
if result.get("already_flat") or _result_fully_done(result):
|
||||
_mark_state(conn, inst_id, "done")
|
||||
_commit(conn)
|
||||
_notify_profit_exit_close(
|
||||
cfg,
|
||||
send_wechat,
|
||||
account_label=account_label,
|
||||
inst_id=inst_id,
|
||||
mult=mult,
|
||||
premium_paid=prem,
|
||||
recycle=None,
|
||||
result={**result, "fully_closed": True},
|
||||
conn=conn,
|
||||
)
|
||||
else:
|
||||
_mark_state(conn, inst_id, "closing")
|
||||
_commit(conn)
|
||||
@@ -353,6 +375,18 @@ def run_options_profit_exits(
|
||||
if result.get("already_flat"):
|
||||
_mark_state(conn, inst_id, "done")
|
||||
_commit(conn)
|
||||
triggered += 1
|
||||
_notify_profit_exit_close(
|
||||
cfg,
|
||||
send_wechat,
|
||||
account_label=account_label,
|
||||
inst_id=inst_id,
|
||||
mult=mult,
|
||||
premium_paid=prem,
|
||||
recycle=recycle,
|
||||
result=result,
|
||||
conn=conn,
|
||||
)
|
||||
continue
|
||||
if not result.get("ok"):
|
||||
_mark_state(conn, inst_id, "active")
|
||||
|
||||
@@ -309,6 +309,11 @@ def _notify_target_close(
|
||||
conn: Any = None,
|
||||
) -> None:
|
||||
"""目标位平仓推送:优先走统一平仓必发(幂等);无 cfg 时回退旧文案."""
|
||||
from lib.options.options_notify_lib import resolve_options_premium_ccy
|
||||
|
||||
ccy = resolve_options_premium_ccy(inst_id=inst_id)
|
||||
d = 6 if ccy in ("ETH", "BTC") else 4
|
||||
mode = "币本位" if ccy != "USDC" else "USDC"
|
||||
if result.get("fully_closed") or result.get("already_flat"):
|
||||
if cfg is not None:
|
||||
try:
|
||||
@@ -324,23 +329,28 @@ def _notify_target_close(
|
||||
close_quote=result.get("locked_bid_px") or result.get("bid"),
|
||||
target_index=target,
|
||||
trigger_idx=idx,
|
||||
premium_ccy=ccy,
|
||||
)
|
||||
# 无论首次/幂等跳过,全平路径不再走下方 fallback,避免重复推
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
if not send_wechat:
|
||||
return
|
||||
try:
|
||||
recv = result.get("premium_received")
|
||||
recv_txt = f"{float(recv):.{d}f} {ccy}" if recv is not None else f"— {ccy}"
|
||||
send_wechat(
|
||||
"\n".join(
|
||||
[
|
||||
"【OKX期权·目标位平仓】",
|
||||
f"账户:{account_label}",
|
||||
f"本位:{mode}",
|
||||
f"合约:{inst_id}",
|
||||
f"目标指数:{target:g}",
|
||||
f"触发指数:{idx:g}",
|
||||
f"提交张数:{result.get('submitted_sheets') or '—'}",
|
||||
f"预估收回:{result.get('premium_received') if result.get('premium_received') is not None else '—'} USDC",
|
||||
f"预估收回:{recv_txt}",
|
||||
f"状态:{'已全平' if (result.get('fully_closed') or result.get('already_flat')) else '挂单中/部分'}",
|
||||
]
|
||||
)
|
||||
@@ -391,7 +401,7 @@ def run_options_target_closes(
|
||||
cancel_orphans_without_position(conn, live_inst_ids=live_ids)
|
||||
_commit_monitor(conn)
|
||||
|
||||
# 先处理已挂单等待成交的,绝不再发微信
|
||||
# 先处理已挂单等待成交的;首次触发已推过「挂单中」,此处仅在全平时走幂等平仓推送
|
||||
for mon in list_closing_targets(conn):
|
||||
inst_id = str(mon.get("inst_id") or "")
|
||||
if not inst_id:
|
||||
@@ -408,6 +418,18 @@ def run_options_target_closes(
|
||||
if inst_id not in pos_by_inst:
|
||||
mark_monitor(conn, int(mon["id"]), status="expired", message="持仓已平")
|
||||
_commit_monitor(conn)
|
||||
target = _safe_float(mon.get("target_index"))
|
||||
idx = _safe_float(mon.get("trigger_idx"))
|
||||
_notify_target_close(
|
||||
cfg,
|
||||
send_wechat,
|
||||
account_label=account_label,
|
||||
inst_id=inst_id,
|
||||
target=float(target) if target is not None else 0.0,
|
||||
idx=float(idx) if idx is not None else 0.0,
|
||||
result={"already_flat": True, "fully_closed": True, "ok": True},
|
||||
conn=conn,
|
||||
)
|
||||
continue
|
||||
result = close_fn(inst_id)
|
||||
idx = _safe_float(pos_by_inst[inst_id].get("idx_px") or pos_by_inst[inst_id].get("idxPx"))
|
||||
@@ -421,6 +443,17 @@ def run_options_target_closes(
|
||||
message="目标位限价平仓完成",
|
||||
)
|
||||
_commit_monitor(conn)
|
||||
target = _safe_float(mon.get("target_index"))
|
||||
_notify_target_close(
|
||||
cfg,
|
||||
send_wechat,
|
||||
account_label=account_label,
|
||||
inst_id=inst_id,
|
||||
target=float(target) if target is not None else 0.0,
|
||||
idx=float(idx) if idx is not None else 0.0,
|
||||
result={**result, "fully_closed": True},
|
||||
conn=conn,
|
||||
)
|
||||
continue
|
||||
mark_monitor(
|
||||
conn,
|
||||
@@ -464,6 +497,17 @@ def run_options_target_closes(
|
||||
if result.get("already_flat"):
|
||||
mark_monitor(conn, int(mon["id"]), status="expired", trigger_idx=idx, message="持仓已平")
|
||||
_commit_monitor(conn)
|
||||
triggered += 1
|
||||
_notify_target_close(
|
||||
cfg,
|
||||
send_wechat,
|
||||
account_label=account_label,
|
||||
inst_id=inst_id,
|
||||
target=target,
|
||||
idx=idx,
|
||||
result=result,
|
||||
conn=conn,
|
||||
)
|
||||
continue
|
||||
if not result.get("ok"):
|
||||
mark_monitor(
|
||||
|
||||
@@ -11,10 +11,10 @@ from lib.options.options_notify_lib import (
|
||||
|
||||
|
||||
class TestOptionsNotify(unittest.TestCase):
|
||||
def test_open_close_messages(self) -> None:
|
||||
def test_open_close_messages_usdc(self) -> None:
|
||||
open_msg = build_options_open_message(
|
||||
account_label="OKX期权",
|
||||
inst_id="ETH-USD-250725-3200-C",
|
||||
inst_id="ETH-USD_UM-250725-3200-C",
|
||||
underlying="ETH",
|
||||
opt_type="C",
|
||||
sheets=2,
|
||||
@@ -23,14 +23,17 @@ class TestOptionsNotify(unittest.TestCase):
|
||||
target_index=3400,
|
||||
signal_note="假突破",
|
||||
trade_id=12,
|
||||
premium_ccy="USDC",
|
||||
margin_mode="usdc",
|
||||
)
|
||||
self.assertIn("【OKX期权·开仓】", open_msg)
|
||||
self.assertIn("ETH-USD-250725-3200-C", open_msg)
|
||||
self.assertIn("ETH-USD_UM-250725-3200-C", open_msg)
|
||||
self.assertIn("目标指数:3400", open_msg)
|
||||
self.assertIn("USDC", open_msg)
|
||||
|
||||
close_msg = build_options_close_message(
|
||||
account_label="OKX期权",
|
||||
inst_id="ETH-USD-250725-3200-C",
|
||||
inst_id="ETH-USD_UM-250725-3200-C",
|
||||
reason="手动平仓",
|
||||
underlying="ETH",
|
||||
opt_type="C",
|
||||
@@ -38,10 +41,45 @@ class TestOptionsNotify(unittest.TestCase):
|
||||
premium_paid=8.5,
|
||||
premium_received=12.0,
|
||||
realized_pnl=3.5,
|
||||
premium_ccy="USDC",
|
||||
)
|
||||
self.assertIn("【OKX期权·平仓】", close_msg)
|
||||
self.assertIn("手动平仓", close_msg)
|
||||
self.assertIn("3.5000", close_msg)
|
||||
self.assertIn("USDC", close_msg)
|
||||
|
||||
def test_open_close_messages_coin(self) -> None:
|
||||
open_msg = build_options_open_message(
|
||||
account_label="OKX期权",
|
||||
inst_id="ETH-USD-250725-3200-C",
|
||||
underlying="ETH",
|
||||
opt_type="C",
|
||||
sheets=1,
|
||||
premium_paid=0.001234,
|
||||
open_quote=0.01234,
|
||||
trade_id=99,
|
||||
premium_ccy="ETH",
|
||||
margin_mode="coin",
|
||||
)
|
||||
self.assertIn("本位:币本位", open_msg)
|
||||
self.assertIn("ETH", open_msg)
|
||||
self.assertNotIn("USDC", open_msg)
|
||||
|
||||
close_msg = build_options_close_message(
|
||||
account_label="OKX期权",
|
||||
inst_id="ETH-USD-250725-3200-C",
|
||||
reason="翻倍出场(1倍)",
|
||||
underlying="ETH",
|
||||
sheets=1,
|
||||
premium_paid=0.001234,
|
||||
premium_received=0.0025,
|
||||
realized_pnl=0.001266,
|
||||
premium_ccy="ETH",
|
||||
margin_mode="coin",
|
||||
)
|
||||
self.assertIn("本位:币本位", close_msg)
|
||||
self.assertIn("翻倍出场", close_msg)
|
||||
self.assertIn("ETH", close_msg)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user