Tune CoinOX env: drop auto-transfer; map leverage to hedge perp opens.
BTC_LEVERAGE/ALT_LEVERAGE now drive永期永续 default leverage in UI and start fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+9
-11
@@ -74,9 +74,9 @@ DAILY_START_CAPITAL=30
|
|||||||
DAILY_LOSS_CAPITAL=20
|
DAILY_LOSS_CAPITAL=20
|
||||||
# 日内盈利后基数(U)
|
# 日内盈利后基数(U)
|
||||||
DAILY_PROFIT_CAPITAL=50
|
DAILY_PROFIT_CAPITAL=50
|
||||||
# BTC 默认杠杆倍数
|
# 永期对冲·永续开仓杠杆(env 页「永期·永续杠杆」;页面未填时回退)
|
||||||
BTC_LEVERAGE=10
|
BTC_LEVERAGE=10
|
||||||
# 山寨币默认杠杆倍数
|
# ETH 永续开仓杠杆(键名沿用 ALT_LEVERAGE)
|
||||||
ALT_LEVERAGE=5
|
ALT_LEVERAGE=5
|
||||||
# 交易日重置小时(北京时间)
|
# 交易日重置小时(北京时间)
|
||||||
TRADING_DAY_RESET_HOUR=8
|
TRADING_DAY_RESET_HOUR=8
|
||||||
@@ -271,16 +271,14 @@ RECONCILE_FLAT_CONFIRM_POLLS=3
|
|||||||
FULL_MARGIN_BUFFER_RATIO=0.98
|
FULL_MARGIN_BUFFER_RATIO=0.98
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# 自动划转(页顶「将 swap 补足到 XU」;与 DAILY_START_CAPITAL 独立,需一致时请设为相同值)
|
# 自动划转(CoinOX 已禁用,勿开启;保留键仅兼容旧 .env)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
AUTO_TRANSFER_ENABLED=false
|
# AUTO_TRANSFER_ENABLED=false
|
||||||
# 交易账户(swap)目标余额 U:每日 8 点(北京)自动划入或划出至 funding;持仓中不划转
|
# AUTO_TRANSFER_AMOUNT=30
|
||||||
AUTO_TRANSFER_AMOUNT=30
|
# AUTO_TRANSFER_FROM=funding
|
||||||
AUTO_TRANSFER_FROM=funding
|
# AUTO_TRANSFER_TO=swap
|
||||||
AUTO_TRANSFER_TO=swap
|
# TRANSFER_CCY=USDT
|
||||||
TRANSFER_CCY=USDT
|
# AUTO_TRANSFER_BJ_HOUR=8
|
||||||
# 北京时间该整点小时内尝试;账簿按 UTC 自然日去重
|
|
||||||
AUTO_TRANSFER_BJ_HOUR=8
|
|
||||||
# 强制清仓整点(北京时间,默认 0=凌晨00点)
|
# 强制清仓整点(北京时间,默认 0=凌晨00点)
|
||||||
FORCE_CLOSE_BJ_HOUR=0
|
FORCE_CLOSE_BJ_HOUR=0
|
||||||
# 是否启用强制清仓(默认关闭,true 才会在整点执行)
|
# 是否启用强制清仓(默认关闭,true 才会在整点执行)
|
||||||
|
|||||||
@@ -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_MAX_TIMES = int(os.getenv("KEY_ALERT_MAX_TIMES", "3"))
|
||||||
KEY_ALERT_INTERVAL_MINUTES = int(os.getenv("KEY_ALERT_INTERVAL_MINUTES", "5"))
|
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"))
|
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_AMOUNT = float(os.getenv("AUTO_TRANSFER_AMOUNT", "30"))
|
||||||
AUTO_TRANSFER_FROM = os.getenv("AUTO_TRANSFER_FROM", "funding")
|
AUTO_TRANSFER_FROM = os.getenv("AUTO_TRANSFER_FROM", "funding")
|
||||||
AUTO_TRANSFER_TO = os.getenv("AUTO_TRANSFER_TO", "swap")
|
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()
|
hedge_plan_option_primary=os.getenv("HEDGE_PLAN_OPTION_PRIMARY", "true").lower()
|
||||||
in ("1", "true", "yes", "on"),
|
in ("1", "true", "yes", "on"),
|
||||||
hedge_plan_budget_buffer=float(os.getenv("HEDGE_PLAN_BUDGET_BUFFER") or "0.95"),
|
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_trade_budget=OKX_OPTIONS_TRADE_BUDGET_USDC,
|
||||||
options_budget_buffer=float(os.getenv("OKX_OPTIONS_BUDGET_BUFFER") or "0.95"),
|
options_budget_buffer=float(os.getenv("OKX_OPTIONS_BUDGET_BUFFER") or "0.95"),
|
||||||
options_compound_full_enabled=os.getenv(
|
options_compound_full_enabled=os.getenv(
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
optionPrimary: root.getAttribute("data-option-primary") !== "0",
|
optionPrimary: root.getAttribute("data-option-primary") !== "0",
|
||||||
opLevTouched: false,
|
opLevTouched: false,
|
||||||
opRatioTouched: false,
|
opRatioTouched: false,
|
||||||
|
perpLevTouched: false,
|
||||||
tradingUsdc: null,
|
tradingUsdc: null,
|
||||||
fundingUsdc: null,
|
fundingUsdc: null,
|
||||||
tradeBudgetUsdc: 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() {
|
function syncUnderlyingUI() {
|
||||||
const uly = state.underlying || "ETH";
|
const uly = state.underlying || "ETH";
|
||||||
document.querySelectorAll(".hp-uly-btn, .hp-uly-btn-oo").forEach(function (b) {
|
document.querySelectorAll(".hp-uly-btn, .hp-uly-btn-oo").forEach(function (b) {
|
||||||
@@ -388,6 +397,11 @@
|
|||||||
if (lab) lab.textContent = uly;
|
if (lab) lab.textContent = uly;
|
||||||
const ooLab = $("hp-oo-uly-label");
|
const ooLab = $("hp-oo-uly-label");
|
||||||
if (ooLab) ooLab.textContent = uly;
|
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() {
|
function syncMoneyUI() {
|
||||||
@@ -1664,7 +1678,7 @@
|
|||||||
strike_interval: numInput("hp-strike-interval", 15),
|
strike_interval: numInput("hp-strike-interval", 15),
|
||||||
min_option_hours: numInput("hp-min-hours", 36),
|
min_option_hours: numInput("hp-min-hours", 36),
|
||||||
option_leverage: numInput("hp-opt-leverage", 100),
|
option_leverage: numInput("hp-opt-leverage", 100),
|
||||||
leverage: numInput("hp-perp-leverage", 100),
|
leverage: numInput("hp-perp-leverage", defaultPerpLeverage(state.underlying)),
|
||||||
moneyness: opMoneyKind(),
|
moneyness: opMoneyKind(),
|
||||||
hours_to_expiry: exp ? hoursFromExpMs(exp.exp_time) : null,
|
hours_to_expiry: exp ? hoursFromExpMs(exp.exp_time) : null,
|
||||||
};
|
};
|
||||||
@@ -1868,6 +1882,11 @@
|
|||||||
renderListStrikes();
|
renderListStrikes();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if ($("hp-perp-leverage")) {
|
||||||
|
$("hp-perp-leverage").addEventListener("input", function () {
|
||||||
|
state.perpLevTouched = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
if ($("hp-opt-leverage")) {
|
if ($("hp-opt-leverage")) {
|
||||||
$("hp-opt-leverage").addEventListener("input", function () {
|
$("hp-opt-leverage").addEventListener("input", function () {
|
||||||
state.opLevTouched = true;
|
state.opLevTouched = true;
|
||||||
@@ -2618,7 +2637,7 @@
|
|||||||
strike_interval: numInput("hp-strike-interval", 15),
|
strike_interval: numInput("hp-strike-interval", 15),
|
||||||
min_option_hours: numInput("hp-min-hours", 36),
|
min_option_hours: numInput("hp-min-hours", 36),
|
||||||
option_leverage: optLev,
|
option_leverage: optLev,
|
||||||
leverage: numInput("hp-perp-leverage", 100),
|
leverage: numInput("hp-perp-leverage", defaultPerpLeverage(state.underlying)),
|
||||||
moneyness: opMoneyKind(),
|
moneyness: opMoneyKind(),
|
||||||
};
|
};
|
||||||
const d = await apiJson("/api/hedge-plan/start", {
|
const d = await apiJson("/api/hedge-plan/start", {
|
||||||
@@ -2684,7 +2703,7 @@
|
|||||||
ask: state.selected.ask,
|
ask: state.selected.ask,
|
||||||
index_px: entry,
|
index_px: entry,
|
||||||
exchange_symbol: (state.market && state.market.exchange_symbol) || "",
|
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),
|
option_leverage: numInput("hp-opt-leverage", 100),
|
||||||
premium_budget: numInput("hp-premium-budget", 0),
|
premium_budget: numInput("hp-premium-budget", 0),
|
||||||
option_perp_ratio: numInput("hp-opt-perp-ratio", 2),
|
option_perp_ratio: numInput("hp-opt-perp-ratio", 2),
|
||||||
|
|||||||
Vendored
+12
-19
@@ -119,7 +119,7 @@ _SHARED_SECTIONS: list[dict[str, Any]] = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
# CoinOX env 页:去掉关键位/AI复盘/永续手工单等无关项
|
# CoinOX env 页:去掉关键位/AI复盘/自动划转等无关项
|
||||||
_COINOX_SHARED_SECTIONS: list[dict[str, Any]] = [
|
_COINOX_SHARED_SECTIONS: list[dict[str, Any]] = [
|
||||||
{
|
{
|
||||||
"title": "企业微信",
|
"title": "企业微信",
|
||||||
@@ -129,14 +129,18 @@ _COINOX_SHARED_SECTIONS: list[dict[str, Any]] = [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "资金与杠杆",
|
"title": "永期·永续杠杆",
|
||||||
"fields": [
|
"fields": [
|
||||||
("POSITION_SIZING_MODE", "计仓模式", "切换须无仓后重启"),
|
(
|
||||||
("RISK_PERCENT", "以损定仓风险%", "单笔风险占资金比例"),
|
"BTC_LEVERAGE",
|
||||||
("FULL_MARGIN_BUFFER_RATIO", "全仓资金缓冲比例", "如 0.98"),
|
"BTC 永续开仓杠杆",
|
||||||
("BTC_LEVERAGE", "BTC 默认杠杆", ""),
|
"永期对冲开永续腿时用;页面未填杠杆时回退本值",
|
||||||
("ALT_LEVERAGE", "山寨默认杠杆", ""),
|
),
|
||||||
("TRADING_DAY_RESET_HOUR", "交易日切点(北京时间)", "整点,默认 8"),
|
(
|
||||||
|
"ALT_LEVERAGE",
|
||||||
|
"ETH 永续开仓杠杆",
|
||||||
|
"永期对冲开 ETH-USDT 永续时用;页面未填杠杆时回退本值",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -147,17 +151,6 @@ _COINOX_SHARED_SECTIONS: list[dict[str, Any]] = [
|
|||||||
("SIM_FEE_RATE", "模拟手续费率", "默认 0.0005"),
|
("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] = {
|
_MODE_SECTION: dict[str, Any] = {
|
||||||
|
|||||||
@@ -845,18 +845,19 @@ def register_hedge_plan_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
|||||||
err = validate_start_body(plan_type, body)
|
err = validate_start_body(plan_type, body)
|
||||||
if err:
|
if err:
|
||||||
return jsonify({"ok": False, "msg": err, "gates": gates}), 400
|
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"):
|
if plan_type == "perp_options" and not body.get("leverage"):
|
||||||
from lib.hedge_plan.hedge_plan_option_primary_lib import is_option_primary
|
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
|
body["leverage"] = 100
|
||||||
else:
|
else:
|
||||||
base = str(body.get("underlying") or "ETH").upper()
|
body["leverage"] = int(cfg.get("alt_leverage") or 5)
|
||||||
if base in ("BTC", "ETH"):
|
|
||||||
body["leverage"] = int(cfg.get("btc_leverage") or 10)
|
|
||||||
else:
|
|
||||||
body["leverage"] = int(cfg.get("alt_leverage") or 5)
|
|
||||||
# 以期权为主:策略启动=盯盘,不现场开仓
|
# 以期权为主:策略启动=盯盘,不现场开仓
|
||||||
if plan_type == "perp_options":
|
if plan_type == "perp_options":
|
||||||
from lib.hedge_plan.hedge_plan_option_primary_lib import is_option_primary
|
from lib.hedge_plan.hedge_plan_option_primary_lib import is_option_primary
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
data-oo-close-mode-enabled="{{ '1' if hedge_plan_oo_close_mode_enabled else '0' }}"
|
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-option-primary="{{ '1' if hedge_plan_option_primary|default(true) else '0' }}"
|
||||||
data-budget-buffer="{{ hedge_plan_budget_buffer | default(0.95) }}"
|
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-sizing-mode="{{ position_sizing_mode | default('risk') }}"
|
||||||
data-is-full-margin="{{ '1' if position_sizing_mode == 'full_margin' else '0' }}">
|
data-is-full-margin="{{ '1' if position_sizing_mode == 'full_margin' else '0' }}">
|
||||||
{% if not hedge_plan_enabled %}
|
{% if not hedge_plan_enabled %}
|
||||||
@@ -96,8 +98,8 @@
|
|||||||
<input type="number" step="any" id="hp-premium-budget" placeholder="预算(执行×0.95)" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
<input type="number" step="any" id="hp-premium-budget" placeholder="预算(执行×0.95)" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||||
</label>
|
</label>
|
||||||
<label class="hp-po-field">
|
<label class="hp-po-field">
|
||||||
<span class="hp-po-field-lab">永续杠杆</span>
|
<span class="hp-po-field-lab">永续杠杆 <em>开仓</em></span>
|
||||||
<input type="number" step="1" id="hp-perp-leverage" value="100" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
<input type="number" step="1" id="hp-perp-leverage" value="{{ hedge_plan_eth_leverage | default(5) }}" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" title="默认取 env 永期·永续杠杆;可按标的切换" />
|
||||||
</label>
|
</label>
|
||||||
<label class="hp-po-field">
|
<label class="hp-po-field">
|
||||||
<span class="hp-po-field-lab">期权杠杆 <em>启动校验</em></span>
|
<span class="hp-po-field-lab">期权杠杆 <em>启动校验</em></span>
|
||||||
@@ -405,4 +407,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/hedge_plan.js?v=49"></script>
|
<script src="/static/hedge_plan.js?v=50"></script>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ DEFAULT_INSTANCE_DISPLAY: dict[str, bool] = {
|
|||||||
"show_nav_options": True,
|
"show_nav_options": True,
|
||||||
"show_nav_options_review": True,
|
"show_nav_options_review": True,
|
||||||
"show_nav_hedge_plan": True,
|
"show_nav_hedge_plan": True,
|
||||||
"show_settings_transfer": True,
|
"show_settings_transfer": False, # CoinOX 不需要永续自动划转
|
||||||
"show_settings_export": True,
|
"show_settings_export": True,
|
||||||
"show_settings_password": True,
|
"show_settings_password": True,
|
||||||
"show_settings_options_swap": False, # CoinOX 已移除 USDT↔USDC 兑换
|
"show_settings_options_swap": False, # CoinOX 已移除 USDT↔USDC 兑换
|
||||||
@@ -87,6 +87,7 @@ def normalize_display_prefs(raw: dict | None) -> dict[str, bool]:
|
|||||||
out["show_nav_strategy_records"] = False
|
out["show_nav_strategy_records"] = False
|
||||||
out["show_nav_system_guide"] = False
|
out["show_nav_system_guide"] = False
|
||||||
out["show_settings_options_swap"] = False
|
out["show_settings_options_swap"] = False
|
||||||
|
out["show_settings_transfer"] = False
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
@@ -138,7 +139,6 @@ def display_meta_for_ui() -> list[dict[str, Any]]:
|
|||||||
"show_nav_env_config",
|
"show_nav_env_config",
|
||||||
]
|
]
|
||||||
settings_keys = [
|
settings_keys = [
|
||||||
"show_settings_transfer",
|
|
||||||
"show_settings_export",
|
"show_settings_export",
|
||||||
"show_settings_password",
|
"show_settings_password",
|
||||||
"show_settings_options_transfer",
|
"show_settings_options_transfer",
|
||||||
|
|||||||
Reference in New Issue
Block a user