revert 860ebef4a7
revert fix(options): expose chain DTE in env UI and show nearest expiries for OO Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1120,17 +1120,12 @@
|
|||||||
if (!sel) return;
|
if (!sel) return;
|
||||||
const prev = sel.value;
|
const prev = sel.value;
|
||||||
const isPoSel = sel.id === "hp-exp-select";
|
const isPoSel = sel.id === "hp-exp-select";
|
||||||
// 永期以期权为主:到期下拉按「最低剩余小时」过滤;期期下拉不过滤,保证明天到期可见
|
|
||||||
const minH = isPoSel && isOptionPrimary() ? numInput("hp-min-hours", 36) : 0;
|
const minH = isPoSel && isOptionPrimary() ? numInput("hp-min-hours", 36) : 0;
|
||||||
sel.innerHTML = '<option value="">选择到期日</option>';
|
sel.innerHTML = '<option value="">选择到期日</option>';
|
||||||
let firstOk = null;
|
let firstOk = null;
|
||||||
let skippedNear = 0;
|
|
||||||
(chain.expiries || []).forEach(function (e) {
|
(chain.expiries || []).forEach(function (e) {
|
||||||
const h = hoursFromExpMs(e.exp_time);
|
const h = hoursFromExpMs(e.exp_time);
|
||||||
if (minH > 0 && h != null && h < minH) {
|
if (minH > 0 && h != null && h < minH) return;
|
||||||
skippedNear += 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const opt = document.createElement("option");
|
const opt = document.createElement("option");
|
||||||
opt.value = String(e.exp_time);
|
opt.value = String(e.exp_time);
|
||||||
const dt = new Date(Number(e.exp_time) < 1e12 ? Number(e.exp_time) * 1000 : Number(e.exp_time));
|
const dt = new Date(Number(e.exp_time) < 1e12 ? Number(e.exp_time) * 1000 : Number(e.exp_time));
|
||||||
@@ -1142,18 +1137,18 @@
|
|||||||
if (!sel.value && firstOk) {
|
if (!sel.value && firstOk) {
|
||||||
sel.value = String(firstOk.exp_time);
|
sel.value = String(firstOk.exp_time);
|
||||||
}
|
}
|
||||||
if (isPoSel && skippedNear > 0 && minH > 0) {
|
|
||||||
const tip = document.createElement("option");
|
|
||||||
tip.disabled = true;
|
|
||||||
tip.textContent = "(已隐藏 " + skippedNear + " 个不足 " + minH + "h 的到期 · 可改左侧最低剩余小时)";
|
|
||||||
sel.appendChild(tip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadChain() {
|
async function loadChain() {
|
||||||
// 拉完整链(按 CHAIN_MAX_DTE);永期「最低剩余小时」只在左侧到期下拉里过滤,不影响期期看到明天到期
|
let url =
|
||||||
const url =
|
|
||||||
"/api/hedge-plan/options-chain?underlying=" + encodeURIComponent(state.underlying);
|
"/api/hedge-plan/options-chain?underlying=" + encodeURIComponent(state.underlying);
|
||||||
|
if (isOptionPrimary()) {
|
||||||
|
url +=
|
||||||
|
"&option_primary=1&min_hours=" +
|
||||||
|
encodeURIComponent(String(numInput("hp-min-hours", 36))) +
|
||||||
|
"&strike_interval=" +
|
||||||
|
encodeURIComponent(String(numInput("hp-strike-interval", 15)));
|
||||||
|
}
|
||||||
const d = await apiJson(url);
|
const d = await apiJson(url);
|
||||||
state.chain = d;
|
state.chain = d;
|
||||||
const idx = $("hp-index-line");
|
const idx = $("hp-index-line");
|
||||||
|
|||||||
Vendored
-2
@@ -92,8 +92,6 @@ HOT_RELOAD_EXACT = frozenset({
|
|||||||
"HEDGE_PLAN_SHOW_OPTIONS_OPTIONS",
|
"HEDGE_PLAN_SHOW_OPTIONS_OPTIONS",
|
||||||
"OKX_SHOW_PERP_FUNDS",
|
"OKX_SHOW_PERP_FUNDS",
|
||||||
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED",
|
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED",
|
||||||
"OKX_OPTIONS_CHAIN_MAX_DTE_DAYS",
|
|
||||||
"OKX_OPTIONS_MAX_DTE_DAYS",
|
|
||||||
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS",
|
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS",
|
||||||
"OKX_TRADE_MODE",
|
"OKX_TRADE_MODE",
|
||||||
"MAX_ACTIVE_HEDGE_PLANS",
|
"MAX_ACTIVE_HEDGE_PLANS",
|
||||||
|
|||||||
Vendored
-12
@@ -151,16 +151,6 @@ _OPTIONS_SECTION: dict[str, Any] = {
|
|||||||
"仅「单独期权」模式生效;默认 0=不限制;按交易所期权合约笔数计数,同合约加仓不占新笔数",
|
"仅「单独期权」模式生效;默认 0=不限制;按交易所期权合约笔数计数,同合约加仓不占新笔数",
|
||||||
),
|
),
|
||||||
("OKX_OPTIONS_DEFAULT_UNDERLY", "默认标的", "如 ETH"),
|
("OKX_OPTIONS_DEFAULT_UNDERLY", "默认标的", "如 ETH"),
|
||||||
(
|
|
||||||
"OKX_OPTIONS_CHAIN_MAX_DTE_DAYS",
|
|
||||||
"期权链展示天数",
|
|
||||||
"默认 14;下拉到期日只出现该天数内的合约(含明天)",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"OKX_OPTIONS_MAX_DTE_DAYS",
|
|
||||||
"开仓最大剩余天数",
|
|
||||||
"默认 2;单独开期权时拒绝更远到期(与链展示天数独立)",
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED",
|
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED",
|
||||||
"链上仅显示有卖一",
|
"链上仅显示有卖一",
|
||||||
@@ -271,8 +261,6 @@ _RUNTIME_ENV_DEFAULTS: dict[str, str] = {
|
|||||||
"HEDGE_PLAN_SHOW_OPTIONS_OPTIONS": "true",
|
"HEDGE_PLAN_SHOW_OPTIONS_OPTIONS": "true",
|
||||||
"OKX_SHOW_PERP_FUNDS": "true",
|
"OKX_SHOW_PERP_FUNDS": "true",
|
||||||
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED": "true",
|
"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": "0",
|
||||||
"OKX_TRADE_MODE": "options",
|
"OKX_TRADE_MODE": "options",
|
||||||
"MAX_ACTIVE_HEDGE_PLANS": "1",
|
"MAX_ACTIVE_HEDGE_PLANS": "1",
|
||||||
|
|||||||
@@ -677,25 +677,17 @@ def register_hedge_plan_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
|||||||
if ex is None:
|
if ex is None:
|
||||||
return jsonify({"ok": False, "msg": "期权交易所未初始化"}), 400
|
return jsonify({"ok": False, "msg": "期权交易所未初始化"}), 400
|
||||||
u = (request.args.get("underlying") or cfg.get("default_underly") or "ETH").upper()
|
u = (request.args.get("underlying") or cfg.get("default_underly") or "ETH").upper()
|
||||||
# 热更新:链展示天数每次读 env
|
|
||||||
chain_max_dte = float(
|
|
||||||
os.getenv("OKX_OPTIONS_CHAIN_MAX_DTE_DAYS")
|
|
||||||
or os.getenv("OKX_OPTIONS_MAX_DTE_DAYS")
|
|
||||||
or cfg.get("chain_max_dte")
|
|
||||||
or 14
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
chain = cfg["build_option_chain"](
|
chain = cfg["build_option_chain"](
|
||||||
ex,
|
ex,
|
||||||
u,
|
u,
|
||||||
max_dte_days=chain_max_dte,
|
max_dte_days=float(cfg.get("chain_max_dte") or 14),
|
||||||
itm_only=False,
|
itm_only=False,
|
||||||
itm_max_dist_usd=float(os.getenv("OKX_OPTIONS_ITM_MAX_DIST_USD") or "30"),
|
itm_max_dist_usd=float(os.getenv("OKX_OPTIONS_ITM_MAX_DIST_USD") or "30"),
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"ok": False, "msg": f"拉取期权链失败: {e}"}), 500
|
return jsonify({"ok": False, "msg": f"拉取期权链失败: {e}"}), 500
|
||||||
# 可选:永期以期权为主时按最低剩余小时/行权间隔过滤(仅当请求显式带 option_primary)
|
# 以期权为主:可选最短剩余小时 / 行权间隔过滤(也回写 hours_to_expiry 供前端)
|
||||||
# 默认拉链不再带此过滤,避免期期看不到明天到期
|
|
||||||
option_primary = (request.args.get("option_primary") or "").strip().lower() in (
|
option_primary = (request.args.get("option_primary") or "").strip().lower() in (
|
||||||
"1",
|
"1",
|
||||||
"true",
|
"true",
|
||||||
@@ -752,7 +744,7 @@ def register_hedge_plan_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
|||||||
"ok": True,
|
"ok": True,
|
||||||
**chain,
|
**chain,
|
||||||
"underlying": u,
|
"underlying": u,
|
||||||
"chain_max_dte_days": chain_max_dte,
|
"chain_max_dte_days": cfg.get("chain_max_dte"),
|
||||||
"account_kind": "options",
|
"account_kind": "options",
|
||||||
"account_label": cfg.get("options_account_label") or "期权账户",
|
"account_label": cfg.get("options_account_label") or "期权账户",
|
||||||
"account_note": "期权腿使用期权账户(交易 USDC)",
|
"account_note": "期权腿使用期权账户(交易 USDC)",
|
||||||
|
|||||||
@@ -406,4 +406,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/hedge_plan.js?v=46"></script>
|
<script src="/static/hedge_plan.js?v=45"></script>
|
||||||
|
|||||||
@@ -364,13 +364,11 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
|||||||
if ex is None:
|
if ex is None:
|
||||||
return jsonify({"ok": False, "msg": err})
|
return jsonify({"ok": False, "msg": err})
|
||||||
u = (request.args.get("underlying") or cfg["default_underly"]).upper()
|
u = (request.args.get("underlying") or cfg["default_underly"]).upper()
|
||||||
# 热更新:链展示天数每次读 env,保存后刷新链即可
|
|
||||||
chain_max_dte = _env_float("OKX_OPTIONS_CHAIN_MAX_DTE_DAYS", float(cfg.get("chain_max_dte_days") or 14))
|
|
||||||
try:
|
try:
|
||||||
chain = cfg["build_option_chain"](
|
chain = cfg["build_option_chain"](
|
||||||
ex,
|
ex,
|
||||||
u,
|
u,
|
||||||
max_dte_days=chain_max_dte,
|
max_dte_days=cfg["chain_max_dte_days"],
|
||||||
itm_only=False,
|
itm_only=False,
|
||||||
itm_max_dist_usd=cfg["itm_max_dist"],
|
itm_max_dist_usd=cfg["itm_max_dist"],
|
||||||
)
|
)
|
||||||
@@ -387,7 +385,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
|||||||
"ok": False,
|
"ok": False,
|
||||||
"msg": chain_err or "暂无到期日,请稍后点「刷新链」",
|
"msg": chain_err or "暂无到期日,请稍后点「刷新链」",
|
||||||
**chain,
|
**chain,
|
||||||
"chain_max_dte_days": chain_max_dte,
|
"chain_max_dte_days": cfg["chain_max_dte_days"],
|
||||||
"ask_liq_filter_enabled": ask_liq_filter,
|
"ask_liq_filter_enabled": ask_liq_filter,
|
||||||
"budget_buffer": budget_buffer,
|
"budget_buffer": budget_buffer,
|
||||||
"trade_budget": cfg["trade_budget"],
|
"trade_budget": cfg["trade_budget"],
|
||||||
@@ -397,7 +395,7 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
|||||||
{
|
{
|
||||||
"ok": True,
|
"ok": True,
|
||||||
**chain,
|
**chain,
|
||||||
"chain_max_dte_days": chain_max_dte,
|
"chain_max_dte_days": cfg["chain_max_dte_days"],
|
||||||
"ask_liq_filter_enabled": ask_liq_filter,
|
"ask_liq_filter_enabled": ask_liq_filter,
|
||||||
"budget_buffer": budget_buffer,
|
"budget_buffer": budget_buffer,
|
||||||
"trade_budget": cfg["trade_budget"],
|
"trade_budget": cfg["trade_budget"],
|
||||||
|
|||||||
Reference in New Issue
Block a user