Warning
Educational & Self-Study Project Only
This project is built strictly for fun, learning, and self-study in quantitative portfolio programming and data visualization. It is NOT financial, investment, or trading advice. Historical backtests and simulated metrics are purely illustrative and do not guarantee future returns.
An interactive, open-source Streamlit dashboard for backtesting long-term Indian stock investment strategies. Built with Python, Pandas, and yfinance, v-portfolio enables dynamic stock filtering, custom portfolio building, cap allocation mixing, and multi-horizon Monte Carlo drawdown backtesting for both domestic Indian equities and hybrid India + US portfolios.
Are you a beginner or non-technical investor looking to explore backtesting without programming?
Check out our step-by-step Beginner's User Guide for plain-English explanations, walkthroughs, and FAQ!
The Coffee Can philosophy focuses on extreme quality and long-term buy-and-hold investing:
- Consistent ROCE: Return on Capital Employed > 15% for each of the last 10 years.
- Revenue Growth: Annual revenue growth > 10% YoY for each of the last 10 years.
- Market Cap: Minimum ₹100 Cr market capitalization.
- Philosophy: Buy great, clean, high-growth businesses and do nothing for 10+ years.
The Moat philosophy focuses on sustainable competitive advantages and fundamental strength:
- Durable Moat: High pricing power derived from Brand, Network Effects, Switching Costs, Cost Advantage, or Regulatory barriers.
- High ROE: Return on Equity > 20% consistently.
- High Margins: Gross margin > 40% indicating strong pricing power and pricing insulation.
- Low Leverage: Debt-to-Equity < 1.0 (conservative capital structure).
- Valuation Discipline: Purchased at fair or intrinsic valuation.
uv is an extremely fast Python package manager and environment resolver.
-
Clone the repository:
git clone https://github.com/kuldipem/v-portfolio.git cd v-portfolio -
Sync dependencies and run application:
uv sync && uv run streamlit run app.py
-
Clone the repository:
git clone https://github.com/kuldipem/v-portfolio.git cd v-portfolio -
Install in editable mode and run application:
pip install -e . && streamlit run app.py
The application will be accessible at http://localhost:8501.
Note: On the first launch, open Stock Universe Setup in the sidebar to configure and save your target universe (Built-in, Nifty index constituents, or custom CSV upload). The configuration persists locally in
.cache/universe_setup.json.
Deploying v-portfolio to Streamlit Community Cloud is fast and free:
- Fork or Push this repository to your GitHub account.
- Log into Streamlit Community Cloud with your GitHub account.
- Click "New app" in the top-right corner.
- Select your repository (
v-portfolio), branch (main), and set the main file path toapp.py. - (Optional) Under Advanced settings... -> Secrets, paste configuration variables if needed (refer to .streamlit/secrets.toml.example).
- Click Deploy! Streamlit will automatically build the environment using
pyproject.tomland launch your dashboard live.
v-portfolio/
├── app.py # Main Streamlit UI dashboard
├── data.py # Stock universe, filtering engine, backtest engine
├── fetcher.py # yfinance API integration with disk caching
├── universe_config.py # Universe configuration persistence & NSE index loader
├── storage.py # Database and snapshot persistence
├── ui_theme.py # Custom CSS styling and dark theme tokens
├── pyproject.toml # Project configuration & dependencies (uv/pip)
├── .streamlit/ # Streamlit configuration & secrets template
├── pages/ # Multipage Streamlit UI components
└── tests/ # Pytest automated test suite
| Feature | Detail |
|---|---|
| 16 Pre-built portfolios | 8 India-only + 8 India+US (80/20 mix) |
| Dynamic stock filter | Filter by ROCE, Revenue Growth, ROE, Gross Margin, D/E, Sector, Moat Type |
| Persisted universe setup | Save a built-in, Nifty index, or uploaded CSV universe once and reuse it |
| Portfolio builder | Scores and ranks up to 100 stocks per portfolio |
| Multi-horizon backtest | 5, 10, 15, 20, 25, 30 year horizons |
| Cap allocation | Large / Mid / Small / Mix 50-30-20 / Mix with 20% US |
| Risk metrics | CAGR, Alpha, Max Drawdown, Sharpe, Sortino, Volatility |
| Radar chart | Visual risk/return profile vs benchmark |
| Sector pie chart | Sector allocation visualization |
| Year-by-year returns | Simulated annual performance table |
| CSV export | Download stock list and backtest results |
| # | Portfolio | Universe | Type |
|---|---|---|---|
| 1 | Coffee Can Large Cap | Nifty 100 | India |
| 2 | Coffee Can Mid Cap | Nifty Midcap 150 | India |
| 3 | Coffee Can Small Cap | Nifty Smallcap 250 | India |
| 4 | Coffee Can Mix (50/30/20) | All caps | India |
| 5 | Buffett Large Cap | Nifty 100 | India |
| 6 | Buffett Mid Cap | Nifty Midcap 150 | India |
| 7 | Buffett Small Cap | Nifty Smallcap 250 | India |
| 8 | Buffett Mix (50/30/20) | All caps | India |
| 9 | Coffee Can Large + 20% US | Nifty 100 + S&P 500 | India + US |
| 10 | Coffee Can Mid + 20% US | Nifty Mid + S&P 500 | India + US |
| 11 | Coffee Can Small + 20% US | Nifty Small + S&P 500 | India + US |
| 12 | Coffee Can Mix + 20% US | All + S&P 500 | India + US |
| 13 | Buffett Large + 20% US | Nifty 100 + S&P 500 | India + US |
| 14 | Buffett Mid + 20% US | Nifty Mid + S&P 500 | India + US |
| 15 | Buffett Small + 20% US | Nifty Small + S&P 500 | India + US |
| 16 | Buffett Mix + 20% US | All + S&P 500 | India + US |
To use real screener data, install yfinance and modify data.py:
import yfinance as yf
def fetch_live_data(symbol: str) -> dict:
ticker = yf.Ticker(symbol + ".NS") # .NS suffix for NSE stocks
info = ticker.info
return {
"roce": info.get("returnOnAssets", 0) * 100,
"roe": info.get("returnOnEquity", 0) * 100,
"gross_margin": info.get("grossMargins", 0) * 100,
"debt_equity": info.get("debtToEquity", 0) / 100,
# ... etc
}| Index | 10Y CAGR | 15Y CAGR | 20Y CAGR |
|---|---|---|---|
| Nifty 50 | ~14.5% | ~14.8% | ~14.5% |
| Nifty 100 | ~14.2% | ~14.5% | ~14.2% |
| Nifty Midcap 150 | ~17.3% | ~18.1% | ~17.8% |
| Nifty Smallcap 250 | ~13.9% | ~12.7% | ~13.9% |
| S&P 500 (USD) | ~11.0% | ~11.5% | ~10.8% |
| S&P 500 (INR adj.) | ~14.0% | ~14.5% | ~13.8% |
Sources: NSE Indices, Primeinvestor.in, bmsmoney.com
- Stock data in
data.pyis based on publicly available research and is approximate/illustrative. - Backtests use historical index CAGR + strategy alpha estimates derived from academic research.
- Simulated annual returns use a seeded normal distribution (volatility-adjusted) for realism.
- This application is for educational and research purposes only — not investment advice.
Contributions are welcome! Please review CONTRIBUTING.md for guidelines on code style, testing, and submitting pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.