---
name: "fund_portfolio_analysis"
description: "Analyze mutual fund and ETF portfolios: compare fund costs and share classes, run Brinson performance attribution, measure correlation and overlap, and assess bond rate risk. Use when a fund lineup, fee stack, attribution report, or diversification question needs real numbers instead of guesses."
metadata: { "includeInPrompt": true }
---

# Fund Portfolio Analysis

## Purpose
Give agents a working method for the five jobs that keep coming up around pooled funds:
pick the cheapest share class for a given horizon, stack up a fund's full cost of ownership,
explain where active return came from, check whether two funds are really different,
and measure what rate moves do to a bond position. Every claim traces back to primary
sources in `references/` and `scratch` notes, or it gets cut.

## Workflow

### 1. Compare fund costs and share classes
- Gather, from the prospectus or fact sheet: front-end load, CDSC schedule, 12b-1 fee,
  other expenses, total expense ratio, minimums, and breakpoint schedule.
- Quick read: A shares carry a front-end load (typically 4 to 5.75%) and low 12b-1 fees
  (0 to 50bps), so they win on long horizons, especially with breakpoints.
  C shares have no front load and low ongoing costs elsewhere, but their 12b-1 fee
  (typically 75 to 100bps) keeps compounding, so they suit horizons under ~5 to 7 years.
  B shares are legacy, with a declining back-end load and conversion to A after some years.
  Institutional/I shares have no loads, no 12b-1, lowest expense ratios, but high minimums.
- Run the numbers, don't eyeball them:
  `bin/fund-analysis.py share-class --amount 100000 --years 10 --return 0.07 ...`
  Report the cheapest class at 1, 3, 5, and 10 year horizons and where the crossover sits.
- For ETFs, skip the loads and stack the full cost: expense ratio + tracking difference
  + bid-ask spread + premium or discount at trade time + tax drag. A fund with a higher
  expense ratio can still be cheaper to own if it tracks tighter (securities lending
  income sometimes pushes tracking difference below the fee). Compare tracking difference
  over three to five years, never one.

### 2. Attribute performance
- Use the Brinson-Hood-Beebower decomposition on sector or asset-class slices:
  Allocation = (wp - wb) x (rb_sector - rb_total), Selection = wb x (rp_sector - rb_sector),
  Interaction = (wp - wb) x (rp_sector - rb_sector). Sum equals active return; if it
  doesn't, the inputs are wrong.
- Inputs: per-segment portfolio weight, benchmark weight, portfolio return, benchmark
  return, and the total benchmark return. Same period, beginning-of-period weights.
- `bin/fund-analysis.py attribution --segments file.json` where each entry holds
  `portfolio_weight`, `benchmark_weight`, `portfolio_return`, `benchmark_return`.
- Read the result as a story: allocation tells whether the big bets were in the right
  sectors, selection tells whether the picks inside each sector beat the benchmark's,
  interaction tells whether overweighting and outpicking lined up together.
  Information ratio = active return / tracking error; above 0.5 is evidence of skill,
  above 1.0 is exceptional (Grinold and Kahn, 1999).

### 3. Check correlation and overlap
- Pull monthly total-return series for each fund (three to five years) and compute the
  Pearson correlation matrix: `bin/fund-analysis.py corr --returns file.csv`.
- Rule of thumb: 0.90+ means the two funds are doing the same job and one is redundant;
  0.70 to 0.90 is concentrated risk; below 0.30 is a real diversifier. Average pairwise
  correlation summarizes the whole lineup.
- Cross-check with holdings overlap. High return correlation with low holdings overlap
  still means the same factor exposure (two large-cap funds correlate near 1.0 even with
  different picks). Names differ, economic exposure stays similar. And watch out for
  cap-weight concentration: multiple index funds can just be the same mega-caps restated.
- Caveat in the output: correlations spike toward 1.0 in crises, exactly when you want
  them low. Report the measurement window.

### 4. Value bonds and measure rate risk
- From coupon, maturity, and yield: `bin/fund-analysis.py bond --face 1000 --coupon 0.05
  --maturity 10 --yield 0.06 --periods 2` returns price, Macaulay and modified duration,
  convexity, and PV01.
- Plain reading: modified duration is roughly the % price move for a 1% yield move.
  A duration of 7.4 means +1% yield costs about 7.4% of price. Duration rises with longer
  maturity, lower coupons, and lower yields. Portfolio duration is the market-value-weighted
  average of the parts.
- For bonds with embedded options (callable, puttable) or MBS, prefer effective duration
  computed from actual prices at shifted yields, and note that callable paper can show
  negative convexity: rate moves hurt more than duration says.
- Every analysis ends with the same line: the measurement window, the source of each
  input, and one sentence saying which number is an estimate.

## Output Contract
- A fund cost comparison reports the cheapest option per horizon and the crossover year.
- An attribution report gives per-segment allocation, selection, interaction, and total
  active return, with weights and returns stated.
- A correlation check gives the matrix, flagged redundant pairs, and the measurement window.
- A bond analysis gives price, durations, convexity, PV01, and a plain-language read of
  what a 1% rate move does.
- No claim without a source. Hypothetical examples are labeled hypothetical.

## Operating Rules
1. Verify every factual claim against a primary source: prospectus, fact sheet, official
   docs, or a cited standard. Unverifiable numbers get cut, not hedged.
2. Never invent fund facts. Real fund names only with real current numbers from a live
   source; otherwise use clearly labeled hypothetical examples.
3. Run the CLI for every calculation. Do the arithmetic in the script, not in the head.
4. Labels matter: expense ratio is not total cost, tracking difference is not tracking
   error, correlation is not overlap, modified duration is not effective duration.
   State which one is being reported.
5. This skill is educational analysis, not investment advice. Say that when the output
   goes anywhere near a real decision.
