Repository navigation
v0.6.0
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
- Rebuild with
make all. Gold migrations 0125 to 0133 apply on the
first read-write open. Nothing re-parses and noreloadis needed. - Set up reference data. Add a
refdatasilver source to
wealthdb.cfg, and write~/.config/refdata.cfgwith the providers
to ask and thecontactthe SEC requires. Then
./collectors/refdata/refdata download(--backfillalso fetches
the months each fund was held),./collectors/refdata/refdata load
andwealthdb load refdata. Without it the report still runs: every
fund is then a leaf of its own andexposure coveragesays so. - Describe what no public source knows, if you want: the
exposure
block ofwealthdb.cfgand a declarations ledger.wealthdb exposure coverage -f ndjsonprints a skeleton record for every
holding still to declare. - Run
wealthdb web refresh, thenwealthdb mcp restart. The
dashboards read new serving tables that the refresh fills. A
running MCP server refuses a schema newer than its binary. make demorebuilds 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,restartandrefreshexit 3 when the gold
snapshot is older than the dashboards need, and say to runweb 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.noteis still allowed. - A collector's
prunerefuses--silver-db. A relative--data-dir
or--secrets-dirmounts that directory of the host; before, Docker
made a named volume of it. - A collector
loadnever 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_overrideinwealthdb.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,
fundsandcoverage. Every view sums to net worth asholdings globalgives it. Seewealthdb/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,
withinexposure.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 broadsize_funds. countriesgives the country of risk;--country domicilethe
country of incorporation.situsgives 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.currenciescounts 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
exposureblock namesproxies(a fund that stands in
for another, withalwaysandleverage),reference_funds,
size_funds,declarations,custody(who keeps each source's
assets, and in which country) andmax_gap_days. - What no source, declaration or proxy describes reads
unknown,
never a guess. Aqualitycolumn on every view and thecoverage
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. -phides every amount and every instrument id a holding is named
by; shares, names and labels stay.- The MCP server has an
exposuretool 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
refdatacollector fetches what each fund holds and what each
security is. It reads only what gold asks for:wealthdb refdata-wantedprints the funds held, the funds the config names,
the funds a held fund holds, and the securities held directly or
through funds. Seecollectors/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, oncerefdata.cfgnames 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, andconstituent_floor_pctsets 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-runplans a run,--provider,--refand--limitnarrow
one, andlogin --checkasks 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 refreshfills, 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_personalon 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 helplists each report's views from the report itself.- The
categorizeaudit 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-documentsrun, 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.jsoncannot 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.
--helpstarts 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 passesmake test.pipreruns only
when a venv's inputs change.make cleanreaches the Go cache. - Every README, DESIGN and AGENTS doc matches the code, and the
open-follow-up lists are known-limit sections. RootAGENTS.md§2
covers the verbs that sign in; a collector that signs in nowhere
states its own live-run rules.