← Documentation

Stock Portfolio Analyzer: Architecture

A Streamlit app (app.py) that only draws screens, on top of a portfolio/ package that does all the calculations. It runs locally with uv and Python 3.12.

app.py · Streamlit UI (screen layout only) portfolio/ calculations, no UI You CSV · manual form Tab 1 Input Transactions session_state.tx transactions in memory Tab 2 Current Portfolio Tab 3 Historical Performance loader.py read & check CSV holdings.py replay trades prices.py yfinance, cached performance.py metrics · XIRR · series data/transactions.csv saved on disk Yahoo Finance only network call tests/ · pytest 18 tests, offline upload raw rows validated transactions positions current prices metrics · chart history current value save / load fetch · cache 15/60 min verifies math
Every number on screen comes from the portfolio/ package. app.py only passes data between modules and draws the results. Yahoo Finance (orange) is the only network call. If it fails, prices.py falls back to each stock's last trade price, so the app still works offline. performance.py also reads the dated transactions to build XIRR cash flows and the daily value series.

How data flows

  1. Upload. In Tab 1 you upload a CSV, load the sample or fill in the manual form.
  2. Validate. loader.normalize_transactions maps column names (for example ticker to symbol), checks every row and reports bad CSV lines.
  3. Save. Valid rows go into st.session_state.tx and are written to data/transactions.csv, so they survive a restart.
  4. Replay trades. holdings.compute_positions goes through the trades in date order and works out the quantity, average cost and realized profit for each stock.
  5. Price. prices.current_prices gets live closing prices from yfinance (cached for 15 minutes). For any stock it can't price, it uses the last trade price.
  6. Measure. performance.performance_summary works out the lifetime totals and xirr. value_over_time combines daily holdings with the price history (cached for 60 minutes).
  7. Render. Tab 2 shows the allocation pie and the Stock Price Breakdown table. Tab 3 shows the six metrics and the trend line.

Modules

FileResponsibilityKey functions
app.pySidebar and three tabs; session state; formattingsave_transactions, add_transactions, money, pct
portfolio/loader.pyRead and check the CSV; save and load the transactions filenormalize_transactions, read_transactions_csv, load_saved, save
portfolio/holdings.pyReplay trades into positionscompute_positions, open_positions, last_trade_prices
portfolio/prices.pyyfinance calls, cached with st.cache_datafetch_live_prices, fetch_price_history, current_prices, clear_cache
portfolio/performance.pyLifetime metrics, XIRR, daily value seriesperformance_summary, xirr, value_over_time
tests/Offline checks against hand-worked sample numberstest_loader.py, test_holdings.py, test_performance.py
pyproject.toml, uv.lockuv project: Streamlit, yfinance, pandas, plotly; pytest for developmentuv run streamlit run app.py, uv run pytest

Key rules