Zerodha portfolio analytics: Markowitz efficient frontier reports with optional Fama-French factor-tilted stock selection
Project description
zerodha_portfolio
Zerodha portfolio analytics toolkit for practical equity allocation decisions:
- Markowitz efficient frontier report for your current holdings
- Fama-French factor-tilted stock selection followed by Markowitz optimization
It is built for users who already think in terms of stocks and quantities and want a visual, explainable report they can use for research, review meetings, or resume/project demonstration.
Install
pip install zerodha-portfolio
What You Input
Both workflows start from a dictionary of stocks and quantities:
portfolio = {
"RELIANCE": 18,
"TCS": 24,
"INFY": 32,
"HDFCBANK": 20,
}
You also provide:
start_date(required)end_date(optional)risk_free_rate(optional, default0.06)
What You Get Back
Both APIs return a Python dictionary with key metrics and a saved HTML report path:
output_htmlsymbolsuser_weightstangency_weightsuser_return,user_vol,user_sharpetangency_return,tangency_vol,tangency_sharpe
The HTML report includes:
- Efficient Frontier curve
- Capital Market Line (CML)
- Your current portfolio point
- Tangency (max-Sharpe) portfolio point
- Portfolio composition tables
- Comparison summary
Workflow 1: Markowitz Report
Use this when you already have a portfolio and want to compare it against the mathematically optimal long-only allocation from the same stock universe.
Example Code
from kiteconnect import KiteConnect
from zerodha_portfolio import generate_markowitz_report
kite = KiteConnect(api_key="your_api_key")
kite.set_access_token("your_access_token")
result = generate_markowitz_report(
kite=kite,
portfolio_quantities={
"RELIANCE": 18,
"TCS": 24,
"INFY": 32,
"HDFCBANK": 20,
},
start_date="2022-01-01",
end_date="2026-02-28",
output_file_name="markowitz_report",
risk_free_rate=0.06,
)
print(result["output_html"])
Example Script and Sample Report
- Script:
examples/example_report.py - Sample output:
examples/markowitz_report.html
Workflow 2: Fama-French -> Markowitz Report
Use this when you want factor-aware stock selection first, and only then run mean-variance optimization on the selected basket.
This workflow:
- Loads Indian Fama-French + Momentum factors (downloaded or local file)
- Estimates each stock's factor betas
- Scores stocks using your factor preference
- Picks top stocks (
top_n) - Runs Markowitz report on that selected set
SMB, HML, WML Meaning
-
SMB(Small Minus Big): size factor -
Positive means tilt toward small-cap stocks
-
Negative means tilt toward large-cap stocks
-
HML(High Minus Low): value factor -
Positive means tilt toward value stocks (high book-to-market)
-
Negative means tilt toward growth stocks
-
WML(Winners Minus Losers): momentum factor -
Positive means tilt toward recent outperformers
-
Negative means tilt toward anti-momentum / reversal
Preference Input Format
Provide factor preferences using -1 to +1:
preference = {
"beta_smb": 1.0, # small-cap tilt
"beta_hml": 1.0, # value tilt
"beta_wml": 1.0, # momentum tilt
}
Examples:
- Small + Value + Momentum:
{"beta_smb": 1.0, "beta_hml": 1.0, "beta_wml": 1.0} - Large + Growth:
{"beta_smb": -1.0, "beta_hml": -1.0} - Neutral on momentum:
{"beta_smb": 0.5, "beta_hml": 0.5, "beta_wml": 0.0}
Example Code
from kiteconnect import KiteConnect
from zerodha_portfolio import generate_fama_french_markowitz_report
kite = KiteConnect(api_key="your_api_key", timeout=30)
kite.set_access_token("your_access_token")
result = generate_fama_french_markowitz_report(
kite=kite,
candidate_quantities={
"RELIANCE": 18,
"TCS": 24,
"INFY": 32,
"HDFCBANK": 20,
"ICICIBANK": 28,
"SBIN": 45,
},
start_date="2022-01-01",
end_date="2026-02-28",
frequency="daily",
preference={"beta_smb": -1.0, "beta_hml": 1.0, "beta_wml": 1.0},
top_n=12,
output_file_name="ff_markowitz_report",
risk_free_rate=0.06,
# Optional fallback if download URL changes:
# factor_file_path=r"C:\\path\\to\\ff_file.csv",
)
print(result["output_html"])
print(result["ff_selected_weights"])
Example Script and Sample Report
- Script:
examples/example_ff_markowitz.py - Sample output:
examples/ff_markowitz_report.html
API Summary
generate_markowitz_report(...)generate_fama_french_markowitz_report(...)download_ff_factor_files(...)load_ff_factors(...)estimate_stock_factor_betas(...)build_factor_tilt_portfolio(...)
Backward-compatible import is preserved:
from zerodha_markowitz import generate_markowitz_report
Output File Behavior
output_html: full output path (highest priority)output_file_name: file name only (saved in script run directory)- If neither is given, a default name is used:
- Markowitz:
markowitz_report.html - FF-Markowitz:
ff_markowitz_report.html
- Markowitz:
Data Source
- IIMA Indian Fama-French + Momentum dataset: https://faculty.iima.ac.in/iffm/Indian-Fama-French-Momentum/
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zerodha_portfolio-0.2.1.tar.gz.
File metadata
- Download URL: zerodha_portfolio-0.2.1.tar.gz
- Upload date:
- Size: 833.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
729e0d208e374596cf1d931c503da41c6214e5e2135577e0c9d63204a0558332
|
|
| MD5 |
fd1b7159407da5d8e7948e1a4f035162
|
|
| BLAKE2b-256 |
d79bdf69f93c6c1f0f181880a24a8a0f224c69fcaea07ebc43a35ca5a8b4668d
|
File details
Details for the file zerodha_portfolio-0.2.1-py3-none-any.whl.
File metadata
- Download URL: zerodha_portfolio-0.2.1-py3-none-any.whl
- Upload date:
- Size: 26.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1f26e8c98b778150d38715e76f183c753b6850a3497f45cbabbd0bcbac6d554
|
|
| MD5 |
387a08b6f1c40bfc06b71d5419ef43a2
|
|
| BLAKE2b-256 |
27994c263643ef46047c6f220b988698fc8c88da4e9eab4e26a545cc5596f685
|