SkillAgentSearch skills...

PyPortfolioOpt

Financial portfolio optimisation in python, including classical efficient frontier, Black-Litterman, Hierarchical Risk Parity

Install / Use

/learn @PyPortfolio/PyPortfolioOpt

README

Welcome to PyPortfolioOpt

<a href="https://pyportfolioopt.readthedocs.io/en/latest/"><img src="https://github.com/PyPortfolio/PyPortfolioOpt/blob/main/media/logo_v1.png?raw=true" width="275" align="right" /></a>

PyPortfolioOpt is a library implementing portfolio optimization methods, including classical mean-variance optimization, Black-Litterman allocation, or shrinkage and Hierarchical Risk Parity. PyPortfolioOpt is inspired by scikit-learn; it is extensive yet easily extensible, for casual investors, or professionals looking for an easy prototyping tool. Whether you are a fundamentals-oriented investor who has identified a handful of undervalued picks, or an algorithmic trader who has a basket of strategies, PyPortfolioOpt can help you combine your alpha sources in a risk-efficient way.

<!-- buttons -->

| | Documentation · Tutorials · Release Notes | |---|---| | Open Source | MIT GC.OS Sponsored | | | Tutorials | Binder | | Community | !discord !slack | | CI/CD | github-actions readthedocs | | Code | !pypi !python-versions !black | | Downloads | PyPI - Downloads PyPI - Downloads Downloads | | Citation | JOSS article |

<!-- content -->

Head over to the documentation on ReadTheDocs to get an in-depth look at the project, or check out the cookbook to see some examples showing the full process from downloading data to building a portfolio.

<center> <img src="https://github.com/PyPortfolio/PyPortfolioOpt/blob/main/media/conceptual_flowchart_v2.png?raw=true" style="width:70%;"/> </center>

Table of contents

🚀 Installation

Using pip

pip install pyportfolioopt

From source

Clone the repository, navigate to the folder, and install using pip:

git clone https://github.com/PyPortfolio/PyPortfolioOpt.git
cd PyPortfolioOpt
pip install .

Getting started

Here is an example on real life stock data, demonstrating how easy it is to find the long-only portfolio that maximises the Sharpe ratio (a measure of risk-adjusted returns).

import pandas as pd
from pypfopt import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns

# Read in price data
df = pd.read_csv("tests/resources/stock_prices.csv", parse_dates=True, index_col="date")

# Calculate expected returns and sample covariance
mu = expected_returns.mean_historical_return(df)
S = risk_models.sample_cov(df)

# Optimize for maximal Sharpe ratio
ef = EfficientFrontier(mu, S)
raw_weights = ef.max_sharpe()
cleaned_weights = ef.clean_weights()
ef.save_weights_to_file("weights.csv")  # saves to file

for name, value in cleaned_weights.items():
    print(f"{name}: {value:.4f}")
GOOG: 0.0458
AAPL: 0.0674
FB: 0.2008
BABA: 0.0849
AMZN: 0.0352
GE: 0.0000
AMD: 0.0000
WMT: 0.0000
BAC: 0.0000
GM: 0.0000
T: 0.0000
UAA: 0.0000
SHLD: 0.0000
XOM: 0.0000
RRC: 0.0000
BBY: 0.0159
MA: 0.3287
PFE: 0.2039
JPM: 0.0000
SBUX: 0.0173
exp_return, volatility, sharpe=ef.portfolio_performance(verbose=True)

round(exp_return, 4), round(volatility, 4), round(sharpe, 4)
Expected annual return: 29.9%
Annual volatility: 21.8%
Sharpe Ratio: 1.38

This is interesting but not useful in itself. However, PyPortfolioOpt provides a method which allows you to convert the above continuous weights to an actual allocation that you could buy. Just enter the most recent prices, and the desired portfolio size ($10,000 in this example):

from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices

latest_prices = get_latest_prices(df)

da = DiscreteAllocation(cleaned_weights, latest_prices, total_portfolio_value=10000)
allocation, leftover = da.greedy_portfolio()
for name, value in allocation.items():
    print(f"{name}: {value}")

print("Funds remaining: ${:.2f}".format(leftover))
MA: 19
PFE: 57
FB: 12
BABA: 4
AAPL: 4
GOOG: 1
SBUX: 2
BBY: 2
Funds remaining: $17.46

Disclaimer: nothing about this project constitues investment advice, and the author bears no responsibiltiy for your subsequent investment decisions. Please refer to the license for more information.

An overview of classical portfolio optimization methods

Harry Markowitz's 1952 paper is the undeniable classic, which turned portfolio optimization from an art into a science. The key insight is that by combining assets with different expected returns and volatilities, one can decide on a mathematically optimal allocation which minimises the risk for a target return – the set of all such optimal portfolios is referred to as the efficient frontier.

<center> <img src="https://github.com/PyPortfolio/PyPortfolioOpt/blob/main/media/efficient_frontier_white.png?raw=true" style="width:60%;"/> </center>

Although much development has been made in the subject, more than half a century later, Markowitz's core ideas are still fundamentally important and see daily use in many portfolio management firms. The main drawback of mean-variance optimization is that the theoretical treatment requires knowledge of the expected returns and the future risk-characteristics (covariance) of the assets. Obviously, if we knew the expected returns of a stock life would be much easier, but the whole game is that stock returns are notoriously hard to forecast. As a substitute, we can derive estimates of the expected return and covariance based on historical data – though we do lose the theoretical guarantees provided by Markowitz, the closer our estimates are to the real values, the better our portfolio will be.

Thus this project provides four major sets of functionality (though of course they are intimately related)

  • Estimates of expected returns
  • Estimates of risk (i.e covariance of asset returns)
  • Objective functions to be optimized
  • Optimizers.

A key design goal of PyPortfolioOpt is modularity – the user should be able to swap in their components while still making use of the framework that PyPortfolioOpt provides.

Features

In this section, we detail some of PyPortfolioOpt's available functionality. More examples are offered in the Jupyter notebooks here. Another good resource is the tests.

A far more comprehensive version of this can be found on ReadTheDocs, as well as possible extensions for more advanced users.

Expected returns

  • Mean historical returns:
    • the simplest and most common approach, which states that the expected return of each asset is equal to the mean of its historical returns.
    • easily interpretable and very intuitive
  • Exponentially weighted mean historical returns:
    • similar to mean historical returns, except it gives exponentially more weight to recent prices
    • it is likely the case that an asset's most recent returns hold more weight than returns from 10 years ago when it

Related Skills

View on GitHub
GitHub Stars5.6k
CategoryFinance
Updated6h ago
Forks1.1k

Languages

Jupyter Notebook

Security Score

100/100

Audited on Apr 1, 2026

No findings