diff --git a/lib/common/static/instance_theme.css b/lib/common/static/instance_theme.css index a9b30d6..6504eb4 100644 --- a/lib/common/static/instance_theme.css +++ b/lib/common/static/instance_theme.css @@ -3372,6 +3372,15 @@ html[data-theme="light"] .settings-side-export-label { html[data-theme="light"] .opt-chain-lev { color: #1a4a8a; } +.opt-chain-delta { + font-variant-numeric: tabular-nums; + white-space: nowrap; + font-weight: 600; + color: #9ad5ff; +} +html[data-theme="light"] .opt-chain-delta { + color: #0b5cad; +} .opt-be-dist-up { color: #5ee89a; } diff --git a/lib/common/static/options_panel.js b/lib/common/static/options_panel.js index b696e9f..a9b6d63 100644 --- a/lib/common/static/options_panel.js +++ b/lib/common/static/options_panel.js @@ -477,7 +477,15 @@ } function strikeTableColspan() { - return 9; + return state.chainView === "t" ? 9 : 10; + } + + function fmtDelta(v) { + if (v === null || v === undefined || v === "") return "—"; + const n = Number(v); + if (!Number.isFinite(n)) return "—"; + const sign = n > 0 ? "+" : ""; + return sign + n.toFixed(3); } function syncChainViewUI() { @@ -1308,6 +1316,7 @@ "" + c.inst_id + "" + "" + fmtPxSz(c.ask, c.ask_sz, c.ask_estimated) + "" + '' + fmtChainLeverage(chainLev) + "" + + '' + fmtDelta(c.delta) + "" + "" + fmtPxSz(c.bid, c.bid_sz) + "" + "" + (c.expiry_be_px != null ? fmt(c.expiry_be_px, 0) : "—") + "" + '' + fmtDist(c.dist_expiry_be) + "" + @@ -1734,6 +1743,9 @@ '行权价: ' + fmt(p.strike, 0) + "" + '张数: ' + fmt(p.pos, 0) + " · 币量 " + fmt(p.eth_amount, 4) + "" + '杠杆倍数: ' + fmtPosLeverage(p) + "" + + 'Delta: ' + + fmtDelta(p.delta != null ? p.delta : p.delta_bs) + + "" + (expAttr ? '到期倒计时: —' : "") + @@ -1742,6 +1754,9 @@ '
权利金' + premTxt + " " + premCcy + "
" + '
开仓均价' + avgTxt + "
" + '
标记价' + markTxt + "
" + + '
Delta' + + fmtDelta(p.delta != null ? p.delta : p.delta_bs) + + "
" + '
指数价' + fmt(p.idx_px, 0) + "
" + '
到期平衡' + fmt(p.expiry_be_px, 0) + "
" + '
平掉回本' + fmt(p.close_be_px, 0) + "
" + diff --git a/lib/exchange/okx_options_lib.py b/lib/exchange/okx_options_lib.py index a4389bc..2c18450 100644 --- a/lib/exchange/okx_options_lib.py +++ b/lib/exchange/okx_options_lib.py @@ -884,6 +884,10 @@ def build_option_chain( mark = q["mark_px"] ask_sz = q["ask_sz"] bid_sz = q["bid_sz"] + # 行情 ticker:delta;兼容个别字段名 + delta = _safe_float(t.get("delta")) + if delta is None: + delta = _safe_float(t.get("deltaBS")) expiry_be = expiry_breakeven_from_ask( opt_type=opt_type, strike=strike, @@ -904,6 +908,7 @@ def build_option_chain( "ask_sz": ask_sz, "bid_sz": bid_sz, "mark_px": mark, + "delta": delta, "ask_estimated": q["ask_estimated"], "expiry_be_px": expiry_be, "dist_expiry_be": strike_distance_to_be(strike, expiry_be), @@ -1843,6 +1848,9 @@ def format_position_row( round(total_premium(avg, eth_amount), 8) if avg is not None and eth_amount > 0 else None ) delta_pa = _safe_float(pos.get("deltaPA")) + delta_bs = _safe_float(pos.get("deltaBS")) + if delta_bs is None: + delta_bs = _safe_float(pos.get("delta")) try: from lib.options.options_margin_mode_lib import margin_mode_from_inst_id @@ -1909,6 +1917,10 @@ def format_position_row( total_premium=premium_paid, margin_mode=row_mode, ), + # 展示用单位 Delta(BS);delta_pa 为仓位美元敏感度 + "delta": delta_bs, + "delta_bs": delta_bs, + "delta_pa": delta_pa, "raw": pos, } diff --git a/lib/hub/hub_bridge_register.py b/lib/hub/hub_bridge_register.py index b113cc2..66b8134 100644 --- a/lib/hub/hub_bridge_register.py +++ b/lib/hub/hub_bridge_register.py @@ -135,6 +135,7 @@ def _enrich_hub_protocol(snap: dict[str, Any], *, app_module: Any) -> dict[str, "premium_paid_usdt": round(float(premium_usdt), 4) if premium_usdt is not None else None, "premium_ccy": p.get("premium_ccy"), "contract_leverage": contract_leverage, + "delta": p.get("delta") if p.get("delta") is not None else p.get("delta_bs"), "mark": p.get("mark") or p.get("mark_px"), "underlying": p.get("underlying"), "source_label": p.get("source_label"), diff --git a/lib/instance/templates/embed_shell.html b/lib/instance/templates/embed_shell.html index a539e18..bfdadd1 100644 --- a/lib/instance/templates/embed_shell.html +++ b/lib/instance/templates/embed_shell.html @@ -9,7 +9,7 @@ - + diff --git a/lib/instance/templates/index.html b/lib/instance/templates/index.html index a6c7af6..fd1b8d0 100644 --- a/lib/instance/templates/index.html +++ b/lib/instance/templates/index.html @@ -19,7 +19,7 @@ {{ pwa_app_name }} - + 合约 卖一/张 杠杆 + Delta 买一/张 到期平衡 平衡价差 @@ -110,7 +111,7 @@ - 请选择到期日 + 请选择到期日 @@ -368,4 +369,4 @@ - + diff --git a/tests/test_options_delta_fields.py b/tests/test_options_delta_fields.py new file mode 100644 index 0000000..67e59ff --- /dev/null +++ b/tests/test_options_delta_fields.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +import unittest + +from lib.exchange.okx_options_lib import format_position_row + + +class OptionsDeltaFieldsTests(unittest.TestCase): + def test_format_position_exposes_delta_bs(self): + row = format_position_row( + { + "instId": "ETH-USD-261015-2500-C", + "pos": "10", + "avgPx": "0.02", + "markPx": "0.025", + "idxPx": "2600", + "optType": "C", + "stk": "2500", + "deltaBS": "0.6123", + "deltaPA": "1.23", + }, + ct_mult=0.1, + ) + self.assertAlmostEqual(row["delta"], 0.6123, places=4) + self.assertAlmostEqual(row["delta_bs"], 0.6123, places=4) + self.assertAlmostEqual(row["delta_pa"], 1.23, places=4) + + def test_format_position_falls_back_delta_field(self): + row = format_position_row( + { + "instId": "BTC-USD-261015-80000-P", + "pos": "1", + "avgPx": "0.01", + "markPx": "0.012", + "idxPx": "82000", + "optType": "P", + "stk": "80000", + "delta": "-0.45", + }, + ct_mult=0.01, + ) + self.assertAlmostEqual(row["delta"], -0.45, places=4) + + +if __name__ == "__main__": + unittest.main()