From 4c48c9556238ffc177b01c462d2a6315b3d1d4aa Mon Sep 17 00:00:00 2001 From: dekun Date: Wed, 14 Oct 2026 12:46:14 +0800 Subject: [PATCH] Tune CoinOX env: drop auto-transfer; map leverage to hedge perp opens. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BTC_LEVERAGE/ALT_LEVERAGE now drive永期永续 default leverage in UI and start fallback. Co-authored-by: Cursor --- .env.example | 20 ++++++------ app.py | 5 ++- lib/common/static/hedge_plan.js | 25 +++++++++++++-- lib/env/env_ui_manifest.py | 31 +++++++------------ lib/hedge_plan/hedge_plan_register.py | 15 ++++----- .../templates/hedge_plan_panel.html | 8 +++-- lib/instance/instance_display_prefs_lib.py | 4 +-- 7 files changed, 62 insertions(+), 46 deletions(-) diff --git a/.env.example b/.env.example index b466ff0..c3a76c5 100644 --- a/.env.example +++ b/.env.example @@ -74,9 +74,9 @@ DAILY_START_CAPITAL=30 DAILY_LOSS_CAPITAL=20 # 日内盈利后基数(U) DAILY_PROFIT_CAPITAL=50 -# BTC 默认杠杆倍数 +# 永期对冲·永续开仓杠杆(env 页「永期·永续杠杆」;页面未填时回退) BTC_LEVERAGE=10 -# 山寨币默认杠杆倍数 +# ETH 永续开仓杠杆(键名沿用 ALT_LEVERAGE) ALT_LEVERAGE=5 # 交易日重置小时(北京时间) TRADING_DAY_RESET_HOUR=8 @@ -271,16 +271,14 @@ RECONCILE_FLAT_CONFIRM_POLLS=3 FULL_MARGIN_BUFFER_RATIO=0.98 # ============================================================================= -# 自动划转(页顶「将 swap 补足到 XU」;与 DAILY_START_CAPITAL 独立,需一致时请设为相同值) +# 自动划转(CoinOX 已禁用,勿开启;保留键仅兼容旧 .env) # ============================================================================= -AUTO_TRANSFER_ENABLED=false -# 交易账户(swap)目标余额 U:每日 8 点(北京)自动划入或划出至 funding;持仓中不划转 -AUTO_TRANSFER_AMOUNT=30 -AUTO_TRANSFER_FROM=funding -AUTO_TRANSFER_TO=swap -TRANSFER_CCY=USDT -# 北京时间该整点小时内尝试;账簿按 UTC 自然日去重 -AUTO_TRANSFER_BJ_HOUR=8 +# AUTO_TRANSFER_ENABLED=false +# AUTO_TRANSFER_AMOUNT=30 +# AUTO_TRANSFER_FROM=funding +# AUTO_TRANSFER_TO=swap +# TRANSFER_CCY=USDT +# AUTO_TRANSFER_BJ_HOUR=8 # 强制清仓整点(北京时间,默认 0=凌晨00点) FORCE_CLOSE_BJ_HOUR=0 # 是否启用强制清仓(默认关闭,true 才会在整点执行) diff --git a/app.py b/app.py index 07a108a..c0137a6 100644 --- a/app.py +++ b/app.py @@ -393,7 +393,8 @@ PRICE_REFRESH_SECONDS = int(os.getenv("PRICE_REFRESH_SECONDS", "5")) KEY_ALERT_MAX_TIMES = int(os.getenv("KEY_ALERT_MAX_TIMES", "3")) KEY_ALERT_INTERVAL_MINUTES = int(os.getenv("KEY_ALERT_INTERVAL_MINUTES", "5")) KEY_BREAKOUT_LIMIT_PCT = float(os.getenv("KEY_BREAKOUT_LIMIT_PCT", "1.5")) -AUTO_TRANSFER_ENABLED = os.getenv("AUTO_TRANSFER_ENABLED", "false").lower() == "true" +# CoinOX 不提供自动划转(env 页已去掉该分区) +AUTO_TRANSFER_ENABLED = False AUTO_TRANSFER_AMOUNT = float(os.getenv("AUTO_TRANSFER_AMOUNT", "30")) AUTO_TRANSFER_FROM = os.getenv("AUTO_TRANSFER_FROM", "funding") AUTO_TRANSFER_TO = os.getenv("AUTO_TRANSFER_TO", "swap") @@ -6974,6 +6975,8 @@ def render_main_page(page="trade", embed_mode=None): hedge_plan_option_primary=os.getenv("HEDGE_PLAN_OPTION_PRIMARY", "true").lower() in ("1", "true", "yes", "on"), hedge_plan_budget_buffer=float(os.getenv("HEDGE_PLAN_BUDGET_BUFFER") or "0.95"), + hedge_plan_btc_leverage=int(BTC_LEVERAGE or 10), + hedge_plan_eth_leverage=int(ALT_LEVERAGE or 5), options_trade_budget=OKX_OPTIONS_TRADE_BUDGET_USDC, options_budget_buffer=float(os.getenv("OKX_OPTIONS_BUDGET_BUFFER") or "0.95"), options_compound_full_enabled=os.getenv( diff --git a/lib/common/static/hedge_plan.js b/lib/common/static/hedge_plan.js index ad2bcc9..61644b2 100644 --- a/lib/common/static/hedge_plan.js +++ b/lib/common/static/hedge_plan.js @@ -40,6 +40,7 @@ optionPrimary: root.getAttribute("data-option-primary") !== "0", opLevTouched: false, opRatioTouched: false, + perpLevTouched: false, tradingUsdc: null, fundingUsdc: null, tradeBudgetUsdc: null, @@ -377,6 +378,14 @@ }; } + function defaultPerpLeverage(uly) { + const u = (uly || "ETH").toUpperCase(); + const btc = Number(root.getAttribute("data-btc-leverage") || 10); + const eth = Number(root.getAttribute("data-eth-leverage") || 5); + if (u === "BTC") return Number.isFinite(btc) && btc > 0 ? btc : 10; + return Number.isFinite(eth) && eth > 0 ? eth : 5; + } + function syncUnderlyingUI() { const uly = state.underlying || "ETH"; document.querySelectorAll(".hp-uly-btn, .hp-uly-btn-oo").forEach(function (b) { @@ -388,6 +397,11 @@ if (lab) lab.textContent = uly; const ooLab = $("hp-oo-uly-label"); if (ooLab) ooLab.textContent = uly; + // 永续开仓杠杆跟随 env(BTC_LEVERAGE / ALT_LEVERAGE=ETH) + const levEl = $("hp-perp-leverage"); + if (levEl && !state.perpLevTouched) { + levEl.value = String(defaultPerpLeverage(uly)); + } } function syncMoneyUI() { @@ -1664,7 +1678,7 @@ strike_interval: numInput("hp-strike-interval", 15), min_option_hours: numInput("hp-min-hours", 36), option_leverage: numInput("hp-opt-leverage", 100), - leverage: numInput("hp-perp-leverage", 100), + leverage: numInput("hp-perp-leverage", defaultPerpLeverage(state.underlying)), moneyness: opMoneyKind(), hours_to_expiry: exp ? hoursFromExpMs(exp.exp_time) : null, }; @@ -1868,6 +1882,11 @@ renderListStrikes(); }); } + if ($("hp-perp-leverage")) { + $("hp-perp-leverage").addEventListener("input", function () { + state.perpLevTouched = true; + }); + } if ($("hp-opt-leverage")) { $("hp-opt-leverage").addEventListener("input", function () { state.opLevTouched = true; @@ -2618,7 +2637,7 @@ strike_interval: numInput("hp-strike-interval", 15), min_option_hours: numInput("hp-min-hours", 36), option_leverage: optLev, - leverage: numInput("hp-perp-leverage", 100), + leverage: numInput("hp-perp-leverage", defaultPerpLeverage(state.underlying)), moneyness: opMoneyKind(), }; const d = await apiJson("/api/hedge-plan/start", { @@ -2684,7 +2703,7 @@ ask: state.selected.ask, index_px: entry, exchange_symbol: (state.market && state.market.exchange_symbol) || "", - leverage: numInput("hp-perp-leverage", 100), + leverage: numInput("hp-perp-leverage", defaultPerpLeverage(state.underlying)), option_leverage: numInput("hp-opt-leverage", 100), premium_budget: numInput("hp-premium-budget", 0), option_perp_ratio: numInput("hp-opt-perp-ratio", 2), diff --git a/lib/env/env_ui_manifest.py b/lib/env/env_ui_manifest.py index 7fb6e32..079a6de 100644 --- a/lib/env/env_ui_manifest.py +++ b/lib/env/env_ui_manifest.py @@ -119,7 +119,7 @@ _SHARED_SECTIONS: list[dict[str, Any]] = [ }, ] -# CoinOX env 页:去掉关键位/AI复盘/永续手工单等无关项 +# CoinOX env 页:去掉关键位/AI复盘/自动划转等无关项 _COINOX_SHARED_SECTIONS: list[dict[str, Any]] = [ { "title": "企业微信", @@ -129,14 +129,18 @@ _COINOX_SHARED_SECTIONS: list[dict[str, Any]] = [ ], }, { - "title": "资金与杠杆", + "title": "永期·永续杠杆", "fields": [ - ("POSITION_SIZING_MODE", "计仓模式", "切换须无仓后重启"), - ("RISK_PERCENT", "以损定仓风险%", "单笔风险占资金比例"), - ("FULL_MARGIN_BUFFER_RATIO", "全仓资金缓冲比例", "如 0.98"), - ("BTC_LEVERAGE", "BTC 默认杠杆", ""), - ("ALT_LEVERAGE", "山寨默认杠杆", ""), - ("TRADING_DAY_RESET_HOUR", "交易日切点(北京时间)", "整点,默认 8"), + ( + "BTC_LEVERAGE", + "BTC 永续开仓杠杆", + "永期对冲开永续腿时用;页面未填杠杆时回退本值", + ), + ( + "ALT_LEVERAGE", + "ETH 永续开仓杠杆", + "永期对冲开 ETH-USDT 永续时用;页面未填杠杆时回退本值", + ), ], }, { @@ -147,17 +151,6 @@ _COINOX_SHARED_SECTIONS: list[dict[str, Any]] = [ ("SIM_FEE_RATE", "模拟手续费率", "默认 0.0005"), ], }, - { - "title": "自动划转", - "fields": [ - ("AUTO_TRANSFER_ENABLED", "启用自动划转", ""), - ("AUTO_TRANSFER_AMOUNT", "目标余额(U)", "交易账户目标 USDT"), - ("AUTO_TRANSFER_FROM", "划出账户", "余额不足时从此账户划入交易账户"), - ("AUTO_TRANSFER_TO", "划入账户", "目标余额所在账户,一般为 swap"), - ("AUTO_TRANSFER_BJ_HOUR", "执行整点(北京时间)", ""), - ("TRANSFER_CCY", "划转币种", ""), - ], - }, ] _MODE_SECTION: dict[str, Any] = { diff --git a/lib/hedge_plan/hedge_plan_register.py b/lib/hedge_plan/hedge_plan_register.py index 926b1a1..8cdd9f0 100644 --- a/lib/hedge_plan/hedge_plan_register.py +++ b/lib/hedge_plan/hedge_plan_register.py @@ -845,18 +845,19 @@ def register_hedge_plan_routes(app: Flask, cfg: dict[str, Any]) -> None: err = validate_start_body(plan_type, body) if err: return jsonify({"ok": False, "msg": err, "gates": gates}), 400 - # 补齐永续杠杆(以期权为主默认 100;保险模式 BTC/ETH 用 btc_leverage) + # 补齐永续杠杆:页面未填时用 env(BTC_LEVERAGE / ALT_LEVERAGE=ETH) if plan_type == "perp_options" and not body.get("leverage"): from lib.hedge_plan.hedge_plan_option_primary_lib import is_option_primary - if is_option_primary(body): + base = str(body.get("underlying") or "ETH").upper() + if base == "BTC": + body["leverage"] = int(cfg.get("btc_leverage") or 10) + elif base == "ETH": + body["leverage"] = int(cfg.get("alt_leverage") or cfg.get("btc_leverage") or 10) + elif is_option_primary(body): body["leverage"] = 100 else: - base = str(body.get("underlying") or "ETH").upper() - if base in ("BTC", "ETH"): - body["leverage"] = int(cfg.get("btc_leverage") or 10) - else: - body["leverage"] = int(cfg.get("alt_leverage") or 5) + body["leverage"] = int(cfg.get("alt_leverage") or 5) # 以期权为主:策略启动=盯盘,不现场开仓 if plan_type == "perp_options": from lib.hedge_plan.hedge_plan_option_primary_lib import is_option_primary diff --git a/lib/hedge_plan/templates/hedge_plan_panel.html b/lib/hedge_plan/templates/hedge_plan_panel.html index 458f350..9bc7a10 100644 --- a/lib/hedge_plan/templates/hedge_plan_panel.html +++ b/lib/hedge_plan/templates/hedge_plan_panel.html @@ -7,6 +7,8 @@ data-oo-close-mode-enabled="{{ '1' if hedge_plan_oo_close_mode_enabled else '0' }}" data-option-primary="{{ '1' if hedge_plan_option_primary|default(true) else '0' }}" data-budget-buffer="{{ hedge_plan_budget_buffer | default(0.95) }}" + data-btc-leverage="{{ hedge_plan_btc_leverage | default(10) }}" + data-eth-leverage="{{ hedge_plan_eth_leverage | default(5) }}" data-sizing-mode="{{ position_sizing_mode | default('risk') }}" data-is-full-margin="{{ '1' if position_sizing_mode == 'full_margin' else '0' }}"> {% if not hedge_plan_enabled %} @@ -96,8 +98,8 @@