Add fee-toggle for backtests, CSV trade download, fee simulation in runner

Backtest runner: added per-trade fee simulation (maker 2bps, taker 5bps).
Each trade now records pnl_gross, pnl_net, and fee. New --no-fees flag
excludes fees from PnL. Output includes pnl_gross/pnl_gross_pct and
fees_total alongside existing pnl (net). Regenerated all 12 backtests.

Server: added /api/backtest/{name}/csv endpoint — returns trades as CSV
with columns time,side,size,price,pnl_gross,pnl_net,fee.
Content-Disposition: attachment triggers browser download.

Dashboard: added "Inc. fees" checkbox toggle in backtest detail panel.
Unchecking shows gross PnL (before fees). "↓ CSV" button downloads
the trade history. Both hidden when detail is closed.
This commit is contained in:
ramseshk
2026-08-04 07:16:41 +00:00
parent e4de21192a
commit ecfdd56d8f
15 changed files with 45829 additions and 38 deletions
+23
View File
@@ -195,6 +195,29 @@ async def get_backtest(name: str):
return JSONResponse({"error": "not found"}, status_code=404)
@app.get("/api/backtest/{name}/csv")
async def get_backtest_csv(name: str):
"""Download backtest trades as CSV."""
from fastapi.responses import Response
fpath = os.path.join(BACKTEST_DIR, f"{name}.json")
if not os.path.exists(fpath):
return JSONResponse({"error": "not found"}, status_code=404)
with open(fpath) as f:
data = json.load(f)
trades = data.get("trades", [])
# Build CSV with headers
header = "time,side,size,price,pnl_gross,pnl_net,fee\n"
rows = []
for t in trades:
rows.append(f"{t.get('time','')},{t.get('side','')},{t.get('size','')},{t.get('price','')},{t.get('pnl_gross',t.get('pnl',''))},{t.get('pnl_net',t.get('pnl',''))},{t.get('fee','0')}")
csv_content = header + "\n".join(rows)
return Response(
content=csv_content,
media_type="text/csv",
headers={"Content-Disposition": f"attachment; filename={name}_trades.csv"}
)
# ═══════════════════════════════════════════════════════════
# Static
# ═══════════════════════════════════════════════════════════