Add OKX three-way trade mode for options vs hedge.
Env OKX_TRADE_MODE selects standalone options, perp hedge, or OO hedge; hide the other module UI and use group or position limits per mode. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Vendored
+7
@@ -91,6 +91,8 @@ HOT_RELOAD_EXACT = frozenset({
|
||||
"HEDGE_PLAN_SHOW_OPTIONS_OPTIONS",
|
||||
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED",
|
||||
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS",
|
||||
"OKX_TRADE_MODE",
|
||||
"MAX_ACTIVE_HEDGE_PLANS",
|
||||
"HEDGE_PLAN_LIVE_ORDER",
|
||||
"HEDGE_PLAN_OPEN_ORDER",
|
||||
"HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS",
|
||||
@@ -145,6 +147,11 @@ SELECT_OPTIONS: dict[str, tuple[tuple[str, str], ...]] = {
|
||||
("budget", "预算金额"),
|
||||
("sheets", "张数"),
|
||||
),
|
||||
"OKX_TRADE_MODE": (
|
||||
("options", "单独期权"),
|
||||
("perp_options", "永期对冲"),
|
||||
("options_options", "期期对冲"),
|
||||
),
|
||||
}
|
||||
|
||||
_SELECT_ALIASES: dict[str, dict[str, str]] = {
|
||||
|
||||
Vendored
+127
-52
@@ -119,6 +119,18 @@ _SHARED_SECTIONS: list[dict[str, Any]] = [
|
||||
},
|
||||
]
|
||||
|
||||
_MODE_SECTION: dict[str, Any] = {
|
||||
"title": "期权/对冲模式",
|
||||
"exchanges": frozenset({"okx"}),
|
||||
"fields": [
|
||||
(
|
||||
"OKX_TRADE_MODE",
|
||||
"交易模式",
|
||||
"三选一:单独期权 / 永期对冲 / 期期对冲.选单独期权时隐藏对冲导航与对冲配置;选对冲时不可单独开期权",
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
_OPTIONS_SECTION: dict[str, Any] = {
|
||||
"title": "期权账户",
|
||||
"exchanges": frozenset({"okx"}),
|
||||
@@ -133,7 +145,7 @@ _OPTIONS_SECTION: dict[str, Any] = {
|
||||
(
|
||||
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS",
|
||||
"期权持仓上限(笔)",
|
||||
"默认 0=不限制;按交易所期权合约笔数计数.期期对冲一次需 2 笔,上限设 1 时无法开期期(须≥2 或 0).同合约加仓不占新笔数.",
|
||||
"仅「单独期权」模式生效;默认 0=不限制;按交易所期权合约笔数计数,同合约加仓不占新笔数",
|
||||
),
|
||||
("OKX_OPTIONS_DEFAULT_UNDERLY", "默认标的", "如 ETH"),
|
||||
(
|
||||
@@ -144,55 +156,69 @@ _OPTIONS_SECTION: dict[str, Any] = {
|
||||
],
|
||||
}
|
||||
|
||||
# 对冲公共字段(不含已由 OKX_TRADE_MODE 取代的 ENABLED/SHOW/MUTUAL)
|
||||
_HEDGE_COMMON_FIELDS: list[tuple[str, str, str]] = [
|
||||
("HEDGE_PLAN_LIVE_ORDER", "允许对冲真实下单", "再与实盘 LIVE_TRADING_ENABLED 同开才可启动"),
|
||||
(
|
||||
"MAX_ACTIVE_HEDGE_PLANS",
|
||||
"对冲组数上限",
|
||||
"默认 1;同时进行中的对冲计划组数(opening/active/partial),可改",
|
||||
),
|
||||
("HEDGE_PLAN_MONITOR_POLL_SECONDS", "对冲监控轮询(秒)", "默认 15"),
|
||||
(
|
||||
"HEDGE_PLAN_BUDGET_BUFFER",
|
||||
"对冲预算缓冲比例",
|
||||
"默认 0.95;仅对冲计划;与期权页 OKX_OPTIONS_BUDGET_BUFFER 独立",
|
||||
),
|
||||
(
|
||||
"HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL",
|
||||
"半腿失败改手动补开",
|
||||
"默认 true;开启时半腿失败不自动平,计划挂 partial,页面可补开;并强制关闭下方自动平",
|
||||
),
|
||||
(
|
||||
"HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION",
|
||||
"半腿失败时自动平期权",
|
||||
"默认 true;若上方「半腿失败改手动补开」开启则本项强制无效",
|
||||
),
|
||||
]
|
||||
|
||||
_HEDGE_PO_FIELDS: list[tuple[str, str, str]] = [
|
||||
("HEDGE_PLAN_OPEN_ORDER", "永期开仓顺序", "options_first 或 perp_first"),
|
||||
("HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS", "永期止损后强制平期权", "保护机制,建议保持 true"),
|
||||
("HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS", "永期止盈后强制平期权", "默认 false,保险腿不平"),
|
||||
]
|
||||
|
||||
_HEDGE_OO_FIELDS: list[tuple[str, str, str]] = [
|
||||
("HEDGE_PLAN_OO_CLOSE_WINNER_ONLY", "期期只平盈利腿", "达目标价只平盈利方"),
|
||||
(
|
||||
"HEDGE_PLAN_OO_CLOSE_MODE_ENABLED",
|
||||
"期期平仓模式(方案C)",
|
||||
"默认 true;开启后页面可选「到期平/全平」;关闭则固定到期平",
|
||||
),
|
||||
(
|
||||
"HEDGE_PLAN_OO_BIAS_SPLIT_BY",
|
||||
"期期做多做空拆分口径",
|
||||
"默认预算金额;budget=按权利金预算分两腿;sheets=先算同张数再按比例拆",
|
||||
),
|
||||
(
|
||||
"HEDGE_PLAN_OO_BIAS_RATIO",
|
||||
"期期做多做空主腿占比",
|
||||
"默认 0.7(即 7:3);做多主腿=Call,做空主腿=Put;须在 0~1 之间",
|
||||
),
|
||||
]
|
||||
|
||||
# 兼容旧测试/全量字段列表(写 env 时仍允许这些键,但 UI 按模式过滤)
|
||||
_HEDGE_PLAN_SECTION: dict[str, Any] = {
|
||||
"title": "对冲计划",
|
||||
"exchanges": frozenset({"okx"}),
|
||||
"fields": [
|
||||
("HEDGE_PLAN_ENABLED", "启用对冲计划", "关闭则隐藏导航且不可开仓"),
|
||||
("HEDGE_PLAN_SHOW_PERP_OPTIONS", "显示永期对冲", "默认 true;关闭后隐藏永期 Tab,不可测算/开仓"),
|
||||
("HEDGE_PLAN_SHOW_OPTIONS_OPTIONS", "显示期期对冲", "默认 true;关闭后隐藏期期 Tab,不可测算/开仓"),
|
||||
("HEDGE_PLAN_LIVE_ORDER", "允许对冲真实下单", "再与实盘 LIVE_TRADING_ENABLED 同开才可启动永期"),
|
||||
("HEDGE_PLAN_OPEN_ORDER", "永期开仓顺序", "options_first 或 perp_first"),
|
||||
("HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS", "永期止损后强制平期权", "保护机制,建议保持 true"),
|
||||
("HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS", "永期止盈后强制平期权", "默认 false,保险腿不平"),
|
||||
("HEDGE_PLAN_OO_CLOSE_WINNER_ONLY", "期期只平盈利腿", "达目标价只平盈利方"),
|
||||
(
|
||||
"HEDGE_PLAN_OO_CLOSE_MODE_ENABLED",
|
||||
"期期平仓模式(方案C)",
|
||||
"默认 true;开启后页面可选「到期平/全平」(盈利腿平后另一腿);关闭则固定到期平",
|
||||
),
|
||||
(
|
||||
"HEDGE_PLAN_OO_BIAS_SPLIT_BY",
|
||||
"期期做多做空拆分口径",
|
||||
"默认预算金额;budget=按权利金预算按比例分两腿;sheets=先算同张数总张数(2n)再按比例拆",
|
||||
),
|
||||
(
|
||||
"HEDGE_PLAN_OO_BIAS_RATIO",
|
||||
"期期做多做空主腿占比",
|
||||
"默认 0.7(即 7:3);做多主腿=Call,做空主腿=Put;须在 0~1 之间",
|
||||
),
|
||||
(
|
||||
"HEDGE_PLAN_BUDGET_BUFFER",
|
||||
"对冲预算缓冲比例",
|
||||
"默认 0.95;仅对冲计划(期期可用预算=交易户×本比例);与期权页 OKX_OPTIONS_BUDGET_BUFFER 独立",
|
||||
),
|
||||
(
|
||||
"HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE",
|
||||
"对冲与期权互斥门控",
|
||||
"默认 true;开启时:有对冲计划则不可单独开期权,有单独期权则不可启动对冲;关闭后两边可同时开",
|
||||
),
|
||||
(
|
||||
"HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL",
|
||||
"半腿失败改手动补开",
|
||||
"默认 true;开启时半腿失败不自动平,计划挂 partial,页面可补开永续/腿B;并强制关闭下方自动平",
|
||||
),
|
||||
("MAX_ACTIVE_HEDGE_PLANS", "最大同时活跃计划数", "建议 1"),
|
||||
("HEDGE_PLAN_MONITOR_POLL_SECONDS", "对冲监控轮询(秒)", "默认 15"),
|
||||
(
|
||||
"HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION",
|
||||
"半腿失败时自动平期权",
|
||||
"默认 true;若上方「半腿失败改手动补开」开启则本项强制无效(不会自动平)",
|
||||
),
|
||||
("HEDGE_PLAN_ENABLED", "启用对冲计划", "已由「交易模式」取代,一般无需再改"),
|
||||
("HEDGE_PLAN_SHOW_PERP_OPTIONS", "显示永期对冲", "已由「交易模式」取代"),
|
||||
("HEDGE_PLAN_SHOW_OPTIONS_OPTIONS", "显示期期对冲", "已由「交易模式」取代"),
|
||||
("HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE", "对冲与期权互斥门控", "已由「交易模式」三选一取代"),
|
||||
*_HEDGE_COMMON_FIELDS,
|
||||
*_HEDGE_PO_FIELDS,
|
||||
*_HEDGE_OO_FIELDS,
|
||||
],
|
||||
}
|
||||
|
||||
@@ -212,6 +238,8 @@ _RUNTIME_ENV_DEFAULTS: dict[str, str] = {
|
||||
"HEDGE_PLAN_SHOW_OPTIONS_OPTIONS": "true",
|
||||
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED": "true",
|
||||
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS": "0",
|
||||
"OKX_TRADE_MODE": "options",
|
||||
"MAX_ACTIVE_HEDGE_PLANS": "1",
|
||||
"HEDGE_PLAN_OO_CLOSE_MODE_ENABLED": "true",
|
||||
"HEDGE_PLAN_OO_BIAS_SPLIT_BY": "budget",
|
||||
"HEDGE_PLAN_OO_BIAS_RATIO": "0.7",
|
||||
@@ -293,24 +321,69 @@ def _build_field(
|
||||
return out
|
||||
|
||||
|
||||
def ui_sections_for_exchange(exchange_key: str) -> list[dict[str, Any]]:
|
||||
def _okx_mode_for_env_ui() -> str:
|
||||
try:
|
||||
from lib.hedge_plan.okx_trade_mode_lib import get_okx_trade_mode
|
||||
|
||||
return get_okx_trade_mode()
|
||||
except Exception:
|
||||
return "options"
|
||||
|
||||
|
||||
def _options_fields_for_mode(mode: str) -> list[tuple[str, str, str]]:
|
||||
fields = list(_OPTIONS_SECTION["fields"])
|
||||
if mode != "options":
|
||||
fields = [f for f in fields if f[0] != "OKX_OPTIONS_MAX_ACTIVE_POSITIONS"]
|
||||
return fields
|
||||
|
||||
|
||||
def _hedge_fields_for_mode(mode: str) -> list[tuple[str, str, str]]:
|
||||
if mode == "perp_options":
|
||||
return [*_HEDGE_COMMON_FIELDS, *_HEDGE_PO_FIELDS]
|
||||
if mode == "options_options":
|
||||
return [*_HEDGE_COMMON_FIELDS, *_HEDGE_OO_FIELDS]
|
||||
return []
|
||||
|
||||
|
||||
def ui_sections_for_exchange(
|
||||
exchange_key: str,
|
||||
*,
|
||||
mode: str | None = None,
|
||||
) -> list[dict[str, Any]]:
|
||||
ex = (exchange_key or "").strip().lower()
|
||||
sections: list[dict[str, Any]] = []
|
||||
live_fields = _EXCHANGE_LIVE_FIELDS.get(ex, _EXCHANGE_LIVE_FIELDS["okx"])
|
||||
sections.append({"title": "交易所与实盘", "fields": live_fields})
|
||||
sections.extend(_SHARED_SECTIONS)
|
||||
if ex in _OPTIONS_SECTION.get("exchanges", frozenset()):
|
||||
sections.append(_OPTIONS_SECTION)
|
||||
if ex in _HEDGE_PLAN_SECTION.get("exchanges", frozenset()):
|
||||
sections.append(_HEDGE_PLAN_SECTION)
|
||||
if ex in _MODE_SECTION.get("exchanges", frozenset()):
|
||||
from lib.hedge_plan.okx_trade_mode_lib import normalize_okx_trade_mode
|
||||
|
||||
m = normalize_okx_trade_mode(mode) if mode else ""
|
||||
if not m:
|
||||
m = _okx_mode_for_env_ui()
|
||||
sections.append(_MODE_SECTION)
|
||||
sections.append({"title": "期权账户", "fields": _options_fields_for_mode(m)})
|
||||
hedge_fields = _hedge_fields_for_mode(m)
|
||||
if hedge_fields:
|
||||
title = "对冲计划·永期" if m == "perp_options" else "对冲计划·期期"
|
||||
sections.append({"title": title, "fields": hedge_fields})
|
||||
return sections
|
||||
|
||||
|
||||
def ui_allowed_keys(exchange_key: str) -> frozenset[str]:
|
||||
"""可写键=当前模式可见字段 + 模式切换键 + 遗留对冲开关(兼容旧脚本写入)."""
|
||||
keys: set[str] = set()
|
||||
for sec in ui_sections_for_exchange(exchange_key):
|
||||
for item in sec["fields"]:
|
||||
keys.add(item[0])
|
||||
ex = (exchange_key or "").strip().lower()
|
||||
if ex == "okx":
|
||||
keys.add("OKX_TRADE_MODE")
|
||||
# 允许写入遗留键,避免旧自动化/手改失败;页面不再展示
|
||||
for item in _HEDGE_PLAN_SECTION["fields"]:
|
||||
keys.add(item[0])
|
||||
for item in _OPTIONS_SECTION["fields"]:
|
||||
keys.add(item[0])
|
||||
return frozenset(keys)
|
||||
|
||||
|
||||
@@ -323,7 +396,9 @@ def build_env_ui_payload(
|
||||
env_lines = read_env_lines(env_path)
|
||||
values = env_get_all(env_lines)
|
||||
groups: list[dict[str, Any]] = []
|
||||
for sec in ui_sections_for_exchange(exchange_key):
|
||||
for sec in ui_sections_for_exchange(
|
||||
exchange_key, mode=values.get("OKX_TRADE_MODE") or ""
|
||||
):
|
||||
fields = [
|
||||
_build_field(key, label, note, schema, values)
|
||||
for key, label, note in sec["fields"]
|
||||
|
||||
@@ -108,15 +108,21 @@ def _build_cfg(app_module: Any) -> dict[str, Any]:
|
||||
|
||||
|
||||
def _hedge_enabled() -> bool:
|
||||
return _env_bool("HEDGE_PLAN_ENABLED", False)
|
||||
from lib.hedge_plan.okx_trade_mode_lib import hedge_module_enabled
|
||||
|
||||
return hedge_module_enabled()
|
||||
|
||||
|
||||
def _show_perp_options() -> bool:
|
||||
return _env_bool("HEDGE_PLAN_SHOW_PERP_OPTIONS", True)
|
||||
from lib.hedge_plan.okx_trade_mode_lib import show_perp_options
|
||||
|
||||
return show_perp_options()
|
||||
|
||||
|
||||
def _show_options_options() -> bool:
|
||||
return _env_bool("HEDGE_PLAN_SHOW_OPTIONS_OPTIONS", True)
|
||||
from lib.hedge_plan.okx_trade_mode_lib import show_options_options
|
||||
|
||||
return show_options_options()
|
||||
|
||||
|
||||
def _oo_close_mode_enabled() -> bool:
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
"""OKX 期权/对冲三选一模式(env: OKX_TRADE_MODE).
|
||||
|
||||
options → 仅单独期权(隐藏对冲导航与对冲 env 配置)
|
||||
perp_options → 仅永期对冲(不可单独开期权;对冲组数上限 MAX_ACTIVE_HEDGE_PLANS)
|
||||
options_options → 仅期期对冲(同上)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
MODE_OPTIONS = "options"
|
||||
MODE_PERP = "perp_options"
|
||||
MODE_OO = "options_options"
|
||||
VALID_MODES = frozenset({MODE_OPTIONS, MODE_PERP, MODE_OO})
|
||||
|
||||
_ALIASES = {
|
||||
"option": MODE_OPTIONS,
|
||||
"standalone": MODE_OPTIONS,
|
||||
"期权": MODE_OPTIONS,
|
||||
"单独期权": MODE_OPTIONS,
|
||||
"po": MODE_PERP,
|
||||
"perp": MODE_PERP,
|
||||
"永期": MODE_PERP,
|
||||
"永期对冲": MODE_PERP,
|
||||
"oo": MODE_OO,
|
||||
"期期": MODE_OO,
|
||||
"期期对冲": MODE_OO,
|
||||
}
|
||||
|
||||
|
||||
def _env_bool(name: str, default: bool = False) -> bool:
|
||||
raw = os.getenv(name)
|
||||
if raw is None or str(raw).strip() == "":
|
||||
return default
|
||||
return str(raw).strip().lower() in ("1", "true", "yes", "on")
|
||||
|
||||
|
||||
def normalize_okx_trade_mode(raw: Optional[str]) -> str:
|
||||
s = str(raw or "").strip().lower()
|
||||
if s in VALID_MODES:
|
||||
return s
|
||||
if s in _ALIASES:
|
||||
return _ALIASES[s]
|
||||
return ""
|
||||
|
||||
|
||||
def legacy_infer_okx_trade_mode() -> str:
|
||||
"""未配置 OKX_TRADE_MODE 时,按旧开关推断,避免已有部署行为突变."""
|
||||
if not _env_bool("HEDGE_PLAN_ENABLED", False):
|
||||
return MODE_OPTIONS
|
||||
show_po = _env_bool("HEDGE_PLAN_SHOW_PERP_OPTIONS", True)
|
||||
show_oo = _env_bool("HEDGE_PLAN_SHOW_OPTIONS_OPTIONS", True)
|
||||
if show_po and not show_oo:
|
||||
return MODE_PERP
|
||||
if show_oo and not show_po:
|
||||
return MODE_OO
|
||||
if show_po:
|
||||
return MODE_PERP
|
||||
if show_oo:
|
||||
return MODE_OO
|
||||
return MODE_OPTIONS
|
||||
|
||||
|
||||
def get_okx_trade_mode() -> str:
|
||||
m = normalize_okx_trade_mode(os.getenv("OKX_TRADE_MODE"))
|
||||
if m:
|
||||
return m
|
||||
return legacy_infer_okx_trade_mode()
|
||||
|
||||
|
||||
def hedge_module_enabled() -> bool:
|
||||
return get_okx_trade_mode() in (MODE_PERP, MODE_OO)
|
||||
|
||||
|
||||
def show_perp_options() -> bool:
|
||||
return get_okx_trade_mode() == MODE_PERP
|
||||
|
||||
|
||||
def show_options_options() -> bool:
|
||||
return get_okx_trade_mode() == MODE_OO
|
||||
|
||||
|
||||
def standalone_options_open_allowed() -> bool:
|
||||
return get_okx_trade_mode() == MODE_OPTIONS
|
||||
|
||||
|
||||
def mode_label(mode: Optional[str] = None) -> str:
|
||||
m = mode or get_okx_trade_mode()
|
||||
return {
|
||||
MODE_OPTIONS: "单独期权",
|
||||
MODE_PERP: "永期对冲",
|
||||
MODE_OO: "期期对冲",
|
||||
}.get(m, m or "—")
|
||||
|
||||
|
||||
def block_standalone_open_by_mode_msg() -> Optional[str]:
|
||||
if standalone_options_open_allowed():
|
||||
return None
|
||||
return (
|
||||
f"当前交易模式为「{mode_label()}」,不可单独开期权;"
|
||||
"请在 env「交易模式」切换为「单独期权」"
|
||||
)
|
||||
@@ -12,19 +12,27 @@ def register_instance_dashboard_routes(
|
||||
login_required: Callable,
|
||||
get_db: Callable,
|
||||
fetch_options_positions: Optional[Callable[[], list[dict[str, Any]]]] = None,
|
||||
hedge_enabled: bool = False,
|
||||
hedge_enabled: bool | Callable[[], bool] = False,
|
||||
enrich_orders: Optional[Callable[[list[dict[str, Any]]], list[dict[str, Any]]]] = None,
|
||||
) -> None:
|
||||
from lib.instance.instance_dashboard_cache import instance_dashboard_store
|
||||
from lib.instance.instance_dashboard_lib import build_instance_dashboard_payload
|
||||
|
||||
def _hedge_on() -> bool:
|
||||
if callable(hedge_enabled):
|
||||
try:
|
||||
return bool(hedge_enabled())
|
||||
except Exception:
|
||||
return False
|
||||
return bool(hedge_enabled)
|
||||
|
||||
def _build() -> dict[str, Any]:
|
||||
conn = get_db()
|
||||
try:
|
||||
payload = build_instance_dashboard_payload(
|
||||
conn,
|
||||
fetch_options_positions=fetch_options_positions,
|
||||
hedge_enabled=bool(hedge_enabled),
|
||||
hedge_enabled=_hedge_on(),
|
||||
)
|
||||
if callable(enrich_orders) and payload.get("ok") and isinstance(payload.get("orders"), dict):
|
||||
items = list(payload["orders"].get("items") or [])
|
||||
|
||||
@@ -73,6 +73,14 @@ def option_position_limit_block_msg(
|
||||
- 期期两腿应一次传入两个 inst_id,在开仓前预检,避免上限=1 时开出半边仓
|
||||
- 拉持仓失败:拒绝开仓(避免绕过上限)
|
||||
"""
|
||||
try:
|
||||
from lib.hedge_plan.okx_trade_mode_lib import standalone_options_open_allowed
|
||||
|
||||
# 对冲模式用 MAX_ACTIVE_HEDGE_PLANS 管「组数」,不占用期权笔数上限
|
||||
if max_active is None and not standalone_options_open_allowed():
|
||||
return None
|
||||
except Exception:
|
||||
pass
|
||||
mx = options_max_active_positions() if max_active is None else int(max_active)
|
||||
if mx <= 0:
|
||||
return None
|
||||
|
||||
@@ -456,6 +456,32 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
||||
pass
|
||||
ask = q.get("ask")
|
||||
ask_sz = q.get("ask_sz")
|
||||
try:
|
||||
from lib.hedge_plan.okx_trade_mode_lib import block_standalone_open_by_mode_msg
|
||||
|
||||
mode_block = block_standalone_open_by_mode_msg()
|
||||
if mode_block:
|
||||
return jsonify(
|
||||
{
|
||||
**q,
|
||||
"ok": True,
|
||||
"can_open": False,
|
||||
"msg": mode_block,
|
||||
"quote_per_unit": ask,
|
||||
"premium_per_sheet": None,
|
||||
"sizing": {
|
||||
"ok": False,
|
||||
"msg": mode_block,
|
||||
"sheets": 0,
|
||||
"eth_amount": 0.0,
|
||||
"total_premium": 0.0,
|
||||
},
|
||||
"available_usdc": available_usdc,
|
||||
"budget_full_usdc": budget if mode == "budget_full" else None,
|
||||
}
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
can_open, block_msg = option_buy_liquidity_ok(ask, ask_sz)
|
||||
if not can_open:
|
||||
# 合约可报价,但不可开仓:返回参考标记价供展示
|
||||
@@ -566,6 +592,14 @@ def register_options_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
||||
ex, err = _require_options_ex(cfg)
|
||||
if ex is None:
|
||||
return jsonify({"ok": False, "msg": err})
|
||||
try:
|
||||
from lib.hedge_plan.okx_trade_mode_lib import block_standalone_open_by_mode_msg
|
||||
|
||||
mode_block = block_standalone_open_by_mode_msg()
|
||||
if mode_block:
|
||||
return jsonify({"ok": False, "msg": mode_block, "can_open": False})
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
from lib.hedge_plan.hedge_options_exclusive_lib import block_standalone_option_open_msg
|
||||
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
{% if not options_enabled %}
|
||||
<div class="flash" style="margin-bottom:12px">期权 API 未启用:请在 <code>crypto_monitor_okx/.env</code> 设置 <code>OKX_OPTIONS_ENABLED=true</code> 及主账户 <code>OKX_OPTIONS_API_*</code>,然后 <code>pm2 restart crypto_okx --update-env</code>.</div>
|
||||
{% endif %}
|
||||
{% if options_enabled and options_open_allowed is defined and not options_open_allowed %}
|
||||
<div class="flash" style="margin-bottom:12px">当前交易模式为对冲(永期/期期),不可单独开期权;持仓可在此查看/平仓.切换请到 env「交易模式」.</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="options-dual-grid">
|
||||
<div class="card options-order-card">
|
||||
<h2>期权下单</h2>
|
||||
<div class="card options-order-card"{% if options_open_allowed is defined and not options_open_allowed %} style="opacity:.72"{% endif %}>
|
||||
<h2>期权下单{% if options_open_allowed is defined and not options_open_allowed %} <small class="muted">(对冲模式已禁用开仓)</small>{% endif %}</h2>
|
||||
<details class="opt-close-rule opt-open-rule">
|
||||
<summary>开仓规则说明</summary>
|
||||
<div class="opt-close-rule-body">
|
||||
|
||||
Reference in New Issue
Block a user