Skip to content

v0.6.0

Choose a tag to compare

@ptu-gh ptu-gh released this 18 Oct 08:07
· 126 commits to main since this release

wealthdb now shows what is really owned. The new exposure report looks
through every fund to the securities it holds, adds what is held
directly, and answers by asset class, sector, country, currency and
security, as of any day. It also says where each holding legally sits.
The fund data comes from public sources through a new collector,
refdata. The report is on the command line, over MCP, in the
read-only skill and in a new Exposure dashboard.

Upgrading

  1. Rebuild with make all. Gold migrations 0125 to 0133 apply on the
    first read-write open. Nothing re-parses and no reload is needed.
  2. Set up reference data. Add a refdata silver source to
    wealthdb.cfg, and write ~/.config/refdata.cfg with the providers
    to ask and the contact the SEC requires. Then
    ./collectors/refdata/refdata download (--backfill also fetches
    the months each fund was held), ./collectors/refdata/refdata load
    and wealthdb load refdata. Without it the report still runs: every
    fund is then a leaf of its own and exposure coverage says so.
  3. Describe what no public source knows, if you want: the exposure
    block of wealthdb.cfg and a declarations ledger. wealthdb exposure coverage -f ndjson prints a skeleton record for every
    holding still to declare.
  4. Run wealthdb web refresh, then wealthdb mcp restart. The
    dashboards read new serving tables that the refresh fills. A
    running MCP server refuses a schema newer than its binary.
  5. make demo rebuilds the demo household. It has a synthetic
    reference-data source, so every exposure view and the dashboard
    work on it.

Breaking for scripts and config

  • wealthdb web start, restart and refresh exit 3 when the gold
    snapshot is older than the dashboards need, and say to run web refresh. Before, start printed a wrong hint and exited 0.
  • The transfer-override ledger refuses a column it does not know, as
    the pins ledger does. note is still allowed.
  • A collector's prune refuses --silver-db. A relative --data-dir
    or --secrets-dir mounts that directory of the host; before, Docker
    made a named volume of it.
  • A collector load never reads a download without a manifest
    (run.json), also in the passes that re-read the whole bronze tree.
  • UBS advice, custody and ADR handling charges are investment fees.
    They were other bank fees. The spending figures move between those
    two categories on the next load.
  • A malformed relationships[].psn_start_override in wealthdb.cfg
    fails every command at config load, not only the UBS one.

Exposure

  • wealthdb exposure <view> reports what is really owned, as of a day
    or at the end of every period of a window (--period): classes,
    sectors, sizes, countries, currencies, situs, securities,
    funds and coverage. Every view sums to net worth as holdings global gives it. See wealthdb/docs/EXPOSURE.md.
  • The look-through replaces a fund by its lines, a fund of funds down
    to three levels, and keeps what the weights leave unexplained as a
    remainder. Each holding joins the fund composition nearest its day,
    within exposure.max_gap_days (default 400).
  • A security's sector and country come from what the sources say about
    it: its issuer's filings, GLEIF, OpenFIGI, the fund lines that name
    it. A depositary receipt reads as the share it stands for. A bond
    held directly reads its type, else its description. Public equity is
    sized large, mid or small by market cap, and where no market cap is
    known, by the weights of broad size_funds.
  • countries gives the country of risk; --country domicile the
    country of incorporation. situs gives the one country whose law
    each holding is an interest under, with no fund looked through: a
    fund at its domicile, a share at its issuer, cash at its bank, a
    property where it stands, each with the basis it rests on.
  • currencies counts a metal and a coin as currencies of their own:
    XAU, BTC.
  • A declarations ledger states what no public source can know: where a
    private fund's value is, by region, country, currency, sector and
    asset class, with shares; and where any holding legally sits. One
    JSON record per line, dated to the document it comes from. A record
    never goes stale, and a misspelt key is refused.
  • The config's exposure block names proxies (a fund that stands in
    for another, with always and leverage), reference_funds,
    size_funds, declarations, custody (who keeps each source's
    assets, and in which country) and max_gap_days.
  • What no source, declaration or proxy describes reads unknown,
    never a guess. A quality column on every view and the coverage
    view say what the figures rest on: how each part of net worth is
    classified, how old each composition is, the labels no map knows,
    the securities no source describes, the private holdings no
    declaration describes, and what each situs rests on.
  • -p hides every amount and every instrument id a holding is named
    by; shares, names and labels stay.
  • The MCP server has an exposure tool with the same views. The
    read-only skill has recipes for allocation, sectors, countries, one
    company through every fund, situs and coverage.
  • An Exposure dashboard in Metabase: net worth by asset class and by
    sector, the classes over time, a world map of the countries, the
    regions with their countries and over time, legal situs, the
    currencies, public equity by size, direct against through funds, and
    how the figures are classified over time. Every figure is a share,
    so the privacy twin shows the same charts. Pickers: currency, time
    range, source, tax wrapper and asset class, so real estate and its
    mortgages can be left out, or public equity read alone.

Reference data

  • The refdata collector fetches what each fund holds and what each
    security is. It reads only what gold asks for: wealthdb refdata-wanted prints the funds held, the funds the config names,
    the funds a held fund holds, and the securities held directly or
    through funds. See collectors/refdata/README.md.
  • Providers: an inbox for a composition obtained some other way, SEC
    N-PORT filings, SEC EDGAR, GLEIF and OpenFIGI, which run by default;
    and, once refdata.cfg names them, the issuers iShares, Xtrackers,
    Invesco, Amundi, SPDR and Sprott, the report readers Swisscanto and
    swissfunddata, and Fidelity 529 plans, which look through to the
    plan's funds. Enabling a provider accepts its terms, quoted in the
    README.
  • A fund without a daily file reads from its reports. A security a held
    fund names but no source describes is looked up by the biggest share
    of net worth first, and constituent_floor_pct sets where to stop.
  • There is no login anywhere. Each provider sees which funds and
    securities are asked about, and never an amount, an account or a
    bank. The root README names it among what leaves the machine.
  • --dry-run plans a run, --provider, --ref and --limit narrow
    one, and login --check asks each provider for its cheapest answer.
  • An engine too old for the wanted list, one that cannot run, or one
    that times out is a plain error. An inbox file whose holdings go on
    past a row of one cell is refused rather than read short.

Dashboards

  • The dashboards read serving tables that web refresh fills, instead
    of running each report's whole history on every tile. The heaviest
    tile went from 3.3 GB of memory to under 200 MB, and the Metabase
    server no longer runs out of memory under a full set of tiles.
  • Wealth Overview and Allocation have a tax wrapper and an asset class
    picker. An account that states no tax wrapper reads
    taxable_personal on every dashboard, Gains and Exposure included.
  • Stacked bars and areas order their bands by size, largest at the
    bottom, and the legend lists them in that order. The ordering is an
    aggregate joined back, so a picker that contradicts a card's own
    filter gives an empty chart instead of a driver error.
  • A holding's name, symbol and class read the same on every refresh.
  • Six privacy models nothing read are retired, as are five Exposure
    cards of earlier builds.

Reports and the engine

  • wealthdb help lists each report's views from the report itself.
  • The categorize audit lists the pairs an override, a reference or a
    stated counter asserts ahead of the named ones, so its cap never
    drops them.
  • Config validation names the same first error on every run.
  • A real gold can be checked after a reload -a: the opt-in harness
    asserts that the reload moved no money and that every position
    carries an admitted class. wealthdb/docs/DESIGN.md §12.5 has the
    three commands.

Collectors

  • carta keeps its fund ledger across a --no-documents run, and reads
    a blob that is not a PDF as not downloaded.
  • ubs-web keeps every portfolio's trades when an export repeats.
  • amex retries a statement rebuild that did not finish.
  • swissquote skips a dump whose run.json cannot be read, with a
    warning, and loads the rest.
  • chase drops an export whose window or format pick did not take,
    instead of saving it under the wrong name.
  • firstcitizens no longer submits an empty sign-in form. schwab-web
    exits non-zero on an interrupt or an empty walk.
  • No 2FA code or device name reaches a log. --help starts no VNC
    server.

Build and docs

  • A checkout pins its own image tag and demo household in .image-tag
    and .demo-root, so a second checkout works on images and a demo of
    its own. The demo's containers are named after its root.
  • Docker collector tests run in their image with no secrets and no
    data mount, so a fresh clone passes make test. pip reruns only
    when a venv's inputs change. make clean reaches the Go cache.
  • Every README, DESIGN and AGENTS doc matches the code, and the
    open-follow-up lists are known-limit sections. Root AGENTS.md §2
    covers the verbs that sign in; a collector that signs in nowhere
    states its own live-run rules.