An institutional-grade quantitative portfolio construction and historical backtesting engine. This application allows users to model, solve, and analyze asset allocations under various risk-budgeting paradigms.
- Documentation Links
- Supported Allocation Methodologies
- Systems Architecture Overview
- File & Package Tree
- Installation & Requirements
- Command Line (CLI) Usage
- Streamlit Web Application
- Troubleshooting & FAQs
To help you integrate, study, or deploy this project, we have created dedicated guides:
- Systems Architecture & Flows: Details structural layout, sequence diagrams for historical data alignment, and flowcharts of solver fallback pipelines.
- Inputs & Outputs Explainer: Documents variable types, dimensions, array shapes, and parameters of the internal library APIs.
- Financial & Mathematical Glossary: Explains the statistical mechanics and formulas (returns, covariance shrinkage, tail risks) backing the portfolio strategies.
All solvers enforce a long-only constraint (
-
Equal Weight (Benchmark)
- Allocates capital uniformly:
$w_i = \frac{1}{N}$ . - Acts as a naive benchmark to compare active risk-prevention models.
- Allocates capital uniformly:
-
Mean-Variance Optimization (Markowitz)
- Solves:
$\min_w \quad w^T \Sigma w - \lambda w^T \mu$ - Combines expected returns (
$\mu$ ) and covariance ($\Sigma$ ), trading off risk aversion ($\lambda$ ).
- Solves:
-
Minimum Variance Portfolio
- Solves:
$\min_w \quad w^T \Sigma w$ - Minimizes total portfolio standard deviation, ignoring expected returns. Useful for defensive, low-volatility tilts.
- Solves:
-
Maximum Sharpe Ratio (Tangency Portfolio)
- Solves:
$\max_w \quad \frac{w^T \mu - r_f}{\sqrt{w^T \Sigma w}}$ - Solved as a convex program using the Sharpe-Lintner variable transformation to locate the tangency point on the Capital Market Line. Falls back to Minimum Variance if all asset risk premiums are negative (
$\mu - r_f \le 0$ ).
- Solves:
-
Risk Parity (Equal Risk Contribution)
- Solves:
$\min_x \quad \frac{1}{2} x^T \Sigma x - \sum \ln(x_i)$ (Spinu 2013) - Balances marginal risk contributions (
$RC_i = w_i \frac{(\Sigma w)_i}{\sigma_p}$ ) instead of capital weight, neutralizing equity-concentration risk.
- Solves:
The system downloads stock prices from Yahoo Finance and interest rates from FRED (with fallback to 13-Week Treasury Bill ^IRX if credentials are empty). The returns are computed and processed via a Ledoit-Wolf shrinkage estimator before entering the CVXPY/Scipy optimization engines. Results are evaluated out-of-sample and rendered via Plotly interactive dashboards.
For detailed sequence maps, please refer to the Systems Architecture Document.
g:\Portfolio-Optimizer/
├── app.py # Interactive Streamlit Web Dashboard
├── main.py # CLI Command Runner
├── config.yaml # Universal defaults & ticker lists
├── requirements.txt # Project library requirements
├── .env.example # Credentials template
├── .env # Local credentials (FRED Key)
├── docs/ # Specifications and guides
│ ├── architecture.md # Systems architecture, flows, and solvers
│ └── input_output_explainer.md # Variable type, shape, and metric indexes
├── reports/ # Output directory for CSV datasets and charts
│ ├── portfolio_weights.csv
│ ├── performance_metrics.csv
│ ├── cumulative_returns.csv
│ ├── backtest_cumulative_returns.png
│ ├── asset_allocations.png
│ ├── risk_contributions.png
│ └── efficient_frontier.png
├── src/
│ └── portfolio_optimizer/ # Library package
│ ├── __init__.py
│ ├── config.py # Parameters & env variables loader
│ ├── data_pipeline.py # Resilient data fetching, cleaning, and cache
│ ├── feature_engineering.py # Daily returns & Ledoit-Wolf covariance
│ ├── optimizers.py # Convex & scipy non-linear solvers
│ ├── evaluation.py # Metrics calculations & backtesting
│ ├── exceptions.py # Package custom exceptions
│ └── visualization.py # Plotly interactive graphs
└── tests/
└── test_optimizers.py # Automated testing suite (pytest)
Ensure Python 3.8+ is installed on your system.
- Clone or download the project to your local drive.
- Install core packages:
pip install -r requirements.txt
- Establish Local Settings:
Copy
.env.exampleto.envto override configuration defaults:You can populatecopy .env.example .env
FRED_API_KEYwith a free key from FRED. If left empty, the pipeline triggers its fallback sequence, pulling the 13-Week Treasury Bill yield (^IRX) directly from Yahoo Finance.
Execute the default backtest pipeline (training weights on 2015–2022 data, backtesting out-of-sample on 2023–2025 data):
python main.pyoptions:
-h, --help show this help message and exit
--tickers TICKERS Comma-separated list of symbols (e.g. SPY,TLT,GLD)
--start START Historical data start date (YYYY-MM-DD)
--end END Historical data end date (YYYY-MM-DD)
--backtest-start BACKTEST Out-of-sample backtest split date (YYYY-MM-DD)
--cov {sample,shrinkage} Covariance matrix estimation model
--no-cache Force download data (disables raw CSV cache)
Example Custom Execution:
python main.py --tickers QQQ,TLT,GLD,SPY --start 2018-01-01 --end 2025-12-31 --backtest-start 2024-01-01 --cov shrinkageThe project is structured with a decoupled React frontend and a FastAPI backend.
- Option A: Automated Launcher (Recommended for Windows):
Double-click
run_dev.batat the project root. This starts the FastAPI backend server (port 8000) and the Vite React server (port 5173) in concurrent console logs. - Option B: Manual Terminals:
- Start the API Server:
Runs on
python server.py
http://127.0.0.1:8000. - Start the React UI client:
Runs on
cd frontend npm run devhttp://localhost:5173.
- Start the API Server:
The workspace is pre-configured for Vercel serverless hosting using vercel.json:
- Serverless Ingestion: Vercel routes
/api/*REST endpoints to the Python handler inapi/index.py. It installs dependencies fromrequirements.txtduring the serverless container initialization. - Static Assets Compilation: Vercel executes the React Vite build tool inside the
frontend/subfolder and serves the static files.
To deploy using Vercel CLI, simply run from the repository root:
vercel