chore: restore codebase to state before 2026-08-11 changes
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+101
-190
@@ -37,15 +37,9 @@
|
||||
let selectSeq = 0;
|
||||
let refreshAllTimer = null;
|
||||
let pendingRefreshTimer = null;
|
||||
let chainSoftTimer = null;
|
||||
let lastChainSoftAt = 0;
|
||||
let chainQuotedAt = 0;
|
||||
let chainLoadInFlight = false;
|
||||
let pendingTtlSeconds = 600;
|
||||
const POSITIONS_STALE_MS = 45000;
|
||||
const PENDING_POLL_MS = 8000;
|
||||
/** 链卖一/买一静默刷新节流:无推送,靠拉;过密会撞 OKX 50011 */
|
||||
const CHAIN_SOFT_POLL_MS = 15000;
|
||||
const orderPanelHome = (function () {
|
||||
const host = document.getElementById("opt-order-panel-host");
|
||||
return host ? host.parentElement : null;
|
||||
@@ -327,7 +321,7 @@
|
||||
[
|
||||
"opt-sheets-amount",
|
||||
"opt-eth-amount",
|
||||
"opt-profit-rr",
|
||||
"opt-target-idx",
|
||||
].forEach(function (id) {
|
||||
harden(document.getElementById(id));
|
||||
});
|
||||
@@ -638,15 +632,6 @@
|
||||
if (el) el.textContent = fmt(buf, 2);
|
||||
}
|
||||
|
||||
function fmtChainQuotedAt() {
|
||||
if (!chainQuotedAt) return "";
|
||||
const d = new Date(chainQuotedAt);
|
||||
const pad = function (n) {
|
||||
return n < 10 ? "0" + n : String(n);
|
||||
};
|
||||
return pad(d.getHours()) + ":" + pad(d.getMinutes()) + ":" + pad(d.getSeconds());
|
||||
}
|
||||
|
||||
function renderIndexLine() {
|
||||
const idx = state.chain && state.chain.index_px;
|
||||
const dte = state.chain && state.chain.chain_max_dte_days;
|
||||
@@ -660,37 +645,12 @@
|
||||
const line = document.getElementById("opt-index-line");
|
||||
if (line) {
|
||||
const liqHint = askLiqFilterOn() ? "仅显示卖一深度≥1张" : "显示全部卖一(含估算~)";
|
||||
const ageHint = chainQuotedAt ? " · 链报价 " + fmtChainQuotedAt() + "(约每15s静默刷新)" : "";
|
||||
line.textContent =
|
||||
"指数 " + state.underlying + " ≈ " + fmt(idx, 2) +
|
||||
" · 默认最近一期 · " + liqHint + " · 实值含平值 · 虚值=价外" + ageHint;
|
||||
" · 默认最近一期 · " + liqHint + " · 实值含平值 · 虚值=价外";
|
||||
}
|
||||
}
|
||||
|
||||
function softRefreshChainThrottled(force) {
|
||||
if (document.hidden) return;
|
||||
if (!document.getElementById("options-root")) return;
|
||||
if (chainLoadInFlight) return;
|
||||
const now = Date.now();
|
||||
if (!force && now - lastChainSoftAt < CHAIN_SOFT_POLL_MS) return;
|
||||
lastChainSoftAt = now;
|
||||
void loadChain({ soft: true });
|
||||
}
|
||||
|
||||
function startChainSoftPoll() {
|
||||
if (chainSoftTimer) return;
|
||||
chainSoftTimer = setInterval(function () {
|
||||
if (!document.getElementById("options-root")) {
|
||||
if (chainSoftTimer) {
|
||||
clearInterval(chainSoftTimer);
|
||||
chainSoftTimer = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
softRefreshChainThrottled(false);
|
||||
}, CHAIN_SOFT_POLL_MS);
|
||||
}
|
||||
|
||||
function pickNearestExpiry(exps) {
|
||||
if (!exps || !exps.length) return "";
|
||||
const now = Date.now();
|
||||
@@ -934,10 +894,11 @@
|
||||
}
|
||||
|
||||
function updateOrderEstimates() {
|
||||
const levEl = document.getElementById("opt-order-leverage");
|
||||
const valueEl = document.getElementById("opt-est-value");
|
||||
const profitEl = document.getElementById("opt-est-profit");
|
||||
const levEl = document.getElementById("opt-order-leverage");
|
||||
const rrEl = document.getElementById("opt-profit-rr");
|
||||
const targetLevEl = document.getElementById("opt-est-leverage");
|
||||
const targetEl = document.getElementById("opt-target-idx");
|
||||
const q = state.orderQuote;
|
||||
if (!q || !q.ok || !q.can_open) {
|
||||
if (levEl) levEl.textContent = "—";
|
||||
@@ -946,6 +907,7 @@
|
||||
profitEl.textContent = "—";
|
||||
profitEl.className = "v";
|
||||
}
|
||||
if (targetLevEl) targetLevEl.textContent = "—";
|
||||
return;
|
||||
}
|
||||
const sz = q.sizing || {};
|
||||
@@ -954,19 +916,30 @@
|
||||
const lev = calcContractLeverage(q.index_px, ethAmount, premium);
|
||||
if (levEl) levEl.textContent = fmtLeverage(lev);
|
||||
|
||||
if (valueEl && profitEl && rrEl) {
|
||||
const rrRaw = rrEl.value;
|
||||
const rr = rrRaw === "" || rrRaw == null ? NaN : Number(rrRaw);
|
||||
if (!Number.isFinite(rr) || rr <= 0 || !(Number(premium) > 0)) {
|
||||
if (valueEl && profitEl && targetEl) {
|
||||
const targetRaw = targetEl.value;
|
||||
if (targetRaw === "" || targetRaw == null) {
|
||||
valueEl.textContent = "—";
|
||||
profitEl.textContent = "—";
|
||||
profitEl.className = "v";
|
||||
if (targetLevEl) targetLevEl.textContent = "—";
|
||||
} else {
|
||||
const targetProfit = Number(premium) * rr;
|
||||
const needRecycle = Number(premium) + targetProfit;
|
||||
valueEl.textContent = fmtUsdc(needRecycle) + " USDC";
|
||||
profitEl.textContent = fmtUsdcSigned(targetProfit);
|
||||
profitEl.className = "v " + pnlCls(targetProfit);
|
||||
const value = estimateExpiryValue(q.opt_type, q.strike, Number(targetRaw), ethAmount);
|
||||
const profit = estimateExpiryProfit(q.opt_type, q.strike, Number(targetRaw), ethAmount, premium);
|
||||
if (value == null || Number.isNaN(value)) {
|
||||
valueEl.textContent = "—";
|
||||
} else {
|
||||
valueEl.textContent = fmtUsdc(value) + " USDC";
|
||||
}
|
||||
if (profit == null || Number.isNaN(profit)) {
|
||||
profitEl.textContent = "—";
|
||||
profitEl.className = "v";
|
||||
} else {
|
||||
profitEl.textContent = fmtUsdcSigned(profit);
|
||||
profitEl.className = "v " + pnlCls(profit);
|
||||
}
|
||||
const targetLev = calcContractLeverage(Number(targetRaw), ethAmount, premium);
|
||||
if (targetLevEl) targetLevEl.textContent = fmtLeverage(targetLev);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1241,16 +1214,11 @@
|
||||
|
||||
async function loadChain(opts) {
|
||||
const soft = !!(opts && opts.soft);
|
||||
// soft 门禁必须在 seq++ 之前,否则叠刷会抬高 seq 导致 inFlight 永不清理
|
||||
if (chainLoadInFlight && soft) return;
|
||||
const uly = state.underlying;
|
||||
const seq = ++chainLoadSeq;
|
||||
const btn = document.getElementById("opt-load-chain");
|
||||
const hadChain = chainHasExpiries(state.chain) && state.chain.underlying === uly;
|
||||
chainLoadInFlight = true;
|
||||
if (btn && !soft) btn.disabled = true;
|
||||
// 已有链时不先清空,避免刷新白屏
|
||||
if (!soft && !hadChain) {
|
||||
if (!soft) {
|
||||
setExpirySelectStatus("加载到期日中…");
|
||||
const tbody = document.getElementById("opt-strike-tbody");
|
||||
if (tbody) {
|
||||
@@ -1261,27 +1229,16 @@
|
||||
try {
|
||||
let d = null;
|
||||
let lastMsg = "";
|
||||
// soft 只试 1 次,避免与 15s 轮询叠加重试打爆 OKX
|
||||
const maxAttempts = soft ? 1 : 3;
|
||||
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||
for (let attempt = 0; attempt < 2; attempt++) {
|
||||
if (seq !== chainLoadSeq) return;
|
||||
d = await apiJson("/api/options/chain?underlying=" + encodeURIComponent(uly));
|
||||
if (seq !== chainLoadSeq) return;
|
||||
if (d && d.ok && chainHasExpiries(d)) break;
|
||||
lastMsg = (d && (d.msg || d.chain_error)) || "暂无到期日";
|
||||
const rateLimited =
|
||||
!!(d && d.rate_limited) ||
|
||||
/50011|Too Many Requests|过于频繁/i.test(String(lastMsg || ""));
|
||||
d = null;
|
||||
if (attempt < maxAttempts - 1) {
|
||||
if (!soft && !hadChain) {
|
||||
setExpirySelectStatus(
|
||||
rateLimited ? "OKX 限频,稍后重试…" : "重试加载到期日…"
|
||||
);
|
||||
}
|
||||
await new Promise(function (resolve) {
|
||||
setTimeout(resolve, rateLimited ? 1200 * (attempt + 1) : 400);
|
||||
});
|
||||
if (attempt === 0) {
|
||||
if (!soft) setExpirySelectStatus("重试加载到期日…");
|
||||
await new Promise(function (resolve) { setTimeout(resolve, 400); });
|
||||
}
|
||||
}
|
||||
if (seq !== chainLoadSeq) return;
|
||||
@@ -1296,19 +1253,13 @@
|
||||
if (soft) return;
|
||||
setExpirySelectStatus("选择到期日");
|
||||
const tbody = document.getElementById("opt-strike-tbody");
|
||||
const friendly =
|
||||
/50011|Too Many Requests|过于频繁/i.test(String(lastMsg || ""))
|
||||
? "OKX 请求过于频繁,请稍后再点「刷新链」"
|
||||
: lastMsg || "暂无到期日,请点「刷新链」";
|
||||
if (tbody) {
|
||||
tbody.innerHTML =
|
||||
'<tr><td colspan="' +
|
||||
strikeTableColspan() +
|
||||
'" class="muted">' +
|
||||
friendly +
|
||||
'<tr><td colspan="' + strikeTableColspan() + '" class="muted">' +
|
||||
(lastMsg || "暂无到期日,请点「刷新链」") +
|
||||
"</td></tr>";
|
||||
}
|
||||
alert(friendly);
|
||||
alert(lastMsg || "加载到期日失败,请点「刷新链」重试");
|
||||
return;
|
||||
}
|
||||
const keepExp = soft ? (document.getElementById("opt-exp-select") || {}).value : "";
|
||||
@@ -1316,8 +1267,6 @@
|
||||
panelCache.chain = d;
|
||||
panelCache.underlying = uly;
|
||||
panelCache.optType = state.optType;
|
||||
chainQuotedAt = Date.now();
|
||||
lastChainSoftAt = chainQuotedAt;
|
||||
syncAskLiqFilterFromChain(d);
|
||||
if (!soft) {
|
||||
state.selectedInst = null;
|
||||
@@ -1348,10 +1297,7 @@
|
||||
"</td></tr>";
|
||||
}
|
||||
} finally {
|
||||
if (seq === chainLoadSeq) {
|
||||
chainLoadInFlight = false;
|
||||
if (btn) btn.disabled = false;
|
||||
}
|
||||
if (seq === chainLoadSeq && btn) btn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1383,13 +1329,15 @@
|
||||
} else if (mode === "sheets") {
|
||||
body.sheets = parseInt(document.getElementById("opt-sheets-amount").value, 10);
|
||||
}
|
||||
const rrRaw = (document.getElementById("opt-profit-rr").value || "").trim();
|
||||
const rr = rrRaw === "" ? 2 : parseFloat(rrRaw);
|
||||
if (!Number.isFinite(rr) || rr <= 0) {
|
||||
alert("盈亏比无效");
|
||||
return false;
|
||||
const tgtRaw = (document.getElementById("opt-target-idx").value || "").trim();
|
||||
if (tgtRaw !== "") {
|
||||
const tgt = parseFloat(tgtRaw);
|
||||
if (!Number.isFinite(tgt) || tgt <= 0) {
|
||||
alert("目标位无效");
|
||||
return false;
|
||||
}
|
||||
body.target_index = tgt;
|
||||
}
|
||||
body.profit_rr = rr;
|
||||
const d = await apiJson("/api/options/open", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -1480,17 +1428,15 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
function formatRrEstimateHtml(rr, premiumPaid) {
|
||||
const r = Number(rr);
|
||||
const prem = Number(premiumPaid);
|
||||
if (!Number.isFinite(r) || r <= 0 || !Number.isFinite(prem) || prem <= 0) return "";
|
||||
const profit = Math.round(prem * r * 100) / 100;
|
||||
const need = Math.round((prem + profit) * 100) / 100;
|
||||
function formatTargetEstimateHtml(optType, strike, targetIdx, ethAmount, premiumPaid) {
|
||||
const value = estimateExpiryValue(optType, strike, targetIdx, ethAmount);
|
||||
const profit = estimateExpiryProfit(optType, strike, targetIdx, ethAmount, premiumPaid);
|
||||
if (value == null && profit == null) return "";
|
||||
let html = '<span class="opt-target-est">';
|
||||
html += '<span class="opt-target-est-item"><span class="k">目标盈利</span><span class="v ' + pnlCls(profit) + '">' +
|
||||
fmtUsdcSigned(profit) + "</span></span>";
|
||||
html += '<span class="opt-target-est-item"><span class="k">需回收</span><span class="v">' +
|
||||
fmtUsdc(need) + " USDC</span></span>";
|
||||
html += '<span class="opt-target-est-item"><span class="k">价值</span><span class="v">' +
|
||||
(value == null ? "—" : fmtUsdc(value) + " USDC") + "</span></span>";
|
||||
html += '<span class="opt-target-est-item"><span class="k">预估盈利</span><span class="v ' + pnlCls(profit) + '">' +
|
||||
(profit == null ? "—" : fmtUsdcSigned(profit)) + "</span></span>";
|
||||
html += "</span>";
|
||||
return html;
|
||||
}
|
||||
@@ -1498,73 +1444,47 @@
|
||||
function renderTargetDelegateRow(p) {
|
||||
const inst = p.inst_id || "";
|
||||
const hedgeTarget = p.hedge_plan_target || null;
|
||||
if (hedgeTarget && hedgeTarget.managed_by === "hedge_plan") {
|
||||
const rr = hedgeTarget.oo_profit_rr != null ? Number(hedgeTarget.oo_profit_rr) : null;
|
||||
const armedTxt =
|
||||
rr != null && Number.isFinite(rr) && rr > 0
|
||||
? "盈亏比 ×" + fmt(rr, 2)
|
||||
: hedgeTarget.target_index != null
|
||||
? "目标 " + fmt(hedgeTarget.target_index, 1)
|
||||
: "托管中";
|
||||
if (hedgeTarget && Number(hedgeTarget.target_index) > 0) {
|
||||
const side = (p.opt_type || hedgeTarget.opt_type || "").toUpperCase() === "P" ? "Put ≤" : "Call ≥";
|
||||
return (
|
||||
'<div class="opt-target-row opt-target-row--managed">' +
|
||||
'<span class="opt-target-row-label">对冲计划</span>' +
|
||||
'<span class="opt-target-armed">计划 #' +
|
||||
hedgeTarget.plan_id +
|
||||
" · " +
|
||||
armedTxt +
|
||||
side +
|
||||
" " +
|
||||
fmt(hedgeTarget.target_index, 1) +
|
||||
"</span>" +
|
||||
'<span class="muted opt-target-row-hint">进行中 · 由对冲计划监控</span>' +
|
||||
'<span class="muted opt-target-row-hint">进行中 · 由对冲计划监控,到位后仅平盈利腿</span>' +
|
||||
"</div>"
|
||||
);
|
||||
}
|
||||
const rrArmed =
|
||||
p.profit_rr != null && p.profit_rr !== ""
|
||||
? Number(p.profit_rr)
|
||||
: p.target_monitor && p.target_monitor.profit_rr != null
|
||||
? Number(p.target_monitor.profit_rr)
|
||||
: null;
|
||||
const armed = rrArmed != null && Number.isFinite(rrArmed) && rrArmed > 0;
|
||||
const tgt = p.target_index != null && p.target_index !== "" ? Number(p.target_index) : null;
|
||||
const armed = tgt != null && Number.isFinite(tgt) && tgt > 0;
|
||||
const ethAmt = posEthAmount(p);
|
||||
const prem = p.premium_paid;
|
||||
const draft =
|
||||
state.targetDraftByInst[inst] != null
|
||||
? String(state.targetDraftByInst[inst])
|
||||
: armed
|
||||
? String(rrArmed)
|
||||
: "2";
|
||||
const estHtml = armed
|
||||
? formatRrEstimateHtml(rrArmed, prem)
|
||||
? formatTargetEstimateHtml(p.opt_type, p.strike, tgt, ethAmt, prem)
|
||||
: '<span class="opt-target-est opt-target-est--idle"></span>';
|
||||
return (
|
||||
'<div class="opt-target-row" data-inst="' +
|
||||
inst +
|
||||
'"' +
|
||||
' data-prem="' +
|
||||
(prem != null ? prem : "") +
|
||||
'"' +
|
||||
' data-armed-rr="' +
|
||||
(armed ? rrArmed : "") +
|
||||
'">' +
|
||||
'<div class="opt-target-row" data-inst="' + inst + '"' +
|
||||
' data-opt-type="' + (p.opt_type || "") + '"' +
|
||||
' data-strike="' + (p.strike != null ? p.strike : "") + '"' +
|
||||
' data-eth="' + (ethAmt != null ? ethAmt : "") + '"' +
|
||||
' data-prem="' + (prem != null ? prem : "") + '"' +
|
||||
' data-armed-target="' + (armed ? tgt : "") + '">' +
|
||||
'<span class="opt-target-row-label">委托</span>' +
|
||||
'<input type="number" class="opt-pos-target-input" data-inst="' +
|
||||
inst +
|
||||
'" step="0.1" min="0.1" placeholder="盈亏比" value="' +
|
||||
draft +
|
||||
'">' +
|
||||
'<button type="button" class="btn-secondary opt-target-set-btn" data-inst="' +
|
||||
inst +
|
||||
'">设定</button>' +
|
||||
'<button type="button" class="btn-secondary opt-target-cancel-btn" data-inst="' +
|
||||
inst +
|
||||
'"' +
|
||||
(armed ? "" : " disabled") +
|
||||
">取消</button>" +
|
||||
(armed ? '<span class="opt-target-armed">盈亏比 ×' + fmt(rrArmed, 2) + "</span>" : "") +
|
||||
'<input type="number" class="opt-pos-target-input" data-inst="' + inst + '" step="0.1" min="0" placeholder="监控目标指数" value="' +
|
||||
(state.targetDraftByInst[inst] != null ? String(state.targetDraftByInst[inst]) : "") + '">' +
|
||||
'<button type="button" class="btn-secondary opt-target-set-btn" data-inst="' + inst + '">设定</button>' +
|
||||
'<button type="button" class="btn-secondary opt-target-cancel-btn" data-inst="' + inst + '"' + (armed ? "" : " disabled") + ">取消</button>" +
|
||||
(armed
|
||||
? '<span class="opt-target-armed">目标 ' + fmt(tgt, 1) + "</span>"
|
||||
: "") +
|
||||
estHtml +
|
||||
'<span class="muted opt-target-row-hint">' +
|
||||
(armed
|
||||
? "监控中 · 买一浮盈达盈亏比后全平"
|
||||
: "默认2 · 买一浮盈达盈亏比×权利金后全平 · 不达标等到期") +
|
||||
(armed ? "监控中 · 到位按买一限价平" : "输入后设定 · 到位按买一限价平 · 到期即止损") +
|
||||
"</span>" +
|
||||
"</div>"
|
||||
);
|
||||
@@ -1576,14 +1496,20 @@
|
||||
if (!est) return;
|
||||
const inp = row.querySelector(".opt-pos-target-input");
|
||||
const typed = inp ? String(inp.value || "").trim() : "";
|
||||
const armed = row.getAttribute("data-armed-rr") || "";
|
||||
const rrRaw = typed !== "" ? typed : armed;
|
||||
if (rrRaw === "") {
|
||||
const armed = row.getAttribute("data-armed-target") || "";
|
||||
const targetRaw = typed !== "" ? typed : armed;
|
||||
if (targetRaw === "") {
|
||||
est.className = "opt-target-est opt-target-est--idle";
|
||||
est.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
const html = formatRrEstimateHtml(rrRaw, row.getAttribute("data-prem"));
|
||||
const html = formatTargetEstimateHtml(
|
||||
row.getAttribute("data-opt-type"),
|
||||
row.getAttribute("data-strike"),
|
||||
targetRaw,
|
||||
row.getAttribute("data-eth"),
|
||||
row.getAttribute("data-prem")
|
||||
);
|
||||
if (!html) {
|
||||
est.className = "opt-target-est opt-target-est--idle";
|
||||
est.innerHTML = "";
|
||||
@@ -1715,9 +1641,9 @@
|
||||
const row = card ? card.querySelector(".opt-target-row") : null;
|
||||
const inp = card ? card.querySelector(".opt-pos-target-input") : null;
|
||||
const raw = inp ? String(inp.value || "").trim() : "";
|
||||
const rr = raw === "" ? 2 : parseFloat(raw);
|
||||
if (!Number.isFinite(rr) || rr <= 0) {
|
||||
alert("请输入有效盈亏比(相对权利金,默认2)");
|
||||
const tgt = parseFloat(raw);
|
||||
if (!Number.isFinite(tgt) || tgt <= 0) {
|
||||
alert("请输入有效目标指数价");
|
||||
return;
|
||||
}
|
||||
if (btn) btn.disabled = true;
|
||||
@@ -1725,16 +1651,17 @@
|
||||
const d = await apiJson("/api/options/target", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ inst_id: inst, profit_rr: rr }),
|
||||
body: JSON.stringify({ inst_id: inst, target_index: tgt }),
|
||||
});
|
||||
if (!d.ok) {
|
||||
alert(d.msg || "设定失败");
|
||||
return;
|
||||
}
|
||||
delete state.targetDraftByInst[inst];
|
||||
if (inp) inp.value = String(rr);
|
||||
if (inp) inp.value = "";
|
||||
if (row) {
|
||||
row.setAttribute("data-armed-rr", String(rr));
|
||||
row.setAttribute("data-armed-target", String(tgt));
|
||||
updatePosTargetEstimate(row);
|
||||
}
|
||||
await refreshAllPositions();
|
||||
} finally {
|
||||
@@ -1774,22 +1701,12 @@
|
||||
}
|
||||
box.hidden = false;
|
||||
host.innerHTML = rows.map(function (t) {
|
||||
const side = (t.opt_type || "").toUpperCase() === "P" ? "Put ≤" : "Call ≥";
|
||||
const managed = t.managed_by === "hedge_plan";
|
||||
let rule;
|
||||
if (t.profit_rr != null && Number(t.profit_rr) > 0) {
|
||||
rule = "盈亏比 ×" + fmt(t.profit_rr, 2);
|
||||
} else if (t.oo_profit_rr != null && Number(t.oo_profit_rr) > 0) {
|
||||
rule = "盈亏比 ×" + fmt(t.oo_profit_rr, 2);
|
||||
} else if (t.target_index != null && Number(t.target_index) > 0) {
|
||||
const side = (t.opt_type || "").toUpperCase() === "P" ? "Put ≤" : "Call ≥";
|
||||
rule = side + " " + fmt(t.target_index, 1);
|
||||
} else {
|
||||
rule = "委托中";
|
||||
}
|
||||
return (
|
||||
'<div class="opt-target-mon-item' + (managed ? " opt-target-mon-item--managed" : "") + '">' +
|
||||
'<code class="opt-target-mon-inst" title="' + (t.inst_id || "") + '">' + (t.inst_id || "") + "</code>" +
|
||||
'<span class="opt-target-mon-rule">' + rule + "</span>" +
|
||||
'<span class="opt-target-mon-rule">' + side + " " + fmt(t.target_index, 1) + "</span>" +
|
||||
(managed
|
||||
? '<span class="opt-target-mon-managed">对冲计划 #' + (t.plan_id || "") + " · 进行中</span>"
|
||||
: '<button type="button" class="btn-secondary opt-target-mon-cancel" data-inst="' + (t.inst_id || "") + '">取消</button>') +
|
||||
@@ -1970,23 +1887,20 @@
|
||||
paintPositions(list);
|
||||
const fromPos = list.reduce(function (targets, p) {
|
||||
if (!p) return targets;
|
||||
if (p.profit_rr != null || p.target_index != null) {
|
||||
if (p.target_index != null) {
|
||||
targets.push({
|
||||
id: p.target_monitor_id,
|
||||
inst_id: p.inst_id,
|
||||
opt_type: p.opt_type,
|
||||
target_index: p.target_index,
|
||||
profit_rr: p.profit_rr,
|
||||
});
|
||||
}
|
||||
const hedgeTarget = p.hedge_plan_target;
|
||||
if (hedgeTarget) {
|
||||
if (hedgeTarget && hedgeTarget.target_index != null) {
|
||||
targets.push({
|
||||
inst_id: p.inst_id,
|
||||
opt_type: p.opt_type || hedgeTarget.opt_type,
|
||||
target_index: hedgeTarget.target_index,
|
||||
oo_profit_rr: hedgeTarget.oo_profit_rr,
|
||||
profit_rr: hedgeTarget.oo_profit_rr,
|
||||
plan_id: hedgeTarget.plan_id,
|
||||
managed_by: hedgeTarget.managed_by,
|
||||
});
|
||||
@@ -2258,7 +2172,6 @@
|
||||
updateUnderlyingLabel();
|
||||
refreshPendingOrders();
|
||||
startPendingOrdersPoll();
|
||||
startChainSoftPoll();
|
||||
const hasCache =
|
||||
chainHasExpiries(panelCache.chain) &&
|
||||
panelCache.underlying === state.underlying &&
|
||||
@@ -2268,8 +2181,8 @@
|
||||
renderExpiries();
|
||||
renderStrikes();
|
||||
refreshAllPositions();
|
||||
// 后台静默刷新,避免缓存过期后到期日变空 / 卖一过期
|
||||
softRefreshChainThrottled(true);
|
||||
// 后台静默刷新,避免缓存过期后到期日变空
|
||||
loadChain({ soft: true });
|
||||
return;
|
||||
}
|
||||
requestAnimationFrame(function () {
|
||||
@@ -2373,17 +2286,17 @@
|
||||
}
|
||||
bindOrderDialogChrome();
|
||||
|
||||
["opt-sheets-amount", "opt-eth-amount", "opt-profit-rr"].forEach(function (id) {
|
||||
["opt-sheets-amount", "opt-eth-amount", "opt-target-idx"].forEach(function (id) {
|
||||
const el = document.getElementById(id);
|
||||
if (!el) return;
|
||||
el.addEventListener("change", function () {
|
||||
if (id === "opt-profit-rr") {
|
||||
if (id === "opt-target-idx") {
|
||||
updateEstimatedProfit();
|
||||
return;
|
||||
}
|
||||
if (state.selectedInst) selectContract(state.selectedInst, null, true);
|
||||
});
|
||||
if (id === "opt-profit-rr") {
|
||||
if (id === "opt-target-idx") {
|
||||
el.addEventListener("input", updateEstimatedProfit);
|
||||
}
|
||||
});
|
||||
@@ -2393,8 +2306,6 @@
|
||||
window.OptionsPanelLive = {
|
||||
refreshSoft: function () {
|
||||
refreshAllPositions();
|
||||
// embed SSE 只通知「该拉了」,不推送链报价;这里节流拉新鲜卖一/买一
|
||||
softRefreshChainThrottled(false);
|
||||
},
|
||||
refreshChain: loadChain,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user