距平衡改为行权价到平衡价的价差
Call 为 BE−K、Put 为 K−BE;链/下单/持仓统一;顺带修复 format_position_row 中 row_mode 引用顺序。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1434,15 +1434,14 @@
|
||||
function fmtDist(v) {
|
||||
if (v === null || v === undefined || Number.isNaN(Number(v))) return "—";
|
||||
const n = Number(v);
|
||||
const sign = n > 0 ? "+" : "";
|
||||
return sign + n.toFixed(1);
|
||||
if (n < 0) return n.toFixed(1);
|
||||
return n.toFixed(1);
|
||||
}
|
||||
|
||||
function distBeClass(v) {
|
||||
if (v === null || v === undefined || Number.isNaN(Number(v))) return "";
|
||||
const n = Number(v);
|
||||
if (n > 0) return "opt-be-dist-up";
|
||||
if (n < 0) return "opt-be-dist-down";
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ from lib.options.options_pricing_lib import (
|
||||
is_shallow_itm,
|
||||
option_moneyness,
|
||||
option_moneyness_label,
|
||||
strike_distance_to_be,
|
||||
)
|
||||
|
||||
_OKX_OPTION_ERR_ZH: dict[str, str] = {
|
||||
@@ -903,7 +904,7 @@ def build_option_chain(
|
||||
"mark_px": mark,
|
||||
"ask_estimated": q["ask_estimated"],
|
||||
"expiry_be_px": expiry_be,
|
||||
"dist_expiry_be": idx_distance_to_be(idx, expiry_be),
|
||||
"dist_expiry_be": strike_distance_to_be(strike, expiry_be, opt_type=opt_type),
|
||||
"moneyness": mny,
|
||||
"moneyness_label": option_moneyness_label(mny),
|
||||
"ct_mult": _safe_float(meta.get("ctMult")) or 0.01,
|
||||
@@ -1050,7 +1051,7 @@ def quote_option_contract(ex: ccxt.okx, inst_id: str) -> dict[str, Any]:
|
||||
"open_block_msg": "" if can_open else open_block_msg,
|
||||
"index_px": idx,
|
||||
"expiry_be_px": expiry_be,
|
||||
"dist_expiry_be": idx_distance_to_be(idx, expiry_be),
|
||||
"dist_expiry_be": strike_distance_to_be(strike, expiry_be, opt_type=str(opt_type or "")),
|
||||
"ct_mult": _safe_float(meta.get("ctMult")) or 0.01,
|
||||
"min_sz": int(_safe_float(meta.get("minSz")) or 1),
|
||||
"tick_sz": tick_sz,
|
||||
@@ -1792,6 +1793,7 @@ def format_position_row(
|
||||
close_breakeven_idx,
|
||||
expiry_breakeven_px,
|
||||
idx_distance_to_be,
|
||||
strike_distance_to_be,
|
||||
total_premium,
|
||||
)
|
||||
|
||||
@@ -1809,6 +1811,16 @@ def format_position_row(
|
||||
opt_type = parsed_type
|
||||
if strike is None:
|
||||
strike = parsed_strike
|
||||
try:
|
||||
from lib.options.options_margin_mode_lib import margin_mode_from_inst_id, premium_ccy_for_mode
|
||||
|
||||
row_mode = margin_mode_from_inst_id(inst_id) if inst_id else "usdc"
|
||||
underly = (inst_id.split("-")[0] if inst_id else "ETH") or "ETH"
|
||||
premium_ccy = premium_ccy_for_mode(row_mode, underly)
|
||||
except Exception:
|
||||
row_mode = "usdc"
|
||||
underly = (inst_id.split("-")[0] if inst_id else "ETH") or "ETH"
|
||||
premium_ccy = "USDC"
|
||||
eth_amount = round(abs(sheets) * ct_mult, 8)
|
||||
premium_paid = (
|
||||
round(total_premium(avg, eth_amount), 8) if avg is not None and eth_amount > 0 else None
|
||||
@@ -1832,16 +1844,6 @@ def format_position_row(
|
||||
ct_mult=ct_mult,
|
||||
)
|
||||
exp_time_ms = normalize_option_exp_ms(pos.get("expTime"), inst_id)
|
||||
try:
|
||||
from lib.options.options_margin_mode_lib import margin_mode_from_inst_id, premium_ccy_for_mode
|
||||
|
||||
row_mode = margin_mode_from_inst_id(inst_id) if inst_id else "usdc"
|
||||
underly = (inst_id.split("-")[0] if inst_id else "ETH") or "ETH"
|
||||
premium_ccy = premium_ccy_for_mode(row_mode, underly)
|
||||
except Exception:
|
||||
row_mode = "usdc"
|
||||
underly = (inst_id.split("-")[0] if inst_id else "ETH") or "ETH"
|
||||
premium_ccy = "USDC"
|
||||
return {
|
||||
"inst_id": inst_id or pos.get("instId"),
|
||||
"pos": sheets,
|
||||
@@ -1867,7 +1869,7 @@ def format_position_row(
|
||||
"avail_pos": _safe_float(pos.get("availPos")),
|
||||
"expiry_be_px": expiry_be,
|
||||
"close_be_px": close_be,
|
||||
"dist_expiry_be": idx_distance_to_be(idx_px, expiry_be),
|
||||
"dist_expiry_be": strike_distance_to_be(strike, expiry_be, opt_type=str(opt_type or "")),
|
||||
"dist_close_be": idx_distance_to_be(idx_px, close_be),
|
||||
"raw": pos,
|
||||
}
|
||||
|
||||
@@ -531,6 +531,25 @@ def idx_distance_to_be(idx_px: float | None, be_px: float | None) -> float | Non
|
||||
return round(float(be_px) - float(idx_px), 2)
|
||||
|
||||
|
||||
def strike_distance_to_be(
|
||||
strike: float | None,
|
||||
be_px: float | None,
|
||||
*,
|
||||
opt_type: str | None = None,
|
||||
) -> float | None:
|
||||
"""行权价到到期平衡价的价差(Call:BE−K, Put:K−BE)."""
|
||||
if strike is None or be_px is None:
|
||||
return None
|
||||
k = float(strike)
|
||||
be = float(be_px)
|
||||
o = (opt_type or "").upper()
|
||||
if o == "C":
|
||||
return round(be - k, 2)
|
||||
if o == "P":
|
||||
return round(k - be, 2)
|
||||
return round(abs(be - k), 2)
|
||||
|
||||
|
||||
def format_options_breakeven_line(
|
||||
*,
|
||||
expiry_be_px: float | None,
|
||||
|
||||
@@ -380,4 +380,4 @@
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/options_expiry_countdown.js?v=1"></script>
|
||||
<script src="/static/options_panel.js?v=69"></script>
|
||||
<script src="/static/options_panel.js?v=70"></script>
|
||||
|
||||
@@ -349,6 +349,13 @@ def test_expiry_breakeven_coin_margin():
|
||||
) == round(2425 / (1 - 0.0187), 2)
|
||||
|
||||
|
||||
def test_strike_distance_to_be():
|
||||
from lib.options.options_pricing_lib import strike_distance_to_be
|
||||
|
||||
assert strike_distance_to_be(2390, 2430, opt_type="C") == 40.0
|
||||
assert strike_distance_to_be(2450, 2411, opt_type="P") == 39.0
|
||||
|
||||
|
||||
def test_straddle_breakeven_band_coin():
|
||||
from lib.options.options_pricing_lib import straddle_breakeven_band
|
||||
|
||||
@@ -454,4 +461,4 @@ def test_format_position_row_breakeven():
|
||||
assert row["expiry_be_px"] == 3515.6
|
||||
assert row["idx_px"] == 3480.0
|
||||
assert row["close_be_px"] is not None
|
||||
assert row["dist_expiry_be"] == 35.6
|
||||
assert row["dist_expiry_be"] == 15.6
|
||||
|
||||
Reference in New Issue
Block a user