Interactive portfolio visualizations for M1 Finance investors
Project description
M1 Portfolio Kit
Better charts for your M1 Finance portfolio. Drop in your holdings CSV and get interactive visualizations that M1's built-in interface doesn't offer.
Runs entirely on your local machine — your financial data never leaves your computer.
Features
Portfolio Heatmap (Landing View)
A treemap heatmap greets you on upload — positions grouped by sector, sized by current value, colored by unrealized return. Click any tile to open a detail panel showing value, cost basis, return, and snapshot-over-snapshot trends for that position.
Charts
| Tab | What it answers |
|---|---|
| 🥧 Allocation | What percentage of my portfolio is each position? |
| 💵 Gain / Loss ($) | Which positions are making or losing me the most dollars? |
| 📊 Gain / Loss (%) | Which positions have the best/worst return rate, regardless of size? |
| ⚖️ Cost vs Value | What did I pay vs what is it worth now? |
| 🎯 Return vs Weight | Are my biggest positions also my best performers? |
| 🕸️ Radar | How does my portfolio score across performance, diversification, and efficiency? |
| 📊 Concentration | How concentrated is my portfolio? HHI score, top-N weight, weight distribution. |
Multi-Snapshot Time-Series Tracking
Upload multiple CSVs (one per export date) to track your portfolio over time:
- 📅 Timeline — Line chart of total portfolio value across snapshots; optional SPY/QQQ overlay
- 📈 Position Trend — Track individual position value and weight across time
- 🔄 Snapshot Diff — Compare oldest vs newest: held positions with deltas, new entries, closed positions
Benchmark Comparison (opt-in)
Enable SPY and/or QQQ overlays on the Timeline tab. Both portfolio and benchmarks are normalized to % return from the first snapshot date for a fair comparison. Requires internet — the checkbox is clearly labeled and off by default.
Concentration Analysis
The Concentration tab gives you three lenses on portfolio concentration — all computed from your CSV with no external data:
- HHI Score — Herfindahl-Hirschman Index (0–10,000). Labeled: Diversified / Moderate / Concentrated.
- Top-N Weight — Cumulative % held in your top N positions. Slider adjustable.
- Weight Distribution — Histogram of position weights across your portfolio.
Privacy Guarantee
No data is written to disk. Uploaded CSVs live in memory for the browser session only. Phase 1 and Phase 2 make zero network requests. The benchmark overlay is strictly opt-in and clearly labeled.
Setup
pip (quickest)
pip install m1-portfolio-kit
m1kit
The app opens at http://localhost:8501.
To enable the optional SPY/QQQ benchmark overlay: pip install "m1-portfolio-kit[benchmarks]"
Docker (no Python required)
docker build -t m1-portfolio-kit .
docker run -p 8501:8501 m1-portfolio-kit
The app opens at http://localhost:8501.
To enable the optional SPY/QQQ benchmark overlay, add RUN pip install yfinance after the
pip install -r requirements.txt line in the Dockerfile before building.
From source
Requires Python 3.10+
git clone https://github.com/JaydotMurf/m1-portfolio-kit.git
cd m1-portfolio-kit
python -m venv venv && source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
streamlit run app.py
Getting your M1 CSV
- Log in to M1 Finance
- Go to Invest → Portfolio → Holdings
- Click the ... overflow menu (top right of the holdings list)
- Select Export CSV
- Save the file — no renaming needed
- Upload it in the app
The export includes all positions with cost basis, current value, and unrealized gain/loss. M1 does not include closed positions in this export.
Contributing
See CONTRIBUTING.md for setup, test, and PR instructions.
Roadmap
- Phase 1 — Single snapshot analysis (heatmap, 7 charts, summary metrics, radar)
- Phase 2 — Multi-snapshot time-series tracking (timeline, position trends, snapshot diffs)
- Phase 3 — Benchmark overlay, sector classification, heatmap landing, click-to-detail
- Phase 4 — Concentration metrics (HHI, top-N weight, weight histogram)
- Phase 5 — Packaging and distribution (Docker, PyPI,
m1kitCLI)
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 m1_portfolio_kit-1.0.0.tar.gz.
File metadata
- Download URL: m1_portfolio_kit-1.0.0.tar.gz
- Upload date:
- Size: 1.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc3bff51faa36fb0320227fced3bb489b90b2682df4bdfdd33a6899d794204d8
|
|
| MD5 |
c845d7eb08040b137c68945e4afd4e12
|
|
| BLAKE2b-256 |
b5435ead2d98b716e5d0de360cd1d67bae710c8fbccaad6fb1d7b653049ab87c
|
Provenance
The following attestation bundles were made for m1_portfolio_kit-1.0.0.tar.gz:
Publisher:
release.yml on JaydotMurf/m1-portfolio-kit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
m1_portfolio_kit-1.0.0.tar.gz -
Subject digest:
bc3bff51faa36fb0320227fced3bb489b90b2682df4bdfdd33a6899d794204d8 - Sigstore transparency entry: 1635391477
- Sigstore integration time:
-
Permalink:
JaydotMurf/m1-portfolio-kit@6defe4ffe5c768952a0396cf8da50684502b9d49 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/JaydotMurf
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6defe4ffe5c768952a0396cf8da50684502b9d49 -
Trigger Event:
push
-
Statement type:
File details
Details for the file m1_portfolio_kit-1.0.0-py3-none-any.whl.
File metadata
- Download URL: m1_portfolio_kit-1.0.0-py3-none-any.whl
- Upload date:
- Size: 20.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
584fec323224fdb9f3dafad08f5d9d4b2feb8bb50f46da344f8b618f20ff9213
|
|
| MD5 |
33c8d6073c9c779d410412add525f48c
|
|
| BLAKE2b-256 |
3de61ba8f2629be178815c94454e714a45e06a751c8a56b6ad586b10ac8ab84d
|
Provenance
The following attestation bundles were made for m1_portfolio_kit-1.0.0-py3-none-any.whl:
Publisher:
release.yml on JaydotMurf/m1-portfolio-kit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
m1_portfolio_kit-1.0.0-py3-none-any.whl -
Subject digest:
584fec323224fdb9f3dafad08f5d9d4b2feb8bb50f46da344f8b618f20ff9213 - Sigstore transparency entry: 1635391503
- Sigstore integration time:
-
Permalink:
JaydotMurf/m1-portfolio-kit@6defe4ffe5c768952a0396cf8da50684502b9d49 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/JaydotMurf
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6defe4ffe5c768952a0396cf8da50684502b9d49 -
Trigger Event:
push
-
Statement type: