QF-Lib Quant Report: full strategy performance analytics

Backend: strategies/quant_report.py
  - equityCurve: daily PnL from trade history
  - monthlyReturns: heatmap matrix (years x months)
  - yearlyReturns: bar chart data with mean
  - monthlyReturnDistribution: histogram bins
  - qqPlot: theoretical vs observed quantiles
  - rollingStats: 6-month rolling return + volatility

API: /api/quant-report/{name}
  Computes full report from any backtest JSON file

Frontend: QuantReport.tsx
  - Strategy Performance chart (equity curve, blue line)
  - Monthly Returns heatmap (blue saturation)
  - Yearly Returns bar chart with mean line
  - Distribution histogram
  - Normal QQ plot with diagonal reference
  - Rolling Statistics (6-month, dual line)
  - QF-Lib header with logo and metadata
  - Access via QF-Lib Report button in detail view
This commit is contained in:
ramseshk
2026-08-06 03:37:25 +00:00
parent 03ebe9e795
commit 0e08543823
5 changed files with 781 additions and 4 deletions
+24
View File
@@ -29,6 +29,7 @@ import sys
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from config.fee_tiers import get_perp_fees, PERPS_TIERS, STAKING_TIERS, STRATEGY_FEE_MODELS
from common.risk import risk_summary
from strategies.quant_report import compute_quant_report
import uvicorn
# ═══════════════════════════════════════════════════════════
@@ -437,6 +438,29 @@ app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
# Main
# ═══════════════════════════════════════════════════════════
@app.get("/api/quant-report/{name}")
async def get_quant_report(name: str):
"""Compute full QF-Lib quant report from a backtest file."""
backtest_path = os.path.join(BACKTEST_DIR, name)
if not os.path.exists(backtest_path):
# Try historical
hist_path = os.path.join(HISTORICAL_DIR, name)
if os.path.exists(hist_path):
backtest_path = hist_path
else:
return JSONResponse({"error": f"Backtest '{name}' not found"}, status_code=404)
try:
with open(backtest_path) as f:
data = json.load(f)
trades = data.get("trades", data.get("trade_history", []))
strategy_name = data.get("name", data.get("strategy", name))
strategy_id = data.get("id", name)
report = compute_quant_report(strategy_name, strategy_id, trades, 100.0)
return JSONResponse(report)
except Exception as e:
return JSONResponse({"error": str(e)}, status_code=500)
def main():
import argparse
parser = argparse.ArgumentParser()