Show option top-of-book size and open option before perp.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+63
-33
@@ -107,14 +107,7 @@ class Matcher:
|
||||
ct_mult = self._ct_mult(option_inst_id)
|
||||
opt_contracts = contracts_for_eth(opt_qty, ct_mult)
|
||||
|
||||
pf = perp_fill(
|
||||
side=perp_side,
|
||||
action="open",
|
||||
bid=float(snap.perp.bid),
|
||||
ask=float(snap.perp.ask),
|
||||
qty_eth=perp_qty,
|
||||
fee_rate=fee_rate,
|
||||
)
|
||||
# 1) 先成交期权(吃卖一);失败则整组不开
|
||||
of = option_fill(
|
||||
action="open",
|
||||
bid=float(oq.bid or 0),
|
||||
@@ -124,18 +117,53 @@ class Matcher:
|
||||
)
|
||||
initial_premium = of.fill_px * opt_qty # 锁定口径:成交价×名义,不含费
|
||||
premium_cost = of.notional + of.fee
|
||||
total_debit = premium_cost + pf.fee # 永续开仓只扣费;期权支付权利金+费
|
||||
|
||||
try:
|
||||
self.ledger.apply_cash(
|
||||
-total_debit,
|
||||
kind="open_debit",
|
||||
-premium_cost,
|
||||
kind="open_option",
|
||||
group_id=group_id,
|
||||
note=f"open {group_id}",
|
||||
note=f"open option {group_id}",
|
||||
)
|
||||
except RuntimeError as e:
|
||||
return OpenResult(ok=False, detail=str(e))
|
||||
|
||||
# 2) 期权确认后再市价成交永续(重新取盘口)
|
||||
snap2 = sess.snapshot()
|
||||
if not snap2.perp or snap2.perp.bid is None or snap2.perp.ask is None:
|
||||
self.ledger.apply_cash(
|
||||
premium_cost,
|
||||
kind="open_option_rollback",
|
||||
group_id=group_id,
|
||||
note=f"rollback option {group_id}: perp book missing",
|
||||
)
|
||||
return OpenResult(
|
||||
ok=False,
|
||||
detail="期权已成交但永续盘口不可用,已回滚期权",
|
||||
)
|
||||
pf = perp_fill(
|
||||
side=perp_side,
|
||||
action="open",
|
||||
bid=float(snap2.perp.bid),
|
||||
ask=float(snap2.perp.ask),
|
||||
qty_eth=perp_qty,
|
||||
fee_rate=fee_rate,
|
||||
)
|
||||
try:
|
||||
self.ledger.apply_cash(
|
||||
-pf.fee,
|
||||
kind="open_perp_fee",
|
||||
group_id=group_id,
|
||||
note=f"open perp {group_id}",
|
||||
)
|
||||
except RuntimeError as e:
|
||||
self.ledger.apply_cash(
|
||||
premium_cost,
|
||||
kind="open_option_rollback",
|
||||
group_id=group_id,
|
||||
note=f"rollback option {group_id}: {e}",
|
||||
)
|
||||
return OpenResult(ok=False, detail=f"期权已成交但永续扣费失败并已回滚: {e}")
|
||||
|
||||
now = int(time.time() * 1000)
|
||||
with self.db._lock:
|
||||
self.db._conn.execute(
|
||||
@@ -160,26 +188,7 @@ class Matcher:
|
||||
pf.slip + of.slip,
|
||||
),
|
||||
)
|
||||
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",
|
||||
"open",
|
||||
perp_side,
|
||||
s.perp_inst_id,
|
||||
perp_qty,
|
||||
None,
|
||||
pf.base_px,
|
||||
pf.fill_px,
|
||||
pf.fee,
|
||||
pf.slip,
|
||||
pf.notional,
|
||||
now,
|
||||
),
|
||||
)
|
||||
# 成交顺序:期权先、永续后(时间戳差 1ms 便于审计)
|
||||
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)
|
||||
@@ -200,6 +209,26 @@ class Matcher:
|
||||
now,
|
||||
),
|
||||
)
|
||||
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",
|
||||
"open",
|
||||
perp_side,
|
||||
s.perp_inst_id,
|
||||
perp_qty,
|
||||
None,
|
||||
pf.base_px,
|
||||
pf.fill_px,
|
||||
pf.fee,
|
||||
pf.slip,
|
||||
pf.notional,
|
||||
now + 1,
|
||||
),
|
||||
)
|
||||
self.db._conn.execute(
|
||||
"""UPDATE positions SET
|
||||
group_id=?, perp_side=?, perp_qty_eth=?, perp_entry_px=?,
|
||||
@@ -233,6 +262,7 @@ class Matcher:
|
||||
"option": of.to_dict(),
|
||||
"initial_premium": initial_premium,
|
||||
"fees": pf.fee + of.fee,
|
||||
"open_sequence": ["option", "perp"],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user