From ed4c650e4bc161150d1f52a4a62d5749cfbf2e98 Mon Sep 17 00:00:00 2001 From: dekun Date: Fri, 9 Oct 2026 00:46:54 +0800 Subject: [PATCH] =?UTF-8?q?fix=E6=9C=9F=E6=9D=83=E4=B8=8B=E5=8D=95?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E6=8C=89=E5=8F=AF=E7=94=A8=E4=BD=99=E9=A2=9D?= =?UTF-8?q?=E6=89=93=E6=BB=A1=EF=BC=9B=E6=8C=81=E4=BB=93=E4=B8=8A=E9=99=90?= =?UTF-8?q?/=E7=BC=93=E5=86=B2/=E9=97=A8=E6=8E=A7=E7=A7=92=E6=95=B0?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC=E8=B0=83=E6=95=B4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- app.py | 2 +- lib/common/static/options_panel.js | 17 +++++++++-------- lib/env/env_ui_manifest.py | 14 ++++++++------ lib/options/options_close_gate_lib.py | 4 ++-- lib/options/options_coin_open_lib.py | 2 +- lib/options/options_margin_mode_lib.py | 14 +++++++------- lib/options/options_position_limit_lib.py | 6 +++--- lib/options/options_register.py | 4 ++-- lib/options/templates/options_panel.html | 10 +++++----- 9 files changed, 38 insertions(+), 35 deletions(-) diff --git a/app.py b/app.py index 05e1674..22e7d84 100644 --- a/app.py +++ b/app.py @@ -4185,7 +4185,7 @@ def render_main_page(page="options", embed_mode=None): in ("1", "true", "yes", "on"), hedge_plan_budget_buffer=float(os.getenv("HEDGE_PLAN_BUDGET_BUFFER") or "0.95"), options_trade_budget=OKX_OPTIONS_TRADE_BUDGET_USDC, - options_budget_buffer=float(os.getenv("OKX_OPTIONS_BUDGET_BUFFER") or "0.95"), + options_budget_buffer=float(os.getenv("OKX_OPTIONS_BUDGET_BUFFER") or "1"), options_compound_full_enabled=os.getenv( "OKX_OPTIONS_COMPOUND_FULL_ENABLED", "true" ).lower() diff --git a/lib/common/static/options_panel.js b/lib/common/static/options_panel.js index 027d845..36b9500 100644 --- a/lib/common/static/options_panel.js +++ b/lib/common/static/options_panel.js @@ -19,7 +19,7 @@ budgetBuffer: (function () { const raw = root.dataset.budgetBuffer; const n = raw != null && raw !== "" ? Number(raw) : NaN; - return !Number.isNaN(n) && n > 0 ? n : 0.95; + return !Number.isNaN(n) && n > 0 ? n : 1; })(), chain: panelCache.chain || null, selectedInst: null, @@ -318,9 +318,10 @@ const el = document.querySelector('input[name="opt-size-mode"]:checked:not(:disabled)'); if (el) return el.value; const any = document.querySelector('input[name="opt-size-mode"]:checked'); - if (any && any.value === "compound_full" && !compoundFullEnabled()) return "sheets"; + if (any && any.value === "compound_full" && !compoundFullEnabled()) return "budget_full"; if (any && any.value === "budget_full" && compoundFullEnabled()) return "compound_full"; - return "sheets"; + // 默认按可用余额打满(复利开时等价全仓复利) + return compoundFullEnabled() ? "compound_full" : "budget_full"; } function applyCompoundModeUi(compoundOn) { @@ -372,13 +373,13 @@ compoundRadio.checked = false; compoundRadio.disabled = true; } - // currentSizeMode 会把残留 compound 映射成 sheets,须实际勾选,避免无选中无法开仓 + // 无有效选中时默认「按可用余额打满」 const checkedOk = document.querySelector('input[name="opt-size-mode"]:checked:not(:disabled)'); if (!checkedOk) { - const sheetsRadio = document.querySelector('input[name="opt-size-mode"][value="sheets"]'); - if (sheetsRadio) { - sheetsRadio.disabled = false; - sheetsRadio.checked = true; + const fullRadio = document.querySelector('input[name="opt-size-mode"][value="budget_full"]'); + if (fullRadio) { + fullRadio.disabled = false; + fullRadio.checked = true; } } } diff --git a/lib/env/env_ui_manifest.py b/lib/env/env_ui_manifest.py index 933d06f..6d198ed 100644 --- a/lib/env/env_ui_manifest.py +++ b/lib/env/env_ui_manifest.py @@ -81,7 +81,7 @@ _OPTIONS_SECTION: dict[str, Any] = { "fields": [ ("OKX_OPTIONS_ENABLED", "启用期权模块", "与上方 OKX_API_* 同源;不再单独配置期权密钥"), ("OKX_OPTIONS_ACCOUNT_LABEL", "期权账户备注", ""), - ("OKX_OPTIONS_BUDGET_BUFFER", "预算缓冲比例", "如 0.95;币本位复利/固定预算共用"), + ("OKX_OPTIONS_BUDGET_BUFFER", "预算缓冲比例", "默认 1;币本位复利/固定预算共用"), ( "OKX_OPTIONS_COIN_COMPOUND", "按交易户USDT复利", @@ -105,12 +105,12 @@ _OPTIONS_SECTION: dict[str, Any] = { ( "OKX_OPTIONS_COIN_SPOT_BUY_BUFFER", "现货买入缓冲", - "相对权利金倍数,默认 1.10(=多买10%);也可写 0.10 表示+10%。按最大可开张数×卖一权利金×本缓冲买币,不全额兑换", + "相对权利金倍数,默认 1.05(=多买5%);也可写 0.05 表示+5%。按最大可开张数×卖一权利金×本缓冲买币,不全额兑换", ), ( "OKX_OPTIONS_MAX_ACTIVE_POSITIONS", "期权持仓上限(笔)", - "默认 0=不限制;按交易所期权合约笔数计数,同合约加仓不占新笔数", + "默认 1=一次一仓;0=不限制;按交易所期权合约笔数计数,同合约加仓不占新笔数", ), ("OKX_OPTIONS_DEFAULT_UNDERLY", "默认标的", "如 ETH"), ( @@ -146,7 +146,7 @@ _OPTIONS_SECTION: dict[str, Any] = { ( "OKX_OPTIONS_CLOSE_HOLD_SECONDS", "门控持续秒数", - "条件达标后需持续满足的秒数,默认 120", + "条件达标后需持续满足的秒数,默认 20", ), ], } @@ -166,11 +166,13 @@ _RUNTIME_ENV_DEFAULTS: dict[str, str] = { "OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED": "true", "OKX_OPTIONS_CHAIN_MAX_DTE_DAYS": "14", "OKX_OPTIONS_MAX_DTE_DAYS": "2", - "OKX_OPTIONS_MAX_ACTIVE_POSITIONS": "0", + "OKX_OPTIONS_MAX_ACTIVE_POSITIONS": "1", + "OKX_OPTIONS_BUDGET_BUFFER": "1", + "OKX_OPTIONS_COIN_SPOT_BUY_BUFFER": "1.05", "OKX_OPTIONS_CLOSE_GATE_MODE": "premium", "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN": "1.05", "OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT": "0", - "OKX_OPTIONS_CLOSE_HOLD_SECONDS": "120", + "OKX_OPTIONS_CLOSE_HOLD_SECONDS": "20", "OKX_TRADE_MODE": "options", } diff --git a/lib/options/options_close_gate_lib.py b/lib/options/options_close_gate_lib.py index 8c4bdad..6700cff 100644 --- a/lib/options/options_close_gate_lib.py +++ b/lib/options/options_close_gate_lib.py @@ -27,7 +27,7 @@ def _close_recycle_mult(premium_ccy: str) -> float: def _close_hold_seconds() -> float: - return _env_float("OKX_OPTIONS_CLOSE_HOLD_SECONDS", 120.0) + return _env_float("OKX_OPTIONS_CLOSE_HOLD_SECONDS", 20.0) def _close_net_pnl_min_usdt() -> float: @@ -36,7 +36,7 @@ def _close_net_pnl_min_usdt() -> float: # 兼容旧引用 CLOSE_RECYCLE_MIN_MULT = _env_float("OKX_OPTIONS_CLOSE_RECYCLE_MULT", 2.0) -CLOSE_RECYCLE_HOLD_SECONDS = _env_float("OKX_OPTIONS_CLOSE_HOLD_SECONDS", 120.0) +CLOSE_RECYCLE_HOLD_SECONDS = _env_float("OKX_OPTIONS_CLOSE_HOLD_SECONDS", 20.0) _lock = threading.Lock() # inst_id -> gate state diff --git a/lib/options/options_coin_open_lib.py b/lib/options/options_coin_open_lib.py index 5da5b4e..df3a1e9 100644 --- a/lib/options/options_coin_open_lib.py +++ b/lib/options/options_coin_open_lib.py @@ -87,7 +87,7 @@ def coin_budget_preview(cfg: dict[str, Any], ex: Any) -> dict[str, Any]: trading_f = float(trading or 0) except (TypeError, ValueError): trading_f = 0.0 - buf = float(cfg.get("budget_buffer") or 0.95) + buf = float(cfg.get("budget_buffer") or 1.0) return compute_coin_budget_usdt(trading_f, buffer=buf) diff --git a/lib/options/options_margin_mode_lib.py b/lib/options/options_margin_mode_lib.py index 553e421..3ea0ca5 100644 --- a/lib/options/options_margin_mode_lib.py +++ b/lib/options/options_margin_mode_lib.py @@ -82,9 +82,9 @@ def compute_coin_budget_usdt( """ bal = max(0.0, float(trading_usdt or 0)) use_compound = _env_bool("OKX_OPTIONS_COIN_COMPOUND", True) if compound is None else bool(compound) - buf = float(buffer) if buffer is not None else _env_float("OKX_OPTIONS_BUDGET_BUFFER", 0.95) + buf = float(buffer) if buffer is not None else _env_float("OKX_OPTIONS_BUDGET_BUFFER", 1.0) if buf <= 0: - buf = 0.95 + buf = 1.0 fixed = ( float(fixed_budget_usdt) if fixed_budget_usdt is not None @@ -129,18 +129,18 @@ def compute_coin_budget_usdt( def normalize_coin_spot_buy_buffer(raw: Any = None) -> float: """ 现货买入相对权利金的倍数缓冲. - env OKX_OPTIONS_COIN_SPOT_BUY_BUFFER 默认 1.10(=多买 10%). - 也可写 0.10 表示 +10%. + env OKX_OPTIONS_COIN_SPOT_BUY_BUFFER 默认 1.05(=多买 5%). + 也可写 0.05 表示 +5%. """ if raw is None: - v = _env_float("OKX_OPTIONS_COIN_SPOT_BUY_BUFFER", 1.10) + v = _env_float("OKX_OPTIONS_COIN_SPOT_BUY_BUFFER", 1.05) else: try: v = float(raw) except (TypeError, ValueError): - v = 1.10 + v = 1.05 if v <= 0: - return 1.10 + return 1.05 if v < 1.0: return 1.0 + v return v diff --git a/lib/options/options_position_limit_lib.py b/lib/options/options_position_limit_lib.py index 23f029c..024bd57 100644 --- a/lib/options/options_position_limit_lib.py +++ b/lib/options/options_position_limit_lib.py @@ -6,12 +6,12 @@ from typing import Any, Optional, Sequence def options_max_active_positions() -> int: - """同时持有的期权合约笔数上限;0=不限制.热更读 env.""" - raw = os.getenv("OKX_OPTIONS_MAX_ACTIVE_POSITIONS", "0") + """同时持有的期权合约笔数上限;0=不限制.默认 1(一次一仓).热更读 env.""" + raw = os.getenv("OKX_OPTIONS_MAX_ACTIVE_POSITIONS", "1") try: v = int(float(str(raw).strip())) except (TypeError, ValueError): - return 0 + return 1 return max(0, v) diff --git a/lib/options/options_register.py b/lib/options/options_register.py index c0f870e..4bb65cb 100644 --- a/lib/options/options_register.py +++ b/lib/options/options_register.py @@ -110,7 +110,7 @@ def _build_cfg(app_module: Any) -> dict[str, Any]: "send_wechat": app_module.send_wechat_msg, "render_main_page": app_module.render_main_page, "trade_budget": _env_float("OKX_OPTIONS_TRADE_BUDGET_USDC", 10.0), - "budget_buffer": _env_float("OKX_OPTIONS_BUDGET_BUFFER", 0.95), + "budget_buffer": _env_float("OKX_OPTIONS_BUDGET_BUFFER", 1.0), "compound_full_enabled": _env_bool("OKX_OPTIONS_COMPOUND_FULL_ENABLED", True), "compound_full_cap_enabled": _env_bool("OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED", False), "compound_full_cap_usdc": _env_float("OKX_OPTIONS_COMPOUND_FULL_CAP_USDC", 300.0), @@ -535,7 +535,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None: chain_err = chain.get("chain_error") # 热更新:每次读 env,保存配置后刷新链即可生效 ask_liq_filter = _env_bool("OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED", True) - budget_buffer = _env_float("OKX_OPTIONS_BUDGET_BUFFER", 0.95) + budget_buffer = _env_float("OKX_OPTIONS_BUDGET_BUFFER", 1.0) coin_budget = None try: from lib.options.options_margin_mode_lib import is_coin_margin_mode diff --git a/lib/options/templates/options_panel.html b/lib/options/templates/options_panel.html index a547ea8..e3f43bf 100644 --- a/lib/options/templates/options_panel.html +++ b/lib/options/templates/options_panel.html @@ -1,6 +1,6 @@
环境配置「链上仅显示有卖一」开启时,隐藏无真实卖一或深度不足 1 张的合约(估算价 ~ 亦不显示)。
  • 开仓只认真实卖一价且卖一深度≥1;无深度时面板显示参考标记价并禁用买入。
  • 链展示近 14 日到期;列表与 T 型默认平值 + 实值3档 + 虚值3档,勾选「展开全部」看全部行权价(若当前为实值/虚值筛选会自动切回「全部」)。
  • -
  • 「按可用余额打满」可用额度 = min(交易户可用 USDC, 单笔预算 {{ '%.2f'|format(options_trade_budget|default(10)|float) }}),再 × 预算缓冲 {{ '%.2f'|format(options_budget_buffer|default(0.95)|float) }} 算张数(env 可改)。
  • +
  • 「按可用余额打满」可用额度 = min(交易户可用 USDC, 单笔预算 {{ '%.2f'|format(options_trade_budget|default(10)|float) }}),再 × 预算缓冲 {{ '%.2f'|format(options_budget_buffer|default(1)|float) }} 算张数(env 可改)。默认选中打满。
  • 「全仓复利」用期权交易户全部可用×缓冲开仓(不受单笔预算限制);可选开启全仓上限;该模式下仅允许同时 1 笔持仓。
  • -
  • 币本位(env OKX_OPTIONS_MARGIN_MODE=coin 默认):按最大可开张数×卖一权利金×现货缓冲(OKX_OPTIONS_COIN_SPOT_BUY_BUFFER 默认1.10)买 ETH/BTC,不全额兑换;平仓后卖回 USDT;对冲仍仅 USDC。有仓勿切换本位。
  • +
  • 币本位(env OKX_OPTIONS_MARGIN_MODE=coin 默认):按最大可开张数×卖一权利金×现货缓冲(OKX_OPTIONS_COIN_SPOT_BUY_BUFFER 默认1.05)买 ETH/BTC,不全额兑换;平仓后卖回 USDT;对冲仍仅 USDC。有仓勿切换本位。
  • 翻倍出场:开仓时可勾选;1倍=盈利等于权利金,买一可回收达标后限价平;持仓卡可改倍数或关闭。
  • 买一平仓

    @@ -159,13 +159,13 @@