Back to catalog

portfolio-analysis

Analyse Indian stock and MF portfolio from broker exports.

Category ๐Ÿ’ฐ Wealth

Portfolio Analysis

When to use

When Joseph provides current holdings (stocks + mutual funds from Indian brokers) and asks for a portfolio-level analysis. Only Indian market โ€” NSE/BSE stocks, SEBI-registered MFs.

Prerequisites

  • Holdings data in wiki/wealth/invest/portfolio/raw/ (CSVs from ICICI Direct / Zerodha)
  • compute_ratios.py from indian-stock-analysis skill for ratio computation
  • Screener.in for stock fundamentals
  • Value Research Online or AMFI for MF data

Folder Structure

portfolio/
โ”œโ”€โ”€ raw/                  โ† Source files from brokers
โ”œโ”€โ”€ analysis/             โ† Per-stock and per-MF analysis
โ”‚   โ”œโ”€โ”€ stocks-consolidated.md
โ”‚   โ”œโ”€โ”€ mf-consolidated.md
โ”‚   โ””โ”€โ”€ overlap-analysis.md
โ”œโ”€โ”€ reports/              โ† Dated portfolio reports
โ”‚   โ””โ”€โ”€ YYYY-MM-DD-portfolio-report.md
โ””โ”€โ”€ README.md

Workflow

1. Ingest & Deduplicate

1. Parse each broker CSV โ†’ extract ticker/scheme, quantity/units, buy price, current value

2. Deduplicate: same stock in ICICI + Zerodha โ†’ merge quantities, average buy price

3. Write raw/ cleaned files + analysis/stocks-consolidated.md and analysis/mf-consolidated.md

2. Stock Analysis (per stock)

1. Pull Screener.in data via extract_screener_summary.js (summary + CAGR + PROS/CONS)

2. Compute ratios via compute_ratios.py โ€” P/E, PEG, ROCE, ROE, D/E, CFO/PAT, earnings yield

3. Classify: dividend compounder / growth compounder / cyclical / deep value

4. Check sector weight in total portfolio

5. Write per-stock file: analysis/{ticker}.md

3. MF Analysis (per fund)

1. Pull fund data: NAV, AUM, expense ratio, 3Y/5Y returns, category

2. Extract top 10 holdings + sector allocation โ€” sources in order of reliability:

  • Value Research (best for NAV, expense, returns, star rating)
  • ETMoney (best for sector allocation %, market cap split)
  • INDmoney (best for top holdings with % weights)
  • Groww (backup for holdings, mid-tier positions)
  • Economic Times (backup for sector, asset allocation)

3. Classify: large-cap / mid-cap / flexi / ELSS / debt / hybrid

4. Check expense ratio vs category average, return consistency

5. Quality rating per dimension (expense, AUM, returns, management, diversification) using โ˜… scale

6. Write per-MF file: analysis/{scheme-slug}.md

4. Overlap & Concentration

1. Full equity exposure = direct stocks + stocks inside MFs

2. Estimate MF stock exposure: Use published portfolio weights ร— MF value (e.g., Coal India 4.91% ร— Parag Parikh FC โ‚น34L = โ‚น1.67L inside MF)

3. Direct + MF overlap: Flag stocks held both directly and inside any MF. Assess if overlap is material (>10% of direct position).

4. MF-to-MF overlap: Build a holdings matrix across all funds. Identify stocks appearing in 3+ funds (HDFC Bank, ICICI Bank are common offenders).

5. Sector concentration: Map every direct stock to a sector. Compute sector % of direct portfolio. Then add estimated MF sector allocation for combined view.

6. Concentration metrics: Top 5 stocks as % of direct, Herfindahl-style concentration, single-stock risk (any position >15% of direct).

7. Flag: over-concentrated sectors (>30% in one sector), redundant funds (same mandate + same holdings), dead money (<โ‚น1L with no catalyst), duplicated ETFs.

8. Write analysis/overlap-analysis.md

5. Portfolio Report

Assemble reports/YYYY-MM-DD-portfolio-report.md:

Section 1 โ€” Executive Summary
  • Total portfolio value, asset class breakdown (stocks, MFs, ETFs, liquid)
  • Equity exposure %, cash/liquid %
  • Portfolio character (1-2 sentences: concentrated? diversified? cyclical tilt?)
Section 2 โ€” Stock Holdings
  • Tier by value: Crown Jewels (>โ‚น10L), Quality (โ‚น5-10L), Smaller (โ‚น1-5L), Tiny (<โ‚น1L)
  • Per stock: strategy, buy price โ†’ CMP, return multiple, P/E, ROCE, Div yield, D/E
  • One-line assessment per stock: Hold / Trim / Exit with reasoning
Section 3 โ€” MF Holdings
  • Per fund: category, NAV, expense, AUM, 3Y/5Y returns vs category, star rating
  • Overlap flags (which direct stocks are inside this fund, which other funds hold same stocks)
  • Quality rating and assessment
Section 4 โ€” ETF Holdings
  • Table: ETF, value, type, action (keep/exit/consolidate)
Section 5 โ€” Concentration Risk
  • Stock-level: top 5 as % of direct, single-stock risk
  • Sector-level: sector breakdown with % of direct
  • MF-level: dominant fund, sector overlap inside MFs
Section 6 โ€” Action Items
  • High priority (trim/exit >โ‚น5L positions or concentration fixes)
  • Medium priority (cost optimization, redundancy cleanup)
  • Low priority (tiny positions, monitoring)
Section 7 โ€” Review Schedule
  • Monthly: execution tracking
  • Quarterly: performance vs category, drift check
  • Semi-annually: full re-analysis
  • Trigger-based: exit conditions per position
Appendix โ€” Full Valuation Matrix
  • All stocks in one table: CMP, P/E, ROCE, Div %, D/E, Value, % of portfolio

Guardrails

Data Provenance (Anti-Hallucination)

  • Every number cites its source: Screener.in / Value Research / AMFI / user input
  • No number without a source tag
  • Unavailable data โ†’ [not available], never fabricated

Computation Rules

  • Ratios already on Screener.in (P/E, ROCE, ROE, D/E, dividend yield, book value) โ†’ use directly, NEVER recompute
  • Ratios NOT on Screener.in (PEG, CFO/PAT, earnings yield, normalized dividend yield) โ†’ compute via compute_ratios.py
  • Validation for computed ratios: script outputs formula + inputs + result for every computed ratio. Example: PEG = P/E (28.3) รท PAT CAGR (18.7%) = 1.51
  • If Screener.in shows a ratio, use it. If it doesn't, compute it. Never recompute what's already there.

Output

  • Nested bullet lists (NOT tables โ€” Slack readability)
  • Every recommendation backed by numbers above it
  • Risk rating: low / medium / high with specific reason

Explicitly Won't

  • Predict prices or targets
  • Give timing advice ("buy before Q3 results")
  • Use unverifiable data sources
  • Mix currencies or markets

Transaction History (Phase 2)

When user provides full broker export (CSV with all trades):

1. Compute XIRR per stock and per MF

2. Identify dead money (<12% XIRR held 5+ years)

3. Map cost basis vs current value

4. Add XIRR section to portfolio report

Pitfalls

1. ICICI Direct and Zerodha CSVs have different formats โ€” parse each separately, don't assume same columns

2. MF scheme names vary across platforms โ€” "HDFC Mid-Cap Opportunities Fund - Growth" vs "HDFCMIDCAP โ€” G" โ€” normalize to scheme name

3. Quantity merging โ€” if same stock in both brokers, sum quantities but keep buy prices separate (can't average without transaction dates)

4. MF overlap is sneaky โ€” 3 flexi-cap funds can hold 60%+ of the same stocks. Always compute actual overlap, don't guess from fund names

5. Screener.in login wall โ€” consolidated data needs login. Standalone page works for summary + CAGR. Use standalone unless consolidated is critical.

6. Binary file reads โ€” some consolidated markdown files may read as binary. Use terminal with cat as fallback when read_file returns binary error.

7. Sector extraction from stock files โ€” sector/industry fields may not have consistent headers. Search for "Strategy bucket" or "Classification" instead of "Sector:".

8. MF NAV discrepancy โ€” consolidated file NAVs may be from earlier dates. Always use current NAV from Value Research/AMFI for per-fund analysis, note the discrepancy.

9. Regular vs Direct plan โ€” ICICI Direct often holds Regular plans (higher expense). Flag the expense gap and suggest switching to Direct if holding long-term.

10. ETFs don't have fundamentals โ€” skip Screener.in for ETFs. Track price/return only. Don't try to compute P/E or ROCE for gold/silver/index ETFs.