{"id":51162738,"url":"https://github.com/memran/portfolio-optimizer","last_synced_at":"2026-06-26T15:31:12.888Z","repository":{"id":362928437,"uuid":"1261320775","full_name":"memran/portfolio-optimizer","owner":"memran","description":"Web-based portfolio optimization tool built with **Streamlit**. ","archived":false,"fork":false,"pushed_at":"2026-06-19T18:27:25.000Z","size":383,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-19T19:23:49.014Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/memran.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-06T14:29:24.000Z","updated_at":"2026-06-19T18:27:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/memran/portfolio-optimizer","commit_stats":null,"previous_names":["memran/portfolio-optimizer"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/memran/portfolio-optimizer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memran%2Fportfolio-optimizer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memran%2Fportfolio-optimizer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memran%2Fportfolio-optimizer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memran%2Fportfolio-optimizer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/memran","download_url":"https://codeload.github.com/memran/portfolio-optimizer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memran%2Fportfolio-optimizer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34823788,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-26T15:31:11.792Z","updated_at":"2026-06-26T15:31:12.876Z","avatar_url":"https://github.com/memran.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📊 Portfolio Optimizer — Streamlit Web App\n\n[![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)\n[![Streamlit](https://img.shields.io/badge/streamlit-1.28%2B-FF4B4B.svg)](https://streamlit.io/)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\n[![Last Commit](https://img.shields.io/github/last-commit/memran/portfolio-optimizer.svg)](https://github.com/memran/portfolio-optimizer/commits/main)\n[![Streamlit App](https://img.shields.io/badge/Streamlit-Live-FF4B4B.svg)](https://portfolio-optimizer-nzrsddmhxnfxgznhckcaav.streamlit.app/)\n\n\u003e 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.\n\n---\n\n## Table of Contents\n\n- [Features](#-features)\n- [Project Structure](#-project-structure)\n- [Which Script Do I Run?](#-which-script-do-i-run)\n- [Quick Start](#-quick-start)\n- [CSV File Format](#-csv-file-format)\n- [Usage Walkthrough](#-usage-walkthrough)\n- [Methodology](#-methodology)\n- [Outputs](#-outputs)\n- [Assumptions \u0026 Limitations](#-assumptions--limitations)\n- [Deployment](#-deployment)\n- [Troubleshooting](#-troubleshooting)\n- [Roadmap](#-roadmap)\n- [Contributing](#-contributing)\n- [License](#-license)\n- [Acknowledgements](#-acknowledgements)\n\n---\n\n## ✨ Features\n\n- 📤 **CSV upload** — works with either raw prices or pre-computed returns.\n- 🧮 **Automatic return calculation** (simple monthly returns) from price data.\n- 🎯 **Two optimization modes:**\n  - Maximum Sharpe ratio (long-only / no short selling)\n  - Maximum Sharpe ratio (short selling allowed)\n- 📈 **Performance metrics** — annualized return, volatility, Sharpe ratio.\n- 📉 **Efficient frontier** plot.\n- 🔥 **Covariance matrix heatmap.**\n- 🏷️ **Optional benchmark column** (e.g., `DSEX`) that can be excluded from the asset set.\n- 📥 **Downloadable weight CSVs** for both optimization modes.\n\n---\n\n## 📂 Project Structure\n\n```\nportfolio-optimizer/\n├── app_price.py            # Streamlit app — input CSV contains raw prices\n├── main.py                 # Streamlit app — input CSV contains pre-computed monthly returns\n├── data/\n│   └── sample_prices.csv   # Sample price file (try the app instantly)\n├── requirements.txt\n├── pyproject.toml\n├── uv.lock\n├── LICENSE\n└── README.md\n```\n\n---\n\n## 🤔 Which Script Do I Run?\n\n| If your CSV contains…                       | Run                              |\n| ------------------------------------------- | -------------------------------- |\n| **Raw prices** (e.g., monthly closing)      | `streamlit run app_price.py`     |\n| **Pre-computed monthly returns**            | `streamlit run main.py`          |\n\nIf unsure, use **`app_price.py`** — it derives returns automatically from prices.\n\n---\n\n## 🚀 Quick Start\n\n### Option A — Using `uv` (recommended, matches `uv.lock`)\n\n```bash\ngit clone https://github.com/memran/portfolio-optimizer.git\ncd portfolio-optimizer\nuv sync\nuv run streamlit run app_price.py\n```\n\n### Option B — Using `pip` + `venv`\n\n```bash\ngit clone https://github.com/memran/portfolio-optimizer.git\ncd portfolio-optimizer\n\npython -m venv .venv\nsource .venv/bin/activate          # Windows: .venv\\Scripts\\activate\n\npip install -r requirements.txt\nstreamlit run app_price.py\n```\n\nThe app will open in your browser at \u003chttp://localhost:8501\u003e.\n\n---\n\n## 📑 CSV File Format\n\n### Prices mode (`app_price.py`)\n\n- First column: **date** in **`dd/mm/yyyy`** format (e.g., `01/01/2014`).\n- Remaining columns: **asset closing prices** (numeric).\n- Optional **benchmark** column (e.g., `DSEX`) — you'll be prompted to exclude it in the UI.\n\n**Example** (`data/sample_prices.csv`):\n\n```csv\nDate,Eastern Bank Ltd,Islami Bank Limited,BRAC Bank,DSEX\n01/01/2014,100.0,95.5,102.3,5000\n01/02/2014,103.5,94.2,98.7,5100\n01/03/2014,105.1,96.8,101.4,5180\n...\n```\n\n\u003e ⚠️ The date parser is hard-coded to `%d/%m/%Y`. Other formats will produce `NaT` and drop those rows.\n\n### Returns mode (`main.py`)\n\n- Columns: `Year`, `Month`, one column per asset, optional `DSEX` (benchmark — auto-dropped).\n- Values: **monthly returns as decimals** (e.g., `0.0123` = 1.23%).\n\n**Example:**\n\n```csv\nYear,Month,Eastern Bank Ltd,Islami Bank Limited,BRAC Bank,DSEX\n2014,1,0.0123,-0.0045,0.0210,0.0150\n2014,2,0.0089,0.0067,-0.0034,0.0098\n...\n```\n\n---\n\n## 🧭 Usage Walkthrough\n\n1. **Upload** your CSV via the file uploader.\n2. (Prices mode) **Select a benchmark** to exclude, or choose `None`.\n3. Review the **Asset Summary** — annualized mean returns and covariance matrix.\n4. Inspect the **Optimal Portfolio (No Short Selling)** card — expected return, volatility, Sharpe ratio, and weights.\n5. View the **Efficient Frontier** plot — the red star marks the max-Sharpe portfolio.\n6. Expand **Optimal Portfolio (Short Selling Allowed)** for the unconstrained variant.\n7. Examine the **Covariance Heatmap** for asset interdependence.\n8. **Download** weight CSVs for either mode.\n\n---\n\n## 📐 Methodology\n\nBuilt on **Markowitz mean–variance optimization** (Modern Portfolio Theory).\n\n**Sharpe ratio**\n\n```\nS = (Rₚ − R_f) / σₚ\n```\n\nwhere `Rₚ` is portfolio return, `R_f` is the risk-free rate (assumed `0`), and `σₚ` is portfolio volatility.\n\n**Annualization** (monthly → annual)\n\n```\nμ_annual = μ_monthly × 12\nΣ_annual = Σ_monthly × 12\n```\n\n**Optimization**\n\n- Solver: SciPy `minimize` with **SLSQP**.\n- Constraint: `Σ wᵢ = 1` (fully invested).\n- Bounds:\n  - Long-only: `0 ≤ wᵢ ≤ 1`\n  - Short selling allowed: `−1 ≤ wᵢ ≤ 1`\n- Objective: minimize `−Sharpe`.\n\nThe efficient frontier is computed by sweeping target returns and minimizing portfolio variance for each.\n\n---\n\n## 📦 Outputs\n\n- Mean annual returns table.\n- Annualized covariance matrix.\n- Optimal portfolio weights (no short selling).\n- Efficient frontier chart with max-Sharpe marker.\n- Short-selling-allowed analysis (expandable section).\n- Covariance heatmap.\n- Download buttons for weight CSV files.\n\n---\n\n## ⚠️ Assumptions \u0026 Limitations\n\n- **Risk-free rate = 0** (not user-configurable yet).\n- **Simple returns** (`pct_change`) by default; log-return mode exists in code but is not exposed in the UI.\n- **No transaction costs, taxes, or slippage.**\n- **No position limits** other than the bounds above.\n- **Annualization factor = 12** — assumes monthly data. Daily/weekly inputs will be mis-annualized.\n- **Date format must be `dd/mm/yyyy`** in prices mode.\n- **Historical performance ≠ future returns.** This tool is for education / research, not investment advice.\n\n---\n\n## ☁️ Live App \u0026 Deployment\n\n**Try it now:** [portfolio-optimizer.streamlit.app](https://portfolio-optimizer-nzrsddmhxnfxgznhckcaav.streamlit.app/)\n\nDeploy to **Streamlit Community Cloud** in three steps:\n\n1. Push the repo to GitHub (already done if you cloned this).\n2. Go to \u003chttps://share.streamlit.io\u003e and click **New app**.\n3. Select your repo, branch `main`, and set **Main file path** to `app_price.py` (or `main.py`).\n\nThe first deploy takes ~1–2 minutes; subsequent pushes redeploy automatically.\n\n---\n\n## 🛟 Troubleshooting\n\n| Symptom | Likely Cause | Fix |\n| --- | --- | --- |\n| `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` |\n| Empty results / all-NaN returns | Non-numeric cells (e.g., `\"1,000\"`) coerced to NaN | Clean the CSV — remove thousand separators and stray text |\n| Optimization fails or weights look random | Too few rows, or singular covariance matrix | Provide more history; ensure at least ~24 monthly observations |\n| Benchmark column appears in the optimization | `DSEX` (or your benchmark) wasn't excluded | Select it in the **\"benchmark column\"** dropdown |\n| `streamlit: command not found` | Virtualenv not activated, or install failed | Re-activate venv and re-run `pip install -r requirements.txt` |\n\n---\n\n## 🗺️ Roadmap\n\n- [ ] Configurable **risk-free rate** in the UI.\n- [ ] Configurable **annualization factor** (daily / weekly / monthly).\n- [ ] **Auto-detect** date formats in `app_price.py`.\n- [ ] Merge `main.py` and `app_price.py` into a single app with a mode toggle.\n- [ ] Additional optimization objectives: **min-variance**, **risk parity**, **Black–Litterman**.\n- [ ] Export full report (PDF / HTML).\n\n---\n\n## 🤝 Contributing\n\nPull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.\n\n1. Fork the repo and create your branch: `git checkout -b feature/my-feature`\n2. Commit your changes: `git commit -m \"feat: add my feature\"`\n3. Push to the branch: `git push origin feature/my-feature`\n4. Open a Pull Request.\n\n---\n\n## 📄 License\n\nReleased under the [MIT License](LICENSE).\n\n---\n\n## 🙏 Acknowledgements\n\n- Markowitz, H. (1952). *Portfolio Selection*. **The Journal of Finance**, 7(1), 77–91.\n- [SciPy SLSQP documentation](https://docs.scipy.org/doc/scipy/reference/optimize.minimize-slsqp.html)\n- [Streamlit documentation](https://docs.streamlit.io/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmemran%2Fportfolio-optimizer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmemran%2Fportfolio-optimizer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmemran%2Fportfolio-optimizer/lists"}