统计已实现盈亏扣手续费,并按平仓时指数冻结为 U。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-08 22:50:21 +08:00
parent e8f8a76753
commit 5e8b578f75
12 changed files with 726 additions and 54 deletions
+112 -6
View File
@@ -377,41 +377,145 @@ def close_option_by_bid1(
open_rows = conn.execute(
"""
SELECT id, premium_paid FROM options_trades
SELECT id, premium_paid, open_fee, premium_ccy, underlying,
exchange_ord_id
FROM options_trades
WHERE inst_id = ? AND status = 'open'
ORDER BY id ASC
""",
(inst_id,),
).fetchall()
from lib.options.options_pnl_settle_lib import (
extract_order_fee,
fee_to_premium_ccy,
resolve_close_index_px,
settle_closed_pnl,
sum_option_order_fees_in_premium,
)
from lib.options.options_time_lib import options_app_now_str
row_ccy = premium_ccy
if open_rows:
row_ccy = str(open_rows[0]["premium_ccy"] or premium_ccy or "").strip() or premium_ccy
underly = str((open_rows[0]["underlying"] if open_rows else "") or "").strip()
close_idx = resolve_close_index_px(
ex, inst_id=inst_id, underlying=underly, hint=index_px
)
# 平仓手续费:优先累计订单号查单;查不到再用本笔下单 info
close_fee_total = 0.0
try:
close_fee_total = sum_option_order_fees_in_premium(
ex,
inst_id=inst_id,
ord_ids=merged_ord,
premium_ccy=row_ccy,
index_px=close_idx,
fetch_order_fn=cfg.get("fetch_option_order"),
)
except Exception:
close_fee_total = 0.0
if close_fee_total <= 0:
fee_hint, fee_hint_ccy = extract_order_fee(
order if isinstance(order, dict) else None
)
if fee_hint > 0:
close_fee_total = fee_to_premium_ccy(
fee_hint,
fee_hint_ccy or row_ccy,
premium_ccy=row_ccy,
index_px=close_idx,
)
total_paid = sum(float(r["premium_paid"] or 0) for r in open_rows)
total_open_fee = sum(float(r["open_fee"] or 0) for r in open_rows)
# 开仓费未落库时按开仓单号补查
if total_open_fee <= 0:
open_oids = [
str(r["exchange_ord_id"] or "").strip()
for r in open_rows
if str(r["exchange_ord_id"] or "").strip()
]
try:
total_open_fee = sum_option_order_fees_in_premium(
ex,
inst_id=inst_id,
ord_ids=open_oids,
premium_ccy=row_ccy,
index_px=close_idx,
fetch_order_fn=cfg.get("fetch_option_order"),
)
except Exception:
total_open_fee = 0.0
allocated = 0.0
allocated_cfee = 0.0
allocated_ofee = 0.0
for i, row in enumerate(open_rows):
paid = float(row["premium_paid"] or 0)
if i == len(open_rows) - 1:
recv = round_premium_amount(
total_recv - allocated, decimals=PREMIUM_DECIMALS_COIN
) or 0.0
row_cfee = round(close_fee_total - allocated_cfee, 8)
stored_ofee = float(row["open_fee"] or 0)
if stored_ofee > 0:
row_ofee = stored_ofee
elif total_paid > 0 and total_open_fee > 0:
row_ofee = round(total_open_fee - allocated_ofee, 8)
else:
row_ofee = round(total_open_fee - allocated_ofee, 8) if total_open_fee > 0 else 0.0
elif total_paid > 0:
share = paid / total_paid
recv = round_premium_amount(
total_recv * (paid / total_paid), decimals=PREMIUM_DECIMALS_COIN
total_recv * share, decimals=PREMIUM_DECIMALS_COIN
) or 0.0
allocated += recv
row_cfee = round(close_fee_total * share, 8)
allocated_cfee += row_cfee
stored_ofee = float(row["open_fee"] or 0)
if stored_ofee > 0:
row_ofee = stored_ofee
else:
row_ofee = round(total_open_fee * share, 8)
allocated_ofee += row_ofee
else:
recv = round_premium_amount(
total_recv / len(open_rows), decimals=PREMIUM_DECIMALS_COIN
) or 0.0
allocated += recv
pnl = round_premium_amount(recv - paid, decimals=PREMIUM_DECIMALS_COIN) or 0.0
note_sql = ""
from lib.options.options_time_lib import options_app_now_str
row_cfee = round(close_fee_total / len(open_rows), 8)
allocated_cfee += row_cfee
stored_ofee = float(row["open_fee"] or 0)
row_ofee = stored_ofee if stored_ofee > 0 else round(
total_open_fee / len(open_rows), 8
)
if stored_ofee <= 0:
allocated_ofee += row_ofee
# 占位顺序必须与 SQL 一致: close_quote/recv/pnl/ord/closed_at/[signal_note]/id
settled = settle_closed_pnl(
premium_paid=paid,
premium_received=recv,
open_fee=row_ofee,
close_fee=row_cfee,
premium_ccy=str(row["premium_ccy"] or row_ccy or premium_ccy),
index_px=close_idx,
)
pnl = settled.get("realized_pnl")
pnl_usdt = settled.get("realized_pnl_usdt")
note_sql = ""
# 占位: close_quote/recv/pnl/ord/closed_at/open_fee/close_fee/fee_ccy/idx/pnl_u/[note]/id
params: list[Any] = [
close_px,
recv,
pnl,
merged_ord,
options_app_now_str(),
row_ofee,
row_cfee,
str(row["premium_ccy"] or row_ccy or premium_ccy or ""),
settled.get("close_index_px"),
pnl_usdt,
]
if signal_note and i == len(open_rows) - 1:
note_sql = """,
@@ -426,6 +530,8 @@ def close_option_by_bid1(
UPDATE options_trades
SET status = 'closed', close_quote = ?, premium_received = ?,
realized_pnl = ?, close_ord_id = ?, closed_at = ?,
open_fee = ?, close_fee = ?, fee_ccy = ?,
close_index_px = ?, realized_pnl_usdt = ?,
close_recv_accum = 0, close_sheets_accum = 0,
close_notional_accum = 0
{note_sql}