Default options chain to ATM plus 3 ITM and 3 OTM.

Apply the same window in list and T views; expand-all remains available on both.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-06 08:55:34 +08:00
parent 7f22bffbc6
commit 25ed46e3f2
2 changed files with 66 additions and 9 deletions
+63 -6
View File
@@ -352,7 +352,7 @@
const typeGroup = document.getElementById("opt-type-btn-group");
if (typeGroup) typeGroup.hidden = isT;
const expandWrap = document.getElementById("opt-strike-expand-wrap");
if (expandWrap) expandWrap.hidden = !isT;
if (expandWrap) expandWrap.hidden = false;
const headList = document.getElementById("opt-strike-head-list");
const headT = document.getElementById("opt-strike-head-t");
const headTCols = document.getElementById("opt-strike-head-t-cols");
@@ -472,16 +472,59 @@
});
}
// 默认窗口:平值 + 实值 3 档 + 虚值 3 档(T 型按行权价 ATM±3)
const DEFAULT_ATM_SIDE = 3;
function sliceAtmWindow(rows, indexPx) {
if (state.strikeExpandAll || !rows.length) return rows;
const atmStrike = findAtmStrike(rows, indexPx);
const idx = rows.findIndex(function (r) { return Number(r.strike) === Number(atmStrike); });
if (idx < 0) return rows.slice(0, Math.min(rows.length, 11));
const start = Math.max(0, idx - 5);
const end = Math.min(rows.length, idx + 6);
const side = DEFAULT_ATM_SIDE;
if (idx < 0) return rows.slice(0, Math.min(rows.length, side * 2 + 1));
const start = Math.max(0, idx - side);
const end = Math.min(rows.length, idx + side + 1);
return rows.slice(start, end);
}
function sliceListByMoneyness(list) {
if (state.strikeExpandAll || !list.length) return list;
const sorted = list.slice().sort(function (a, b) {
return Number(a.strike) - Number(b.strike);
});
const itm = [];
const atm = [];
const otm = [];
sorted.forEach(function (c) {
const m = String(c.moneyness || "").toLowerCase();
if (m === "atm") atm.push(c);
else if (m === "itm") itm.push(c);
else if (m === "otm") otm.push(c);
});
if (!atm.length && !itm.length && !otm.length) {
const indexPx = state.chain && state.chain.index_px;
return sliceAtmWindow(
sorted.map(function (c) { return { strike: c.strike, _c: c }; }),
indexPx
).map(function (r) { return r._c; });
}
const n = DEFAULT_ATM_SIDE;
const isPut = String(state.optType || "").toUpperCase() === "P";
// Call: ITM 在下方取靠近 ATM 的末 N;OTM 取前 N。Put 相反。
const pickedItm = isPut ? itm.slice(0, n) : itm.slice(-n);
const pickedOtm = isPut ? otm.slice(-n) : otm.slice(0, n);
return pickedItm.concat(atm, pickedOtm).sort(function (a, b) {
return Number(a.strike) - Number(b.strike);
});
}
function strikeWindowHintHtml(cols) {
return (
'<td colspan="' +
cols +
'" class="muted opt-strike-hint">默认显示平值 + 实值3档 + 虚值3档 · 勾选「展开全部」查看该到期全部行权价</td>'
);
}
function straddleAskPerUnit(callAsk, putAsk) {
const c = Number(callAsk);
const p = Number(putAsk);
@@ -950,7 +993,8 @@
state.selectedInst = null;
return;
}
const list = filterChainContracts(exp.contracts);
let list = filterChainContracts(exp.contracts);
list = sliceListByMoneyness(list);
if (!list.length) {
const label = moneyFilterLabel();
const suffix = label ? label : optTypeLabel(state.optType);
@@ -961,11 +1005,18 @@
}
let matchedSelected = false;
const indexPx = state.chain && state.chain.index_px;
const atmStrike = findAtmStrike(
list.map(function (c) { return { strike: c.strike }; }),
indexPx
);
list.forEach(function (c) {
const tr = document.createElement("tr");
tr.className = "opt-strike-row";
tr.setAttribute("data-inst", c.inst_id);
if (c.moneyness) tr.classList.add("opt-row-" + c.moneyness);
if (atmStrike != null && Number(c.strike) === Number(atmStrike)) {
tr.classList.add("opt-strike-row-atm");
}
const chainLev = calcAskLeverage(indexPx, c.ask);
tr.innerHTML =
"<td>" + c.strike + "</td>" +
@@ -982,6 +1033,12 @@
tbody.appendChild(tr);
if (c.inst_id === prevSelected) matchedSelected = true;
});
if (!state.strikeExpandAll && list.length >= 1) {
const hint = document.createElement("tr");
hint.className = "opt-strike-hint-row";
hint.innerHTML = strikeWindowHintHtml(cols);
tbody.appendChild(hint);
}
finishStrikeRender(tbody, prevSelected, matchedSelected);
}
@@ -1046,7 +1103,7 @@
if (!state.strikeExpandAll && rows.length >= 1) {
const hint = document.createElement("tr");
hint.className = "opt-strike-hint-row";
hint.innerHTML = '<td colspan="' + cols + '" class="muted opt-strike-hint">默认显示 ATM ±5 档 · 勾选「展开全部」查看该到期全部行权价</td>';
hint.innerHTML = strikeWindowHintHtml(cols);
tbody.appendChild(hint);
}
finishStrikeRender(tbody, prevSelected, matchedSelected);