diff --git a/crypto_monitor_okx/app.py b/crypto_monitor_okx/app.py index 708f89d..cd93061 100644 --- a/crypto_monitor_okx/app.py +++ b/crypto_monitor_okx/app.py @@ -6793,6 +6793,7 @@ def render_main_page(page="trade", 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_default_underly=OKX_OPTIONS_DEFAULT_UNDERLY, options_chain_ask_liq_filter=os.getenv( "OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED", "true" diff --git a/lib/common/static/options_panel.js b/lib/common/static/options_panel.js index 2b408f2..d9ff3c9 100644 --- a/lib/common/static/options_panel.js +++ b/lib/common/static/options_panel.js @@ -16,6 +16,11 @@ strikeExpandAll: false, /** 环境 OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED;链接口可热更新 */ askLiqFilter: root.dataset.askLiqFilter !== "0", + budgetBuffer: (function () { + const raw = root.dataset.budgetBuffer; + const n = raw != null && raw !== "" ? Number(raw) : NaN; + return !Number.isNaN(n) && n > 0 ? n : 0.95; + })(), chain: panelCache.chain || null, selectedInst: null, orderQuote: null, @@ -568,6 +573,15 @@ } } + function applyBudgetBuffer(raw) { + if (raw == null || raw === "") return; + const buf = Number(raw); + if (Number.isNaN(buf) || buf <= 0) return; + state.budgetBuffer = buf; + const el = document.getElementById("opt-budget-buf"); + if (el) el.textContent = fmt(buf, 2); + } + function renderIndexLine() { const idx = state.chain && state.chain.index_px; const dte = state.chain && state.chain.chain_max_dte_days; @@ -575,6 +589,9 @@ const el = document.getElementById("opt-chain-dte"); if (el) el.textContent = String(Math.round(dte)); } + if (state.chain && state.chain.budget_buffer != null) { + applyBudgetBuffer(state.chain.budget_buffer); + } const line = document.getElementById("opt-index-line"); if (line) { const liqHint = askLiqFilterOn() ? "仅显示卖一深度≥1张" : "显示全部卖一(含估算~)"; @@ -2055,6 +2072,7 @@ } function bootOptionsPanel() { + applyBudgetBuffer(state.budgetBuffer); updateSizeInputs(); syncMoneyFilterButtons(); syncChainViewUI(); diff --git a/lib/options/options_register.py b/lib/options/options_register.py index 5d196f7..eb7e163 100644 --- a/lib/options/options_register.py +++ b/lib/options/options_register.py @@ -373,6 +373,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) if not expiries: return jsonify( { @@ -381,6 +382,8 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None: **chain, "chain_max_dte_days": cfg["chain_max_dte_days"], "ask_liq_filter_enabled": ask_liq_filter, + "budget_buffer": budget_buffer, + "trade_budget": cfg["trade_budget"], } ) return jsonify( @@ -389,6 +392,8 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None: **chain, "chain_max_dte_days": cfg["chain_max_dte_days"], "ask_liq_filter_enabled": ask_liq_filter, + "budget_buffer": budget_buffer, + "trade_budget": cfg["trade_budget"], } ) diff --git a/lib/options/templates/options_panel.html b/lib/options/templates/options_panel.html index 84e6da3..2cf1ffb 100644 --- a/lib/options/templates/options_panel.html +++ b/lib/options/templates/options_panel.html @@ -1,5 +1,6 @@
- +