This project explores equity portfolio construction with Modern Portfolio Theory. It ranks NIFTY 50 stocks by risk-adjusted performance, selects the strongest candidates, simulates thousands of portfolio allocations, plots the efficient frontier, and compares the optimized portfolio against the NIFTY 50 benchmark.
- Loads historical NIFTY 50 closing-price data.
- Cleans missing values and removes unavailable tickers.
- Calculates CAGR, annualized volatility, and Sharpe ratio for each stock.
- Selects the top 15 stocks by Sharpe ratio.
- Simulates random portfolio weights to estimate return, volatility, and Sharpe ratio.
- Uses constrained optimization to trace the efficient frontier.
- Calculates the number of shares for an example investment amount.
- Backtests the selected portfolio against the NIFTY 50 benchmark.
- Reports portfolio metrics including return, volatility, beta, alpha, Sharpe ratio, Treynor ratio, drawdown, and downside-risk measures.
.
├── markovitz.ipynb # Main analysis notebook
├── requirements.txt # Python dependencies
├── data/
│ └── README.md # Dataset expectations
└── README.md
Create a virtual environment and install the required packages:
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txtIf you are running the notebook in Google Colab, install the packages from requirements.txt in a setup cell before running the analysis.
The original notebook expects a CSV file named nifty50 (1).csv with a Date column and one price column per ticker. The dataset is not committed to this repository, so place your CSV in the project root before running the notebook.
Expected shape:
Date,RELIANCE.NS,TCS.NS,INFY.NS,...
2020-01-01,1495.42,2167.30,731.20,...
The later backtest section also downloads recent prices through Yahoo Finance using yfinance and pandas-datareader.
The notebook follows a classic mean-variance workflow:
- Estimate each stock's historical return with CAGR.
- Estimate annualized risk from daily percentage returns.
- Rank stocks with the Sharpe ratio, using a risk-free rate assumption.
- Generate random long-only portfolios and identify the highest Sharpe allocation.
- Solve constrained optimization problems for target returns to approximate the efficient frontier.
- Compare the optimized portfolio with the market benchmark over a later period.
- The analysis depends on a local CSV that must be supplied separately.
- The notebook contains hardcoded dates, tickers, and risk-free-rate assumptions.
- The workflow is exploratory rather than packaged as reusable Python modules.
- Results may change when market data changes or Yahoo Finance returns missing values.
- Replace the manual CSV upload with a reproducible data download step.
- Move repeated calculations into a small Python module.
- Add saved charts or screenshots of the efficient frontier and benchmark comparison.
- Add configuration for tickers, dates, investment amount, and risk-free rate.
- Add tests for the portfolio metric calculations.