Add active hedge plan tab
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -109,7 +109,7 @@
|
|||||||
b.classList.toggle("active", on);
|
b.classList.toggle("active", on);
|
||||||
b.setAttribute("aria-selected", on ? "true" : "false");
|
b.setAttribute("aria-selected", on ? "true" : "false");
|
||||||
});
|
});
|
||||||
["perp_options", "options_options", "history", "stats"].forEach(function (id) {
|
["perp_options", "options_options", "active", "history", "stats"].forEach(function (id) {
|
||||||
const panel = $("hp-tab-" + id);
|
const panel = $("hp-tab-" + id);
|
||||||
if (!panel) return;
|
if (!panel) return;
|
||||||
const on = id === tab;
|
const on = id === tab;
|
||||||
@@ -720,6 +720,8 @@
|
|||||||
syncTabUI();
|
syncTabUI();
|
||||||
if (state.tab === "perp_options" || state.tab === "options_options") {
|
if (state.tab === "perp_options" || state.tab === "options_options") {
|
||||||
void loadGates();
|
void loadGates();
|
||||||
|
} else if (state.tab === "active") {
|
||||||
|
void loadActivePlans();
|
||||||
} else if (state.tab === "history") {
|
} else if (state.tab === "history") {
|
||||||
void loadHistory();
|
void loadHistory();
|
||||||
} else if (state.tab === "stats") {
|
} else if (state.tab === "stats") {
|
||||||
@@ -868,6 +870,60 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function activeTargetLabel(p) {
|
||||||
|
if (p.plan_type === "perp_options") {
|
||||||
|
return "止盈 " + fmt(p.tp) + " · 止损 " + fmt(p.sl);
|
||||||
|
}
|
||||||
|
return "上破 " + fmt(p.target_price_up || p.target_price) + " · 下破 " + fmt(p.target_price_down || p.target_price);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadActivePlans() {
|
||||||
|
const tbody = $("hp-active-tbody");
|
||||||
|
if (!tbody) return;
|
||||||
|
try {
|
||||||
|
const d = await apiJson("/api/hedge-plan/active");
|
||||||
|
const rows = d.plans || [];
|
||||||
|
if (!rows.length) {
|
||||||
|
tbody.innerHTML = '<tr><td colspan="8" class="muted">暂无进行中的计划</td></tr>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tbody.innerHTML = "";
|
||||||
|
rows.forEach(function (p) {
|
||||||
|
const tr = document.createElement("tr");
|
||||||
|
const typeLabel = p.plan_type === "perp_options" ? "永期" : "期期";
|
||||||
|
const contracts = p.contracts_summary || "—";
|
||||||
|
tr.innerHTML =
|
||||||
|
"<td>#" +
|
||||||
|
p.id +
|
||||||
|
"</td><td>" +
|
||||||
|
typeLabel +
|
||||||
|
"</td><td>" +
|
||||||
|
(p.underlying || "") +
|
||||||
|
"</td><td class=\"hp-contracts-cell\" title=\"" +
|
||||||
|
String(contracts).replace(/"/g, """) +
|
||||||
|
"\"><code>" +
|
||||||
|
contracts +
|
||||||
|
"</code></td><td>" +
|
||||||
|
(p.status || "") +
|
||||||
|
"</td><td>" +
|
||||||
|
activeTargetLabel(p) +
|
||||||
|
"</td><td>" +
|
||||||
|
(p.opened_at || "—") +
|
||||||
|
'</td><td class="hp-hist-actions"><button type="button" class="btn-secondary hp-btn-detail" data-id="' +
|
||||||
|
p.id +
|
||||||
|
'">成交细节</button></td>';
|
||||||
|
tbody.appendChild(tr);
|
||||||
|
});
|
||||||
|
tbody.querySelectorAll(".hp-btn-detail").forEach(function (btn) {
|
||||||
|
btn.addEventListener("click", function () {
|
||||||
|
void showPlanDetail(Number(btn.getAttribute("data-id")));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
tbody.innerHTML = '<tr><td colspan="8" class="err">' + (e.message || e) + "</td></tr>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function reasonLabel(r) {
|
function reasonLabel(r) {
|
||||||
const map = {
|
const map = {
|
||||||
perp_tp: "永续止盈",
|
perp_tp: "永续止盈",
|
||||||
|
|||||||
@@ -522,6 +522,28 @@ def register_hedge_plan_routes(app: Flask, cfg: dict[str, Any]) -> None:
|
|||||||
conn.close()
|
conn.close()
|
||||||
return jsonify({"ok": True, "plans": merged})
|
return jsonify({"ok": True, "plans": merged})
|
||||||
|
|
||||||
|
@app.route("/api/hedge-plan/active")
|
||||||
|
@lr
|
||||||
|
def api_hedge_active():
|
||||||
|
from lib.hedge_plan.hedge_plan_db import (
|
||||||
|
attach_legs_to_plans,
|
||||||
|
init_hedge_plan_tables,
|
||||||
|
list_plans,
|
||||||
|
)
|
||||||
|
|
||||||
|
conn = cfg["get_db"]()
|
||||||
|
try:
|
||||||
|
init_hedge_plan_tables(conn)
|
||||||
|
rows = []
|
||||||
|
for status in ("opening", "active", "partial"):
|
||||||
|
rows.extend(list_plans(conn, status=status, limit=80))
|
||||||
|
rows.sort(key=lambda row: int(row.get("id") or 0), reverse=True)
|
||||||
|
plans = attach_legs_to_plans(conn, rows)
|
||||||
|
conn.commit()
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
return jsonify({"ok": True, "plans": plans})
|
||||||
|
|
||||||
@app.route("/api/hedge-plan/stats")
|
@app.route("/api/hedge-plan/stats")
|
||||||
@lr
|
@lr
|
||||||
def api_hedge_stats():
|
def api_hedge_stats():
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
<div class="hp-tabs" role="tablist" aria-label="对冲计划分类">
|
<div class="hp-tabs" role="tablist" aria-label="对冲计划分类">
|
||||||
<button type="button" class="hp-tab active" role="tab" aria-selected="true" data-tab="perp_options">永期对冲</button>
|
<button type="button" class="hp-tab active" role="tab" aria-selected="true" data-tab="perp_options">永期对冲</button>
|
||||||
<button type="button" class="hp-tab" role="tab" aria-selected="false" data-tab="options_options">期期对冲</button>
|
<button type="button" class="hp-tab" role="tab" aria-selected="false" data-tab="options_options">期期对冲</button>
|
||||||
|
<button type="button" class="hp-tab" role="tab" aria-selected="false" data-tab="active">进行中的计划</button>
|
||||||
<button type="button" class="hp-tab" role="tab" aria-selected="false" data-tab="history">历史记录</button>
|
<button type="button" class="hp-tab" role="tab" aria-selected="false" data-tab="history">历史记录</button>
|
||||||
<button type="button" class="hp-tab" role="tab" aria-selected="false" data-tab="stats">统计分析</button>
|
<button type="button" class="hp-tab" role="tab" aria-selected="false" data-tab="stats">统计分析</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -198,6 +199,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="hp-tab-active" class="hp-tab-panel hidden" role="tabpanel" hidden>
|
||||||
|
<div class="card">
|
||||||
|
<h2>进行中的计划</h2>
|
||||||
|
<p class="muted">仅显示已启动但尚未结束的计划;可查看每条腿的当前记录状态。</p>
|
||||||
|
<div class="options-strike-table-wrap">
|
||||||
|
<table class="options-strike-table hp-history-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th><th>类型</th><th>标的</th><th>合约</th><th>状态</th><th>目标/止盈止损</th><th>开仓</th><th>操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="hp-active-tbody">
|
||||||
|
<tr><td colspan="8" class="muted">加载中…</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="hp-tab-history" class="hp-tab-panel hidden" role="tabpanel" hidden>
|
<div id="hp-tab-history" class="hp-tab-panel hidden" role="tabpanel" hidden>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>历史记录</h2>
|
<h2>历史记录</h2>
|
||||||
@@ -235,4 +255,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/hedge_plan.js?v=12"></script>
|
<script src="/static/hedge_plan.js?v=13"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user