BVB Index Distribution

About this app

This project compares a personal BVB portfolio against the BET index distribution and suggests how to invest available cash to move the portfolio closer to the index — using buy-only allocations (no selling).

Everything runs as a static GitHub Pages app: no backend, no database. Data is loaded directly from the repository (CSV + JSON snapshots) and computed in the browser.

Pages

Technical overview

Stack

  • Frontend: HTML + CSS + vanilla JavaScript (no framework).
  • Charts: Chart.js (CDN) for Allocation History.
  • Hosting: GitHub Pages (static site).
  • Automation: GitHub Actions for daily scraping.
  • Scraper: Python script (scripts/scrape_bvb.py).

Data flow

  • The app reads CSV/JSON directly from the repo (static snapshots).
  • A GitHub Action runs daily, fetches fresh BET weights, and commits a new snapshot file.
  • The UI always uses the latest committed snapshot (deterministic + reproducible).
  • The Allocation History page lists daily CSVs via the GitHub Contents API and loads them from raw GitHub URLs.
Why static snapshots?
It ensures the app works without a backend and can reproduce results for any past day by using the committed files. It also avoids rate limits and availability issues of querying live sources from the browser.

Index data (BET weights)

BET weights are stored as daily CSV snapshots under input/bvb_distribution/. A separate process (GitHub Actions + Python) fetches the data once per day and commits:

CSV format example:

symbol,weight
TLV,19.92
SNP,18.59
SNG,11.59
H2O,11.39
...

The app normalizes weights to 100% for the selected universe (symbols present in the snapshot), then uses these normalized weights as the target.

Allocation History (time-series)

The Allocation History page visualizes how index weights change across the daily snapshots. By default it loads the last 3 months (or all available if fewer).

Data is loaded directly from the repository using GitHub’s Contents API (file list) + raw GitHub URLs (CSV content).

Portfolio input formats

1) Portfolio CSV upload

Upload a CSV with the following format:

symbol,value
SNP,126506.66
TLV,122179.18
SNG,77051.70
H2O,75628.80
BRD,45400.00
...
CASH_VALUE,12023.80

Currency is not enforced; calculations assume all values are in the same currency.

2) TradeVille copy / paste import

You can paste the TradeVille portfolio table directly. The parser is intentionally tolerant: it ignores headers and extra text, and extracts instrument rows it can safely parse.

Example (realistic TradeVille paste):

Instrumente BVB in RON
simbol    Nume                       sold     Pret piata   evaluare      Pondere
SNP       OMV Petrom                 128,368  0.9855       126,506.66    20.54%
TLV       Banca Transilvania         4,027    30.34        122,179.18    19.84%
SNG       S.n.g.n. Romgaz            7,783    9.90         77,051.70     12.51%
H2O       Hidroelectrica             606      124.8        75,628.80     12.28%
...
RON       RON                        12,023.80

Tracker calculations

1) Portfolio weights

2) Index weights

3) Differences table

The main table shows both:

Buy-only suggestion algorithm (with fees)

When Enable New Investment is ON, the app proposes buy-only allocations that aim to reduce deviation from the index, while respecting real trading constraints.

Constraints

High-level approach

  1. Compute target value per symbol from normalized index weights and current portfolio total.
  2. Compute “underweight” symbols (those below target).
  3. Allocate budget iteratively:
    • Start from most underweight.
    • Propose a feasible order: whole shares at market price + estimated fee.
    • Respect minimum-per-symbol and remaining cash.
    • After initial pass, spend remaining cash to further reduce deviation (even if improvement is small), while still respecting min-per-symbol and fees.
  4. Show results as:
    • “Investment Suggestions” cards (per symbol: shares × price + fee).
    • “Portfolio after applying suggestions” table to validate the new weights/differences.
Note: Fees are estimates and stored as a static snapshot (for reproducibility). The tier selection is based on total portfolio value (stocks + cash) and uses the best available snapshot in the repo.

Disclaimer

This tool is for personal tracking and convenience only. It does not provide financial advice. Always verify orders, prices, and fees in your broker before trading.