env 锁定币本位并清掉对冲/USDC 配置项。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+6
-45
@@ -102,11 +102,11 @@ OKX_POSITION_INST_TYPE=SWAP
|
|||||||
EXCHANGE_DISPLAY_NAME=OKX
|
EXCHANGE_DISPLAY_NAME=OKX
|
||||||
# 企业微信推送里展示的账户备注
|
# 企业微信推送里展示的账户备注
|
||||||
# OKX_ACCOUNT_LABEL=
|
# OKX_ACCOUNT_LABEL=
|
||||||
# 顶栏是否显示 USDT 资金/交易账户(热更);false 时总资金仅计期权 USDC 侧
|
# 顶栏是否显示 USDT 资金/交易账户(热更);币本位买币仍会显示交易账户可用额
|
||||||
OKX_SHOW_PERP_FUNDS=true
|
OKX_SHOW_PERP_FUNDS=true
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# 期权模块(与上方 OKX_API_* 同源;修改启用开关后须重启 PM2)
|
# 期权模块(币本位专用;与上方 OKX_API_* 同源;修改启用开关后须重启 PM2)
|
||||||
# 详见 docs/期权方案.md 与 docs/期权用法.md
|
# 详见 docs/期权方案.md 与 docs/期权用法.md
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
OKX_OPTIONS_ENABLED=true
|
OKX_OPTIONS_ENABLED=true
|
||||||
@@ -116,7 +116,7 @@ OKX_OPTIONS_ENABLED=true
|
|||||||
# OKX_OPTIONS_API_PASSPHRASE=
|
# OKX_OPTIONS_API_PASSPHRASE=
|
||||||
OKX_OPTIONS_ACCOUNT_LABEL=账户·期权
|
OKX_OPTIONS_ACCOUNT_LABEL=账户·期权
|
||||||
|
|
||||||
# 单笔期权本位: coin(默认,币本位+USDT买币桥) | usdc(权利金USDC;对冲仍仅USDC)
|
# 固定币本位(USDT买币桥);历史 OKX_OPTIONS_MARGIN_MODE=usdc 会被忽略并视为 coin
|
||||||
OKX_OPTIONS_MARGIN_MODE=coin
|
OKX_OPTIONS_MARGIN_MODE=coin
|
||||||
OKX_OPTIONS_COIN_COMPOUND=true
|
OKX_OPTIONS_COIN_COMPOUND=true
|
||||||
OKX_OPTIONS_COIN_BUDGET_USDT=10
|
OKX_OPTIONS_COIN_BUDGET_USDT=10
|
||||||
@@ -125,18 +125,10 @@ OKX_OPTIONS_COIN_MAX_USDT=50
|
|||||||
# 现货买入相对权利金缓冲:1.10=多买10%;也可写 0.10。按最大可开张数×权利金×缓冲买币,不全额兑换
|
# 现货买入相对权利金缓冲:1.10=多买10%;也可写 0.10。按最大可开张数×权利金×缓冲买币,不全额兑换
|
||||||
OKX_OPTIONS_COIN_SPOT_BUY_BUFFER=1.10
|
OKX_OPTIONS_COIN_SPOT_BUY_BUFFER=1.10
|
||||||
|
|
||||||
OKX_OPTIONS_TRADE_BUDGET_USDC=10
|
|
||||||
OKX_OPTIONS_BUDGET_BUFFER=0.95
|
OKX_OPTIONS_BUDGET_BUFFER=0.95
|
||||||
# 全仓复利:开启时隐藏单笔预算且不可用打满;关闭后恢复单笔预算
|
# 交易模式固定单独期权(历史 perp_options / options_options 读取时归一为 options)
|
||||||
OKX_OPTIONS_COMPOUND_FULL_ENABLED=true
|
|
||||||
OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED=false
|
|
||||||
OKX_OPTIONS_COMPOUND_FULL_CAP_USDC=300
|
|
||||||
# 交易模式三选一(热更):options=单独期权 / perp_options=永期对冲 / options_options=期期对冲
|
|
||||||
# 选单独期权时隐藏对冲导航与对冲配置;选对冲时不可单独开期权,仓位按「对冲组数上限」
|
|
||||||
OKX_TRADE_MODE=options
|
OKX_TRADE_MODE=options
|
||||||
# 永期对冲改为: OKX_TRADE_MODE=perp_options
|
# 期权同时持仓上限(笔);0=不限制;同合约加仓不占新笔数;热更
|
||||||
# 期期对冲改为: OKX_TRADE_MODE=options_options
|
|
||||||
# 仅单独期权模式:期权同时持仓上限(笔);0=不限制;同合约加仓不占新笔数;热更
|
|
||||||
OKX_OPTIONS_MAX_ACTIVE_POSITIONS=0
|
OKX_OPTIONS_MAX_ACTIVE_POSITIONS=0
|
||||||
OKX_OPTIONS_DEFAULT_UNDERLY=ETH
|
OKX_OPTIONS_DEFAULT_UNDERLY=ETH
|
||||||
# 期权链仅显示卖一深度≥1张的合约(估算卖一/无深度不显示);false 则显示全部
|
# 期权链仅显示卖一深度≥1张的合约(估算卖一/无深度不显示);false 则显示全部
|
||||||
@@ -148,46 +140,15 @@ OKX_OPTIONS_PROFIT_ALERT_RATIO=1.0
|
|||||||
OKX_OPTIONS_POLL_SECONDS=15
|
OKX_OPTIONS_POLL_SECONDS=15
|
||||||
OKX_OPTIONS_TD_MODE=isolated
|
OKX_OPTIONS_TD_MODE=isolated
|
||||||
OKX_OPTIONS_ALLOW_MARKET_CLOSE=false
|
OKX_OPTIONS_ALLOW_MARKET_CLOSE=false
|
||||||
# 对冲买期权等成交超时(秒);超时撤未成交部分,未完全成交则开仓失败
|
# 开仓成交超时(秒);超时撤未成交部分,未完全成交则开仓失败
|
||||||
OKX_OPTIONS_OPEN_FILL_TIMEOUT_SEC=12
|
OKX_OPTIONS_OPEN_FILL_TIMEOUT_SEC=12
|
||||||
# 目标平仓门控(目标位触发后按买一平仓前需满足)
|
# 目标平仓门控(目标位触发后按买一平仓前需满足)
|
||||||
OKX_OPTIONS_CLOSE_GATE_MODE=premium
|
OKX_OPTIONS_CLOSE_GATE_MODE=premium
|
||||||
# premium:可回收≥权利金×倍数;net_pnl:净盈亏(买一可回收−权利金)折USDT≥下限
|
# premium:可回收≥权利金×倍数;net_pnl:净盈亏(买一可回收−权利金)折USDT≥下限
|
||||||
OKX_OPTIONS_CLOSE_RECYCLE_MULT=2
|
|
||||||
OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN=1.05
|
OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN=1.05
|
||||||
OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT=0
|
OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT=0
|
||||||
OKX_OPTIONS_CLOSE_HOLD_SECONDS=120
|
OKX_OPTIONS_CLOSE_HOLD_SECONDS=120
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# 对冲计划(仅 OKX;由 OKX_TRADE_MODE 控制是否启用;详见 docs/对冲计划开发方案.md)
|
|
||||||
# =============================================================================
|
|
||||||
# 以下三项已由 OKX_TRADE_MODE 取代,保留兼容旧部署(未配置 TRADE_MODE 时仍可读)
|
|
||||||
HEDGE_PLAN_ENABLED=false
|
|
||||||
HEDGE_PLAN_SHOW_PERP_OPTIONS=false
|
|
||||||
HEDGE_PLAN_SHOW_OPTIONS_OPTIONS=false
|
|
||||||
HEDGE_PLAN_LIVE_ORDER=false
|
|
||||||
# 永期子模式:true=以期权为主;false=保险模式(页面标题前标识,不可页内切换)
|
|
||||||
HEDGE_PLAN_OPTION_PRIMARY=true
|
|
||||||
HEDGE_PLAN_OPEN_ORDER=options_first
|
|
||||||
HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS=true
|
|
||||||
HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS=false
|
|
||||||
HEDGE_PLAN_OO_CLOSE_WINNER_ONLY=true
|
|
||||||
# 方案C:期期页面显示「平仓模式」(到期平/全平);关则固定到期平.默认开启,页面默认选全平
|
|
||||||
HEDGE_PLAN_OO_CLOSE_MODE_ENABLED=true
|
|
||||||
# 期期「做多/做空」拆分口径:budget=按权利金预算(默认);sheets=先算同张数总张数(2n)再按比例拆
|
|
||||||
HEDGE_PLAN_OO_BIAS_SPLIT_BY=budget
|
|
||||||
# 期期「做多/做空」主腿占比(0~1,默认 0.7=7:3);做多主腿=Call,做空主腿=Put
|
|
||||||
HEDGE_PLAN_OO_BIAS_RATIO=0.7
|
|
||||||
# 对冲与单独期权互斥(默认 true):有对冲计划不可单独开期权;有单独期权不可启动对冲;false=可同时开
|
|
||||||
HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE=true
|
|
||||||
# 半腿失败改手动补开(默认 true):不自动平已成腿,计划挂 partial,页面补开;开启时下方自动平强制无效
|
|
||||||
HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL=true
|
|
||||||
# 对冲组数上限(默认 1;opening/active/partial 计入);仅永期/期期模式生效;热更
|
|
||||||
MAX_ACTIVE_HEDGE_PLANS=1
|
|
||||||
HEDGE_PLAN_MONITOR_POLL_SECONDS=15
|
|
||||||
# 半腿失败自动平期权;若 MANUAL_COMPLETE_ON_PARTIAL=true 则运行时强制无效(建议一并写成 false)
|
|
||||||
HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION=false
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
#
|
#
|
||||||
|
|||||||
Vendored
-34
@@ -88,18 +88,11 @@ HOT_RELOAD_EXACT = frozenset({
|
|||||||
"APP_AUTH_DISABLED",
|
"APP_AUTH_DISABLED",
|
||||||
"APP_SESSION_DAYS",
|
"APP_SESSION_DAYS",
|
||||||
"WECHAT_WEBHOOK",
|
"WECHAT_WEBHOOK",
|
||||||
"HEDGE_PLAN_ENABLED",
|
|
||||||
"HEDGE_PLAN_SHOW_PERP_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_CHAIN_MAX_DTE_DAYS",
|
||||||
"OKX_OPTIONS_MAX_DTE_DAYS",
|
"OKX_OPTIONS_MAX_DTE_DAYS",
|
||||||
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS",
|
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS",
|
||||||
"OKX_OPTIONS_COMPOUND_FULL_ENABLED",
|
|
||||||
"OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED",
|
|
||||||
"OKX_OPTIONS_COMPOUND_FULL_CAP_USDC",
|
|
||||||
"OKX_OPTIONS_TRADE_BUDGET_USDC",
|
|
||||||
"OKX_OPTIONS_BUDGET_BUFFER",
|
"OKX_OPTIONS_BUDGET_BUFFER",
|
||||||
"OKX_OPTIONS_COIN_COMPOUND",
|
"OKX_OPTIONS_COIN_COMPOUND",
|
||||||
"OKX_OPTIONS_COIN_BUDGET_USDT",
|
"OKX_OPTIONS_COIN_BUDGET_USDT",
|
||||||
@@ -107,27 +100,10 @@ HOT_RELOAD_EXACT = frozenset({
|
|||||||
"OKX_OPTIONS_COIN_MAX_USDT",
|
"OKX_OPTIONS_COIN_MAX_USDT",
|
||||||
"OKX_OPTIONS_COIN_SPOT_BUY_BUFFER",
|
"OKX_OPTIONS_COIN_SPOT_BUY_BUFFER",
|
||||||
"OKX_OPTIONS_CLOSE_GATE_MODE",
|
"OKX_OPTIONS_CLOSE_GATE_MODE",
|
||||||
"OKX_OPTIONS_CLOSE_RECYCLE_MULT",
|
|
||||||
"OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN",
|
"OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN",
|
||||||
"OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT",
|
"OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT",
|
||||||
"OKX_OPTIONS_CLOSE_HOLD_SECONDS",
|
"OKX_OPTIONS_CLOSE_HOLD_SECONDS",
|
||||||
"OKX_TRADE_MODE",
|
"OKX_TRADE_MODE",
|
||||||
"MAX_ACTIVE_HEDGE_PLANS",
|
|
||||||
"HEDGE_PLAN_LIVE_ORDER",
|
|
||||||
"HEDGE_PLAN_OPTION_PRIMARY",
|
|
||||||
"HEDGE_PLAN_OPEN_ORDER",
|
|
||||||
"HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS",
|
|
||||||
"HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS",
|
|
||||||
"HEDGE_PLAN_OO_CLOSE_WINNER_ONLY",
|
|
||||||
"HEDGE_PLAN_OO_CLOSE_MODE_ENABLED",
|
|
||||||
"HEDGE_PLAN_OO_BIAS_SPLIT_BY",
|
|
||||||
"HEDGE_PLAN_OO_BIAS_RATIO",
|
|
||||||
"HEDGE_PLAN_BUDGET_BUFFER",
|
|
||||||
"HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE",
|
|
||||||
"HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL",
|
|
||||||
"MAX_ACTIVE_HEDGE_PLANS",
|
|
||||||
"HEDGE_PLAN_MONITOR_POLL_SECONDS",
|
|
||||||
"HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION",
|
|
||||||
})
|
})
|
||||||
|
|
||||||
SENSITIVE_EXACT = frozenset({
|
SENSITIVE_EXACT = frozenset({
|
||||||
@@ -164,17 +140,9 @@ SELECT_OPTIONS: dict[str, tuple[tuple[str, str], ...]] = {
|
|||||||
("spot", "spot 现货"),
|
("spot", "spot 现货"),
|
||||||
),
|
),
|
||||||
"TRANSFER_CCY": (("USDT", "USDT"),),
|
"TRANSFER_CCY": (("USDT", "USDT"),),
|
||||||
"HEDGE_PLAN_OO_BIAS_SPLIT_BY": (
|
|
||||||
("budget", "预算金额"),
|
|
||||||
("sheets", "张数"),
|
|
||||||
),
|
|
||||||
"OKX_TRADE_MODE": (
|
"OKX_TRADE_MODE": (
|
||||||
("options", "单独期权"),
|
("options", "单独期权"),
|
||||||
),
|
),
|
||||||
"OKX_OPTIONS_MARGIN_MODE": (
|
|
||||||
("coin", "币本位(USDT买币桥)"),
|
|
||||||
("usdc", "USDC(USDⓈ权利金)"),
|
|
||||||
),
|
|
||||||
"OKX_OPTIONS_CLOSE_GATE_MODE": (
|
"OKX_OPTIONS_CLOSE_GATE_MODE": (
|
||||||
("premium", "权利金倍数"),
|
("premium", "权利金倍数"),
|
||||||
("net_pnl", "净盈亏(USDT)"),
|
("net_pnl", "净盈亏(USDT)"),
|
||||||
@@ -243,8 +211,6 @@ def _field_type(key: str, value: str) -> str:
|
|||||||
return "bool"
|
return "bool"
|
||||||
if key.endswith("_ENABLED") or key.startswith("RISK_MOOD_") or key in (
|
if key.endswith("_ENABLED") or key.startswith("RISK_MOOD_") or key in (
|
||||||
"OKX_SHOW_PERP_FUNDS",
|
"OKX_SHOW_PERP_FUNDS",
|
||||||
"HEDGE_PLAN_SHOW_PERP_OPTIONS",
|
|
||||||
"HEDGE_PLAN_SHOW_OPTIONS_OPTIONS",
|
|
||||||
):
|
):
|
||||||
return "bool"
|
return "bool"
|
||||||
try:
|
try:
|
||||||
|
|||||||
Vendored
+19
-85
@@ -27,8 +27,8 @@ _EXCHANGE_LIVE_FIELDS: dict[str, list[tuple[str, str, str]]] = {
|
|||||||
("OKX_ACCOUNT_LABEL", "账户备注", "企业微信推送中显示"),
|
("OKX_ACCOUNT_LABEL", "账户备注", "企业微信推送中显示"),
|
||||||
(
|
(
|
||||||
"OKX_SHOW_PERP_FUNDS",
|
"OKX_SHOW_PERP_FUNDS",
|
||||||
"显示永续资金",
|
"显示USDT资金/交易账户",
|
||||||
"默认关闭;开启后顶栏显示 USDT 资金/交易账户。币本位期权仍会显示交易账户以便买币",
|
"默认关闭;开启后顶栏显示 USDT 资金与交易账户。币本位期权买币仍会显示交易账户可用额",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
"binance": [
|
"binance": [
|
||||||
@@ -64,59 +64,34 @@ _OPTIONS_SECTION: dict[str, Any] = {
|
|||||||
"title": "期权账户",
|
"title": "期权账户",
|
||||||
"exchanges": frozenset({"okx"}),
|
"exchanges": frozenset({"okx"}),
|
||||||
"fields": [
|
"fields": [
|
||||||
("OKX_OPTIONS_ENABLED", "启用期权模块", "与永续共用上方 OKX_API_*;不再单独配置期权密钥"),
|
("OKX_OPTIONS_ENABLED", "启用期权模块", "与上方 OKX_API_* 同源;不再单独配置期权密钥"),
|
||||||
("OKX_OPTIONS_ACCOUNT_LABEL", "期权账户备注", ""),
|
("OKX_OPTIONS_ACCOUNT_LABEL", "期权账户备注", ""),
|
||||||
(
|
("OKX_OPTIONS_BUDGET_BUFFER", "预算缓冲比例", "如 0.95;币本位复利/固定预算共用"),
|
||||||
"OKX_OPTIONS_MARGIN_MODE",
|
|
||||||
"单笔期权本位",
|
|
||||||
"usdc=USDⓈ权利金;coin=币本位+USDT买币桥(默认)。有持仓/半成品桥时勿切换;改后需重启",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"OKX_OPTIONS_TRADE_BUDGET_USDC",
|
|
||||||
"单笔预算(USDC)",
|
|
||||||
"仅 USDC 模式且全仓复利关闭时显示/生效;用于「按可用余额打满」及张数/币数上限",
|
|
||||||
),
|
|
||||||
("OKX_OPTIONS_BUDGET_BUFFER", "预算缓冲比例", "如 0.95;USDC 打满/全仓复利与币本位复利共用"),
|
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_COIN_COMPOUND",
|
"OKX_OPTIONS_COIN_COMPOUND",
|
||||||
"币本位按交易户USDT复利",
|
"按交易户USDT复利",
|
||||||
"默认 true;预算=交易账户USDT×缓冲;关闭则用下方固定 USDT 预算×缓冲",
|
"默认 true;预算=交易账户USDT×缓冲;关闭则用下方固定 USDT 预算×缓冲",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_COIN_BUDGET_USDT",
|
"OKX_OPTIONS_COIN_BUDGET_USDT",
|
||||||
"币本位固定预算(USDT)",
|
"固定预算(USDT)",
|
||||||
"仅币本位且复利关闭时生效",
|
"仅复利关闭时生效",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_COIN_MAX_USDT_ENABLED",
|
"OKX_OPTIONS_COIN_MAX_USDT_ENABLED",
|
||||||
"币本位单笔上限开关",
|
"单笔上限开关",
|
||||||
"默认 false=靠人工转走控规模;true 时预算不超过下方 N U",
|
"默认 false=靠人工转走控规模;true 时预算不超过下方 N U",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_COIN_MAX_USDT",
|
"OKX_OPTIONS_COIN_MAX_USDT",
|
||||||
"币本位单笔上限(USDT)",
|
"单笔上限(USDT)",
|
||||||
"仅上限开关开启时生效",
|
"仅上限开关开启时生效",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_COIN_SPOT_BUY_BUFFER",
|
"OKX_OPTIONS_COIN_SPOT_BUY_BUFFER",
|
||||||
"币本位现货买入缓冲",
|
"现货买入缓冲",
|
||||||
"相对权利金倍数,默认 1.10(=多买10%);也可写 0.10 表示+10%。按最大可开张数×卖一权利金×本缓冲买币,不全额兑换",
|
"相对权利金倍数,默认 1.10(=多买10%);也可写 0.10 表示+10%。按最大可开张数×卖一权利金×本缓冲买币,不全额兑换",
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"OKX_OPTIONS_COMPOUND_FULL_ENABLED",
|
|
||||||
"全仓复利开关",
|
|
||||||
"默认 true;仅 USDC 模式。开启时隐藏单笔预算且不可用打满预算,下单以全仓复利为主;关闭则恢复单笔预算并隐藏全仓复利",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED",
|
|
||||||
"全仓复利上限开关",
|
|
||||||
"仅全仓复利开启时有意义;默认 false=不设上限用期权户全部可用;true 时按下方上限封顶",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"OKX_OPTIONS_COMPOUND_FULL_CAP_USDC",
|
|
||||||
"全仓复利上限(USDC)",
|
|
||||||
"仅「全仓复利」且「上限开关」都开启时生效;例如 300",
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS",
|
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS",
|
||||||
"期权持仓上限(笔)",
|
"期权持仓上限(笔)",
|
||||||
@@ -131,7 +106,7 @@ _OPTIONS_SECTION: dict[str, Any] = {
|
|||||||
(
|
(
|
||||||
"OKX_OPTIONS_MAX_DTE_DAYS",
|
"OKX_OPTIONS_MAX_DTE_DAYS",
|
||||||
"开仓最大剩余天数",
|
"开仓最大剩余天数",
|
||||||
"默认 2;单独开期权时拒绝更远到期(与链展示天数独立)",
|
"默认 2;开仓时拒绝更远到期(与链展示天数独立)",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED",
|
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED",
|
||||||
@@ -141,17 +116,12 @@ _OPTIONS_SECTION: dict[str, Any] = {
|
|||||||
(
|
(
|
||||||
"OKX_OPTIONS_CLOSE_GATE_MODE",
|
"OKX_OPTIONS_CLOSE_GATE_MODE",
|
||||||
"目标平仓门控模式",
|
"目标平仓门控模式",
|
||||||
"premium=可回收≥权利金×倍数(币本位默认×1.05);net_pnl=净盈亏折USDT≥阈值",
|
"premium=可回收≥权利金×倍数(默认×1.05);net_pnl=净盈亏折USDT≥阈值",
|
||||||
),
|
|
||||||
(
|
|
||||||
"OKX_OPTIONS_CLOSE_RECYCLE_MULT",
|
|
||||||
"门控权利金倍数(USDC)",
|
|
||||||
"仅 premium 模式;USDC 权利金仓默认 2",
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN",
|
"OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN",
|
||||||
"门控权利金倍数(币本位)",
|
"门控权利金倍数",
|
||||||
"仅 premium 模式;ETH/BTC 权利金仓默认 1.05",
|
"仅 premium 模式;默认 1.05",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT",
|
"OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT",
|
||||||
@@ -182,9 +152,7 @@ _RUNTIME_ENV_DEFAULTS: dict[str, str] = {
|
|||||||
"OKX_OPTIONS_CHAIN_MAX_DTE_DAYS": "14",
|
"OKX_OPTIONS_CHAIN_MAX_DTE_DAYS": "14",
|
||||||
"OKX_OPTIONS_MAX_DTE_DAYS": "2",
|
"OKX_OPTIONS_MAX_DTE_DAYS": "2",
|
||||||
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS": "0",
|
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS": "0",
|
||||||
"OKX_OPTIONS_MARGIN_MODE": "coin",
|
|
||||||
"OKX_OPTIONS_CLOSE_GATE_MODE": "premium",
|
"OKX_OPTIONS_CLOSE_GATE_MODE": "premium",
|
||||||
"OKX_OPTIONS_CLOSE_RECYCLE_MULT": "2",
|
|
||||||
"OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN": "1.05",
|
"OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN": "1.05",
|
||||||
"OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT": "0",
|
"OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT": "0",
|
||||||
"OKX_OPTIONS_CLOSE_HOLD_SECONDS": "120",
|
"OKX_OPTIONS_CLOSE_HOLD_SECONDS": "120",
|
||||||
@@ -194,13 +162,14 @@ _RUNTIME_ENV_DEFAULTS: dict[str, str] = {
|
|||||||
|
|
||||||
def _effective_env_value(key: str, file_values: dict[str, str], schema_default: str = "") -> str:
|
def _effective_env_value(key: str, file_values: dict[str, str], schema_default: str = "") -> str:
|
||||||
if key == "OKX_TRADE_MODE":
|
if key == "OKX_TRADE_MODE":
|
||||||
# 展示值必须与运行时 get_okx_trade_mode() 一致(始终单独期权)
|
|
||||||
try:
|
try:
|
||||||
from lib.options.okx_trade_mode_lib import get_okx_trade_mode
|
from lib.options.okx_trade_mode_lib import get_okx_trade_mode
|
||||||
|
|
||||||
return get_okx_trade_mode()
|
return get_okx_trade_mode()
|
||||||
except Exception:
|
except Exception:
|
||||||
return "options"
|
return "options"
|
||||||
|
if key == "OKX_OPTIONS_MARGIN_MODE":
|
||||||
|
return "coin"
|
||||||
if key in file_values:
|
if key in file_values:
|
||||||
file_val = str(file_values.get(key) or "").strip()
|
file_val = str(file_values.get(key) or "").strip()
|
||||||
if file_val:
|
if file_val:
|
||||||
@@ -313,24 +282,7 @@ def build_env_ui_payload(
|
|||||||
return groups
|
return groups
|
||||||
|
|
||||||
|
|
||||||
# 币本位专属 / USDC 专属(配置页互斥隐藏)
|
# 币本位专用:按复利/上限/门控模式标记 hidden
|
||||||
_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:
|
def _field_current(fields: list[dict[str, Any]], key: str, default: str = "") -> str:
|
||||||
for f in fields:
|
for f in fields:
|
||||||
if f.get("key") == key:
|
if f.get("key") == key:
|
||||||
@@ -339,37 +291,19 @@ def _field_current(fields: list[dict[str, Any]], key: str, default: str = "") ->
|
|||||||
|
|
||||||
|
|
||||||
def _mark_options_section_hidden(fields: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
def _mark_options_section_hidden(fields: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||||
"""按本位/门控模式/全仓复利标记 hidden(供 SSR/前端;切换开关仍可再显示)."""
|
"""按门控模式/复利/单笔上限标记 hidden."""
|
||||||
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()
|
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_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"))
|
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]] = []
|
out: list[dict[str, Any]] = []
|
||||||
for f in fields:
|
for f in fields:
|
||||||
key = str(f.get("key") or "")
|
key = str(f.get("key") or "")
|
||||||
hide = False
|
hide = False
|
||||||
if is_coin and key in _USDC_ONLY_ENV_KEYS:
|
if key == "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN" and gate_mode != "premium":
|
||||||
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
|
hide = True
|
||||||
elif key == "OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT" and gate_mode != "net_pnl":
|
elif key == "OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT" and gate_mode != "net_pnl":
|
||||||
hide = True
|
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:
|
elif key == "OKX_OPTIONS_COIN_BUDGET_USDT" and coin_compound_on:
|
||||||
hide = True
|
hide = True
|
||||||
elif key == "OKX_OPTIONS_COIN_MAX_USDT" and not coin_max_on:
|
elif key == "OKX_OPTIONS_COIN_MAX_USDT" and not coin_max_on:
|
||||||
|
|||||||
@@ -118,23 +118,8 @@ def register_instance_settings_routes(
|
|||||||
if not clean:
|
if not clean:
|
||||||
return jsonify({"ok": True, "changed_keys": [], "restart_required": False})
|
return jsonify({"ok": True, "changed_keys": [], "restart_required": False})
|
||||||
if "OKX_OPTIONS_MARGIN_MODE" in clean:
|
if "OKX_OPTIONS_MARGIN_MODE" in clean:
|
||||||
try:
|
# 币本位专用机:忽略任何写入,强制 coin
|
||||||
from lib.options.options_margin_mode_lib import normalize_options_margin_mode
|
clean["OKX_OPTIONS_MARGIN_MODE"] = "coin"
|
||||||
from lib.options.options_spot_bridge_lib import mode_switch_block_msg
|
|
||||||
|
|
||||||
lines = read_env_lines(env_path)
|
|
||||||
old_mode = normalize_options_margin_mode(env_get(lines, "OKX_OPTIONS_MARGIN_MODE") or "coin")
|
|
||||||
new_mode = normalize_options_margin_mode(clean.get("OKX_OPTIONS_MARGIN_MODE"))
|
|
||||||
if old_mode != new_mode:
|
|
||||||
conn_m = get_db()
|
|
||||||
try:
|
|
||||||
block = mode_switch_block_msg(conn_m, None)
|
|
||||||
if block:
|
|
||||||
return jsonify({"ok": False, "msg": block}), 400
|
|
||||||
finally:
|
|
||||||
conn_m.close()
|
|
||||||
except Exception as e:
|
|
||||||
return jsonify({"ok": False, "msg": f"本位切换校验失败: {e}"}), 400
|
|
||||||
changed = apply_env_updates(env_path, clean)
|
changed = apply_env_updates(env_path, clean)
|
||||||
groups = parse_env_example_schema(example_path)
|
groups = parse_env_example_schema(example_path)
|
||||||
reload_info = apply_env_reload(env_path, get_db, changed, groups)
|
reload_info = apply_env_reload(env_path, get_db, changed, groups)
|
||||||
|
|||||||
@@ -24,22 +24,14 @@ def _env_float(name: str, default: float) -> float:
|
|||||||
|
|
||||||
|
|
||||||
def normalize_options_margin_mode(raw: Any = None) -> str:
|
def normalize_options_margin_mode(raw: Any = None) -> str:
|
||||||
"""返回 usdc | coin;未配置时默认币本位."""
|
"""币本位专用机:始终 coin;历史 usdc 配置读取时亦归一为 coin."""
|
||||||
if raw is None:
|
del raw
|
||||||
raw = os.getenv("OKX_OPTIONS_MARGIN_MODE")
|
|
||||||
v = str(raw or MODE_COIN).strip().lower()
|
|
||||||
if v in ("usdc", "usdc_margin", "usd_margin", "u本位", "u"):
|
|
||||||
return MODE_USDC
|
|
||||||
if v in ("coin", "coin_margin", "crypto", "crypto_margin", "币本位"):
|
|
||||||
return MODE_COIN
|
|
||||||
# 空串或未知值:默认币本位
|
|
||||||
if not v:
|
|
||||||
return MODE_COIN
|
|
||||||
return MODE_COIN
|
return MODE_COIN
|
||||||
|
|
||||||
|
|
||||||
def is_coin_margin_mode(raw: Any = None) -> bool:
|
def is_coin_margin_mode(raw: Any = None) -> bool:
|
||||||
return normalize_options_margin_mode(raw) == MODE_COIN
|
del raw
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def inst_family_for_underlying(underlying: str, *, margin_mode: str | None = None) -> str:
|
def inst_family_for_underlying(underlying: str, *, margin_mode: str | None = None) -> str:
|
||||||
|
|||||||
@@ -72,16 +72,30 @@ class RemoveHedgeSmokeTests(unittest.TestCase):
|
|||||||
from lib.env.env_schema import select_options_for
|
from lib.env.env_schema import select_options_for
|
||||||
|
|
||||||
titles = [s["title"] for s in ui_sections_for_exchange("okx")]
|
titles = [s["title"] for s in ui_sections_for_exchange("okx")]
|
||||||
self.assertNotIn("期权/对冲模式", titles)
|
|
||||||
self.assertTrue(any("对冲" not in t for t in titles))
|
|
||||||
for t in titles:
|
for t in titles:
|
||||||
self.assertNotIn("对冲", t)
|
self.assertNotIn("对冲", t)
|
||||||
labels = [f[1] for s in ui_sections_for_exchange("okx") for f in s["fields"]]
|
labels = [f[1] for s in ui_sections_for_exchange("okx") for f in s["fields"]]
|
||||||
for lab in labels:
|
for lab in labels:
|
||||||
self.assertNotIn("对冲", lab)
|
self.assertNotIn("对冲", lab)
|
||||||
|
keys = [f[0] for s in ui_sections_for_exchange("okx") for f in s["fields"]]
|
||||||
|
self.assertNotIn("OKX_OPTIONS_MARGIN_MODE", keys)
|
||||||
|
self.assertNotIn("OKX_OPTIONS_TRADE_BUDGET_USDC", keys)
|
||||||
|
self.assertNotIn("OKX_OPTIONS_COMPOUND_FULL_ENABLED", keys)
|
||||||
|
self.assertNotIn("OKX_OPTIONS_CLOSE_RECYCLE_MULT", keys)
|
||||||
|
self.assertIn("OKX_OPTIONS_COIN_COMPOUND", keys)
|
||||||
mode_opts = [o["value"] for o in select_options_for("OKX_TRADE_MODE")]
|
mode_opts = [o["value"] for o in select_options_for("OKX_TRADE_MODE")]
|
||||||
self.assertEqual(mode_opts, ["options"])
|
self.assertEqual(mode_opts, ["options"])
|
||||||
|
|
||||||
|
def test_margin_mode_locked_coin(self):
|
||||||
|
from lib.options.options_margin_mode_lib import (
|
||||||
|
is_coin_margin_mode,
|
||||||
|
normalize_options_margin_mode,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(normalize_options_margin_mode("usdc"), "coin")
|
||||||
|
self.assertEqual(normalize_options_margin_mode("coin"), "coin")
|
||||||
|
self.assertTrue(is_coin_margin_mode("usdc"))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user