From 4994aaab16bc2f2ed9afa59c59b32d57a5a0c323 Mon Sep 17 00:00:00 2001 From: dekun Date: Sun, 26 Jul 2026 18:32:05 +0800 Subject: [PATCH] Implement dual target-close paths and residual option expiry. Document and enforce: A full dual-leg close, B perp-only when deep OTM with residual archive that does not block next open, and expiry settlement when target is missed. Co-authored-by: Cursor --- backend/app/api/trades.py | 63 +----- backend/app/models/db.py | 22 +++ backend/app/sim/matcher.py | 312 ++++++++++++++++++++++++++++++ backend/app/sim/pnl.py | 67 +++++++ backend/app/sim/pricing.py | 16 ++ backend/app/strategy/engine.py | 66 ++++++- backend/tests/test_p1_p2_rules.py | 12 ++ docs/ETH对冲策略说明.mm | 2 +- docs/ETH对冲策略说明.xmind | Bin 114932 -> 6846 bytes docs/策略说明.md | 73 +++++-- frontend/src/api/client.ts | 8 + frontend/src/labels.ts | 8 +- frontend/src/pages/Plan.tsx | 16 +- scripts/gen_strategy_xmind.py | 48 ++--- 14 files changed, 595 insertions(+), 118 deletions(-) create mode 100644 backend/app/sim/pnl.py diff --git a/backend/app/api/trades.py b/backend/app/api/trades.py index a9b3679..e087df2 100644 --- a/backend/app/api/trades.py +++ b/backend/app/api/trades.py @@ -5,6 +5,7 @@ from typing import Annotated, Any from fastapi import APIRouter, Depends, HTTPException from ..models.db import get_db +from ..sim.pnl import summarize_fills_pnl from .auth import require_user router = APIRouter(prefix="/api/trades", tags=["trades"]) @@ -14,68 +15,6 @@ def _row(r: Any) -> dict: return dict(r) -def summarize_fills_pnl(fills: list[Any]) -> dict[str, float | None]: - """ - 从成交明细重算腿盈亏与净盈亏。 - 价差盈亏按 fill_px(成交价);手续费另扣。 - 净盈亏 = 期权盈亏 + 永续盈亏 − 全部手续费(开+平)。 - """ - rows = [dict(x) for x in fills] - opt_open = next( - (f for f in rows if f.get("leg") == "option" and f.get("action") == "open"), - None, - ) - opt_close = next( - (f for f in rows if f.get("leg") == "option" and f.get("action") == "close"), - None, - ) - perp_open = next( - (f for f in rows if f.get("leg") == "perp" and f.get("action") == "open"), - None, - ) - perp_close = next( - (f for f in rows if f.get("leg") == "perp" and f.get("action") == "close"), - None, - ) - - option_pnl: float | None = None - if opt_open and opt_close: - qty = float(opt_open.get("qty_eth") or opt_close.get("qty_eth") or 0) - option_pnl = (float(opt_close["fill_px"]) - float(opt_open["fill_px"])) * qty - - perp_pnl: float | None = None - if perp_open and perp_close: - qty = float(perp_open.get("qty_eth") or perp_close.get("qty_eth") or 0) - side = str(perp_open.get("side") or "") - o = float(perp_open["fill_px"]) - c = float(perp_close["fill_px"]) - if side == "long": - perp_pnl = (c - o) * qty - else: - perp_pnl = (o - c) * qty - - fees_total = sum(float(f.get("fee") or 0) for f in rows) - gross = None - net = None - if option_pnl is not None and perp_pnl is not None: - gross = option_pnl + perp_pnl - net = gross - fees_total - elif option_pnl is not None: - gross = option_pnl - net = option_pnl - fees_total - elif perp_pnl is not None: - gross = perp_pnl - net = perp_pnl - fees_total - - return { - "option_pnl": option_pnl, - "perp_pnl": perp_pnl, - "fees_total": fees_total, - "gross_pnl": gross, - "net_pnl": net, - } - - @router.get("/groups") async def list_groups(_user: Annotated[str, Depends(require_user)]) -> dict: db = get_db() diff --git a/backend/app/models/db.py b/backend/app/models/db.py index af27207..0bc2df1 100644 --- a/backend/app/models/db.py +++ b/backend/app/models/db.py @@ -97,6 +97,28 @@ CREATE TABLE IF NOT EXISTS strategy_state ( last_error TEXT, updated_at_ms INTEGER NOT NULL ); + +CREATE TABLE IF NOT EXISTS residual_options ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + group_id TEXT NOT NULL UNIQUE, + option_inst_id TEXT NOT NULL, + option_side TEXT NOT NULL, + option_qty_eth REAL NOT NULL, + option_qty_contracts REAL, + option_entry_px REAL NOT NULL, + strike REAL, + expiry_ymd TEXT, + expiry_ms INTEGER, + entry_index_px REAL, + initial_premium REAL DEFAULT 0, + status TEXT NOT NULL DEFAULT 'pending', + created_at_ms INTEGER NOT NULL, + settled_at_ms INTEGER, + settle_px REAL, + settle_pnl REAL, + note TEXT, + FOREIGN KEY(group_id) REFERENCES groups(group_id) +); """ diff --git a/backend/app/sim/matcher.py b/backend/app/sim/matcher.py index 1c660a6..96bd708 100644 --- a/backend/app/sim/matcher.py +++ b/backend/app/sim/matcher.py @@ -13,6 +13,7 @@ from ..strategy.session import get_session from .ledger import Ledger from .liquidity import bid_covers_eth, bid_mark_ok, contracts_for_eth from .pricing import ( + is_deep_otm, option_expiry_settle, option_fill, option_intrinsic, @@ -576,6 +577,317 @@ class Matcher: }, ) + def option_is_deep_otm(self) -> bool: + """活跃组期权是否远虚(内在价值≈0)。""" + pos = self.current_position() + if pos.get("status") != "open" or not pos.get("group_id"): + return False + group_id = str(pos["group_id"]) + option_inst_id = str(pos.get("option_inst_id") or "") + option_side = str(pos.get("option_side") or "") + strike = self._group_strike(group_id, option_inst_id) + spot = self._close_spot_px(get_session().snapshot()) + if strike is None or spot is None: + return False + return is_deep_otm( + option_side=option_side, strike=float(strike), spot=float(spot) + ) + + def close_perp_abandon_option(self, *, reason: str = "target_perp_only") -> CloseResult: + """ + 目标平仓 B:只平永续,期权归档为到期残留(不再盯盘、不挡新开)。 + """ + s = get_settings() + pos = self.current_position() + if pos.get("status") != "open" or not pos.get("group_id"): + return CloseResult(ok=False, detail="无持仓可平") + + group_id = str(pos["group_id"]) + sess = get_session() + snap = sess.snapshot() + if not snap.perp or snap.perp.bid is None or snap.perp.ask is None: + return CloseResult(ok=False, detail="永续盘口不可用") + + option_inst_id = str(pos["option_inst_id"]) + option_side = str(pos["option_side"]) + strike = self._group_strike(group_id, option_inst_id) + spot = self._close_spot_px(snap) + if strike is None or spot is None: + return CloseResult(ok=False, detail="无法判断远虚:缺行权价或标的价") + if not is_deep_otm( + option_side=option_side, strike=float(strike), spot=float(spot) + ): + return CloseResult(ok=False, detail="期权非远虚,应走双腿全平") + + fee_rate = self._fee_rate() + perp_side = str(pos["perp_side"]) + perp_qty = float(pos["perp_qty_eth"]) + perp_entry = float(pos["perp_entry_px"]) + pf = perp_fill( + side=perp_side, + action="close", + bid=float(snap.perp.bid), + ask=float(snap.perp.ask), + qty_eth=perp_qty, + fee_rate=fee_rate, + ) + if perp_side == "long": + perp_pnl = (pf.fill_px - perp_entry) * perp_qty + else: + perp_pnl = (perp_entry - pf.fill_px) * perp_qty + self.ledger.apply_cash( + perp_pnl - pf.fee, + kind="close_perp", + group_id=group_id, + note=f"close perp {reason} abandon option", + ) + + g = self.db.fetchone("SELECT * FROM groups WHERE group_id=?", (group_id,)) + expiry_ymd = str(g["expiry_ymd"]) if g and g["expiry_ymd"] else None + expiry_ms = None + if expiry_ymd: + try: + from ..exchange.expiry import expiry_ms_from_ymd + + expiry_ms = int(expiry_ms_from_ymd(expiry_ymd)) + except Exception: + expiry_ms = None + + now = int(time.time() * 1000) + open_fees = float((g["fees"] if g else 0) or 0) + fees = open_fees + pf.fee + slip = float((g["slip_cost"] if g else 0) or 0) + pf.slip + # 暂记永续段实现盈亏;期权到期结算后再按全部成交重算 + interim_net = perp_pnl - open_fees - pf.fee + + with self.db._lock: + self.db._conn.execute( + """INSERT INTO fills(group_id, leg, action, side, inst_id, qty_eth, qty_contracts, + base_px, fill_px, fee, slip, notional, ts_ms) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)""", + ( + group_id, + "perp", + "close", + "flat", + s.perp_inst_id, + perp_qty, + None, + pf.base_px, + pf.fill_px, + pf.fee, + pf.slip, + pf.notional, + now, + ), + ) + self.db._conn.execute( + """INSERT INTO residual_options( + group_id, option_inst_id, option_side, option_qty_eth, option_qty_contracts, + option_entry_px, strike, expiry_ymd, expiry_ms, entry_index_px, + initial_premium, status, created_at_ms, note + ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)""", + ( + group_id, + option_inst_id, + option_side, + float(pos["option_qty_eth"]), + float(pos["option_qty_contracts"] or 0), + float(pos["option_entry_px"]), + float(strike), + expiry_ymd, + expiry_ms, + float(pos["entry_index_px"] or 0), + float(pos["initial_premium"] or 0), + "pending", + now, + f"abandoned after {reason}; deep_otm spot={spot:.4f} K={strike}", + ), + ) + self.db._conn.execute( + """UPDATE groups SET status=?, close_reason=?, realized_pnl=?, + fees=?, slip_cost=?, note=? WHERE group_id=?""", + ( + "option_residual", + reason, + interim_net, + fees, + slip, + f"perp_closed; option residual until expiry", + group_id, + ), + ) + self.db._conn.execute( + """UPDATE positions SET + group_id=NULL, perp_side=NULL, perp_qty_eth=0, perp_entry_px=NULL, + option_inst_id=NULL, option_side=NULL, option_qty_eth=0, option_qty_contracts=0, + option_entry_px=NULL, entry_index_px=NULL, initial_premium=0, status='flat' + WHERE id=1""" + ) + self.db._conn.commit() + + return CloseResult( + ok=True, + detail="perp_closed_option_residual", + data={ + "group_id": group_id, + "reason": reason, + "mode": "target_perp_only", + "perp_pnl": perp_pnl, + "interim_net": interim_net, + "option_abandoned": True, + "strike": float(strike), + "spot": float(spot), + }, + ) + + def list_residual_options(self, *, pending_only: bool = True) -> list[dict[str, Any]]: + if pending_only: + rows = self.db.fetchall( + "SELECT * FROM residual_options WHERE status='pending' ORDER BY created_at_ms ASC" + ) + else: + rows = self.db.fetchall( + "SELECT * FROM residual_options ORDER BY created_at_ms DESC LIMIT 100" + ) + return [dict(r) for r in rows] + + def settle_due_residuals(self, *, now_ms: int | None = None) -> list[dict[str, Any]]: + """到期结算所有 pending 残留期权(不扫描进活跃组平仓)。""" + now = int(now_ms if now_ms is not None else time.time() * 1000) + pending = self.db.fetchall( + "SELECT * FROM residual_options WHERE status='pending' ORDER BY id ASC" + ) + out: list[dict[str, Any]] = [] + for row in pending: + ems = row["expiry_ms"] + if ems is None: + ymd = row["expiry_ymd"] + if ymd: + try: + from ..exchange.expiry import expiry_ms_from_ymd + + ems = int(expiry_ms_from_ymd(str(ymd))) + except Exception: + continue + else: + continue + if now < int(ems): + continue + r = self._settle_one_residual(dict(row), now_ms=now) + if r: + out.append(r) + return out + + def settle_all_residuals_now(self) -> list[dict[str, Any]]: + """紧急:立即按内在价值结算全部残留(不等到期)。""" + pending = self.db.fetchall( + "SELECT * FROM residual_options WHERE status='pending' ORDER BY id ASC" + ) + now = int(time.time() * 1000) + out: list[dict[str, Any]] = [] + for row in pending: + r = self._settle_one_residual(dict(row), now_ms=now, force=True) + if r: + out.append(r) + return out + + def _settle_one_residual( + self, row: dict[str, Any], *, now_ms: int, force: bool = False + ) -> dict[str, Any] | None: + group_id = str(row["group_id"]) + sess = get_session() + snap = sess.snapshot() + spot = self._close_spot_px(snap) + strike = row["strike"] + if strike is None or spot is None: + logger = __import__("logging").getLogger(__name__) + logger.warning("residual settle skip %s: no strike/spot", group_id) + return None + fee_rate = self._fee_rate() + intrinsic = option_intrinsic( + option_side=str(row["option_side"]), + strike=float(strike), + spot=float(spot), + ) + of = option_expiry_settle( + intrinsic=float(intrinsic), + qty_eth=float(row["option_qty_eth"]), + fee_rate=fee_rate, + ) + opt_entry = float(row["option_entry_px"]) + opt_qty = float(row["option_qty_eth"]) + opt_pnl = (of.fill_px - opt_entry) * opt_qty + opt_cash = of.notional - of.fee + self.ledger.apply_cash( + opt_cash, + kind="close_option", + group_id=group_id, + note=f"residual option expiry settle{' force' if force else ''}", + ) + + with self.db._lock: + self.db._conn.execute( + """INSERT INTO fills(group_id, leg, action, side, inst_id, qty_eth, qty_contracts, + base_px, fill_px, fee, slip, notional, ts_ms) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)""", + ( + group_id, + "option", + "close", + "flat", + str(row["option_inst_id"]), + opt_qty, + float(row["option_qty_contracts"] or 0), + of.base_px, + of.fill_px, + of.fee, + of.slip, + of.notional, + now_ms, + ), + ) + fills = self.db._conn.execute( + "SELECT * FROM fills WHERE group_id=? ORDER BY id ASC", (group_id,) + ).fetchall() + from ..sim.pnl import summarize_fills_pnl + + summary = summarize_fills_pnl(list(fills)) + net = summary.get("net_pnl") + if net is None: + net = opt_pnl - of.fee + g = self.db._conn.execute( + "SELECT fees, slip_cost FROM groups WHERE group_id=?", (group_id,) + ).fetchone() + fees = float(g["fees"] or 0) + of.fee + slip = float(g["slip_cost"] or 0) + of.slip + self.db._conn.execute( + """UPDATE residual_options SET status=?, settled_at_ms=?, settle_px=?, settle_pnl=?, note=? + WHERE group_id=?""", + ( + "settled", + now_ms, + of.fill_px, + opt_pnl, + "settled at intrinsic", + group_id, + ), + ) + self.db._conn.execute( + """UPDATE groups SET status=?, close_at_ms=?, realized_pnl=?, fees=?, slip_cost=? + WHERE group_id=?""", + ("closed", now_ms, float(net), fees, slip, group_id), + ) + self.db._conn.commit() + + return { + "group_id": group_id, + "option_pnl": opt_pnl, + "settle_px": of.fill_px, + "net_pnl": net, + "forced": force, + } + def unrealized(self) -> dict[str, Any]: pos = self.current_position() if pos.get("status") != "open": diff --git a/backend/app/sim/pnl.py b/backend/app/sim/pnl.py new file mode 100644 index 0000000..af2f521 --- /dev/null +++ b/backend/app/sim/pnl.py @@ -0,0 +1,67 @@ +"""从成交明细汇总腿盈亏与净盈亏。""" + +from __future__ import annotations + +from typing import Any + + +def summarize_fills_pnl(fills: list[Any]) -> dict[str, float | None]: + """ + 价差盈亏按 fill_px;手续费另扣。 + 净盈亏 = 期权盈亏 + 永续盈亏 − 全部手续费(开+平)。 + 允许只有永续已平、期权尚未结算的半组。 + """ + rows = [dict(x) for x in fills] + opt_open = next( + (f for f in rows if f.get("leg") == "option" and f.get("action") == "open"), + None, + ) + opt_close = next( + (f for f in rows if f.get("leg") == "option" and f.get("action") == "close"), + None, + ) + perp_open = next( + (f for f in rows if f.get("leg") == "perp" and f.get("action") == "open"), + None, + ) + perp_close = next( + (f for f in rows if f.get("leg") == "perp" and f.get("action") == "close"), + None, + ) + + option_pnl: float | None = None + if opt_open and opt_close: + qty = float(opt_open.get("qty_eth") or opt_close.get("qty_eth") or 0) + option_pnl = (float(opt_close["fill_px"]) - float(opt_open["fill_px"])) * qty + + perp_pnl: float | None = None + if perp_open and perp_close: + qty = float(perp_open.get("qty_eth") or perp_close.get("qty_eth") or 0) + side = str(perp_open.get("side") or "") + o = float(perp_open["fill_px"]) + c = float(perp_close["fill_px"]) + if side == "long": + perp_pnl = (c - o) * qty + else: + perp_pnl = (o - c) * qty + + fees_total = sum(float(f.get("fee") or 0) for f in rows) + gross = None + net = None + if option_pnl is not None and perp_pnl is not None: + gross = option_pnl + perp_pnl + net = gross - fees_total + elif option_pnl is not None: + gross = option_pnl + net = option_pnl - fees_total + elif perp_pnl is not None: + gross = perp_pnl + net = perp_pnl - fees_total + + return { + "option_pnl": option_pnl, + "perp_pnl": perp_pnl, + "fees_total": fees_total, + "gross_pnl": gross, + "net_pnl": net, + } diff --git a/backend/app/sim/pricing.py b/backend/app/sim/pricing.py index fe88469..7acccc4 100644 --- a/backend/app/sim/pricing.py +++ b/backend/app/sim/pricing.py @@ -29,6 +29,22 @@ def option_intrinsic(*, option_side: str, strike: float, spot: float) -> float: return 0.0 +def is_deep_otm( + *, + option_side: str, + strike: float, + spot: float, + max_intrinsic: float = 0.01, +) -> bool: + """ + 远虚:内在价值≈0(多头期权已无行权价值)。 + 100×杠杆 ATM 在标的波动约1%后常落入此状态。 + """ + return option_intrinsic( + option_side=option_side, strike=strike, spot=spot + ) <= float(max_intrinsic) + + def option_expiry_settle( *, intrinsic: float, diff --git a/backend/app/strategy/engine.py b/backend/app/strategy/engine.py index 96cb98b..f331f2d 100644 --- a/backend/app/strategy/engine.py +++ b/backend/app/strategy/engine.py @@ -88,6 +88,7 @@ class StrategyEngine: "can_open": allow_open, "last_error": last_error, "position": upl, + "residuals": self.matcher.list_residual_options(pending_only=True), "ledger": self.ledger.snapshot(), } @@ -118,16 +119,24 @@ class StrategyEngine: async def emergency_close(self) -> dict[str, Any]: async with self._lock: - # 紧急全平:绕过期权流动性/偏差校验 - r = self.matcher.close_group(reason="emergency", bypass_liquidity=True) - if r.ok: - self._after_close() + close_data: dict[str, Any] | None = None + detail = "flat" + ok = True + pos = self.matcher.current_position() + if pos.get("status") == "open": + r = self.matcher.close_group(reason="emergency", bypass_liquidity=True) + ok = r.ok + detail = r.detail + close_data = r.data + if r.ok: + self._after_close() + residuals = self.matcher.settle_all_residuals_now() return { "close": { - "ok": r.ok, - "detail": r.detail, - "liquidity_wait": r.liquidity_wait, - "data": r.data, + "ok": ok, + "detail": detail, + "data": close_data, + "residuals_settled": residuals, }, "state": self.state(), } @@ -175,9 +184,27 @@ class StrategyEngine: reason: str, bypass_liquidity: bool, pending_close: bool, + abandon_if_deep_otm: bool = False, ) -> None: if not pending_close: self._set_state(phase="closing", last_error=None) + + # 目标平仓 B:远虚 → 只平永续,期权归档 + if abandon_if_deep_otm and reason != "expiry" and self.matcher.option_is_deep_otm(): + r = await asyncio.to_thread( + self.matcher.close_perp_abandon_option, + reason="target_perp_only", + ) + if r.ok: + self._after_close() + self._set_state( + last_error=None, + phase="resting", + ) + else: + self._set_state(phase="closing", last_error=r.detail) + return + r = await asyncio.to_thread( self.matcher.close_group, reason=reason, @@ -186,12 +213,25 @@ class StrategyEngine: if r.ok: self._after_close() elif r.liquidity_wait and not bypass_liquidity: + # 等待期间若已变成远虚,下一 tick 走归档 + if self.matcher.option_is_deep_otm(): + r2 = await asyncio.to_thread( + self.matcher.close_perp_abandon_option, + reason="target_perp_only", + ) + if r2.ok: + self._after_close() + return self._set_state(phase="liquidity_wait", last_error=r.detail) else: self._set_state(phase="closing", last_error=r.detail) + async def _settle_residuals(self) -> None: + await asyncio.to_thread(self.matcher.settle_due_residuals) + async def _maybe_expiry_close(self) -> bool: """若持仓已到期则强制全平。返回是否触发到期平仓。""" + await self._settle_residuals() pos = self.matcher.current_position() if pos.get("status") != "open": return False @@ -206,6 +246,7 @@ class StrategyEngine: reason="expiry", bypass_liquidity=True, pending_close=pending, + abandon_if_deep_otm=False, ) return True @@ -242,6 +283,9 @@ class StrategyEngine: await asyncio.sleep(1) async def _tick_async(self) -> None: + # 残留期权到期结算(与活跃组隔离,不挡开仓) + await self._settle_residuals() + s = get_settings() st = self.db.fetchone("SELECT * FROM strategy_state WHERE id=1") assert st is not None @@ -260,7 +304,7 @@ class StrategyEngine: ) pos = self.matcher.current_position() - # 有未平仓:只盯平仓,绝不开下一组 + # 有活跃持仓:只盯当前组平仓;残留期权不在此扫描 if pos.get("status") == "open": upl = self.matcher.unrealized() expired = check_expiry_close(expiry_ms=self._position_expiry_ms(upl)) @@ -276,13 +320,17 @@ class StrategyEngine: if expired.should_close: reason = "expiry" bypass = True + abandon = False else: reason = decision.reason or "liquidity_retry" bypass = False + # 目标达标(或流动性等待重试)时:远虚走只平永续 + abandon = bool(decision.should_close or pending_close) await self._close_open_position( reason=reason, bypass_liquidity=bypass, pending_close=pending_close, + abandon_if_deep_otm=abandon, ) else: self._set_state(phase="open", last_error=None) diff --git a/backend/tests/test_p1_p2_rules.py b/backend/tests/test_p1_p2_rules.py index 6e76650..fc10b78 100644 --- a/backend/tests/test_p1_p2_rules.py +++ b/backend/tests/test_p1_p2_rules.py @@ -144,6 +144,18 @@ def test_expiry_close() -> None: assert d3.should_close is True +def test_deep_otm_and_expiry_settle() -> None: + from app.sim.pricing import is_deep_otm, option_expiry_settle, option_intrinsic + + assert is_deep_otm(option_side="call", strike=1860, spot=1840) is True + assert is_deep_otm(option_side="call", strike=1860, spot=1882) is False + assert is_deep_otm(option_side="put", strike=1860, spot=1882) is True + assert option_intrinsic(option_side="call", strike=1860, spot=1840) == 0.0 + settled = option_expiry_settle(intrinsic=0.0, qty_eth=2.0, fee_rate=0.0005) + assert settled.fill_px == 0.0 + assert settled.notional == 0.0 + + def test_option_intrinsic_and_close_bid_floor() -> None: from app.sim.pricing import ( option_expiry_settle, diff --git a/docs/ETH对冲策略说明.mm b/docs/ETH对冲策略说明.mm index 12dcae5..1ffe430 100644 --- a/docs/ETH对冲策略说明.mm +++ b/docs/ETH对冲策略说明.mm @@ -1,4 +1,4 @@ - + diff --git a/docs/ETH对冲策略说明.xmind b/docs/ETH对冲策略说明.xmind index 565bbe09068146cab74c59bf0285f1556d30cf3f..b929fdab60faa334bcb8ef563ed94a22951845c6 100644 GIT binary patch literal 6846 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 literal 114932 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%0D`T+OJ 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 YRP}X#X0Nj0;s*bXfGJxl2S2#}7al+-_y7O^ diff --git a/docs/策略说明.md b/docs/策略说明.md index 37220ad..7e1bf35 100644 --- a/docs/策略说明.md +++ b/docs/策略说明.md @@ -101,11 +101,12 @@ ## 4. 平仓机制 -任一触发 → **该组永续 + 期权全部平掉**(先期权、后永续)。 +平仓分两大类:**① 目标平仓**(净盈利达标);**② 到期平仓**(目标未达标,拖到到期)。 +目标平仓又分两种落地方式(双腿全平 / 只平永续+期权归档到期)。 -### 4.1 净盈利达标(主出场) +### 4.1 目标平仓(第一优先级) -**净盈利**口径(盯盘用): +**净盈利**口径(盯盘用,主要看买一,不看标记价): ``` 净盈利 ≈ 永续浮盈 + 期权浮盈 − 预估平仓手续费 @@ -119,32 +120,72 @@ 说明:权利金倍数模式下,**1× = 赚回一倍权利金金额的净利**(例如权利金 20.41,目标约 20.41,不是 40.82)。 -### 4.2 到期自动全平 +达标后按期权状态走下面 **A / B** 两套(不是互相替换,按能否平掉期权分支): +#### 4.1.A 双腿全平(期权仍有可平价值 / 非远虚) + +- 条件:净利达标,且期权 **不是远虚**(仍可能有买一可平)。 +- 动作:校验买一深度 + 买一/标记偏差(默认 ≤30%)→ **先平期权、再平永续**。 +- 通不过流动性 → `liquidity_wait`,继续等待(不改开仓组)。 + +#### 4.1.B 只平永续 + 期权归档到期(远虚) + +筛选约 **100× 杠杆** 期权时,标的波动约 **1%** 量级后,买方腿常变为**远虚**(内在价值≈0),买一往往枯死、整组硬平会卡死。 + +- 条件:净利达标,且期权已是 **虚值且远虚**(内在价值 ≈ 0)。 +- 动作: + 1. **只市价平掉永续**,兑现净利里永续那一截; + 2. 本张期权 **不再盯盘、不再参与平仓扫描**,归档为「到期残留」; + 3. 因期权 **逐仓**,残留 **不占用活跃持仓**,**不挡住下一组开仓**; + 4. 下一组开平仓 **只扫当前活跃组期权**,不扫描历史残留腿; + 5. 残留期权到到期日再按 **内在价值** 单独结算(多半接近 0)。 + +> 直觉:能双腿平就走 A;期权已经远虚平不掉就走 B,别把永续利润和下一单机会一起卡死。 + +### 4.2 到期平仓(目标未达标) + +- 净利一直未达标 → **不主动砍仓**,持有到期权到期。 - 到达期权到期时刻(OKX:UTC 08:00 = **上海 16:00**)→ 原因 `expiry`。 -- **对齐实盘**:期权按标的结算价的 **内在价值** 入账(不吃盘口、无价差滑点);永续仍市价平掉。 -- 策略 **暂停时仍执行**,避免拖过期。 +- **活跃组**:期权按标的结算价的 **内在价值** 入账;若永续仍在则市价平掉。 +- **残留组**(曾走 4.1.B):仅结算归档期权,不碰当前活跃仓。 +- 策略 **暂停时仍执行到期结算**,避免拖过期。 - 波动小、拖到到期:权利金亏损视为 **预算内成本**,可接受。 -### 4.3 平仓流动性闸门(常规出场) +### 4.3 平仓流动性闸门(仅 4.1.A) -常规净盈利平仓时: +双腿全平时: - 期权买一深度需覆盖平仓名义; - 买一相对标记偏差默认 ≤ **30%**(`close_bid_mark_max_pct`); -- 不满足 → `liquidity_wait`,继续等待,不改开仓。 +- 不满足 → `liquidity_wait`,继续等待。 -**紧急全平**:绕过上述闸门;期权价取 max(买一, 标记, 内在价值)。 +**4.1.B / 到期 / 紧急全平**:不适用「必须卖掉期权买一」这套闸门(到期与残留按内在价值;紧急可绕过)。 -### 4.4 其它平仓入口 +**紧急全平**:活跃组尽量双腿平掉;残留期权一并按内在价值结算。 + +### 4.4 其它平仓入口 / 原因码 | 原因码 | 含义 | |--------|------| -| `fixed_usdt` / `premium_multiple` | 净盈利达标 | -| `expiry` | 到期自动全平 | +| `fixed_usdt` / `premium_multiple` | 目标平仓 · 双腿全平(4.1.A) | +| `target_perp_only` | 目标平仓 · 只平永续,期权归档到期(4.1.B) | +| `expiry` | 到期结算(活跃组或残留期权) | | `emergency` | 界面紧急全平 | | `manual` | 手动平仓 | +### 4.5 流程总览 + +``` +有活跃持仓 + ├─ 净利达标? + │ ├─ 是 · 期权远虚(内在价值≈0)→ 平永续,期权归档到期,可开下一组 + │ └─ 是 · 非远虚 → 试双腿全平(流动性闸门)→ 失败则等待 + └─ 否 → 持有直到到期 → 内在价值结算(+ 若有永续则平永续) + +残留期权(已归档) + └─ 仅到期结算;不参与盯盘、不参与下一组平仓扫描 +``` + --- ## 5. 策略侧重点 @@ -155,8 +196,9 @@ | **概率与轮次** | 波动日可能多轮;磨盘日可能零轮或一轮认亏 | | **确定性时间规则** | 用周末跳过、到期全平,**不做**难以精准的横盘识别 | | **费用后净利** | 出场看扣完预估平仓费后的净盈利,避免「账面赚、平完亏」 | -| **单组纪律** | 有仓不开下一组,防止重叠风险 | +| **单组纪律** | 活跃持仓最多 1 组;远虚归档的残留期权不挡下一组(逐仓) | | **权利金是成本预算** | 小波动拖到期亏权利金,属于策略设计内损耗,不是异常 bug | +| **目标平仓两分支** | 能平期权则双腿全平;远虚则只平永续、期权到期归档 | 适合对外表述: @@ -173,7 +215,7 @@ | **横盘 / 低波动** | 高 | Theta 消耗权利金;永续几乎不贡献利润 | 周末跳过;到期认亏全平;接受磨损日 | | **方向选错** | 中高 | 卖一比价并非预测圣杯;错向时期权可能失利,永续端也可能承压 | 净盈利达标才兑现;到期强平止损时间 | | **开平滑点与手续费** | 中 | 双边 taker + 滑点侵蚀小目标利润 | 目标默认 15U 需覆盖费用;勿把目标设过低 | -| **期权流动性** | 中 | 平仓买一薄、偏差大 → 等待 | 流动性闸门;到期/紧急可绕过 | +| **期权流动性** | 中 | 远虚时买一枯死 | 4.1.B 只平永续+归档;到期内在价值结算 | | **杠杆与保证金** | 中 | 永续 3×,标的急跌/急涨挤压保证金 | 控制名义、保留资金缓冲;实盘注意强平线 | | **同到期 ATM 拥挤** | 低–中 | 临近到期价差与盘口恶化 | `min_option_hours`;到期强平 | | **SIM≠实盘** | 高(若直接外推) | 本地撮合、深度与成交假设简化 | 小资金实盘验证后再放大 | @@ -258,3 +300,4 @@ | 2026-07-25 | 初稿:对齐当前开平仓、周末跳过、到期全平、净盈利口径与资金建议 | | 2026-07-25 | 平仓顺序改为先期权后永续(与开仓同理:薄腿优先) | | 2026-07-26 | 到期按内在价值结算(对齐实盘);紧急平仓仍用 max(买一,标记,内在价值) | +| 2026-07-26 | 明确两套目标平仓:双腿全平 / 远虚只平永续+期权归档到期;到期为未达标路径 | diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index c2b7d4e..d040705 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -166,6 +166,14 @@ export type PlanState = { initial_premium?: number; premium_gap?: number; }; + residuals?: { + group_id: string; + option_inst_id: string; + option_side: string; + strike: number | null; + expiry_ymd: string | null; + status: string; + }[]; ledger: { equity: number; available: number; reserved: number }; }; diff --git a/frontend/src/labels.ts b/frontend/src/labels.ts index 2eb5b74..73adf4c 100644 --- a/frontend/src/labels.ts +++ b/frontend/src/labels.ts @@ -3,6 +3,7 @@ const STATUS_ZH: Record = { open: "持仓中", closed: "已平仓", + option_residual: "期权残留待到期", }; const SIDE_ZH: Record = { @@ -23,9 +24,10 @@ const ACTION_ZH: Record = { }; const CLOSE_REASON_ZH: Record = { - fixed_usdt: "固定净盈利达标", - premium_multiple: "权利金倍数达标", - expiry: "到期自动全平", + fixed_usdt: "固定净盈利达标·双腿全平", + premium_multiple: "权利金倍数达标·双腿全平", + target_perp_only: "净盈利达标·只平永续(期权归档)", + expiry: "到期结算", emergency: "紧急全平", manual: "手动平仓", liquidity_retry: "流动性等待后续平仓", diff --git a/frontend/src/pages/Plan.tsx b/frontend/src/pages/Plan.tsx index 3f9b9cf..f9d851c 100644 --- a/frontend/src/pages/Plan.tsx +++ b/frontend/src/pages/Plan.tsx @@ -134,7 +134,8 @@ export default function PlanPage() {

SIM 本地撮合 · 行情{" "} {(snap?.exchange || "okx").toUpperCase()} - {snap?.perp_inst_id ? ` · ${snap.perp_inst_id}` : ""} · 净盈利达标或到期全平 + {snap?.perp_inst_id ? ` · ${snap.perp_inst_id}` : ""} · + 目标平仓(双腿/远虚只平永续) · 未达标则到期结算

{err ?
{err}
: null} @@ -228,6 +229,19 @@ export default function PlanPage() { 当前组 {pos?.group_id || "—"} +
+ 残留期权(待到期) + + {plan?.residuals && plan.residuals.length > 0 + ? plan.residuals + .map( + (r) => + `${r.group_id}:${r.option_inst_id || "?"}@${r.expiry_ymd || "?"}` + ) + .join(" · ") + : "无"} + +
信号方向 {biasTag} diff --git a/scripts/gen_strategy_xmind.py b/scripts/gen_strategy_xmind.py index f6e2928..c869e3f 100644 --- a/scripts/gen_strategy_xmind.py +++ b/scripts/gen_strategy_xmind.py @@ -395,41 +395,35 @@ def bodies() -> dict[str, list[str]]: topic( "平仓", [ - L("触发即全平 · 先期权后永续"), + L("两大类:目标平仓 · 到期平仓"), G( - "主出场", + "目标A · 双腿全平", [ - "净利 = 双腿浮盈 − 预估平仓费", - "默认目标 ≥ 15 USDT", - "或 ≥ 权利金 × 1.0", + "净利达标 + 期权非远虚", + "先期权后永续", + "流动性闸门:深度 + 标记偏差30%", ], ), G( - "流动性闸门", + "目标B · 只平永续", [ - "买一深度足够", - "买一偏离标记 ≤ 30%", - "不满足则等待", + "净利达标 + 期权远虚(内在约0)", + "100x杠杆下波动约1%常远虚", + "期权归档到期 · 不再盯盘", + "逐仓不挡下一组开仓", + "下一组不扫描残留期权", ], ), G( - "到期全平", + "到期平仓", [ - "上海 16:00(OKX)", - "绕过闸门 · 暂停也执行", - "亏权利金 = 预算成本", + "目标未达标 → 持有到到期", + "期权按内在价值结算", + "活跃组若有永续一并平", + "残留组只结归档期权", ], ), L("另有:紧急全平 / 手动平仓"), - G( - "执行", - [ - "① 确认期权买一", - "② 平期权入账", - "③ 瞬时平永续", - "④ 失败则回滚", - ], - ), ], style_id="sty-ops_close", marker="arrow-down", @@ -551,15 +545,15 @@ def mm_flat() -> list[str]: mm("心法与节奏", [mm(x) for x in ["有波动多做", "目标 15U", "休息 5 分钟", "最多 1 组"]]), mm("仓位结构", [mm(x) for x in ["永续 1 · 期权 2", "先期权后永续", "ATM 选向"]]), mm("开仓", [mm(x) for x in ["前置检查", "选约门槛", "四步执行"]]), - mm("平仓", [mm(x) for x in ["净利达标", "流动性闸门", "到期全平"]]), + mm("平仓", [mm(x) for x in ["目标A双腿", "目标B只平永续", "到期结算"]]), mm("关键参数", [mm(x) for x in ["仓位/杠杆/费率", "目标/休息/周末", "选约/偏差"]]), ], ), - mm("⑥ 风险评估", [mm(x) for x in ["横盘磨损", "SIM≠实盘", "方向/流动性/保证金", "不做卖方与叠仓"]]), + mm("⑥ 风险评估", [mm(x) for x in ["横盘磨损", "SIM≠实盘", "方向/流动性/保证金", "残留不挡新开"]]), mm("⑦ 纪律要求", [mm(x) for x in [ - "单组 · 休息 · 周末", - "不硬砸 · 看净利", - "不报复 · 不叠仓", + "活跃1组 · 残留可共存", + "远虚归档 · 不挡新开", + "看净利 · 不报复", "SIM 后再放大", ]]), ]