feat: options sheet sizing, ITM/OTM labels, and 14-day chain view

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-07 09:06:45 +08:00
parent d6d1ac5818
commit c1647822fb
8 changed files with 172 additions and 29 deletions
+20 -5
View File
@@ -84,6 +84,7 @@ def _build_cfg(app_module: Any) -> dict[str, Any]:
"budget_buffer": _env_float("OKX_OPTIONS_BUDGET_BUFFER", 0.95),
"default_underly": (os.getenv("OKX_OPTIONS_DEFAULT_UNDERLY") or "ETH").strip().upper(),
"max_dte_days": _env_float("OKX_OPTIONS_MAX_DTE_DAYS", 2.0),
"chain_max_dte_days": _env_float("OKX_OPTIONS_CHAIN_MAX_DTE_DAYS", 14.0),
"itm_max_dist": _env_float("OKX_OPTIONS_ITM_MAX_DIST_USD", 30.0),
"td_mode": (os.getenv("OKX_OPTIONS_TD_MODE") or "cross").strip(),
"allow_market_close": _env_bool("OKX_OPTIONS_ALLOW_MARKET_CLOSE", False),
@@ -136,11 +137,11 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
chain = cfg["build_option_chain"](
ex,
u,
max_dte_days=cfg["max_dte_days"],
itm_only=True,
max_dte_days=cfg["chain_max_dte_days"],
itm_only=False,
itm_max_dist_usd=cfg["itm_max_dist"],
)
return jsonify({"ok": True, **chain})
return jsonify({"ok": True, **chain, "chain_max_dte_days": cfg["chain_max_dte_days"]})
@app.route("/api/options/quote")
@lr
@@ -160,20 +161,27 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
mode = (request.args.get("mode") or "budget_full").strip()
budget = cfg["trade_budget"]
eth_amount = None
sheet_count = None
try:
if request.args.get("eth_amount"):
eth_amount = float(request.args.get("eth_amount"))
except (TypeError, ValueError):
pass
try:
if request.args.get("sheets"):
sheet_count = int(request.args.get("sheets"))
except (TypeError, ValueError):
pass
if ask is None or ask <= 0:
return jsonify({**q, "ok": False, "msg": "暂无卖一价"})
sizing = calc_order_size(
quote_per_unit=float(ask),
ct_mult=float(ct_mult),
min_sz=int(min_sz),
budget_usdc=budget if mode != "eth_amount" else None,
budget_usdc=budget if mode == "budget_full" else None,
budget_buffer=cfg["budget_buffer"],
eth_amount=eth_amount if mode == "eth_amount" else None,
sheets=sheet_count if mode == "sheets" else None,
budget_cap=cfg["trade_budget"],
)
return jsonify(
@@ -206,18 +214,25 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
ct_mult = float(q.get("ct_mult") or 0.01)
min_sz = int(q.get("min_sz") or 1)
eth_amount = None
sheet_count = None
if mode == "eth_amount":
try:
eth_amount = float(data.get("eth_amount"))
except (TypeError, ValueError):
return jsonify({"ok": False, "msg": "ETH 数量无效"})
elif mode == "sheets":
try:
sheet_count = int(data.get("sheets"))
except (TypeError, ValueError):
return jsonify({"ok": False, "msg": "张数无效"})
sizing = calc_order_size(
quote_per_unit=float(ask),
ct_mult=ct_mult,
min_sz=min_sz,
budget_usdc=cfg["trade_budget"] if mode != "eth_amount" else None,
budget_usdc=cfg["trade_budget"] if mode == "budget_full" else None,
budget_buffer=cfg["budget_buffer"],
eth_amount=eth_amount,
sheets=sheet_count,
budget_cap=cfg["trade_budget"],
)
if not sizing.get("ok"):