# ffn

Performance stats, drawdowns and portfolio weights from a DataFrame of prices.

*https://stockmarketstack.com/tools/ffn · Market Analysis & Portfolio Optimization Libraries*

## Facts

### At a glance

| Field | Value |
| --- | --- |
| Vendor | Philippe Morissette |
| Category | Market Analysis & Portfolio Optimization Libraries |
| Job | performance_analytics |
| Website | https://github.com/pmorissette/ffn |
| Pricing model | open-source |
| Free tier | true |
| Open source | true |
| Licence | MIT |
| Self-hosted | true |
| Tested hands-on | false |
| Last updated | 2026-09-19 |

### Coverage

| Field | Value |
| --- | --- |
| Asset classes | stocks, etf |
| Markets | global |
| Works outside the US | true |
| Data latency | none |
| Platforms | library |
| AI features | none |

### Interfaces

| Field | Value |
| --- | --- |
| API | false |
| Webhooks | false |
| Scripting | Python |
| Python | true |
| Spreadsheet add-in | false |
| MCP server | false |
| Export | csv |

### Capabilities

Yes: none

No: charting, screening, scanning, backtesting, automation, live_trading, paper_trading, portfolio_tracking, broker_import, tax_reporting, alerts, news, options_analysis

*Verified: pricing 2026-09-19; capabilities 2026-09-19; coverage 2026-09-19.*

## What it is

ffn takes a pandas DataFrame of prices and gives back a statistics object.
`prices.calc_stats().display()` prints total and annualised returns, Sharpe, Sortino, Calmar,
max drawdown and drawdown details, monthly and yearly return tables, and lookback returns —
per column and across the group. `GroupStats` handles many series at once, `to_csv` writes the
table out, and `plot()` and `plot_corr_heatmap()` draw the usual two pictures.

Beyond the stats table there are two things that are not obvious from the name. Portfolio
weighting is built in — `calc_inv_vol_weights`, `calc_mean_var_weights` with a Ledoit-Wolf
covariance estimate, `calc_erc_weights` for equal risk contribution, plus `limit_weights` and the
clustering helpers `calc_clusters` and `calc_ftca`. And so is a small set of overfitting
diagnostics — `calc_deflated_sharpe_ratio` and `calc_prob_backtest_overfitting` — which is more
than most performance libraries in this category offer at all.

## Pricing

Free, MIT-licensed, nothing to buy. `pip install ffn` is the entire product. The dependency list
is heavier than the code suggests — pandas, numpy, scipy, scikit-learn, matplotlib, tabulate,
decorator and yfinance — which is why the README still recommends installing into a scientific
Python distribution.

## Data & coverage

ffn ships no market data. The one fetcher is `ffn.get('aapl,msft', start='2010-01-01')`, which
downloads Yahoo Finance prices through yfinance; anything else you load yourself from a CSV or a
[market data API](https://stockmarketstack.com/categories/market-data-apis). The library has no instrument model at all, so
asset classes and markets are whatever your price columns happen to be.

## Integrations

[bt](https://stockmarketstack.com/tools/bt) is the companion backtester by the same author and the tie is structural rather
than nominal — bt depends on `ffn>=1.1.2`, `bt.Result` subclasses `ffn.GroupStats`, and the stats
table, the plots and `to_csv` a bt user sees are all this package.
[yfinance](https://stockmarketstack.com/tools/yfinance) is the price source behind `ffn.get`.

Repository state on 19 September 2026: release 1.2.2 on 17 September, last commit to `master` the
same day, 4 open issues, not archived. Python 3.9 through 3.13.

## Limitations

- Prices in, not returns. Feeding a returns series directly is a common first mistake; convert it
  with `to_price_index()` first.
- No simulation. There is no order, no cost model and no rebalancing schedule here — that is bt,
  and it is a separate install.
- No HTML report. The output is a printed table, a DataFrame or a CSV, which is the opposite
  trade-off from QuantStats.
- The weighting functions are convenience, not an optimizer. No custom objective, no linear
  constraints, no transaction-cost term.
- PyPI still classifies it Development Status :: 4 - Beta after twelve years, the same as bt.
- yfinance is a hard dependency even if you never touch `ffn.get`.

## Alternatives

[QuantStats](https://stockmarketstack.com/tools/quantstats) if what you want is a tearsheet to send someone;
[empyrical-reloaded](https://stockmarketstack.com/tools/empyrical-reloaded) if you want the bare numbers and the smallest
dependency footprint; [bt](https://stockmarketstack.com/tools/bt) when the question has moved from measuring a series to
simulating a rule.

## FAQ

### Is ffn maintained, and by whom?

Yes, and it is the liveliest library in this section. Version 1.2.2 was released on 17 September 2026 and the last commit to `master` is from the same day, with four open issues and no archive flag. Philippe Morissette remains the repository owner and the name on PyPI, but the handover is older than the version numbers suggest — every tagged release since v0.3.5 in January 2021 was cut by Tim Paine, who now has more commits on the repository than Morissette does, and Morissette's own last commit landed in April 2018.

### What is the difference between ffn and bt?

They are the same author's two halves of one idea. ffn measures — statistics, drawdowns, weighting schemes — and bt simulates, walking a price index one row at a time. bt depends on ffn, its `Result` object subclasses `ffn.GroupStats`, and `bt.get` is an alias for `ffn.get`. If you only want the statistics, install ffn alone and skip the backtester.

### Does ffn take prices or returns?

Prices. `prices.calc_stats()` is the entry point, and returns-only inputs go through `to_price_index()` first. This is the practical difference from QuantStats and empyrical, both of which start from a returns series.

### Can ffn compute portfolio weights?

Yes — inverse volatility, mean-variance with a Ledoit-Wolf covariance estimate, and equal risk contribution, plus clustering helpers and a `limit_weights` cap. It is not a dedicated optimizer with constraints and objectives, but for a handful of standard schemes it saves pulling in one.

## Also from Philippe Morissette

- [bt](https://stockmarketstack.com/tools/bt.md)

## Also worth comparing

- [empyrical-reloaded](https://stockmarketstack.com/tools/empyrical-reloaded.md) — The maintained fork of Quantopian's empyrical — risk statistics, no plots.
- [QuantStats](https://stockmarketstack.com/tools/quantstats.md) — HTML tearsheets and about eighty risk metrics from one pandas series of returns.
- [arch](https://stockmarketstack.com/tools/arch.md) — GARCH and the rest of the volatility-model family, plus the tests you need around them.
- [pandas-ta](https://stockmarketstack.com/tools/pandas-ta.md) — The DataFrame indicator library whose repo is gone and whose last release is a year old.
- [PyPortfolioOpt](https://stockmarketstack.com/tools/pyportfolioopt.md) — Prices in, weights out — efficient frontier, Black-Litterman and HRP.
- [Riskfolio-Lib](https://stockmarketstack.com/tools/riskfolio-lib.md) — Twenty-six convex risk measures, four objectives, one cvxpy-backed optimiser.
