期期: green index after lower target, USDC transfer, clearer selected state.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-19 08:16:44 +08:00
parent 79420904f4
commit 3093d07167
3 changed files with 182 additions and 12 deletions
+75 -3
View File
@@ -32,6 +32,7 @@
ooCloseModeEnabled: root.getAttribute("data-oo-close-mode-enabled") !== "0",
ooCloseMode: "close_all",
tradingUsdc: null,
fundingUsdc: null,
tradeBudgetUsdc: null,
budgetBuffer: 0.95,
};
@@ -185,6 +186,9 @@
if (acct.trading_usdc != null && acct.trading_usdc !== "") {
state.tradingUsdc = Number(acct.trading_usdc);
}
if (acct.funding_usdc != null && acct.funding_usdc !== "") {
state.fundingUsdc = Number(acct.funding_usdc);
}
if (chain && chain.trade_budget_usdc != null && chain.trade_budget_usdc !== "") {
state.tradeBudgetUsdc = Number(chain.trade_budget_usdc);
}
@@ -200,11 +204,49 @@
fmt(acct.funding_usdc, 2);
const el = $("hp-opt-bal-line");
if (el) el.textContent = line;
const oo = $("hp-oo-bal-line");
if (oo) oo.textContent = line;
const fundEl = $("hp-oo-funding-usdc");
const tradeEl = $("hp-oo-trading-usdc");
if (fundEl) fundEl.textContent = fmt(acct.funding_usdc, 2);
if (tradeEl) tradeEl.textContent = fmt(acct.trading_usdc, 2);
autoFillOoSheets();
}
function setOoXferMsg(text, kind) {
const el = $("hp-oo-xfer-msg");
if (!el) return;
el.textContent = text || "";
el.classList.toggle("is-err", kind === "err");
el.classList.toggle("is-ok", kind === "ok");
}
function ooXferDir() {
const sel = $("hp-oo-xfer-dir");
return (sel && sel.value) || "funding_to_trading";
}
async function submitOoUsdcTransfer(amount) {
const dir = ooXferDir();
const from = dir === "trading_to_funding" ? "trading" : "funding";
const to = dir === "trading_to_funding" ? "funding" : "trading";
setOoXferMsg("划转中…", null);
try {
const d = await apiJson("/api/options/transfer", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ccy: "USDC", from: from, to: to, amount: amount }),
});
if (!d.ok) {
setOoXferMsg(d.msg || "划转失败", "err");
return;
}
setOoXferMsg("划转成功", "ok");
if ($("hp-oo-xfer-amount")) $("hp-oo-xfer-amount").value = "";
await loadChain();
} catch (e) {
setOoXferMsg(e.message || "划转失败", "err");
}
}
function resolveOoBudget() {
const buf = state.budgetBuffer > 0 ? state.budgetBuffer : 0.95;
const trading = state.tradingUsdc;
@@ -294,6 +336,8 @@
document.querySelectorAll(".hp-oo-size-mode").forEach(function (b) {
const on = b.getAttribute("data-oo-size") === state.ooSheetsMode;
b.classList.toggle("active", on);
b.classList.toggle("is-selected", on);
b.setAttribute("aria-pressed", on ? "true" : "false");
});
}
@@ -305,6 +349,8 @@
document.querySelectorAll(".hp-oo-close-mode").forEach(function (b) {
const on = b.getAttribute("data-oo-close") === state.ooCloseMode;
b.classList.toggle("active", on);
b.classList.toggle("is-selected", on);
b.setAttribute("aria-pressed", on ? "true" : "false");
});
}
@@ -515,7 +561,7 @@
"指数 " + uly + " " + fmt(d.index_px, 2) + " · " + (d.inst_family || "") + " · 实值含平值";
}
const ooIdx = $("hp-oo-index");
if (ooIdx) ooIdx.textContent = "指数 " + uly + " " + fmt(d.index_px, 2);
if (ooIdx) ooIdx.textContent = "指数 " + fmt(d.index_px, 2);
setOptionsBalance(d);
fillExpSelect($("hp-exp-select"), d);
fillExpSelect($("hp-oo-exp-select"), d);
@@ -992,6 +1038,32 @@
updateOoBudgetLine(null);
});
});
if ($("hp-oo-xfer-btn")) {
$("hp-oo-xfer-btn").addEventListener("click", function () {
const amount = Number(($("hp-oo-xfer-amount") && $("hp-oo-xfer-amount").value) || 0);
if (!(amount > 0)) {
setOoXferMsg("请输入有效数量", "err");
return;
}
void submitOoUsdcTransfer(amount);
});
}
if ($("hp-oo-xfer-all")) {
$("hp-oo-xfer-all").addEventListener("click", function () {
const dir = ooXferDir();
const max =
dir === "trading_to_funding" ? Number(state.tradingUsdc || 0) : Number(state.fundingUsdc || 0);
if (!(max > 0)) {
setOoXferMsg("划出账户可用余额不足", "err");
return;
}
const amt = Math.floor(max * 100) / 100;
const label = dir === "trading_to_funding" ? "交易 → 资金" : "资金 → 交易";
if (!window.confirm("确认全部划转?\n方向:" + label + "\n数量:" + amt + " USDC")) return;
if ($("hp-oo-xfer-amount")) $("hp-oo-xfer-amount").value = String(amt);
void submitOoUsdcTransfer(amt);
});
}
if ($("hp-preview-btn"))
$("hp-preview-btn").addEventListener("click", function () {
state.mode = "perp_options";
+82 -1
View File
@@ -3258,6 +3258,70 @@ html[data-theme="light"] .opt-be-dist-down {
flex-direction: column;
gap: 8px;
}
.hedge-plan-page-wrap .hp-oo-target-row {
align-items: flex-end;
flex-wrap: wrap;
gap: 10px 14px;
}
.hedge-plan-page-wrap .hp-oo-index {
display: inline-flex;
align-items: center;
margin: 0 0 2px;
padding: 4px 0;
font-size: 0.9rem;
font-weight: 700;
font-variant-numeric: tabular-nums;
color: #3dd68c;
white-space: nowrap;
}
.hedge-plan-page-wrap .hp-oo-transfer {
margin: 10px 0 4px;
padding: 10px 12px;
border-radius: 8px;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.06);
}
.hedge-plan-page-wrap .hp-oo-transfer-bals {
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 6px 8px;
margin-bottom: 8px;
font-size: 0.78rem;
}
.hedge-plan-page-wrap .hp-oo-transfer-bals strong {
color: var(--text, #e6edf3);
font-variant-numeric: tabular-nums;
}
.hedge-plan-page-wrap .hp-oo-transfer-unit {
opacity: 0.75;
}
.hedge-plan-page-wrap .hp-oo-transfer-form {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
margin: 0;
}
.hedge-plan-page-wrap .hp-oo-transfer-form select,
.hedge-plan-page-wrap .hp-oo-transfer-form input[type="number"] {
font-size: 0.74rem;
}
.hedge-plan-page-wrap .hp-oo-transfer-form input[type="number"] {
width: 96px;
max-width: 30vw;
}
.hedge-plan-page-wrap .hp-oo-transfer-msg {
margin: 6px 0 0;
font-size: 0.72rem;
min-height: 1.1em;
}
.hedge-plan-page-wrap .hp-oo-transfer-msg.is-err {
color: #ff8a8a;
}
.hedge-plan-page-wrap .hp-oo-transfer-msg.is-ok {
color: #3dd68c;
}
.hedge-plan-page-wrap .hp-oo-controls {
display: grid;
grid-template-columns: 1fr 1fr;
@@ -3289,12 +3353,29 @@ html[data-theme="light"] .opt-be-dist-down {
min-width: 4.5em;
justify-content: center;
padding: 5px 8px;
position: relative;
}
.hedge-plan-page-wrap .hp-oo-check {
display: none;
margin-right: 4px;
font-weight: 700;
}
.hedge-plan-page-wrap .hp-oo-size-mode.is-selected,
.hedge-plan-page-wrap .hp-oo-close-mode.is-selected,
.hedge-plan-page-wrap .hp-oo-size-mode.active,
.hedge-plan-page-wrap .hp-oo-close-mode.active {
border-color: var(--accent, #00d4ff);
color: var(--text, #fff);
background: rgba(0, 212, 255, 0.12);
background: rgba(0, 212, 255, 0.16);
box-shadow: inset 0 0 0 1px rgba(0, 212, 255, 0.35);
font-weight: 700;
}
.hedge-plan-page-wrap .hp-oo-size-mode.is-selected .hp-oo-check,
.hedge-plan-page-wrap .hp-oo-close-mode.is-selected .hp-oo-check,
.hedge-plan-page-wrap .hp-oo-size-mode.active .hp-oo-check,
.hedge-plan-page-wrap .hp-oo-close-mode.active .hp-oo-check {
display: inline;
color: var(--accent, #00d4ff);
}
.hedge-plan-page-wrap #hp-oo-close-mode-row.hidden {
display: none !important;
+25 -8
View File
@@ -132,25 +132,42 @@
<button type="button" class="btn-secondary hp-uly-btn-oo active" data-uly="ETH">ETH</button>
<button type="button" class="btn-secondary hp-uly-btn-oo" data-uly="BTC">BTC</button>
</div>
<div class="form-row hp-target-row">
<div class="form-row hp-target-row hp-oo-target-row">
<label>上破目标 <input type="number" step="any" id="hp-target-up" placeholder="向上突破" /></label>
<label>下破目标 <input type="number" step="any" id="hp-target-down" placeholder="向下突破" /></label>
<span id="hp-oo-index" class="hp-oo-index" aria-live="polite">指数 —</span>
</div>
<div class="hp-oo-transfer" id="hp-oo-transfer">
<div class="hp-oo-transfer-bals muted">
<span>资金 <strong id="hp-oo-funding-usdc"></strong></span>
<span class="hp-oo-transfer-sep">·</span>
<span>交易 <strong id="hp-oo-trading-usdc"></strong></span>
<span class="hp-oo-transfer-unit">USDC</span>
</div>
<div class="form-row hp-oo-transfer-form">
<select id="hp-oo-xfer-dir" aria-label="划转方向">
<option value="funding_to_trading" selected>资金 → 交易</option>
<option value="trading_to_funding">交易 → 资金</option>
</select>
<input type="number" id="hp-oo-xfer-amount" min="0.01" step="0.01" placeholder="数量" />
<button type="button" class="btn-secondary btn-sm" id="hp-oo-xfer-all">全部</button>
<button type="button" class="btn-primary btn-sm" id="hp-oo-xfer-btn">划转</button>
</div>
<p class="muted hp-oo-transfer-msg" id="hp-oo-xfer-msg"></p>
</div>
<div id="hp-oo-index" class="muted hp-quote-line"></div>
<div id="hp-oo-bal-line" class="muted hp-quote-line"></div>
<div class="hp-oo-controls">
<div class="hp-oo-ctrl">
<span class="hp-oo-ctrl-lab">张数</span>
<div class="hp-oo-seg" role="group" aria-label="自动张数">
<button type="button" class="btn-secondary hp-oo-size-mode active" data-oo-size="same_sheets" title="两腿同张数,总权利金≤预算">同张数</button>
<button type="button" class="btn-secondary hp-oo-size-mode" data-oo-size="split_budget" title="预算对半拆到两腿">均分</button>
<button type="button" class="btn-secondary hp-oo-size-mode is-selected" data-oo-size="same_sheets" title="两腿同张数,总权利金≤预算"><span class="hp-oo-check" aria-hidden="true"></span>同张数</button>
<button type="button" class="btn-secondary hp-oo-size-mode" data-oo-size="split_budget" title="预算对半拆到两腿"><span class="hp-oo-check" aria-hidden="true"></span>均分</button>
</div>
</div>
<div class="hp-oo-ctrl" id="hp-oo-close-mode-row">
<span class="hp-oo-ctrl-lab" title="仅控制盈利腿平掉后的另一腿">平仓</span>
<div class="hp-oo-seg" role="group" aria-label="平仓模式">
<button type="button" class="btn-secondary hp-oo-close-mode active" data-oo-close="close_all" title="盈利腿平后立刻买一清另一腿(无2×,失败重试)">全平</button>
<button type="button" class="btn-secondary hp-oo-close-mode" data-oo-close="hold_expiry" title="盈利腿平后另一腿持有至到期">到期平</button>
<button type="button" class="btn-secondary hp-oo-close-mode is-selected" data-oo-close="close_all" title="盈利腿平后立刻买一清另一腿(无2×,失败重试)"><span class="hp-oo-check" aria-hidden="true"></span>全平</button>
<button type="button" class="btn-secondary hp-oo-close-mode" data-oo-close="hold_expiry" title="盈利腿平后另一腿持有至到期"><span class="hp-oo-check" aria-hidden="true"></span>到期平</button>
</div>
</div>
</div>
@@ -281,4 +298,4 @@
</div>
</div>
</div>
<script src="/static/hedge_plan.js?v=17"></script>
<script src="/static/hedge_plan.js?v=18"></script>