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:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user