修复 BTC 币本位期权净盈亏被 round4 抹成 0 的精度问题。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -11,9 +11,11 @@ from lib.options.options_close_gate_lib import (
|
||||
update_close_gate,
|
||||
)
|
||||
from lib.options.options_pricing_lib import (
|
||||
PREMIUM_DECIMALS_COIN,
|
||||
estimate_close_by_bids,
|
||||
fetch_option_mark_px,
|
||||
is_stub_bid_px,
|
||||
round_premium_amount,
|
||||
total_premium,
|
||||
)
|
||||
|
||||
@@ -304,7 +306,9 @@ def close_option_by_bid1(
|
||||
|
||||
px = float(order.get("px", locked_bid_px))
|
||||
oid = str((order.get("data") or {}).get("ordId") or "")
|
||||
prem_recv = round(total_premium(px, level_sheets * ct_mult), 4)
|
||||
prem_recv = round_premium_amount(
|
||||
total_premium(px, level_sheets * ct_mult), decimals=PREMIUM_DECIMALS_COIN
|
||||
) or 0.0
|
||||
time.sleep(0.6)
|
||||
invalidate_option_positions_cache()
|
||||
raw2 = cfg["fetch_option_positions"](ex)
|
||||
@@ -344,14 +348,20 @@ def close_option_by_bid1(
|
||||
for i, row in enumerate(open_rows):
|
||||
paid = float(row["premium_paid"] or 0)
|
||||
if i == len(open_rows) - 1:
|
||||
recv = round(prem_recv - allocated, 4)
|
||||
recv = round_premium_amount(
|
||||
prem_recv - allocated, decimals=PREMIUM_DECIMALS_COIN
|
||||
) or 0.0
|
||||
elif total_paid > 0:
|
||||
recv = round(prem_recv * (paid / total_paid), 4)
|
||||
recv = round_premium_amount(
|
||||
prem_recv * (paid / total_paid), decimals=PREMIUM_DECIMALS_COIN
|
||||
) or 0.0
|
||||
allocated += recv
|
||||
else:
|
||||
recv = round(prem_recv / len(open_rows), 4)
|
||||
recv = round_premium_amount(
|
||||
prem_recv / len(open_rows), decimals=PREMIUM_DECIMALS_COIN
|
||||
) or 0.0
|
||||
allocated += recv
|
||||
pnl = round(recv - paid, 4)
|
||||
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
|
||||
|
||||
|
||||
@@ -95,6 +95,8 @@ def forget_close_gate_for_inst(inst_id: str) -> None:
|
||||
|
||||
def net_pnl_from_display_row(row: dict[str, Any]) -> float | None:
|
||||
"""与持仓卡「净盈亏」同口径:买一可回收 − 权利金;残档买一则无净值."""
|
||||
from lib.options.options_pricing_lib import PREMIUM_DECIMALS_COIN, round_premium_amount
|
||||
|
||||
preview = row.get("close_preview") if isinstance(row.get("close_preview"), dict) else {}
|
||||
if preview.get("bid_invalid"):
|
||||
return None
|
||||
@@ -112,7 +114,9 @@ def net_pnl_from_display_row(row: dict[str, Any]) -> float | None:
|
||||
recv = _safe_float(preview.get("total_received"))
|
||||
paid = _safe_float(row.get("premium_paid"))
|
||||
if covered > 0 and recv is not None and paid is not None:
|
||||
return round(recv - paid, 4)
|
||||
ccy = str(row.get("premium_ccy") or "").strip().upper()
|
||||
decimals = PREMIUM_DECIMALS_COIN if ccy in ("ETH", "BTC") else None
|
||||
return round_premium_amount(recv - paid, ccy=ccy or None, decimals=decimals)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,24 @@ from __future__ import annotations
|
||||
import math
|
||||
from typing import Any
|
||||
|
||||
# 币本位权利金常为 1e-4~1e-5 量级(尤其 BTC);round(...,4) 会把净盈亏抹成 0
|
||||
PREMIUM_DECIMALS_COIN = 8
|
||||
PREMIUM_DECIMALS_FIAT = 4
|
||||
|
||||
|
||||
def round_premium_amount(v: float | None, *, ccy: str | None = None, decimals: int | None = None) -> float | None:
|
||||
"""权利金/回收/币盈亏入账精度:ETH/BTC 用 8 位,USDC 等用法币 4 位."""
|
||||
if v is None:
|
||||
return None
|
||||
try:
|
||||
n = float(v)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
if decimals is None:
|
||||
unit = (ccy or "").strip().upper()
|
||||
decimals = PREMIUM_DECIMALS_COIN if unit in ("ETH", "BTC") else PREMIUM_DECIMALS_FIAT
|
||||
return round(n, int(decimals))
|
||||
|
||||
|
||||
def ct_mult_from_meta(meta: dict[str, Any] | None) -> float:
|
||||
if not meta:
|
||||
@@ -276,7 +294,7 @@ def estimate_close_by_bids(
|
||||
"available_sheets": sz,
|
||||
"sheets": take,
|
||||
"eth_amount": eth_amount,
|
||||
"received": round(received, 4),
|
||||
"received": round_premium_amount(received, decimals=PREMIUM_DECIMALS_COIN),
|
||||
}
|
||||
)
|
||||
total_received += received
|
||||
@@ -288,15 +306,16 @@ def estimate_close_by_bids(
|
||||
estimated_pnl_ratio_pct = None
|
||||
if premium_paid is not None and covered > 0:
|
||||
paid = float(premium_paid)
|
||||
estimated_pnl = round(total_received - paid, 4)
|
||||
if paid > 0:
|
||||
# 必须用 8 位:BTC 权利金常约 1e-4,round(...,4) 会把盈亏抹成 0
|
||||
estimated_pnl = round_premium_amount(total_received - paid, decimals=PREMIUM_DECIMALS_COIN)
|
||||
if paid > 0 and estimated_pnl is not None:
|
||||
estimated_pnl_ratio_pct = round(estimated_pnl / paid * 100.0, 2)
|
||||
return {
|
||||
"levels": levels,
|
||||
"covered_sheets": covered,
|
||||
"uncovered_sheets": remaining,
|
||||
"total_received": round(total_received, 4),
|
||||
"avg_px": round(avg_px, 4) if avg_px is not None else None,
|
||||
"total_received": round_premium_amount(total_received, decimals=PREMIUM_DECIMALS_COIN),
|
||||
"avg_px": round(avg_px, 8) if avg_px is not None else None,
|
||||
"estimated_pnl": estimated_pnl,
|
||||
"estimated_pnl_ratio_pct": estimated_pnl_ratio_pct,
|
||||
"bid_invalid": False,
|
||||
|
||||
@@ -59,11 +59,13 @@ def profit_exit_hit(
|
||||
|
||||
|
||||
def required_recycle_usdc(premium_paid: float, mult: float) -> float | None:
|
||||
from lib.options.options_pricing_lib import PREMIUM_DECIMALS_COIN, round_premium_amount
|
||||
|
||||
prem = float(premium_paid or 0)
|
||||
m = float(mult or 0)
|
||||
if prem <= 0 or m <= 0:
|
||||
return None
|
||||
return round(prem * (1.0 + m), 4)
|
||||
return round_premium_amount(prem * (1.0 + m), decimals=PREMIUM_DECIMALS_COIN)
|
||||
|
||||
|
||||
def set_profit_exit(
|
||||
|
||||
@@ -1209,7 +1209,11 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
||||
sizing = dict(sizing)
|
||||
sizing["sheets"] = sheets
|
||||
sizing["eth_amount"] = round(sheets * ct_mult, 8)
|
||||
sizing["total_premium"] = round(fill_px * sheets * ct_mult, 4)
|
||||
from lib.options.options_pricing_lib import PREMIUM_DECIMALS_COIN, round_premium_amount
|
||||
|
||||
sizing["total_premium"] = round_premium_amount(
|
||||
fill_px * sheets * ct_mult, decimals=PREMIUM_DECIMALS_COIN
|
||||
)
|
||||
conn = cfg["get_db"]()
|
||||
trade_id = None
|
||||
target_mon = None
|
||||
|
||||
Reference in New Issue
Block a user