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:
@@ -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);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<li><strong>列表</strong>含卖一/买一;<strong>T 型</strong>仅卖一(买方开仓),中间为跨式双买测算。</li>
|
||||
<li>环境配置「链上仅显示有卖一」开启时,隐藏无真实卖一或深度不足 1 张的合约(估算价 <strong>~</strong> 亦不显示)。</li>
|
||||
<li><strong>开仓只认真实卖一价且卖一深度≥1</strong>;无深度时面板显示参考标记价并禁用买入。</li>
|
||||
<li>链展示近 <span id="opt-chain-dte">14</span> 日到期;<strong>T 型</strong>默认 ATM ±5 档,可展开全部。</li>
|
||||
<li>链展示近 <span id="opt-chain-dte">14</span> 日到期;列表与 T 型默认<strong>平值 + 实值3档 + 虚值3档</strong>,勾选「展开全部」看全部行权价。</li>
|
||||
<li>「按可用余额打满」可用额度 = min(交易户可用 USDC, 单笔预算 <strong id="opt-trade-budget">{{ '%.2f'|format(options_trade_budget|default(10)|float) }}</strong>),再 × 预算缓冲 <strong id="opt-budget-buf">{{ '%.2f'|format(options_budget_buffer|default(0.95)|float) }}</strong> 算张数(env 可改)。</li>
|
||||
<li>平仓仅买一限价,详见说明文档。</li>
|
||||
</ul>
|
||||
@@ -43,7 +43,7 @@
|
||||
<button type="button" class="btn-secondary opt-money-btn active" data-money="all">全部</button>
|
||||
<button type="button" class="btn-secondary opt-money-btn" data-money="itm">实值</button>
|
||||
<button type="button" class="btn-secondary opt-money-btn" data-money="otm">虚值</button>
|
||||
<label id="opt-strike-expand-wrap" class="opt-strike-expand-label" hidden>
|
||||
<label id="opt-strike-expand-wrap" class="opt-strike-expand-label">
|
||||
<input type="checkbox" id="opt-strike-expand-all"> 展开全部
|
||||
</label>
|
||||
<button type="button" class="btn-secondary" id="opt-load-chain">刷新链</button>
|
||||
@@ -324,4 +324,4 @@
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/options_expiry_countdown.js?v=1"></script>
|
||||
<script src="/static/options_panel.js?v=51"></script>
|
||||
<script src="/static/options_panel.js?v=52"></script>
|
||||
|
||||
Reference in New Issue
Block a user