diff --git a/lib/common/static/instance_settings_prefs.js b/lib/common/static/instance_settings_prefs.js
index e8d15e6..362ab9f 100644
--- a/lib/common/static/instance_settings_prefs.js
+++ b/lib/common/static/instance_settings_prefs.js
@@ -351,7 +351,7 @@
body.appendChild(panelsWrap);
body.dataset.envModeSectionIdx = String(modeSectionIdx);
bindTradeModeAutoRefresh(body);
- bindCompoundBudgetVisibility(body);
+ bindOptionsSectionVisibility(body);
return body;
}
@@ -363,27 +363,104 @@
return input ? input.closest(".env-field-row") : null;
}
- function syncCompoundBudgetVisibility(body) {
+ function envFieldValue(body, key, fallback) {
+ const input = body && body.querySelector('.env-field-input[data-env-key="' + key + '"]');
+ if (!input) return fallback;
+ return String(input.value || fallback || "").trim();
+ }
+
+ function envTruthy(v) {
+ return ["1", "true", "yes", "on"].indexOf(String(v || "").toLowerCase()) >= 0;
+ }
+
+ function setEnvRowHidden(row, hide) {
+ if (!row) return;
+ row.hidden = !!hide;
+ row.style.display = hide ? "none" : "";
+ }
+
+ var COIN_ONLY_ENV_KEYS = [
+ "OKX_OPTIONS_COIN_COMPOUND",
+ "OKX_OPTIONS_COIN_BUDGET_USDT",
+ "OKX_OPTIONS_COIN_MAX_USDT_ENABLED",
+ "OKX_OPTIONS_COIN_MAX_USDT",
+ "OKX_OPTIONS_COIN_SPOT_BUY_BUFFER",
+ "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN",
+ ];
+ var USDC_ONLY_ENV_KEYS = [
+ "OKX_OPTIONS_TRADE_BUDGET_USDC",
+ "OKX_OPTIONS_COMPOUND_FULL_ENABLED",
+ "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED",
+ "OKX_OPTIONS_COMPOUND_FULL_CAP_USDC",
+ "OKX_OPTIONS_CLOSE_RECYCLE_MULT",
+ ];
+
+ function syncOptionsSectionVisibility(body) {
if (!body) return;
- const compoundSel = body.querySelector(
- '.env-field-input[data-env-key="OKX_OPTIONS_COMPOUND_FULL_ENABLED"]'
- );
- const budgetRow = envFieldRowByKey(body, "OKX_OPTIONS_TRADE_BUDGET_USDC");
- if (!budgetRow) return;
- const compoundOn = !compoundSel || String(compoundSel.value || "").toLowerCase() === "true";
- budgetRow.hidden = compoundOn;
- budgetRow.style.display = compoundOn ? "none" : "";
+ var margin = (envFieldValue(body, "OKX_OPTIONS_MARGIN_MODE", "coin") || "coin").toLowerCase();
+ var isCoin = margin !== "usdc";
+ var gateMode = (envFieldValue(body, "OKX_OPTIONS_CLOSE_GATE_MODE", "premium") || "premium").toLowerCase();
+ var compoundOn = envTruthy(envFieldValue(body, "OKX_OPTIONS_COMPOUND_FULL_ENABLED", "true"));
+ var coinCompoundOn = envTruthy(envFieldValue(body, "OKX_OPTIONS_COIN_COMPOUND", "true"));
+ var coinMaxOn = envTruthy(envFieldValue(body, "OKX_OPTIONS_COIN_MAX_USDT_ENABLED", "false"));
+ var compoundCapOn = envTruthy(envFieldValue(body, "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED", "false"));
+
+ COIN_ONLY_ENV_KEYS.forEach(function (key) {
+ setEnvRowHidden(envFieldRowByKey(body, key), !isCoin);
+ });
+ USDC_ONLY_ENV_KEYS.forEach(function (key) {
+ setEnvRowHidden(envFieldRowByKey(body, key), isCoin);
+ });
+
+ // 门控子项:按模式显隐(仍受本位过滤)
+ if (isCoin) {
+ setEnvRowHidden(envFieldRowByKey(body, "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN"), gateMode !== "premium");
+ } else {
+ setEnvRowHidden(envFieldRowByKey(body, "OKX_OPTIONS_CLOSE_RECYCLE_MULT"), gateMode !== "premium");
+ }
+ setEnvRowHidden(envFieldRowByKey(body, "OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT"), gateMode !== "net_pnl");
+
+ if (!isCoin) {
+ setEnvRowHidden(envFieldRowByKey(body, "OKX_OPTIONS_TRADE_BUDGET_USDC"), compoundOn);
+ setEnvRowHidden(envFieldRowByKey(body, "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED"), !compoundOn);
+ setEnvRowHidden(
+ envFieldRowByKey(body, "OKX_OPTIONS_COMPOUND_FULL_CAP_USDC"),
+ !(compoundOn && compoundCapOn)
+ );
+ }
+ if (isCoin) {
+ setEnvRowHidden(envFieldRowByKey(body, "OKX_OPTIONS_COIN_BUDGET_USDT"), coinCompoundOn);
+ setEnvRowHidden(envFieldRowByKey(body, "OKX_OPTIONS_COIN_MAX_USDT"), !coinMaxOn);
+ }
+ }
+
+ function bindOptionsSectionVisibility(body) {
+ if (!body) return;
+ syncOptionsSectionVisibility(body);
+ var keys = [
+ "OKX_OPTIONS_MARGIN_MODE",
+ "OKX_OPTIONS_CLOSE_GATE_MODE",
+ "OKX_OPTIONS_COMPOUND_FULL_ENABLED",
+ "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED",
+ "OKX_OPTIONS_COIN_COMPOUND",
+ "OKX_OPTIONS_COIN_MAX_USDT_ENABLED",
+ ];
+ keys.forEach(function (key) {
+ var el = body.querySelector('.env-field-input[data-env-key="' + key + '"]');
+ if (!el || el.dataset.optionsVisBound === "1") return;
+ el.dataset.optionsVisBound = "1";
+ el.addEventListener("change", function () {
+ syncOptionsSectionVisibility(body);
+ });
+ });
+ }
+
+ function syncCompoundBudgetVisibility(body) {
+ syncOptionsSectionVisibility(body);
}
function bindCompoundBudgetVisibility(body) {
- if (!body) return;
- syncCompoundBudgetVisibility(body);
- const compoundSel = body.querySelector(
- '.env-field-input[data-env-key="OKX_OPTIONS_COMPOUND_FULL_ENABLED"]'
- );
- if (!compoundSel || compoundSel.dataset.compoundBudgetBound === "1") return;
- compoundSel.dataset.compoundBudgetBound = "1";
- compoundSel.addEventListener("change", () => syncCompoundBudgetVisibility(body));
+ bindOptionsSectionVisibility(body);
}
function bindTradeModeAutoRefresh(body) {
diff --git a/lib/env/env_ui_manifest.py b/lib/env/env_ui_manifest.py
index 57e12f5..efc994d 100644
--- a/lib/env/env_ui_manifest.py
+++ b/lib/env/env_ui_manifest.py
@@ -480,7 +480,7 @@ def build_env_ui_payload(
_build_field(key, label, note, schema, values)
for key, label, note in sec["fields"]
]
- fields = _mark_compound_budget_hidden(fields)
+ fields = _mark_options_section_hidden(fields)
groups.append({
"title": sec["title"],
"fields": fields,
@@ -489,18 +489,68 @@ def build_env_ui_payload(
return groups
-def _mark_compound_budget_hidden(fields: list[dict[str, Any]]) -> list[dict[str, Any]]:
- """全仓复利开启时标记单笔预算为 hidden(供 SSR/前端隐藏;切换开关仍可再显示)."""
- compound_on = True
+# 币本位专属 / USDC 专属(配置页互斥隐藏)
+_COIN_ONLY_ENV_KEYS = frozenset({
+ "OKX_OPTIONS_COIN_COMPOUND",
+ "OKX_OPTIONS_COIN_BUDGET_USDT",
+ "OKX_OPTIONS_COIN_MAX_USDT_ENABLED",
+ "OKX_OPTIONS_COIN_MAX_USDT",
+ "OKX_OPTIONS_COIN_SPOT_BUY_BUFFER",
+ "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN",
+})
+_USDC_ONLY_ENV_KEYS = frozenset({
+ "OKX_OPTIONS_TRADE_BUDGET_USDC",
+ "OKX_OPTIONS_COMPOUND_FULL_ENABLED",
+ "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED",
+ "OKX_OPTIONS_COMPOUND_FULL_CAP_USDC",
+ "OKX_OPTIONS_CLOSE_RECYCLE_MULT",
+})
+
+
+def _field_current(fields: list[dict[str, Any]], key: str, default: str = "") -> str:
for f in fields:
- if f.get("key") == "OKX_OPTIONS_COMPOUND_FULL_ENABLED":
- compound_on = _env_truthy(str(f.get("current") or f.get("default") or "true"))
- break
- if not compound_on:
- return fields
+ if f.get("key") == key:
+ return str(f.get("current") or f.get("default") or default).strip()
+ return default
+
+
+def _mark_options_section_hidden(fields: list[dict[str, Any]]) -> list[dict[str, Any]]:
+ """按本位/门控模式/全仓复利标记 hidden(供 SSR/前端;切换开关仍可再显示)."""
+ margin = (_field_current(fields, "OKX_OPTIONS_MARGIN_MODE", "coin") or "coin").lower()
+ is_coin = margin != "usdc"
+ gate_mode = (_field_current(fields, "OKX_OPTIONS_CLOSE_GATE_MODE", "premium") or "premium").lower()
+ compound_on = _env_truthy(_field_current(fields, "OKX_OPTIONS_COMPOUND_FULL_ENABLED", "true"))
+ coin_compound_on = _env_truthy(_field_current(fields, "OKX_OPTIONS_COIN_COMPOUND", "true"))
+ coin_max_on = _env_truthy(_field_current(fields, "OKX_OPTIONS_COIN_MAX_USDT_ENABLED", "false"))
+ compound_cap_on = _env_truthy(
+ _field_current(fields, "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED", "false")
+ )
+
out: list[dict[str, Any]] = []
for f in fields:
- if f.get("key") == "OKX_OPTIONS_TRADE_BUDGET_USDC":
+ key = str(f.get("key") or "")
+ hide = False
+ if is_coin and key in _USDC_ONLY_ENV_KEYS:
+ hide = True
+ elif (not is_coin) and key in _COIN_ONLY_ENV_KEYS:
+ hide = True
+ elif key == "OKX_OPTIONS_CLOSE_RECYCLE_MULT" and gate_mode != "premium":
+ hide = True
+ elif key == "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN" and gate_mode != "premium":
+ hide = True
+ elif key == "OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT" and gate_mode != "net_pnl":
+ hide = True
+ elif key == "OKX_OPTIONS_TRADE_BUDGET_USDC" and compound_on:
+ hide = True
+ elif key == "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED" and not compound_on:
+ hide = True
+ elif key == "OKX_OPTIONS_COMPOUND_FULL_CAP_USDC" and not (compound_on and compound_cap_on):
+ hide = True
+ elif key == "OKX_OPTIONS_COIN_BUDGET_USDT" and coin_compound_on:
+ hide = True
+ elif key == "OKX_OPTIONS_COIN_MAX_USDT" and not coin_max_on:
+ hide = True
+ if hide:
item = dict(f)
item["hidden"] = True
out.append(item)
@@ -509,6 +559,11 @@ def _mark_compound_budget_hidden(fields: list[dict[str, Any]]) -> list[dict[str,
return out
+def _mark_compound_budget_hidden(fields: list[dict[str, Any]]) -> list[dict[str, Any]]:
+ """兼容旧调用名."""
+ return _mark_options_section_hidden(fields)
+
+
def filter_updates_for_ui(exchange_key: str, updates: dict[str, str]) -> dict[str, str]:
allowed = ui_allowed_keys(exchange_key)
return {k: v for k, v in (updates or {}).items() if k in allowed}
diff --git a/lib/instance/templates/embed_shell.html b/lib/instance/templates/embed_shell.html
index 5c729ca..efb7378 100644
--- a/lib/instance/templates/embed_shell.html
+++ b/lib/instance/templates/embed_shell.html
@@ -155,7 +155,7 @@ const ORDER_ENTRY_MODEL_CODE_TO_CATEGORY = {{ entry_model_code_to_category | toj
-
+
diff --git a/lib/instance/templates/index.html b/lib/instance/templates/index.html
index cf396d1..2e64eb5 100644
--- a/lib/instance/templates/index.html
+++ b/lib/instance/templates/index.html
@@ -2097,6 +2097,6 @@ document.addEventListener("DOMContentLoaded", function () {
});
{% endif %}
-
+