Count hand-valued assets into the wealth figure

A wealth figure that ignores the house is not a wealth figure. Assets
without a market feed - a house, a car, a private loan - are now added
by hand on the Wealth page with a stated value, a currency and the day
the estimate was made; a negative value records a liability. They are
registry entities in assets.finance like everything else, join the
per-currency totals immediately, and a currency held only in an asset
earns its own line.
This commit is contained in:
Lars Nolden
2026-09-14 09:29:19 +02:00
parent a1480af74d
commit 77f4ea5655
15 changed files with 564 additions and 29 deletions
+27
View File
@@ -27,6 +27,17 @@ export interface Instrument {
quote?: string;
quoted_at?: string;
}
// Asset is a possession valued by hand: a house, a car, anything without a
// market feed. value is what the owner states it is worth and valued_at the
// day that estimate was made. A negative value records a liability.
export interface Asset {
id: string;
name: string;
kind?: string;
currency: string;
value: string;
valued_at: string;
}
// Investment is the broker-native leg of a fact. Cash movement always stays in
// Facts.amount, so a position-only event carries a zero amount. Quantity is an
// exact signed decimal, not money: negative removes from the holding.
@@ -107,6 +118,7 @@ export interface Dataset {
tags: Tag[];
merchants: Merchant[];
instruments: Instrument[];
assets: Asset[];
transactions: Transaction[];
}
export interface Connection {
@@ -384,13 +396,27 @@ export interface WealthTotal {
currency: string;
cash: string;
positions: string;
// assets is the stated value of every hand-valued asset in this currency,
// and wealth is cash, positions and assets together.
assets: string;
wealth: string;
unpriced: number;
}
// WealthAsset is one hand-valued asset as the journal records it: the value is
// stated, never quoted, and carries the day it was stated.
export interface WealthAsset {
asset_id: string;
name: string;
kind?: string;
currency: string;
value: string;
valued_at: string;
}
// Wealth is a reconciliation report computed from the journal rather than the
// analytics index, so it can be checked against a bank or broker's own screen.
export interface Wealth {
accounts: WealthAccount[];
assets: WealthAsset[];
totals: WealthTotal[];
}
export class APIError extends Error {
@@ -461,6 +487,7 @@ export function normalizeState(state: State): State {
"tags",
"merchants",
"instruments",
"assets",
"transactions",
] as const) {
if (!(key in state.data))