Build a Portfolio Sector Weight Analyzer in Python

Day 70 of 100 Days Coding Challenge: Python

Yesterday’s mission was neat labels; today’s mission is guardrails. After building a sector classifier, I wired up a real diversification warning that uses my actual holdings. Diversification isn’t a hedge against everything, but it’s a reliable seatbelt against unsystematic risk—the “one company or one industry sneezes, and my portfolio catches a cold” problem. During COVID, anyone parked entirely in hospitality learned this the hard way.

This little alarm is more than a nag; it’s a planning tool. You can use it for sector rotation, thematic tilts, or just sanity checks alongside momentum and RSI. I also like it for quick overlap checks: if a few ETFs secretly pile into the same sector, this makes the crowding visible. Honestly, the feature pays off all the tiny utilities I’ve been adding—now they sing together instead of humming alone.

Today’s Motivation / Challenge

I wanted a single, honest number that says, “Are you concentrated or not?” The challenge: turn tickers into sectors, sectors into dollars, and dollars into weights—without burying the user in math or menus.

Purpose of the Code (Object)

The program reads your tracked tickers and your share counts, fetches current prices, and calculates market value per holding. It then groups by sector (treating multi-sector and bond ETFs as their own diversified buckets) and shows each sector’s weight. If any one slice is larger than your chosen threshold, you get a clear warning.

AI Prompt

“Refactor the diversification function to be small, readable, and robust. Keep inputs flexible, handle ETFs cleanly, and print a concise sector weight table followed by any threshold warnings.”

Functions & Features

  • Record or update shares for each tracked symbol.
  • Classify holdings by sector, with special handling for multi-sector and bond ETFs.
  • Compute sector weights using Market Value = Shares × Price.
  • Trigger a diversification warning if any sector exceeds a threshold (e.g., 35%).

Requirements / Setup

  • Python 3.10+

Install:

pip install yfinance pandas matplotlib

Minimal Code Sample

def sector_weights(rows, threshold=0.35):

    # rows: list of {symbol, sector, shares, price}

    df = pd.DataFrame(rows)

    df[“market_value”] = df[“shares”] * df[“price”]

    total = df[“market_value”].sum()

    if total <= 0:

        return {}, []

    weights = (df.groupby(“sector”)[“market_value”].sum() / total).sort_values(ascending=False)

    offenders = [(s, w) for s, w in weights.items() if w >= threshold]

    return dict(weights), offenders

Compute sector weights from actual dollars; return all weights plus any over the threshold.

Stock Tracker

Notes / Lessons Learned

I initially forgot to store share counts. Which meant every stock was treated like I owned exactly one share—cute for demos, terrible for truth. I was sure I’d written a “set shares” function before; apparently Past Me left Future Me a polite illusion. Once I added a quick way to save shares in stocks.json, the numbers snapped into place.

The joy here is leverage: Python fetches prices, lines up sectors, and crunches totals in seconds. What used to be a spreadsheet slog is now a button press. Also, beware ETF overlap—their tickers look diverse, but their guts sometimes aren’t.

Optional Ideas for Expansion

  • Add “max sector cap” rules per account and print suggested trades to rebalance.
  • Show a tiny trendline of each sector’s weight over time (store daily snapshots).
  • Include an “overlap matrix” for ETFs using their published holdings, if available.