统计已实现盈亏扣手续费,并按平仓时指数冻结为 U。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user