fix期权复盘与数据统计双口径盈亏,并修复卖回封顶导致盈利单冻成亏损。

平仓卖光可卖币后再按账户差分结算复盘;数据统计改为历史币盈亏×卖回价;复盘展示初始权利金与盈利率,并附历史修复脚本。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-13 09:10:13 +08:00
parent d4de6a23ae
commit 9d77a430e5
16 changed files with 2858 additions and 2242 deletions
+22 -26
View File
@@ -102,12 +102,8 @@
var kpi = $("ods-kpi");
var groups = $("ods-stats-groups");
if (!kpi || !groups) return Promise.resolve();
var qs = new URLSearchParams();
qs.set("source_type", sourceType());
qs.set("sync", "0");
return fetch("/api/options/review/stats?" + qs.toString(), {
credentials: "same-origin",
})
// 口径 B:期权历史币盈亏×卖回价(/api/options/stats),与复盘账户差分独立
return fetch("/api/options/stats", { credentials: "same-origin" })
.then(function (r) {
return r.json();
})
@@ -117,19 +113,26 @@
groups.innerHTML = "";
return;
}
var k = data.kpi || {};
var unit = data.pnl_unit || "U";
var net = data.net_realized_pnl;
var avg =
data.total_closed > 0 && net != null
? Number(net) / Number(data.total_closed)
: null;
kpi.innerHTML = [
["笔数", k.total],
["已复盘率", (k.review_rate || 0) + "%"],
["胜率", (k.win_rate || 0) + "%"],
["累计盈亏", fmtPnl(k.pnl_sum)],
["平均盈亏", fmtPnl(k.avg_pnl)],
["平均持有", fmtHold(k.avg_hold_sec)],
["已平笔数", data.total_closed || 0],
["胜率", (data.win_rate || 0) + "%"],
["盈亏比", data.profit_loss_ratio != null ? data.profit_loss_ratio : "—"],
["累计盈亏", fmtPnl(net)],
["平均盈利", data.avg_win != null ? fmtPnl(data.avg_win) : "—"],
["平均亏损", data.avg_loss != null ? fmtPnl(-Math.abs(Number(data.avg_loss))) : "—"],
["平均持有", fmtHold(data.avg_hold_sec)],
]
.map(function (pair) {
var cls = "";
if (pair[0] === "累计盈亏") cls = pnlClass(k.pnl_sum);
if (pair[0] === "平均盈亏") cls = pnlClass(k.avg_pnl);
if (pair[0] === "累计盈亏") cls = pnlClass(net);
if (pair[0] === "平均盈利") cls = "pnl-pos";
if (pair[0] === "平均亏损") cls = "pnl-neg";
return (
'<div class="ods-kpi-tile"><div class="ods-kpi-label">' +
pair[0] +
@@ -141,18 +144,11 @@
);
})
.join("");
var html = [
renderGroup("按类型", data.by_source_type),
renderGroup("按标的", data.by_underlying),
renderGroup("按策略", data.by_strategy),
renderGroup("对冲结束原因", data.by_close_reason),
renderGroup("持有周期", data.by_hold_bucket),
renderGroup("Call/Put", data.by_opt_type),
]
.filter(Boolean)
.join("");
groups.innerHTML =
html || '<div class="muted" style="font-size:.76rem">暂无分组数据</div>';
'<div class="muted" style="font-size:.76rem">数据统计口径:期权历史盈亏×平仓卖回价(与复盘账户差分独立)。单位 ' +
unit +
(avg != null ? " · 笔均 " + fmtPnl(avg) : "") +
"</div>";
})
.catch(function () {
kpi.innerHTML = '<div class="muted" style="font-size:.76rem">统计加载失败</div>';