Automates a daily portfolio snapshot using Hargreaves Lansdown prices. It reads your holdings, scrapes current prices, computes portfolio values, stores a rolling history in daily_totals.csv, renders an HTML summary, and can notify you by push and optionally email.
python main.pyis the main entrypoint.- The GitHub Actions workflow runs the same entrypoint on a schedule.
- Holdings data is expected in
HL_Daily_Prices_Data/units.csvwhen running in automation. - Outputs are written locally to:
daily_totals.csvsummaries/daily_summary-YYYY-MM-DD.htmlsummaries/latest.html
main.pyorchestrates the run.pull_and_collate.pyloads holdings, scrapes HL, and builds the portfolio DataFrame.persistence.pyupdates daily history and loads prior snapshots.html_summary.pybuilds the HTML report.notifications.pyformats and sends push/email notifications..github/workflows/daily.ymlruns the scheduled job.
- Create and activate a virtual environment.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt- Provide holdings data.
- Copy your private
units.csvintoHL_Daily_Prices_Data/units.csv, or adapt the path if you are running differently. sample_units.csvis an example shape only.
Expected columns in units.csv:
fundunitsurl
- Optional notification config in
.env.
Push via ntfy:
NTFY_BASE_URL=https://ntfy.sh
NTFY_TOPIC=your_reserved_or_random_topic
NTFY_TOKEN=your_token_if_requiredEmail via SMTP:
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your_email@example.com
SMTP_PASS=your_app_password
EMAIL_FROM=your_email@example.com
EMAIL_TO=recipient@example.com- Run it.
python main.pyRun the lightweight verification suite locally:
python -m py_compile main.py config.py persistence.py notifications.py pull_and_collate.py price_scraper.py html_summary.py
pytestThe tests cover stable helpers only: history lookup, push formatting, price parsing, and deterministic transformation logic. They do not hit live network services.
The workflow in .github/workflows/daily.yml:
- checks out this repo
- installs dependencies
- clones the private data repo
- seeds prior
daily_totals.csvhistory if available - runs
python main.py - uploads outputs as artifacts
- commits refreshed outputs back to the private data repo
Required secrets for the current workflow:
DATA_REPO_TOKENNTFY_TOPIC- optional
NTFY_BASE_URL - optional
NTFY_TOKEN
- Generated outputs and local/private data are intentionally ignored by git.
- If you use
ntfy.sh, a reserved topic plusNTFY_TOKENis the secure setup. A public guessable topic is not. - Email is optional. If SMTP settings are not present, email sending is skipped.