Component · L4

Metrics

github.com/juanmmm21/quant-metrics-calculator

Performance analytics toolkit computing Sharpe, Sortino, profit factor and equity curves.

Lines
689
Files
24
Test files
6
Commits
17
Started
29 Jun 2026
Last commit
6 Jul 2026
  • Python 100%

● Where it sits

Layer 4 of Quant — risk & audit.

Analysis package that processes closed trade history and the equity curve to compute statistical performance metrics: Sharpe Ratio, Sortino Ratio, Profit Factor, max drawdown, and win rate. Tenth module of the quant-core-infra ecosystem.

Repository: github.com/juanmmm21/quant-metrics-calculator

What it is and what problem it solves

Evaluating a strategy by absolute PnL alone is insufficient. You need to measure risk-adjusted return (Sharpe/Sortino), consistency (profit factor, win rate), and worst-case scenario (max drawdown).

This module transforms fills and the equity curve into a unified performance report, compatible with the output of event-driven-backtester and market-condition-simulator.


Role in quant-core-infra

event-driven-backtester ──► fills + equity curve ──┐
market-condition-simulator ──► executions ─────────┤
                                                   ▼
                                      quant-metrics-calculator
                                                   │
                                                   ▼
                                      trade-audit-logger / quant-terminal-web

Closes the quantitative evaluation loop of the backtest.


Purpose

Demonstrates:

  • Periodic return calculation from the equity curve
  • Sharpe and Sortino with an annualized risk-free rate
  • Profit factor and win rate from FIFO round-trips
  • Max drawdown and total return
  • JSON/JSONL pipelines compatible with the ecosystem

Computed metrics

MetricFormula / method
Sharpemean(excess_returns) / std(excess_returns) × √periods_per_year
Sortinomean(excess_returns) / downside_std × √periods_per_year
Profit factorgross_profit / gross_loss
Max drawdownmax((peak - equity) / peak) over the curve
Total return(final_equity - initial_equity) / initial_equity
Win ratewinning_trades / trade_count

Round-trips are reconstructed using long-only FIFO from buy/sell fills.


Architecture

fills JSONL + equity JSON
         │
         ▼
PerformanceCalculator
         │
    ┌────┼────┬──────────┬────────────┐
    ▼    ▼    ▼          ▼            ▼
Returns Sharpe Sortino Drawdown ProfitFactor
    │                              │
    └──────── FIFO reconstructor ──┘
                   │
                   ▼
          PerformanceMetrics

Configuration: MetricsConfig

ParameterDefaultDescription
risk_free_rate_annual0.02Annual risk-free rate (2%)
periods_per_year252Annualization periods (trading days)
min_observations2Minimum returns required for ratios

Requirements

  • Python 3.11+

Installation

cd quant-metrics-calculator
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

CLI usage

quant-metrics-calculator compute \
  --fills samples/btcusdt_fills.jsonl \
  --equity samples/btcusdt_equity.json \
  --symbol BTCUSDT \
  --risk-free-rate 0.02 \
  --output metrics.json

Expected output (excerpt)

{
  "sharpe_ratio": "1.42",
  "sortino_ratio": "2.10",
  "profit_factor": "1.85",
  "max_drawdown_pct": "0.00594",
  "total_return_pct": "0.003",
  "win_rate": "0.5",
  "trade_count": 2
}

Input formats

Fills (JSONL)

{
  "order_id": "ord-1",
  "symbol": "BTCUSDT",
  "side": "buy",
  "quantity": "0.01",
  "price": "100",
  "commission": "0.1",
  "filled_at": "2024-01-01T12:00:00.000Z"
}

Equity curve (JSON array or object with equity_curve)

[
  {"event_time": "2024-01-01T12:00:00.000Z", "equity": "10000"},
  {"event_time": "2024-01-01T13:00:00.000Z", "equity": "10090"}
]

Programmatic usage

from decimal import Decimal

from quant_metrics_calculator import MetricsConfig, run_metrics_pipeline

metrics = run_metrics_pipeline(
    fills_path="fills.jsonl",
    equity_path="equity.json",
    symbol="BTCUSDT",
    config=MetricsConfig(risk_free_rate_annual=Decimal("0.03")),
)

Development

pytest -q
ruff check src tests
mypy src

Troubleshooting

SymptomLikely causeSolution
sell quantity exceeds open long positionOut-of-order fills or implicit shortSort chronologically; long-only FIFO
Sharpe/Sortino at 0Too few points in the equity curveAdd more observations or lower min_observations
equity_curve must not be emptyEmpty equity fileProvide at least one equity point

Roadmap

  • Short-selling support in the FIFO reconstructor
  • Rolling metrics (30d rolling Sharpe)
  • HTML/PDF export for quant-terminal-web
  • Direct integration with event-driven-backtester's JSON output

License

MIT

esc
↑↓ navigate↵ open