QuantStats
HTML tearsheets and about eighty risk metrics from one pandas series of returns.
by Ran Aroussi
Last updated
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
mainis 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-reloaded — The maintained fork of Quantopian's empyrical — risk statistics, no plots.
- ffn — Performance stats, drawdowns and portfolio weights from a DataFrame of prices.
- arch — GARCH and the rest of the volatility-model family, plus the tests you need around them.
- pandas-ta — The DataFrame indicator library whose repo is gone and whose last release is a year old.
- PyPortfolioOpt — Prices in, weights out — efficient frontier, Black-Litterman and HRP.
- Riskfolio-Lib — Twenty-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.