QuantStats

HTML tearsheets and about eighty risk metrics from one pandas series of returns.

by Ran Aroussi

Last updated

From
Free
Licence
Apache-2.0
Self-hosted
Yes
Platforms
Library

What it is

QuantStats is three modules over a returns series. quantstats.stats exposes 78 public functions, most of them metrics — Sharpe, Sortino and its adjusted variant, CAGR, Calmar, Ulcer index, Kelly criterion, CVaR, gain-to-pain, risk of ruin; quantstats.plots draws the usual performance pictures; and quantstats.reports assembles both into a tearsheet. qs.reports.html(returns, "SPY") writes a self-contained HTML file with metrics against a benchmark, and that one line is what most people install the library for.

qs.extend_pandas() monkey-patches the metrics onto pandas.Series, so returns.sharpe() and returns.plot_snapshot() work directly. The January 2026 release added Monte Carlo simulation — qs.stats.montecarlo(returns, sims=1000, bust=-0.20, goal=0.50) returns bust and goal probabilities and plots the paths. It is tagged 0.0.78 on GitHub but reached PyPI only as 0.0.81, three same-day bugfix bumps later; 0.0.78, 0.0.79 and 0.0.80 were never published.

What it is not is a backtester or a portfolio system. It never sees an order, a position or a holding; the input is a vector of periodic returns and everything on the page is derived from it.

Pricing

Free, Apache-2.0 per LICENSE.txt, nothing for sale — no pro build, no hosted tearsheets, no data bundle. pip install quantstats, or the author's conda channel.

Data & coverage

No data ships with the package. You supply a returns series; the benchmark argument accepts either another series or a ticker string, in which case it is fetched from Yahoo Finance through yfinance. That dependency is not optional — yfinance>=0.2.40 is in the install requirements, so a statistics library pulls a Yahoo scraper into every environment that installs it. Both packages are by the same author, which is why nobody has been in a hurry to separate them.

Asset classes and markets are whatever your returns series covers. The library does no currency conversion and has no concept of an instrument.

Integrations

The natural pairing is with yfinance for prices and any backtester that can hand you a returns series — bt, VectorBT and Zipline-reloaded all can. Lumibot generates its tearsheets through the quantstats-lumi fork rather than this package.

Requirements are Python 3.10 or newer since the January 2026 release, plus pandas, numpy, scipy, matplotlib, seaborn and tabulate. Plotly is an optional extra behind plots.to_plotly().

Limitations

  • Every metric is period-based. Win rate, consecutive wins and payoff ratio count return periods, not trades, and the README spells out that a multi-day discretionary trade will not agree with broker-level statistics.
  • There is still no documentation site. The README has said "Full documentation coming soon" since 2019; the reference is help() and the source.
  • Maintenance is one person working in bursts, and the quiet stretches are long. Nothing shipped for two years between July 2023 and July 2025; the last commit to main is 13 January 2026, and 19 pull requests are open behind it.
  • Saving the monthly-returns heatmap also displays it. This is in the README's own "Known Issues", unfixed.
  • No export beyond the HTML report — metrics come back as DataFrames you write out yourself.

Alternatives

ffn computes a comparable statistics table from prices rather than returns and adds weighting schemes; empyrical-reloaded is the bare numeric layer with no plots at all. quantstats-lumi is the same tearsheet under a different maintainer. If the returns come out of a vectorised sweep, VectorBT already carries its own stats and you may not need a second library.

Specs

Interfaces
Python, Python
Export
None
Asset classes
Stocks, ETF
Markets
Global
Platforms
Library
AI features
None
Pricing verified
Capabilities verified
Coverage verified

Also from Ran Aroussi

Also worth comparing

  • empyrical-reloadedThe maintained fork of Quantopian's empyrical — risk statistics, no plots.
  • ffnPerformance stats, drawdowns and portfolio weights from a DataFrame of prices.
  • archGARCH and the rest of the volatility-model family, plus the tests you need around them.
  • pandas-taThe DataFrame indicator library whose repo is gone and whose last release is a year old.
  • PyPortfolioOptPrices in, weights out — efficient frontier, Black-Litterman and HRP.
  • Riskfolio-LibTwenty-six convex risk measures, four objectives, one cvxpy-backed optimiser.

FAQ

Is QuantStats still maintained?

Yes, but in bursts and by one person. The last release on PyPI is 0.0.81, uploaded 13 January 2026, and the last commit to main is from the same day. Before that came a two-year silence — nothing at all between 0.0.62 on 6 July 2023 and 0.0.64 on 14 July 2025 — and then fourteen releases in eight weeks, ending 5 September 2025. The repository is not archived; 14 issues and 19 pull requests are open.

Should I use QuantStats or the quantstats-lumi fork?

quantstats-lumi is Lumiwealth's fork, published because the original looked abandoned in early 2024 — a reading that the 2025 and 2026 releases have since overtaken. It is the more recently touched of the two (1.1.5 on 1 June 2026, last commit 9 September 2026) but has 152 stars against 7,644, imports as quantstats_lumi, and carries the Lumibot team's priorities. Use the original unless a bug you hit is already fixed there.

Does QuantStats need market data of its own?

No. It takes a pandas Series of periodic returns indexed by date, from wherever you compute it. The convenience helper qs.utils.download_returns pulls Yahoo Finance prices through yfinance, which is a hard dependency of the package rather than an optional extra.

Why do my QuantStats win rates disagree with my broker statement?

Because the library measures return periods, not trades. Win rate is the share of days (or weeks, or months) with a positive return, so one five-day trade that closed green can still be counted as three winning days and two losing ones. The README says this explicitly. For trade-level statistics you want a trading journal, not a returns library.