Split fee stats by leg and hide LIVE slip.

SIM shows perp/option fees and slip separately; LIVE keeps real exchange fees only with slip forced to zero.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-29 16:37:18 +08:00
parent 8518a207a7
commit 1c75db4a19
8 changed files with 122 additions and 20 deletions
+23 -2
View File
@@ -3,10 +3,14 @@ import { apiFetch } from "../api/client";
import { closeReasonZh } from "../labels";
type Summary = {
mode?: "SIM" | "LIVE" | string;
show_slip?: boolean;
groups: number;
wins: number;
win_rate: number;
total_pnl: number;
fees_perp?: number;
fees_option?: number;
total_fees: number;
total_slip: number;
close_reasons: Record<string, number>;
@@ -26,6 +30,7 @@ export default function StatsPage() {
const reasonEntries = s
? Object.entries(s.close_reasons).sort((a, b) => b[1] - a[1])
: [];
const showSlip = s?.show_slip ?? s?.mode !== "LIVE";
return (
<div className="card">
@@ -46,11 +51,27 @@ export default function StatsPage() {
<span className="mono">{s.total_pnl.toFixed(2)}</span>
</div>
<div className="kv">
<span> / </span>
<span></span>
<span className="mono">
{s.total_fees.toFixed(2)} / {s.total_slip.toFixed(2)}
{(s.fees_perp ?? 0).toFixed(4)}
</span>
</div>
<div className="kv">
<span></span>
<span className="mono">
{(s.fees_option ?? 0).toFixed(4)}
</span>
</div>
<div className="kv">
<span></span>
<span className="mono">{s.total_fees.toFixed(4)}</span>
</div>
{showSlip ? (
<div className="kv">
<span></span>
<span className="mono">{s.total_slip.toFixed(4)}</span>
</div>
) : null}
<div className="kv" style={{ alignItems: "flex-start" }}>
<span></span>
<span className="mono" style={{ textAlign: "right" }}>
+25
View File
@@ -10,7 +10,10 @@ import {
type PnlSummary = {
option_pnl: number | null;
perp_pnl: number | null;
fees_perp?: number;
fees_option?: number;
fees_total: number;
slip_total?: number;
gross_pnl: number | null;
net_pnl: number | null;
};
@@ -41,6 +44,7 @@ type Group = {
hold_basis?: string | null;
strike?: number | null;
settle_index_px?: number | null;
exec_mode?: string | null;
expiry_settle?: ExpirySettle | null;
pnl_summary?: PnlSummary;
};
@@ -349,10 +353,31 @@ export default function TradesPage() {
{fmt(summary.perp_pnl)}
</span>
</div>
<div className="kv">
<span></span>
<span className="mono">
{fmt(summary.fees_perp ?? 0, 4)}
</span>
</div>
<div className="kv">
<span></span>
<span className="mono">
{fmt(summary.fees_option ?? 0, 4)}
</span>
</div>
<div className="kv">
<span></span>
<span className="mono">{fmt(summary.fees_total, 4)}</span>
</div>
{String(selectedGroup.exec_mode || "").toUpperCase() !==
"LIVE" ? (
<div className="kv">
<span></span>
<span className="mono">
{fmt(summary.slip_total ?? 0, 4)}
</span>
</div>
) : null}
<div className="kv">
<span>
<strong></strong>