An open API service indexing awesome lists of open source software.

https://github.com/memran/portfolio-optimizer

Web-based portfolio optimization tool built with **Streamlit**.
https://github.com/memran/portfolio-optimizer

Last synced: 8 days ago
JSON representation

Web-based portfolio optimization tool built with **Streamlit**.

Awesome Lists containing this project

README

          

# ๐Ÿ“Š Portfolio Optimizer โ€” Streamlit Web App

[![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
[![Streamlit](https://img.shields.io/badge/streamlit-1.28%2B-FF4B4B.svg)](https://streamlit.io/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Last Commit](https://img.shields.io/github/last-commit/memran/portfolio-optimizer.svg)](https://github.com/memran/portfolio-optimizer/commits/main)
[![Streamlit App](https://img.shields.io/badge/Streamlit-Live-FF4B4B.svg)](https://portfolio-optimizer-nzrsddmhxnfxgznhckcaav.streamlit.app/)

> A web-based portfolio optimization tool that computes the optimal asset allocation by maximizing the Sharpe ratio, plots the efficient frontier, and visualizes asset covariance โ€” all from a CSV upload.

---

## Table of Contents

- [Features](#-features)
- [Project Structure](#-project-structure)
- [Which Script Do I Run?](#-which-script-do-i-run)
- [Quick Start](#-quick-start)
- [CSV File Format](#-csv-file-format)
- [Usage Walkthrough](#-usage-walkthrough)
- [Methodology](#-methodology)
- [Outputs](#-outputs)
- [Assumptions & Limitations](#-assumptions--limitations)
- [Deployment](#-deployment)
- [Troubleshooting](#-troubleshooting)
- [Roadmap](#-roadmap)
- [Contributing](#-contributing)
- [License](#-license)
- [Acknowledgements](#-acknowledgements)

---

## โœจ Features

- ๐Ÿ“ค **CSV upload** โ€” works with either raw prices or pre-computed returns.
- ๐Ÿงฎ **Automatic return calculation** (simple monthly returns) from price data.
- ๐ŸŽฏ **Two optimization modes:**
- Maximum Sharpe ratio (long-only / no short selling)
- Maximum Sharpe ratio (short selling allowed)
- ๐Ÿ“ˆ **Performance metrics** โ€” annualized return, volatility, Sharpe ratio.
- ๐Ÿ“‰ **Efficient frontier** plot.
- ๐Ÿ”ฅ **Covariance matrix heatmap.**
- ๐Ÿท๏ธ **Optional benchmark column** (e.g., `DSEX`) that can be excluded from the asset set.
- ๐Ÿ“ฅ **Downloadable weight CSVs** for both optimization modes.

---

## ๐Ÿ“‚ Project Structure

```
portfolio-optimizer/
โ”œโ”€โ”€ app_price.py # Streamlit app โ€” input CSV contains raw prices
โ”œโ”€โ”€ main.py # Streamlit app โ€” input CSV contains pre-computed monthly returns
โ”œโ”€โ”€ data/
โ”‚ โ””โ”€โ”€ sample_prices.csv # Sample price file (try the app instantly)
โ”œโ”€โ”€ requirements.txt
โ”œโ”€โ”€ pyproject.toml
โ”œโ”€โ”€ uv.lock
โ”œโ”€โ”€ LICENSE
โ””โ”€โ”€ README.md
```

---

## ๐Ÿค” Which Script Do I Run?

| If your CSV containsโ€ฆ | Run |
| ------------------------------------------- | -------------------------------- |
| **Raw prices** (e.g., monthly closing) | `streamlit run app_price.py` |
| **Pre-computed monthly returns** | `streamlit run main.py` |

If unsure, use **`app_price.py`** โ€” it derives returns automatically from prices.

---

## ๐Ÿš€ Quick Start

### Option A โ€” Using `uv` (recommended, matches `uv.lock`)

```bash
git clone https://github.com/memran/portfolio-optimizer.git
cd portfolio-optimizer
uv sync
uv run streamlit run app_price.py
```

### Option B โ€” Using `pip` + `venv`

```bash
git clone https://github.com/memran/portfolio-optimizer.git
cd portfolio-optimizer

python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate

pip install -r requirements.txt
streamlit run app_price.py
```

The app will open in your browser at .

---

## ๐Ÿ“‘ CSV File Format

### Prices mode (`app_price.py`)

- First column: **date** in **`dd/mm/yyyy`** format (e.g., `01/01/2014`).
- Remaining columns: **asset closing prices** (numeric).
- Optional **benchmark** column (e.g., `DSEX`) โ€” you'll be prompted to exclude it in the UI.

**Example** (`data/sample_prices.csv`):

```csv
Date,Eastern Bank Ltd,Islami Bank Limited,BRAC Bank,DSEX
01/01/2014,100.0,95.5,102.3,5000
01/02/2014,103.5,94.2,98.7,5100
01/03/2014,105.1,96.8,101.4,5180
...
```

> โš ๏ธ The date parser is hard-coded to `%d/%m/%Y`. Other formats will produce `NaT` and drop those rows.

### Returns mode (`main.py`)

- Columns: `Year`, `Month`, one column per asset, optional `DSEX` (benchmark โ€” auto-dropped).
- Values: **monthly returns as decimals** (e.g., `0.0123` = 1.23%).

**Example:**

```csv
Year,Month,Eastern Bank Ltd,Islami Bank Limited,BRAC Bank,DSEX
2014,1,0.0123,-0.0045,0.0210,0.0150
2014,2,0.0089,0.0067,-0.0034,0.0098
...
```

---

## ๐Ÿงญ Usage Walkthrough

1. **Upload** your CSV via the file uploader.
2. (Prices mode) **Select a benchmark** to exclude, or choose `None`.
3. Review the **Asset Summary** โ€” annualized mean returns and covariance matrix.
4. Inspect the **Optimal Portfolio (No Short Selling)** card โ€” expected return, volatility, Sharpe ratio, and weights.
5. View the **Efficient Frontier** plot โ€” the red star marks the max-Sharpe portfolio.
6. Expand **Optimal Portfolio (Short Selling Allowed)** for the unconstrained variant.
7. Examine the **Covariance Heatmap** for asset interdependence.
8. **Download** weight CSVs for either mode.

---

## ๐Ÿ“ Methodology

Built on **Markowitz meanโ€“variance optimization** (Modern Portfolio Theory).

**Sharpe ratio**

```
S = (Rโ‚š โˆ’ R_f) / ฯƒโ‚š
```

where `Rโ‚š` is portfolio return, `R_f` is the risk-free rate (assumed `0`), and `ฯƒโ‚š` is portfolio volatility.

**Annualization** (monthly โ†’ annual)

```
ฮผ_annual = ฮผ_monthly ร— 12
ฮฃ_annual = ฮฃ_monthly ร— 12
```

**Optimization**

- Solver: SciPy `minimize` with **SLSQP**.
- Constraint: `ฮฃ wแตข = 1` (fully invested).
- Bounds:
- Long-only: `0 โ‰ค wแตข โ‰ค 1`
- Short selling allowed: `โˆ’1 โ‰ค wแตข โ‰ค 1`
- Objective: minimize `โˆ’Sharpe`.

The efficient frontier is computed by sweeping target returns and minimizing portfolio variance for each.

---

## ๐Ÿ“ฆ Outputs

- Mean annual returns table.
- Annualized covariance matrix.
- Optimal portfolio weights (no short selling).
- Efficient frontier chart with max-Sharpe marker.
- Short-selling-allowed analysis (expandable section).
- Covariance heatmap.
- Download buttons for weight CSV files.

---

## โš ๏ธ Assumptions & Limitations

- **Risk-free rate = 0** (not user-configurable yet).
- **Simple returns** (`pct_change`) by default; log-return mode exists in code but is not exposed in the UI.
- **No transaction costs, taxes, or slippage.**
- **No position limits** other than the bounds above.
- **Annualization factor = 12** โ€” assumes monthly data. Daily/weekly inputs will be mis-annualized.
- **Date format must be `dd/mm/yyyy`** in prices mode.
- **Historical performance โ‰  future returns.** This tool is for education / research, not investment advice.

---

## โ˜๏ธ Live App & Deployment

**Try it now:** [portfolio-optimizer.streamlit.app](https://portfolio-optimizer-nzrsddmhxnfxgznhckcaav.streamlit.app/)

Deploy to **Streamlit Community Cloud** in three steps:

1. Push the repo to GitHub (already done if you cloned this).
2. Go to and click **New app**.
3. Select your repo, branch `main`, and set **Main file path** to `app_price.py` (or `main.py`).

The first deploy takes ~1โ€“2 minutes; subsequent pushes redeploy automatically.

---

## ๐Ÿ›Ÿ Troubleshooting

| Symptom | Likely Cause | Fix |
| --- | --- | --- |
| `ValueError: time data ... doesn't match format` | Dates are not `dd/mm/yyyy` | Re-format the date column or adjust `format=` in `app_price.py:22` |
| Empty results / all-NaN returns | Non-numeric cells (e.g., `"1,000"`) coerced to NaN | Clean the CSV โ€” remove thousand separators and stray text |
| Optimization fails or weights look random | Too few rows, or singular covariance matrix | Provide more history; ensure at least ~24 monthly observations |
| Benchmark column appears in the optimization | `DSEX` (or your benchmark) wasn't excluded | Select it in the **"benchmark column"** dropdown |
| `streamlit: command not found` | Virtualenv not activated, or install failed | Re-activate venv and re-run `pip install -r requirements.txt` |

---

## ๐Ÿ—บ๏ธ Roadmap

- [ ] Configurable **risk-free rate** in the UI.
- [ ] Configurable **annualization factor** (daily / weekly / monthly).
- [ ] **Auto-detect** date formats in `app_price.py`.
- [ ] Merge `main.py` and `app_price.py` into a single app with a mode toggle.
- [ ] Additional optimization objectives: **min-variance**, **risk parity**, **Blackโ€“Litterman**.
- [ ] Export full report (PDF / HTML).

---

## ๐Ÿค Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

1. Fork the repo and create your branch: `git checkout -b feature/my-feature`
2. Commit your changes: `git commit -m "feat: add my feature"`
3. Push to the branch: `git push origin feature/my-feature`
4. Open a Pull Request.

---

## ๐Ÿ“„ License

Released under the [MIT License](LICENSE).

---

## ๐Ÿ™ Acknowledgements

- Markowitz, H. (1952). *Portfolio Selection*. **The Journal of Finance**, 7(1), 77โ€“91.
- [SciPy SLSQP documentation](https://docs.scipy.org/doc/scipy/reference/optimize.minimize-slsqp.html)
- [Streamlit documentation](https://docs.streamlit.io/)