Add hub strategy calculator page with trend and roll risk-based sizing.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6804,3 +6804,146 @@ body.funds-fullscreen-open {
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 策略计算器 ── */
|
||||
.calc-layout {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.calc-card {
|
||||
padding: 16px 18px;
|
||||
}
|
||||
|
||||
.calc-card h2 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 1rem;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.calc-hint {
|
||||
margin: 0 0 14px;
|
||||
font-size: 0.78rem;
|
||||
color: var(--muted);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.calc-form-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px 12px;
|
||||
}
|
||||
|
||||
.calc-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
font-size: 0.78rem;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.calc-field input,
|
||||
.calc-field select {
|
||||
background: var(--bg-elevated);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text);
|
||||
border-radius: 8px;
|
||||
padding: 8px 10px;
|
||||
font-size: 0.82rem;
|
||||
font-family: var(--mono);
|
||||
}
|
||||
|
||||
.calc-actions {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.calc-result {
|
||||
margin-top: 14px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid var(--border-soft);
|
||||
}
|
||||
|
||||
.calc-result.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.calc-summary {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 8px 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.calc-summary div {
|
||||
background: var(--bg-elevated);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: 8px;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.calc-summary span {
|
||||
display: block;
|
||||
font-size: 0.72rem;
|
||||
color: var(--muted);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.calc-summary strong {
|
||||
font-family: var(--mono);
|
||||
font-size: 0.86rem;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.calc-pnl-profit {
|
||||
color: var(--green) !important;
|
||||
}
|
||||
|
||||
.calc-pnl-loss {
|
||||
color: var(--red) !important;
|
||||
}
|
||||
|
||||
.calc-table-wrap {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.calc-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.calc-table th,
|
||||
.calc-table td {
|
||||
padding: 7px 8px;
|
||||
border-bottom: 1px solid var(--border-soft);
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.calc-table th {
|
||||
color: var(--muted);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.calc-error {
|
||||
color: var(--red);
|
||||
font-size: 0.82rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.calc-empty {
|
||||
color: var(--muted);
|
||||
font-size: 0.82rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.calc-layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.calc-form-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
return displayPref("show_nav_ai", true);
|
||||
}
|
||||
|
||||
function showNavCalculatorPref() {
|
||||
return displayPref("show_nav_calculator", true);
|
||||
}
|
||||
|
||||
function syncNavVisibility(data) {
|
||||
const d = (data && data.display) || {};
|
||||
const navFunds = document.getElementById("nav-funds");
|
||||
@@ -40,11 +44,13 @@
|
||||
const navPlan = document.getElementById("nav-plan");
|
||||
const navArchive = document.getElementById("nav-archive");
|
||||
const navAi = document.getElementById("nav-ai");
|
||||
const navCalc = document.getElementById("nav-calculator");
|
||||
if (navFunds) navFunds.classList.toggle("nav-hidden", d.show_nav_funds === false);
|
||||
if (navDash) navDash.classList.toggle("nav-hidden", d.show_nav_dashboard === false);
|
||||
if (navPlan) navPlan.classList.toggle("nav-hidden", d.show_nav_plan === false);
|
||||
if (navArchive) navArchive.classList.toggle("nav-hidden", d.show_nav_archive === false);
|
||||
if (navAi) navAi.classList.toggle("nav-hidden", d.show_nav_ai === false);
|
||||
if (navCalc) navCalc.classList.toggle("nav-hidden", d.show_nav_calculator === false);
|
||||
}
|
||||
|
||||
function pageNavAllowed(page) {
|
||||
@@ -53,6 +59,7 @@
|
||||
if (page === "plan") return showNavPlanPref();
|
||||
if (page === "archive") return showNavArchivePref();
|
||||
if (page === "ai") return showNavAiPref();
|
||||
if (page === "calculator") return showNavCalculatorPref();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -64,12 +71,14 @@
|
||||
const planCb = document.getElementById("pref-show-nav-plan");
|
||||
const archiveCb = document.getElementById("pref-show-nav-archive");
|
||||
const aiCb = document.getElementById("pref-show-nav-ai");
|
||||
const calcCb = document.getElementById("pref-show-nav-calculator");
|
||||
if (pnlCb) pnlCb.checked = d.show_account_pnl !== false;
|
||||
if (fundsCb) fundsCb.checked = d.show_nav_funds !== false;
|
||||
if (dashCb) dashCb.checked = d.show_nav_dashboard !== false;
|
||||
if (planCb) planCb.checked = d.show_nav_plan !== false;
|
||||
if (archiveCb) archiveCb.checked = d.show_nav_archive !== false;
|
||||
if (aiCb) aiCb.checked = d.show_nav_ai !== false;
|
||||
if (calcCb) calcCb.checked = d.show_nav_calculator !== false;
|
||||
syncNavVisibility(data);
|
||||
}
|
||||
|
||||
@@ -1035,6 +1044,7 @@
|
||||
if (p.includes("dashboard")) return "dashboard";
|
||||
if (p.includes("funds")) return "funds";
|
||||
if (p.includes("plan")) return "plan";
|
||||
if (p.includes("calculator")) return "calculator";
|
||||
if (p.includes("market")) return "market";
|
||||
if (p.includes("/ai")) return "ai";
|
||||
return "monitor";
|
||||
@@ -1046,6 +1056,7 @@
|
||||
if (page === "dashboard") return "page-dashboard";
|
||||
if (page === "funds") return "page-funds";
|
||||
if (page === "plan") return "page-plan";
|
||||
if (page === "calculator") return "page-calculator";
|
||||
if (page === "market") return "page-market";
|
||||
if (page === "ai") return "page-ai";
|
||||
return "page-monitor";
|
||||
@@ -1091,6 +1102,9 @@
|
||||
} else if (window.hubPlanPage && window.hubPlanPage.destroy) {
|
||||
window.hubPlanPage.destroy();
|
||||
}
|
||||
if (page === "calculator" && window.hubCalculatorPage) {
|
||||
window.hubCalculatorPage.init();
|
||||
}
|
||||
if (page === "funds" && window.hubFundsPage) {
|
||||
window.hubFundsPage.init();
|
||||
} else if (window.hubFundsPage && window.hubFundsPage.destroy) {
|
||||
@@ -3770,6 +3784,7 @@
|
||||
const planCb = document.getElementById("pref-show-nav-plan");
|
||||
const archiveCb = document.getElementById("pref-show-nav-archive");
|
||||
const aiCb = document.getElementById("pref-show-nav-ai");
|
||||
const calcCb = document.getElementById("pref-show-nav-calculator");
|
||||
return {
|
||||
version: 1,
|
||||
display: {
|
||||
@@ -3779,6 +3794,7 @@
|
||||
show_nav_plan: planCb ? !!planCb.checked : true,
|
||||
show_nav_archive: archiveCb ? !!archiveCb.checked : true,
|
||||
show_nav_ai: aiCb ? !!aiCb.checked : true,
|
||||
show_nav_calculator: calcCb ? !!calcCb.checked : true,
|
||||
},
|
||||
exchanges: rows.map((card) => {
|
||||
const caps = [];
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* 中控策略计算器:趋势回调 / 滚仓历史测算
|
||||
*/
|
||||
(function () {
|
||||
const page = document.getElementById("page-calculator");
|
||||
if (!page) return;
|
||||
|
||||
let inited = false;
|
||||
|
||||
function $(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
function esc(s) {
|
||||
return String(s == null ? "" : s)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
|
||||
function num(id) {
|
||||
const el = $(id);
|
||||
if (!el) return null;
|
||||
const n = Number(el.value);
|
||||
return Number.isFinite(n) ? n : null;
|
||||
}
|
||||
|
||||
function fmt(v, digits) {
|
||||
if (v == null || v === "") return "—";
|
||||
const n = Number(v);
|
||||
if (!Number.isFinite(n)) return esc(v);
|
||||
if (digits != null) return n.toFixed(digits);
|
||||
return String(n);
|
||||
}
|
||||
|
||||
function fmtU(v) {
|
||||
if (v == null || v === "") return "—";
|
||||
const n = Number(v);
|
||||
if (!Number.isFinite(n)) return "—";
|
||||
return (n >= 0 ? "+" : "") + n.toFixed(2) + "U";
|
||||
}
|
||||
|
||||
function pnlClass(v) {
|
||||
const n = Number(v);
|
||||
if (!Number.isFinite(n) || n === 0) return "";
|
||||
return n > 0 ? "calc-pnl-profit" : "calc-pnl-loss";
|
||||
}
|
||||
|
||||
function syncTrendAddLabel() {
|
||||
const dir = ($("calc-trend-direction") && $("calc-trend-direction").value) || "long";
|
||||
const lab = $("calc-trend-add-label");
|
||||
if (lab) lab.textContent = dir === "short" ? "补仓下沿价" : "补仓上沿价";
|
||||
}
|
||||
|
||||
function renderTrendTable(rows) {
|
||||
if (!rows || !rows.length) {
|
||||
return '<p class="calc-empty">无档位数据</p>';
|
||||
}
|
||||
let html =
|
||||
'<div class="calc-table-wrap"><table class="calc-table"><thead><tr>' +
|
||||
"<th>档位</th><th>触发价</th><th>张数</th><th>加仓后均价</th><th>止盈盈利</th><th>止损金额</th><th>盈亏比</th>" +
|
||||
"</tr></thead><tbody>";
|
||||
rows.forEach(function (r) {
|
||||
html +=
|
||||
"<tr>" +
|
||||
"<td>" +
|
||||
esc(r.label) +
|
||||
"</td>" +
|
||||
"<td>" +
|
||||
fmt(r.price, 4) +
|
||||
"</td>" +
|
||||
"<td>" +
|
||||
fmt(r.contracts, 4) +
|
||||
"</td>" +
|
||||
"<td>" +
|
||||
fmt(r.avg_entry, 4) +
|
||||
"</td>" +
|
||||
'<td class="' +
|
||||
pnlClass(r.profit_u) +
|
||||
'">' +
|
||||
fmtU(r.profit_u) +
|
||||
"</td>" +
|
||||
"<td>" +
|
||||
fmtU(r.risk_u) +
|
||||
"</td>" +
|
||||
"<td>" +
|
||||
(r.rr != null ? fmt(r.rr, 2) + ":1" : "—") +
|
||||
"</td>" +
|
||||
"</tr>";
|
||||
});
|
||||
html += "</tbody></table></div>";
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderTrendResult(data) {
|
||||
const box = $("calc-trend-result");
|
||||
if (!box) return;
|
||||
box.classList.remove("hidden");
|
||||
box.innerHTML =
|
||||
'<div class="calc-summary">' +
|
||||
"<div><span>计划保证金</span><strong>" +
|
||||
fmt(data.plan_margin_u, 2) +
|
||||
"U</strong></div>" +
|
||||
"<div><span>止损预算</span><strong>" +
|
||||
fmt(data.risk_budget_u, 2) +
|
||||
"U</strong></div>" +
|
||||
"<div><span>总张数</span><strong>" +
|
||||
fmt(data.target_contracts, 4) +
|
||||
"</strong></div>" +
|
||||
"<div><span>首仓张数</span><strong>" +
|
||||
fmt(data.first_contracts, 4) +
|
||||
"</strong></div>" +
|
||||
'<div><span>首仓止盈盈利</span><strong class="' +
|
||||
pnlClass(data.first_profit_u) +
|
||||
'">' +
|
||||
fmtU(data.first_profit_u) +
|
||||
"</strong></div>" +
|
||||
"<div><span>首仓盈亏比</span><strong>" +
|
||||
(data.first_rr != null ? fmt(data.first_rr, 2) + ":1" : "—") +
|
||||
"</strong></div>" +
|
||||
"</div>" +
|
||||
renderTrendTable(data.rows);
|
||||
}
|
||||
|
||||
function renderRollResult(data) {
|
||||
const box = $("calc-roll-result");
|
||||
if (!box) return;
|
||||
box.classList.remove("hidden");
|
||||
box.innerHTML =
|
||||
'<div class="calc-summary">' +
|
||||
"<div><span>风险预算</span><strong>" +
|
||||
fmt(data.risk_budget_u, 2) +
|
||||
"U</strong></div>" +
|
||||
"<div><span>本次加仓张数</span><strong>" +
|
||||
fmt(data.add_contracts, 4) +
|
||||
"</strong></div>" +
|
||||
"<div><span>合并后张数</span><strong>" +
|
||||
fmt(data.qty_after, 4) +
|
||||
"</strong></div>" +
|
||||
"<div><span>合并后均价</span><strong>" +
|
||||
fmt(data.avg_entry_after, 4) +
|
||||
"</strong></div>" +
|
||||
"<div><span>打到新止损亏损</span><strong class=\"calc-pnl-loss\">" +
|
||||
fmtU(-Math.abs(Number(data.loss_at_sl_u) || 0)) +
|
||||
"</strong></div>" +
|
||||
'<div><span>到达首仓止盈盈利</span><strong class="' +
|
||||
pnlClass(data.profit_at_tp_u) +
|
||||
'">' +
|
||||
fmtU(data.profit_at_tp_u) +
|
||||
"</strong></div>" +
|
||||
"<div><span>金额盈亏比</span><strong>" +
|
||||
(data.rr != null ? fmt(data.rr, 2) + ":1" : "—") +
|
||||
"</strong></div>" +
|
||||
"<div><span>下一滚仓序号</span><strong>第 " +
|
||||
esc(data.leg_index_next) +
|
||||
" 次</strong></div>" +
|
||||
"</div>";
|
||||
}
|
||||
|
||||
function showErr(boxId, msg) {
|
||||
const box = $(boxId);
|
||||
if (!box) return;
|
||||
box.classList.remove("hidden");
|
||||
box.innerHTML = '<p class="calc-error">' + esc(msg || "计算失败") + "</p>";
|
||||
}
|
||||
|
||||
async function submitTrend(e) {
|
||||
e.preventDefault();
|
||||
const body = {
|
||||
direction: ($("calc-trend-direction") && $("calc-trend-direction").value) || "long",
|
||||
capital_usdt: num("calc-trend-capital"),
|
||||
risk_percent: num("calc-trend-risk"),
|
||||
leverage: num("calc-trend-leverage"),
|
||||
entry_price: num("calc-trend-entry"),
|
||||
stop_loss: num("calc-trend-sl"),
|
||||
add_upper: num("calc-trend-add-upper"),
|
||||
take_profit: num("calc-trend-tp"),
|
||||
dca_legs: num("calc-trend-dca-legs") || 5,
|
||||
contract_size: num("calc-trend-contract-size") || 1,
|
||||
};
|
||||
try {
|
||||
const r = await fetch("/api/calculator/trend", {
|
||||
method: "POST",
|
||||
credentials: "same-origin",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
const j = await r.json();
|
||||
if (!j.ok) {
|
||||
showErr("calc-trend-result", j.msg || "计算失败");
|
||||
return;
|
||||
}
|
||||
renderTrendResult(j.data);
|
||||
} catch (err) {
|
||||
showErr("calc-trend-result", String(err));
|
||||
}
|
||||
}
|
||||
|
||||
async function submitRoll(e) {
|
||||
e.preventDefault();
|
||||
const body = {
|
||||
direction: ($("calc-roll-direction") && $("calc-roll-direction").value) || "long",
|
||||
capital_usdt: num("calc-roll-capital"),
|
||||
risk_percent: num("calc-roll-risk"),
|
||||
qty_existing: num("calc-roll-qty"),
|
||||
entry_existing: num("calc-roll-entry"),
|
||||
take_profit: num("calc-roll-tp"),
|
||||
add_price: num("calc-roll-add-price"),
|
||||
new_stop_loss: num("calc-roll-sl"),
|
||||
legs_done: num("calc-roll-legs-done") || 0,
|
||||
};
|
||||
try {
|
||||
const r = await fetch("/api/calculator/roll", {
|
||||
method: "POST",
|
||||
credentials: "same-origin",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
const j = await r.json();
|
||||
if (!j.ok) {
|
||||
showErr("calc-roll-result", j.msg || "计算失败");
|
||||
return;
|
||||
}
|
||||
renderRollResult(j.data);
|
||||
} catch (err) {
|
||||
showErr("calc-roll-result", String(err));
|
||||
}
|
||||
}
|
||||
|
||||
function bindOnce() {
|
||||
if (inited) return;
|
||||
inited = true;
|
||||
const trendForm = $("calc-trend-form");
|
||||
const rollForm = $("calc-roll-form");
|
||||
const dirSel = $("calc-trend-direction");
|
||||
if (trendForm) trendForm.addEventListener("submit", submitTrend);
|
||||
if (rollForm) rollForm.addEventListener("submit", submitRoll);
|
||||
if (dirSel) {
|
||||
dirSel.addEventListener("change", syncTrendAddLabel);
|
||||
syncTrendAddLabel();
|
||||
}
|
||||
}
|
||||
|
||||
window.hubCalculatorPage = {
|
||||
init: bindOnce,
|
||||
destroy: function () {},
|
||||
};
|
||||
})();
|
||||
@@ -15,7 +15,7 @@
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
|
||||
<noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript>
|
||||
<link rel="stylesheet" href="/assets/app.css?v=20260614-macro-panel-padding" />
|
||||
<link rel="stylesheet" href="/assets/app.css?v=20260614-calculator" />
|
||||
<link rel="stylesheet" href="/assets/account_risk_badge.css?v=3" />
|
||||
<script src="/assets/account_risk_badge.js?v=3"></script>
|
||||
<link rel="stylesheet" href="/assets/dashboard.css?v=20260612-dash-monitor-count" />
|
||||
@@ -51,6 +51,7 @@
|
||||
<a href="/plan" id="nav-plan">开仓计划</a>
|
||||
<a href="/monitor" id="nav-monitor">监控区</a>
|
||||
<a href="/market" id="nav-market">行情区</a>
|
||||
<a href="/calculator" id="nav-calculator">计算器</a>
|
||||
<a href="/archive" id="nav-archive">内照明心</a>
|
||||
<a href="/dashboard" id="nav-dashboard">数据看板</a>
|
||||
<a href="/ai" id="nav-ai">AI 教练</a>
|
||||
@@ -695,6 +696,122 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="page-calculator" class="page hidden">
|
||||
<div class="page-head">
|
||||
<h1><span class="head-tag">CAL</span> 策略计算器</h1>
|
||||
<p class="page-desc">历史行情测算 · 以损定仓 · 价格均为手动输入</p>
|
||||
</div>
|
||||
<div class="calc-layout">
|
||||
<section class="calc-card card">
|
||||
<h2>趋势回调计算器</h2>
|
||||
<p class="calc-hint">逻辑与实例策略页一致:首仓 50% + 补仓网格;止损金额 = 资金 × 风险%。</p>
|
||||
<form id="calc-trend-form" class="calc-form">
|
||||
<div class="calc-form-grid">
|
||||
<label class="calc-field">
|
||||
<span>交易资金 (U)</span>
|
||||
<input id="calc-trend-capital" type="number" min="0.01" step="any" value="1000" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>风险 %</span>
|
||||
<input id="calc-trend-risk" type="number" min="0.1" step="0.1" value="5" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>杠杆</span>
|
||||
<input id="calc-trend-leverage" type="number" min="1" step="1" value="5" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>方向</span>
|
||||
<select id="calc-trend-direction">
|
||||
<option value="long">做多</option>
|
||||
<option value="short">做空</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>首仓入场价</span>
|
||||
<input id="calc-trend-entry" type="number" min="0" step="any" placeholder="手动输入" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>止损价</span>
|
||||
<input id="calc-trend-sl" type="number" min="0" step="any" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span id="calc-trend-add-label">补仓上沿价</span>
|
||||
<input id="calc-trend-add-upper" type="number" min="0" step="any" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>止盈价</span>
|
||||
<input id="calc-trend-tp" type="number" min="0" step="any" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>补仓档数</span>
|
||||
<input id="calc-trend-dca-legs" type="number" min="1" max="20" step="1" value="5" />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>合约乘数</span>
|
||||
<input id="calc-trend-contract-size" type="number" min="0.0001" step="any" value="1" title="USDT 线性合约默认 1" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="calc-actions">
|
||||
<button type="submit" class="primary">计算</button>
|
||||
</div>
|
||||
</form>
|
||||
<div id="calc-trend-result" class="calc-result hidden"></div>
|
||||
</section>
|
||||
|
||||
<section class="calc-card card">
|
||||
<h2>滚仓计算器</h2>
|
||||
<p class="calc-hint">逻辑与实例滚仓一致:合并持仓打到新止损 ≈ 账户风险;止盈锁定首仓;加仓价手动输入。</p>
|
||||
<form id="calc-roll-form" class="calc-form">
|
||||
<div class="calc-form-grid">
|
||||
<label class="calc-field">
|
||||
<span>交易资金 (U)</span>
|
||||
<input id="calc-roll-capital" type="number" min="0.01" step="any" value="1000" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>总风险 %</span>
|
||||
<input id="calc-roll-risk" type="number" min="0.1" step="0.1" value="5" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>方向</span>
|
||||
<select id="calc-roll-direction">
|
||||
<option value="long">做多</option>
|
||||
<option value="short">做空</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>现有张数</span>
|
||||
<input id="calc-roll-qty" type="number" min="0.0001" step="any" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>现有均价</span>
|
||||
<input id="calc-roll-entry" type="number" min="0" step="any" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>首仓止盈价</span>
|
||||
<input id="calc-roll-tp" type="number" min="0" step="any" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>加仓价</span>
|
||||
<input id="calc-roll-add-price" type="number" min="0" step="any" placeholder="手动输入" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>新统一止损</span>
|
||||
<input id="calc-roll-sl" type="number" min="0" step="any" required />
|
||||
</label>
|
||||
<label class="calc-field">
|
||||
<span>已完成滚仓次数</span>
|
||||
<input id="calc-roll-legs-done" type="number" min="0" max="3" step="1" value="0" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="calc-actions">
|
||||
<button type="submit" class="primary">计算</button>
|
||||
</div>
|
||||
</form>
|
||||
<div id="calc-roll-result" class="calc-result hidden"></div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="page-settings" class="page hidden">
|
||||
<div class="page-head">
|
||||
<h1><span class="head-tag">CFG</span> 系统设置</h1>
|
||||
@@ -735,6 +852,10 @@
|
||||
<input type="checkbox" id="pref-show-nav-ai" checked />
|
||||
顶栏显示「AI 教练」
|
||||
</label>
|
||||
<label class="chk-label settings-display-chk">
|
||||
<input type="checkbox" id="pref-show-nav-calculator" checked />
|
||||
顶栏显示「计算器」
|
||||
</label>
|
||||
<p class="settings-display-hint">保存至 hub_settings.json,换浏览器同样生效。关闭导航后对应页面将不可从顶栏进入,直接访问 URL 会跳回监控区。</p>
|
||||
</div>
|
||||
<div class="settings-macro-panel card">
|
||||
@@ -823,11 +944,12 @@
|
||||
<script src="/assets/chart_draw.js?v=20260609-market-day-split"></script>
|
||||
<script src="/assets/chart.js?v=20260609-prev-day-lines"></script>
|
||||
<script src="/assets/plan.js?v=20260614-entry-plan-scheme"></script>
|
||||
<script src="/assets/calculator.js?v=1"></script>
|
||||
<script src="/assets/archive.js?v=20260612-archive-ai-chat"></script>
|
||||
<script src="/assets/funds.js?v=20260609-hub-funds-fold"></script>
|
||||
<script src="/assets/dashboard.js?v=20260612-dash-monitor-count"></script>
|
||||
<script src="/assets/ai_review_render.js?v=3"></script>
|
||||
<script src="/assets/time_close_ui.js?v=2"></script>
|
||||
<script src="/assets/app.js?v=20260614-nav-feature-toggles"></script>
|
||||
<script src="/assets/app.js?v=20260614-calculator"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user