PyPortfolioOpt
Financial portfolio optimisation in python, including classical efficient frontier, Black-Litterman, Hierarchical Risk Parity
Install / Use
/learn @PyPortfolio/PyPortfolioOptREADME
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 |
| |
| Tutorials |
|
| Community |
|
| CI/CD |
|
| Code |
|
| Downloads |
|
| Citation | JOSS article |
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
- Table of contents
- Getting started
- A quick example
- An overview of classical portfolio optimization methods
- Features
- Advantages over existing implementations
- Project principles and design decisions
- Testing
- Citing PyPortfolioOpt
- Contributing
- Getting in touch
🚀 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
claude-opus-4-5-migration
99.2kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
model-usage
344.4kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
TrendRadar
50.5k⭐AI-driven public opinion & trend monitor with multi-platform aggregation, RSS, and smart alerts.🎯 告别信息过载,你的 AI 舆情监控助手与热点筛选工具!聚合多平台热点 + RSS 订阅,支持关键词精准筛选。AI 智能筛选新闻 + AI 翻译 + AI 分析简报直推手机,也支持接入 MCP 架构,赋能 AI 自然语言对话分析、情感洞察与趋势预测等。支持 Docker ,数据本地/云端自持。集成微信/飞书/钉钉/Telegram/邮件/ntfy/bark/slack 等渠道智能推送。
mcp-for-beginners
15.7kThis open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.
