Two new bottom-of-dashboard tables: Panel 28 'META vests — value at vest vs today': one row per BUY activity. Shows vest-day price * shares + what those same shares would be worth at today's META quote, plus the hypo P&L if Viktor had held everything (color-text on the gain columns). Panel 29 'META sells — realized PNL vs if held until today': one row per SELL with FIFO-matched cost basis (LEAST/GREATEST overlap in cumulative-share space). Shows realized P&L, the counterfactual P&L had he held until today, and the 'missed by' delta = (today_price - sell_price) * shares. Both pull today_price dynamically from quote_latest via a CTE so they self-update as Yahoo updates the META quote. Schwab account is empty so no live activity is expected.
2670 lines
86 KiB
JSON
2670 lines
86 KiB
JSON
{
|
||
"annotations": {
|
||
"list": [
|
||
{
|
||
"builtIn": 1,
|
||
"datasource": {
|
||
"type": "datasource",
|
||
"uid": "grafana"
|
||
},
|
||
"enable": true,
|
||
"hide": true,
|
||
"iconColor": "rgba(0, 211, 255, 1)",
|
||
"name": "Annotations & Alerts",
|
||
"type": "dashboard"
|
||
},
|
||
{
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"enable": true,
|
||
"hide": false,
|
||
"iconColor": "purple",
|
||
"name": "Milestones",
|
||
"target": {
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"refId": "Anno",
|
||
"rawSql": "WITH daily AS (SELECT d.valuation_date, SUM(d.total_value) AS nw FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date), crossings AS (SELECT t, (SELECT MIN(valuation_date) FROM daily WHERE nw >= t::numeric) AS d FROM unnest(ARRAY[100000, 250000, 500000, 750000, 1000000]) AS t) SELECT d::timestamptz AS time, '£' || CASE WHEN t >= 1000000 THEN (t/1000000)::int::text || 'M' ELSE (t/1000)::int::text || 'k' END AS text FROM crossings WHERE d IS NOT NULL ORDER BY d"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"description": "Wealth — net worth, contributions, and growth over time. Backed by the wealthfolio_sync PG mirror of Wealthfolio's SQLite, refreshed hourly by the pg-sync sidecar.",
|
||
"editable": true,
|
||
"fiscalYearStartMonth": 0,
|
||
"id": null,
|
||
"links": [],
|
||
"panels": [
|
||
{
|
||
"id": 1,
|
||
"title": "Net worth (current)",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 4,
|
||
"x": 0,
|
||
"y": 0
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "fixed",
|
||
"fixedColor": "green"
|
||
},
|
||
"decimals": 2
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH latest AS (SELECT DISTINCT ON (d.account_id) d.account_id, d.total_value, d.net_contribution, d.cash_balance, d.investment_market_value FROM dav_corrected d JOIN accounts a ON a.id = d.account_id ORDER BY d.account_id, d.valuation_date DESC) SELECT SUM(total_value) AS net_worth FROM latest"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 2,
|
||
"title": "Net contribution (cumulative)",
|
||
"description": "Total deposits minus withdrawals across all accounts.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 4,
|
||
"x": 4,
|
||
"y": 0
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "fixed",
|
||
"fixedColor": "blue"
|
||
},
|
||
"decimals": 2
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH latest AS (SELECT DISTINCT ON (d.account_id) d.account_id, d.total_value, d.net_contribution, d.cash_balance, d.investment_market_value FROM dav_corrected d JOIN accounts a ON a.id = d.account_id ORDER BY d.account_id, d.valuation_date DESC) SELECT SUM(net_contribution) AS contribution FROM latest"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 3,
|
||
"title": "Growth (unrealised)",
|
||
"description": "Net worth minus net contribution — the gain on everything you've put in.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 4,
|
||
"x": 8,
|
||
"y": 0
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 2,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH latest AS (SELECT DISTINCT ON (d.account_id) d.account_id, d.total_value, d.net_contribution, d.cash_balance, d.investment_market_value FROM dav_corrected d JOIN accounts a ON a.id = d.account_id ORDER BY d.account_id, d.valuation_date DESC) SELECT (SUM(total_value) - SUM(net_contribution)) AS growth FROM latest"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 4,
|
||
"title": "ROI %",
|
||
"description": "Growth / net contribution × 100. Excludes accounts with zero/negative contribution (Schwab) to avoid distortion.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 3,
|
||
"x": 12,
|
||
"y": 0
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "percent",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 2,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "yellow",
|
||
"value": 0
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 5
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH latest AS (SELECT DISTINCT ON (d.account_id) d.account_id, d.total_value, d.net_contribution, d.cash_balance, d.investment_market_value FROM dav_corrected d JOIN accounts a ON a.id = d.account_id ORDER BY d.account_id, d.valuation_date DESC) SELECT (SUM(total_value - net_contribution) / NULLIF(SUM(net_contribution), 0) * 100) AS roi_pct FROM latest WHERE net_contribution > 0"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 5,
|
||
"title": "Net worth — total over time",
|
||
"description": "Daily total_value summed across all accounts (base GBP). Declining segments overlaid in red.",
|
||
"type": "timeseries",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 10,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 12
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "fixed",
|
||
"fixedColor": "green"
|
||
},
|
||
"unit": "currencyGBP",
|
||
"decimals": 2,
|
||
"custom": {
|
||
"drawStyle": "line",
|
||
"lineWidth": 2,
|
||
"fillOpacity": 20,
|
||
"pointSize": 4,
|
||
"showPoints": "never",
|
||
"spanNulls": true,
|
||
"axisPlacement": "auto",
|
||
"stacking": {
|
||
"group": "A",
|
||
"mode": "none"
|
||
}
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "net_worth"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "displayName",
|
||
"value": "Net worth"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "decline"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "displayName",
|
||
"value": "Decline"
|
||
},
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "red"
|
||
}
|
||
},
|
||
{
|
||
"id": "custom.spanNulls",
|
||
"value": false
|
||
},
|
||
{
|
||
"id": "custom.fillOpacity",
|
||
"value": 0
|
||
},
|
||
{
|
||
"id": "custom.lineWidth",
|
||
"value": 3
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"legend": {
|
||
"calcs": [
|
||
"last",
|
||
"max"
|
||
],
|
||
"displayMode": "table",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "multi",
|
||
"sort": "desc"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "time_series",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), series AS (SELECT valuation_date, SUM(total_value) AS nw FROM daily_account_valuation WHERE $__timeFilter(valuation_date) AND valuation_date <= (SELECT d FROM max_complete) GROUP BY valuation_date), labeled AS (SELECT valuation_date, nw, LAG(nw) OVER (ORDER BY valuation_date) AS prev_nw, LEAD(nw) OVER (ORDER BY valuation_date) AS next_nw FROM series) SELECT valuation_date::timestamp AS \"time\", nw AS net_worth, CASE WHEN (prev_nw IS NOT NULL AND nw < prev_nw) OR (next_nw IS NOT NULL AND next_nw < nw) THEN nw END AS decline FROM labeled ORDER BY valuation_date"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 6,
|
||
"title": "Net contribution vs market value",
|
||
"description": "Net contribution = cumulative deposits − withdrawals. Market value = total_value (cash + investments). Gap between the two = unrealised growth.",
|
||
"type": "timeseries",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 10,
|
||
"w": 12,
|
||
"x": 0,
|
||
"y": 22
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "palette-classic"
|
||
},
|
||
"unit": "currencyGBP",
|
||
"decimals": 2,
|
||
"custom": {
|
||
"drawStyle": "line",
|
||
"lineWidth": 2,
|
||
"fillOpacity": 0,
|
||
"pointSize": 4,
|
||
"showPoints": "never",
|
||
"spanNulls": true,
|
||
"axisPlacement": "auto",
|
||
"stacking": {
|
||
"group": "A",
|
||
"mode": "none"
|
||
}
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "market_value"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "green"
|
||
}
|
||
},
|
||
{
|
||
"id": "displayName",
|
||
"value": "Market value"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "net_contribution"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "blue"
|
||
}
|
||
},
|
||
{
|
||
"id": "displayName",
|
||
"value": "Net contribution"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"legend": {
|
||
"calcs": [
|
||
"last"
|
||
],
|
||
"displayMode": "table",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "multi",
|
||
"sort": "desc"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "time_series",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM dav_corrected d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)) SELECT valuation_date::timestamp AS \"time\", SUM(net_contribution) AS net_contribution, SUM(total_value) AS market_value FROM dav_corrected WHERE $__timeFilter(valuation_date) AND valuation_date <= (SELECT d FROM max_complete) GROUP BY valuation_date ORDER BY valuation_date"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 7,
|
||
"title": "Growth (market value − contribution) over time",
|
||
"description": "Unrealised gain across all accounts. Filled area to emphasise the wealth created above the contributed capital. Declining segments overlaid in red.",
|
||
"type": "timeseries",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 10,
|
||
"w": 12,
|
||
"x": 12,
|
||
"y": 22
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "fixed",
|
||
"fixedColor": "#56A64B"
|
||
},
|
||
"unit": "currencyGBP",
|
||
"decimals": 2,
|
||
"custom": {
|
||
"drawStyle": "line",
|
||
"lineWidth": 2,
|
||
"fillOpacity": 50,
|
||
"gradientMode": "opacity",
|
||
"pointSize": 4,
|
||
"showPoints": "never",
|
||
"spanNulls": true,
|
||
"axisPlacement": "auto",
|
||
"stacking": {
|
||
"group": "A",
|
||
"mode": "none"
|
||
}
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "growth"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "displayName",
|
||
"value": "Growth"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "decline"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "displayName",
|
||
"value": "Decline"
|
||
},
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "red"
|
||
}
|
||
},
|
||
{
|
||
"id": "custom.spanNulls",
|
||
"value": false
|
||
},
|
||
{
|
||
"id": "custom.fillOpacity",
|
||
"value": 0
|
||
},
|
||
{
|
||
"id": "custom.lineWidth",
|
||
"value": 3
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"legend": {
|
||
"calcs": [
|
||
"last",
|
||
"max"
|
||
],
|
||
"displayMode": "table",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "multi",
|
||
"sort": "desc"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "time_series",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM dav_corrected d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), series AS (SELECT valuation_date, (SUM(total_value) - SUM(net_contribution)) AS g FROM dav_corrected WHERE $__timeFilter(valuation_date) AND valuation_date <= (SELECT d FROM max_complete) GROUP BY valuation_date), labeled AS (SELECT valuation_date, g, LAG(g) OVER (ORDER BY valuation_date) AS prev_g, LEAD(g) OVER (ORDER BY valuation_date) AS next_g FROM series) SELECT valuation_date::timestamp AS \"time\", g AS growth, CASE WHEN (prev_g IS NOT NULL AND g < prev_g) OR (next_g IS NOT NULL AND next_g < g) THEN g END AS decline FROM labeled ORDER BY valuation_date"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 8,
|
||
"title": "Per-account stacked — total value",
|
||
"description": "Stacked area showing each account's contribution to total net worth over time. Useful for spotting which account drives the trajectory.",
|
||
"type": "timeseries",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 11,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 40
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "palette-classic"
|
||
},
|
||
"unit": "currencyGBP",
|
||
"decimals": 2,
|
||
"custom": {
|
||
"drawStyle": "line",
|
||
"lineWidth": 1,
|
||
"fillOpacity": 70,
|
||
"pointSize": 3,
|
||
"showPoints": "never",
|
||
"spanNulls": true,
|
||
"axisPlacement": "auto",
|
||
"stacking": {
|
||
"group": "A",
|
||
"mode": "normal"
|
||
}
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"legend": {
|
||
"calcs": [
|
||
"last"
|
||
],
|
||
"displayMode": "table",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "multi",
|
||
"sort": "desc"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "time_series",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)) SELECT d.valuation_date::timestamp AS \"time\", a.name AS metric, d.total_value AS value FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE $__timeFilter(d.valuation_date) AND d.valuation_date <= (SELECT d FROM max_complete) ORDER BY d.valuation_date, a.name"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 9,
|
||
"title": "Cash vs invested (stacked)",
|
||
"description": "Daily breakdown of uninvested broker cash vs market value of investments. WORKPLACE_PENSION accounts (Fidelity) are reclassified entirely as invested — Wealthfolio dumps pension wrappers into cash_balance because it doesn't track the underlying fund holdings, but they are not actually cash.",
|
||
"type": "timeseries",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 10,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 51
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "palette-classic"
|
||
},
|
||
"unit": "currencyGBP",
|
||
"decimals": 2,
|
||
"custom": {
|
||
"drawStyle": "line",
|
||
"lineWidth": 1,
|
||
"fillOpacity": 70,
|
||
"pointSize": 3,
|
||
"showPoints": "never",
|
||
"spanNulls": true,
|
||
"axisPlacement": "auto",
|
||
"stacking": {
|
||
"group": "A",
|
||
"mode": "normal"
|
||
}
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "cash"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "#FADE2A"
|
||
}
|
||
},
|
||
{
|
||
"id": "displayName",
|
||
"value": "Cash"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "invested"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "#56A64B"
|
||
}
|
||
},
|
||
{
|
||
"id": "displayName",
|
||
"value": "Invested"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"legend": {
|
||
"calcs": [
|
||
"last"
|
||
],
|
||
"displayMode": "table",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "multi",
|
||
"sort": "desc"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "time_series",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)) SELECT d.valuation_date::timestamp AS \"time\", SUM(CASE WHEN a.account_type = 'WORKPLACE_PENSION' THEN 0 ELSE d.cash_balance END) AS cash, SUM(CASE WHEN a.account_type = 'WORKPLACE_PENSION' THEN d.cash_balance + d.investment_market_value ELSE d.investment_market_value END) AS invested FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE $__timeFilter(d.valuation_date) AND d.valuation_date <= (SELECT d FROM max_complete) GROUP BY d.valuation_date ORDER BY d.valuation_date"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 10,
|
||
"title": "Activity log",
|
||
"description": "Recent activities (BUY / SELL / DEPOSIT / WITHDRAWAL / DIVIDEND / etc.) across all accounts. Limited to 100 most recent.",
|
||
"type": "table",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 14,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 104
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"custom": {
|
||
"align": "auto",
|
||
"displayMode": "auto"
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "amount"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyGBP"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"cellHeight": "sm",
|
||
"footer": {
|
||
"show": false
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "SELECT a.activity_date AS \"date\", acc.name AS \"account\", a.activity_type AS \"type\", a.asset_id AS \"asset\", a.quantity AS \"qty\", a.unit_price AS \"unit_price\", a.amount AS \"amount\", a.currency AS \"ccy\", a.notes AS \"notes\" FROM activities a LEFT JOIN accounts acc ON acc.id = a.account_id WHERE $__timeFilter(a.activity_date) ORDER BY a.activity_date DESC LIMIT 100"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 11,
|
||
"title": "12mo return",
|
||
"description": "Modified-Dietz return over the trailing 12 months: market_gain / (nw_12mo_ago + 0.5 × contributions_12mo). Excludes new money in — answers 'how did my investments perform' rather than 'how much did my net worth change'.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 3,
|
||
"x": 15,
|
||
"y": 0
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "percent",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 2,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "yellow",
|
||
"value": 0
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 5
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH latest AS (SELECT DISTINCT ON (d.account_id) d.account_id, d.valuation_date AS d_now, d.total_value AS nw_now, d.net_contribution AS contrib_now FROM dav_corrected d JOIN accounts a ON a.id = d.account_id ORDER BY d.account_id, d.valuation_date DESC), ago AS (SELECT DISTINCT ON (l.account_id) l.account_id, d.total_value AS nw_ago, d.net_contribution AS contrib_ago FROM latest l JOIN dav_corrected d ON d.account_id = l.account_id AND d.valuation_date <= l.d_now - INTERVAL '12 months' ORDER BY l.account_id, d.valuation_date DESC), agg AS (SELECT (SELECT SUM(nw_now) FROM latest) AS nw_now, (SELECT SUM(contrib_now) FROM latest) AS contrib_now, (SELECT SUM(nw_ago) FROM ago) AS nw_ago, (SELECT SUM(contrib_ago) FROM ago) AS contrib_ago) SELECT ROUND((((nw_now - nw_ago - (contrib_now - contrib_ago)) / NULLIF(nw_ago + 0.5 * (contrib_now - contrib_ago), 0)) * 100)::numeric, 2) AS pct_12mo FROM agg"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 15,
|
||
"title": "12mo contrib",
|
||
"description": "Net contributions (deposits − withdrawals) over the trailing 12 months. How much new money you put in — independent of market movement.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 3,
|
||
"x": 18,
|
||
"y": 0
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "fixed",
|
||
"fixedColor": "blue"
|
||
},
|
||
"decimals": 2
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH latest AS (SELECT DISTINCT ON (d.account_id) d.account_id, d.valuation_date AS d_now, d.total_value AS nw_now, d.net_contribution AS contrib_now FROM dav_corrected d JOIN accounts a ON a.id = d.account_id ORDER BY d.account_id, d.valuation_date DESC), ago AS (SELECT DISTINCT ON (l.account_id) l.account_id, d.total_value AS nw_ago, d.net_contribution AS contrib_ago FROM latest l JOIN dav_corrected d ON d.account_id = l.account_id AND d.valuation_date <= l.d_now - INTERVAL '12 months' ORDER BY l.account_id, d.valuation_date DESC), agg AS (SELECT (SELECT SUM(nw_now) FROM latest) AS nw_now, (SELECT SUM(contrib_now) FROM latest) AS contrib_now, (SELECT SUM(nw_ago) FROM ago) AS nw_ago, (SELECT SUM(contrib_ago) FROM ago) AS contrib_ago) SELECT (contrib_now - contrib_ago) AS contrib_12mo FROM agg"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 16,
|
||
"title": "12mo gain",
|
||
"description": "Trailing 12-month market gain in £ — the change in net worth minus net contributions. What the markets gave you, separate from money you added in.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 3,
|
||
"x": 21,
|
||
"y": 0
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 2,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH latest AS (SELECT DISTINCT ON (d.account_id) d.account_id, d.valuation_date AS d_now, d.total_value AS nw_now, d.net_contribution AS contrib_now FROM dav_corrected d JOIN accounts a ON a.id = d.account_id ORDER BY d.account_id, d.valuation_date DESC), ago AS (SELECT DISTINCT ON (l.account_id) l.account_id, d.total_value AS nw_ago, d.net_contribution AS contrib_ago FROM latest l JOIN dav_corrected d ON d.account_id = l.account_id AND d.valuation_date <= l.d_now - INTERVAL '12 months' ORDER BY l.account_id, d.valuation_date DESC), agg AS (SELECT (SELECT SUM(nw_now) FROM latest) AS nw_now, (SELECT SUM(contrib_now) FROM latest) AS contrib_now, (SELECT SUM(nw_ago) FROM ago) AS nw_ago, (SELECT SUM(contrib_ago) FROM ago) AS contrib_ago) SELECT ((nw_now - nw_ago) - (contrib_now - contrib_ago)) AS gain_12mo FROM agg"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 17,
|
||
"title": "Δ 1d (all)",
|
||
"description": "Net worth delta over the trailing window (latest snapshot minus snapshot from N days ago). Includes new money paid in (salary, vests, deposits) AND market gains.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 6,
|
||
"x": 0,
|
||
"y": 4
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 0,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), now_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC), past_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d - INTERVAL '1 day' FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC) SELECT (SELECT SUM(total_value) FROM now_snap) - (SELECT SUM(total_value) FROM past_snap) AS delta"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 21,
|
||
"title": "Δ 1d (mkt)",
|
||
"description": "Pure market gain over the trailing window — net-worth delta minus net-contribution delta. Excludes new money paid in. Apples-to-apples with the Growth panel.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 6,
|
||
"x": 0,
|
||
"y": 8
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 0,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM dav_corrected d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), now_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value, d.net_contribution FROM dav_corrected d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC), past_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value, d.net_contribution FROM dav_corrected d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d - INTERVAL '1 day' FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC) SELECT ((SELECT SUM(total_value) FROM now_snap) - (SELECT SUM(total_value) FROM past_snap)) - ((SELECT SUM(net_contribution) FROM now_snap) - (SELECT SUM(net_contribution) FROM past_snap)) AS market_delta"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 18,
|
||
"title": "Δ 7d (all)",
|
||
"description": "Net worth delta over the trailing window (latest snapshot minus snapshot from N days ago). Includes new money paid in (salary, vests, deposits) AND market gains.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 6,
|
||
"x": 6,
|
||
"y": 4
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 0,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), now_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC), past_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d - INTERVAL '7 days' FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC) SELECT (SELECT SUM(total_value) FROM now_snap) - (SELECT SUM(total_value) FROM past_snap) AS delta"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 22,
|
||
"title": "Δ 7d (mkt)",
|
||
"description": "Pure market gain over the trailing window — net-worth delta minus net-contribution delta. Excludes new money paid in. Apples-to-apples with the Growth panel.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 6,
|
||
"x": 6,
|
||
"y": 8
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 0,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM dav_corrected d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), now_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value, d.net_contribution FROM dav_corrected d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC), past_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value, d.net_contribution FROM dav_corrected d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d - INTERVAL '7 days' FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC) SELECT ((SELECT SUM(total_value) FROM now_snap) - (SELECT SUM(total_value) FROM past_snap)) - ((SELECT SUM(net_contribution) FROM now_snap) - (SELECT SUM(net_contribution) FROM past_snap)) AS market_delta"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 19,
|
||
"title": "Δ 30d (all)",
|
||
"description": "Net worth delta over the trailing window (latest snapshot minus snapshot from N days ago). Includes new money paid in (salary, vests, deposits) AND market gains.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 6,
|
||
"x": 12,
|
||
"y": 4
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 0,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), now_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC), past_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d - INTERVAL '30 days' FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC) SELECT (SELECT SUM(total_value) FROM now_snap) - (SELECT SUM(total_value) FROM past_snap) AS delta"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 23,
|
||
"title": "Δ 30d (mkt)",
|
||
"description": "Pure market gain over the trailing window — net-worth delta minus net-contribution delta. Excludes new money paid in. Apples-to-apples with the Growth panel.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 6,
|
||
"x": 12,
|
||
"y": 8
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 0,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM dav_corrected d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), now_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value, d.net_contribution FROM dav_corrected d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC), past_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value, d.net_contribution FROM dav_corrected d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d - INTERVAL '30 days' FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC) SELECT ((SELECT SUM(total_value) FROM now_snap) - (SELECT SUM(total_value) FROM past_snap)) - ((SELECT SUM(net_contribution) FROM now_snap) - (SELECT SUM(net_contribution) FROM past_snap)) AS market_delta"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 20,
|
||
"title": "Δ 90d (all)",
|
||
"description": "Net worth delta over the trailing window (latest snapshot minus snapshot from N days ago). Includes new money paid in (salary, vests, deposits) AND market gains.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 6,
|
||
"x": 18,
|
||
"y": 4
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 0,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), now_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC), past_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value FROM daily_account_valuation d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d - INTERVAL '90 days' FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC) SELECT (SELECT SUM(total_value) FROM now_snap) - (SELECT SUM(total_value) FROM past_snap) AS delta"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 24,
|
||
"title": "Δ 90d (mkt)",
|
||
"description": "Pure market gain over the trailing window — net-worth delta minus net-contribution delta. Excludes new money paid in. Apples-to-apples with the Growth panel.",
|
||
"type": "stat",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 4,
|
||
"w": 6,
|
||
"x": 18,
|
||
"y": 8
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"unit": "currencyGBP",
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"decimals": 0,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"colorMode": "value",
|
||
"graphMode": "area",
|
||
"justifyMode": "center",
|
||
"orientation": "auto",
|
||
"reduceOptions": {
|
||
"calcs": [
|
||
"lastNotNull"
|
||
],
|
||
"fields": "",
|
||
"values": false
|
||
},
|
||
"textMode": "auto"
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM dav_corrected d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), now_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value, d.net_contribution FROM dav_corrected d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC), past_snap AS (SELECT DISTINCT ON (d.account_id) d.total_value, d.net_contribution FROM dav_corrected d JOIN accounts a ON a.id = d.account_id WHERE d.valuation_date <= (SELECT d - INTERVAL '90 days' FROM max_complete) ORDER BY d.account_id, d.valuation_date DESC) SELECT ((SELECT SUM(total_value) FROM now_snap) - (SELECT SUM(total_value) FROM past_snap)) - ((SELECT SUM(net_contribution) FROM now_snap) - (SELECT SUM(net_contribution) FROM past_snap)) AS market_delta"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 12,
|
||
"title": "Yearly investment return %",
|
||
"description": "Modified-Dietz return per calendar year: market_gain / (nw_start + 0.5 × contributions). Pure investment performance — excludes new contributions, so a £100k vest doesn't show as 100% growth. Negative bars = market losses (e.g., 2022 bear market).",
|
||
"type": "barchart",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 11,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 61
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"unit": "percent",
|
||
"decimals": 1,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "yellow",
|
||
"value": 0
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 5
|
||
}
|
||
]
|
||
},
|
||
"custom": {
|
||
"axisPlacement": "auto",
|
||
"axisLabel": "",
|
||
"fillOpacity": 80,
|
||
"gradientMode": "none",
|
||
"lineWidth": 1
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "year"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "unit",
|
||
"value": "string"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"barRadius": 0,
|
||
"barWidth": 0.6,
|
||
"groupWidth": 0.7,
|
||
"orientation": "auto",
|
||
"showValue": "always",
|
||
"stacking": "none",
|
||
"xField": "year",
|
||
"xTickLabelRotation": 0,
|
||
"legend": {
|
||
"displayMode": "list",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "single",
|
||
"sort": "none"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM dav_corrected d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), yearly AS (SELECT EXTRACT(YEAR FROM valuation_date)::int AS yr, valuation_date, SUM(total_value) AS nw, SUM(net_contribution) AS contrib FROM dav_corrected WHERE valuation_date <= (SELECT d FROM max_complete) GROUP BY valuation_date), endpoints AS (SELECT yr, (array_agg(nw ORDER BY valuation_date ASC))[1] AS nw_start, (array_agg(nw ORDER BY valuation_date DESC))[1] AS nw_end, (array_agg(contrib ORDER BY valuation_date ASC))[1] AS contrib_start, (array_agg(contrib ORDER BY valuation_date DESC))[1] AS contrib_end FROM yearly GROUP BY yr) SELECT yr::text AS year, ROUND((((nw_end - nw_start - (contrib_end - contrib_start)) / NULLIF(nw_start + 0.5 * (contrib_end - contrib_start), 0)) * 100)::numeric, 2) AS return_pct FROM endpoints WHERE (nw_start + 0.5 * (contrib_end - contrib_start)) > 0 ORDER BY yr"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 13,
|
||
"title": "Annual change decomposition — contributions vs market gain",
|
||
"description": "Each calendar year's net worth change split into 'new money in' (contributions − withdrawals) and 'market gain' (everything else: price appreciation, dividends, etc.). Shows whether you grew because you saved or because the market did the work. Negative bars = withdrawals or market losses.",
|
||
"type": "barchart",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 11,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 72
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "palette-classic"
|
||
},
|
||
"unit": "currencyGBP",
|
||
"decimals": 2,
|
||
"custom": {
|
||
"axisPlacement": "auto",
|
||
"axisLabel": "",
|
||
"fillOpacity": 80,
|
||
"gradientMode": "none",
|
||
"lineWidth": 1
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "year"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "unit",
|
||
"value": "string"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "contributions"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "blue"
|
||
}
|
||
},
|
||
{
|
||
"id": "displayName",
|
||
"value": "Net contributions"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "market_gain"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "#56A64B"
|
||
}
|
||
},
|
||
{
|
||
"id": "displayName",
|
||
"value": "Market gain"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"barRadius": 0,
|
||
"barWidth": 0.6,
|
||
"groupWidth": 0.7,
|
||
"orientation": "auto",
|
||
"showValue": "auto",
|
||
"stacking": "normal",
|
||
"xField": "year",
|
||
"xTickLabelRotation": 0,
|
||
"legend": {
|
||
"calcs": [
|
||
"sum"
|
||
],
|
||
"displayMode": "table",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "multi",
|
||
"sort": "desc"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM dav_corrected d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), yearly AS (SELECT EXTRACT(YEAR FROM valuation_date)::int AS yr, valuation_date, SUM(total_value) AS nw, SUM(net_contribution) AS contrib FROM dav_corrected WHERE valuation_date <= (SELECT d FROM max_complete) GROUP BY valuation_date), endpoints AS (SELECT yr, (array_agg(nw ORDER BY valuation_date ASC))[1] AS nw_start, (array_agg(nw ORDER BY valuation_date DESC))[1] AS nw_end, (array_agg(contrib ORDER BY valuation_date ASC))[1] AS contrib_start, (array_agg(contrib ORDER BY valuation_date DESC))[1] AS contrib_end FROM yearly GROUP BY yr) SELECT yr::text AS year, ROUND((contrib_end - contrib_start)::numeric, 0) AS contributions, ROUND((nw_end - nw_start - (contrib_end - contrib_start))::numeric, 0) AS market_gain FROM endpoints ORDER BY yr"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 25,
|
||
"title": "Monthly contributions vs market gain",
|
||
"description": "Each month's net contributions vs market gain as two lines. Where the green (market) line crosses above the blue (contributions) line is when investments out-earn savings for that month. Months below zero on the green line = market drawdowns.",
|
||
"type": "timeseries",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 11,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 83
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "palette-classic"
|
||
},
|
||
"unit": "currencyGBP",
|
||
"decimals": 0,
|
||
"custom": {
|
||
"drawStyle": "line",
|
||
"lineWidth": 2,
|
||
"fillOpacity": 0,
|
||
"pointSize": 5,
|
||
"showPoints": "auto",
|
||
"spanNulls": true,
|
||
"axisPlacement": "auto",
|
||
"stacking": {
|
||
"group": "A",
|
||
"mode": "none"
|
||
}
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "contributions"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "blue"
|
||
}
|
||
},
|
||
{
|
||
"id": "displayName",
|
||
"value": "Net contributions"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "market_gain"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "color",
|
||
"value": {
|
||
"mode": "fixed",
|
||
"fixedColor": "#56A64B"
|
||
}
|
||
},
|
||
{
|
||
"id": "displayName",
|
||
"value": "Market gain"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"legend": {
|
||
"calcs": [
|
||
"last",
|
||
"sum"
|
||
],
|
||
"displayMode": "table",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "multi",
|
||
"sort": "desc"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "time_series",
|
||
"rawSql": "WITH active_count AS (SELECT COUNT(*) AS n FROM accounts), max_complete AS (SELECT MAX(valuation_date) AS d FROM (SELECT d.valuation_date, COUNT(*) AS c FROM dav_corrected d JOIN accounts a ON a.id = d.account_id GROUP BY d.valuation_date) x WHERE c >= (SELECT n FROM active_count)), monthly AS (SELECT date_trunc('month', valuation_date)::date AS month, valuation_date, SUM(total_value) AS nw, SUM(net_contribution) AS contrib FROM dav_corrected WHERE valuation_date <= (SELECT d FROM max_complete) GROUP BY valuation_date), endpoints AS (SELECT month, (array_agg(nw ORDER BY valuation_date ASC))[1] AS nw_start, (array_agg(nw ORDER BY valuation_date DESC))[1] AS nw_end, (array_agg(contrib ORDER BY valuation_date ASC))[1] AS contrib_start, (array_agg(contrib ORDER BY valuation_date DESC))[1] AS contrib_end FROM monthly GROUP BY month) SELECT month::timestamp AS time, ROUND((contrib_end - contrib_start)::numeric, 0) AS contributions, ROUND((nw_end - nw_start - (contrib_end - contrib_start))::numeric, 0) AS market_gain FROM endpoints ORDER BY month"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 14,
|
||
"title": "Per-account ROI %",
|
||
"description": "(market value − net contribution) / net contribution × 100, latest snapshot. Excludes accounts with zero/negative net contribution (Schwab — RSU vests sold = negative contribution distorts the ratio). Pension shows 0% because Wealthfolio doesn't track underlying fund holdings, so cost_basis = 0 and 'growth' is just the cash balance reported.",
|
||
"type": "barchart",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 10,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 94
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "thresholds"
|
||
},
|
||
"unit": "percent",
|
||
"decimals": 2,
|
||
"thresholds": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "yellow",
|
||
"value": 0
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 10
|
||
}
|
||
]
|
||
},
|
||
"custom": {
|
||
"axisPlacement": "auto",
|
||
"axisLabel": "",
|
||
"fillOpacity": 80,
|
||
"gradientMode": "none",
|
||
"lineWidth": 1
|
||
}
|
||
},
|
||
"overrides": []
|
||
},
|
||
"options": {
|
||
"barRadius": 0,
|
||
"barWidth": 0.6,
|
||
"groupWidth": 0.7,
|
||
"orientation": "horizontal",
|
||
"showValue": "always",
|
||
"stacking": "none",
|
||
"xField": "account",
|
||
"legend": {
|
||
"displayMode": "list",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "single",
|
||
"sort": "none"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH latest AS (SELECT DISTINCT ON (d.account_id) a.name, d.total_value, d.net_contribution FROM dav_corrected d JOIN accounts a ON a.id = d.account_id ORDER BY d.account_id, d.valuation_date DESC) SELECT name AS account, ROUND(((total_value - net_contribution) / NULLIF(net_contribution, 0) * 100)::numeric, 2) AS roi_pct FROM latest WHERE net_contribution > 0 ORDER BY roi_pct DESC"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 26,
|
||
"title": "Positions",
|
||
"description": "Currently-held positions: shares, cost basis, latest market price, and unrealised return. Latest holdings_snapshots TOTAL aggregate + latest quote per asset.",
|
||
"type": "table",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 8,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 32
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"custom": {
|
||
"align": "auto",
|
||
"displayMode": "auto"
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "shares"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "avg cost"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyGBP"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "last"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyGBP"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "market value"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyGBP"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "cost"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyGBP"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "gain"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyGBP"
|
||
},
|
||
{
|
||
"id": "custom.cellOptions",
|
||
"value": {
|
||
"type": "color-text"
|
||
}
|
||
},
|
||
{
|
||
"id": "thresholds",
|
||
"value": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "return %"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "percent"
|
||
},
|
||
{
|
||
"id": "custom.cellOptions",
|
||
"value": {
|
||
"type": "color-text"
|
||
}
|
||
},
|
||
{
|
||
"id": "thresholds",
|
||
"value": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"cellHeight": "sm",
|
||
"footer": {
|
||
"show": false
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "SELECT a.symbol, a.name, p.quantity AS shares, p.average_cost AS \"avg cost\", q.close AS \"last\", (p.quantity * q.close) AS \"market value\", p.total_cost_basis AS cost, ((p.quantity * q.close) - p.total_cost_basis) AS gain, CASE WHEN p.total_cost_basis > 0 THEN ((p.quantity * q.close) / p.total_cost_basis - 1) * 100 END AS \"return %\", p.currency, q.day AS \"as of\" FROM positions_latest p LEFT JOIN assets a ON a.id = p.asset_id LEFT JOIN quote_latest q ON q.asset_id = p.asset_id ORDER BY (p.quantity * q.close) DESC NULLS LAST"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 27,
|
||
"title": "META RSU vest value — Schwab account",
|
||
"description": "Daily total value of Viktor's META RSU holdings in the Schwab workplace account, in USD. Vest schedule: 1,119 shares vested 2020-11 → 2026-02, all sold 2023-04 → 2026-02 as they vested. The Schwab account is now effectively empty (~$64 residual). Yahoo quote for META powers WF's daily mark.",
|
||
"type": "timeseries",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 9,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 118
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"color": {
|
||
"mode": "fixed",
|
||
"fixedColor": "blue"
|
||
},
|
||
"unit": "currencyUSD",
|
||
"decimals": 0,
|
||
"custom": {
|
||
"drawStyle": "line",
|
||
"lineWidth": 2,
|
||
"fillOpacity": 25,
|
||
"pointSize": 4,
|
||
"showPoints": "never",
|
||
"spanNulls": true,
|
||
"axisPlacement": "auto",
|
||
"stacking": {
|
||
"group": "A",
|
||
"mode": "none"
|
||
}
|
||
}
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "rsu_value"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "displayName",
|
||
"value": "META RSU value (USD)"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"legend": {
|
||
"calcs": [
|
||
"last",
|
||
"max"
|
||
],
|
||
"displayMode": "table",
|
||
"placement": "bottom"
|
||
},
|
||
"tooltip": {
|
||
"mode": "single",
|
||
"sort": "desc"
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "time_series",
|
||
"rawSql": "SELECT valuation_date::timestamp AS \"time\", total_value AS rsu_value FROM daily_account_valuation WHERE account_id = '72d34e09-c1a6-41aa-99ea-abe3305ecc4a' AND $__timeFilter(valuation_date) ORDER BY valuation_date"
|
||
}
|
||
],
|
||
"timeFrom": "6y"
|
||
},
|
||
{
|
||
"id": 28,
|
||
"title": "META vests — value at vest vs today",
|
||
"description": "One row per BUY (vest event). Vest-day price × shares is what each tranche was worth when it landed; 'value today' is what the same shares would be worth at META's current quote. The Hypo gain columns show the unrealized P&L if Viktor had held every vest.",
|
||
"type": "table",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 12,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 127
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"custom": {
|
||
"align": "auto",
|
||
"displayMode": "auto"
|
||
},
|
||
"decimals": 2
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "shares"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "vest price"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "vest value"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "today price"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "value today"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "hypo gain"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
},
|
||
{
|
||
"id": "custom.cellOptions",
|
||
"value": {
|
||
"type": "color-text"
|
||
}
|
||
},
|
||
{
|
||
"id": "thresholds",
|
||
"value": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "hypo %"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 1
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "percent"
|
||
},
|
||
{
|
||
"id": "custom.cellOptions",
|
||
"value": {
|
||
"type": "color-text"
|
||
}
|
||
},
|
||
{
|
||
"id": "thresholds",
|
||
"value": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"cellHeight": "sm",
|
||
"footer": {
|
||
"show": true,
|
||
"reducer": [
|
||
"sum"
|
||
],
|
||
"fields": [
|
||
"shares",
|
||
"vest value",
|
||
"value today",
|
||
"hypo gain"
|
||
]
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH px AS (SELECT close AS today_price FROM quote_latest WHERE asset_id='4f60833d-0bfb-484f-8ee6-f129af72e137') SELECT activity_date::date AS vest_date, quantity AS shares, unit_price AS \"vest price\", (quantity*unit_price) AS \"vest value\", (SELECT today_price FROM px) AS \"today price\", (quantity * (SELECT today_price FROM px)) AS \"value today\", (quantity * ((SELECT today_price FROM px) - unit_price)) AS \"hypo gain\", (((SELECT today_price FROM px) / unit_price - 1) * 100) AS \"hypo %\" FROM activities WHERE asset_id='4f60833d-0bfb-484f-8ee6-f129af72e137' AND activity_type='BUY' ORDER BY activity_date"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": 29,
|
||
"title": "META sells — realized PNL vs 'if held until today'",
|
||
"description": "One row per SELL, with vest-price matched FIFO against the original BUY lots. Realized P&L = (sell - matched vest) × shares. Missed-opportunity = (today's META price - sell price) × shares; positive means holding would have outperformed selling.",
|
||
"type": "table",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"gridPos": {
|
||
"h": 12,
|
||
"w": 24,
|
||
"x": 0,
|
||
"y": 139
|
||
},
|
||
"fieldConfig": {
|
||
"defaults": {
|
||
"custom": {
|
||
"align": "auto",
|
||
"displayMode": "auto"
|
||
},
|
||
"decimals": 2
|
||
},
|
||
"overrides": [
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "shares"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "sell price"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "vest price (FIFO)"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "realized PNL"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
},
|
||
{
|
||
"id": "custom.cellOptions",
|
||
"value": {
|
||
"type": "color-text"
|
||
}
|
||
},
|
||
{
|
||
"id": "thresholds",
|
||
"value": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "PNL if held"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
},
|
||
{
|
||
"id": "custom.cellOptions",
|
||
"value": {
|
||
"type": "color-text"
|
||
}
|
||
},
|
||
{
|
||
"id": "thresholds",
|
||
"value": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "red",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "green",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"matcher": {
|
||
"id": "byName",
|
||
"options": "missed by"
|
||
},
|
||
"properties": [
|
||
{
|
||
"id": "decimals",
|
||
"value": 2
|
||
},
|
||
{
|
||
"id": "unit",
|
||
"value": "currencyUSD"
|
||
},
|
||
{
|
||
"id": "custom.cellOptions",
|
||
"value": {
|
||
"type": "color-text"
|
||
}
|
||
},
|
||
{
|
||
"id": "thresholds",
|
||
"value": {
|
||
"mode": "absolute",
|
||
"steps": [
|
||
{
|
||
"color": "green",
|
||
"value": null
|
||
},
|
||
{
|
||
"color": "red",
|
||
"value": 0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"options": {
|
||
"cellHeight": "sm",
|
||
"footer": {
|
||
"show": true,
|
||
"reducer": [
|
||
"sum"
|
||
],
|
||
"fields": [
|
||
"shares",
|
||
"realized PNL",
|
||
"PNL if held",
|
||
"missed by"
|
||
]
|
||
}
|
||
},
|
||
"targets": [
|
||
{
|
||
"refId": "A",
|
||
"datasource": {
|
||
"type": "grafana-postgresql-datasource",
|
||
"uid": "wealth-pg"
|
||
},
|
||
"rawQuery": true,
|
||
"editorMode": "code",
|
||
"format": "table",
|
||
"rawSql": "WITH px AS (SELECT close AS today_price FROM quote_latest WHERE asset_id='4f60833d-0bfb-484f-8ee6-f129af72e137'), lots AS (SELECT activity_date::date AS vest_date, quantity, unit_price AS vest_price, SUM(quantity) OVER (ORDER BY activity_date, id) AS lot_end, SUM(quantity) OVER (ORDER BY activity_date, id) - quantity AS lot_start FROM activities WHERE asset_id='4f60833d-0bfb-484f-8ee6-f129af72e137' AND activity_type='BUY'), sells AS (SELECT activity_date::date AS sell_date, quantity AS sell_qty, unit_price AS sell_price, SUM(quantity) OVER (ORDER BY activity_date, id) AS sell_end, SUM(quantity) OVER (ORDER BY activity_date, id) - quantity AS sell_start FROM activities WHERE asset_id='4f60833d-0bfb-484f-8ee6-f129af72e137' AND activity_type='SELL'), matched AS (SELECT s.sell_date, s.sell_price, l.vest_price, GREATEST(LEAST(l.lot_end, s.sell_end) - GREATEST(l.lot_start, s.sell_start), 0::numeric) AS qty FROM sells s CROSS JOIN lots l WHERE LEAST(l.lot_end, s.sell_end) > GREATEST(l.lot_start, s.sell_start)) SELECT sell_date, SUM(qty) AS shares, MIN(sell_price) AS \"sell price\", (SUM(qty*vest_price)/SUM(qty)) AS \"vest price (FIFO)\", SUM(qty*(sell_price-vest_price)) AS \"realized PNL\", (SUM(qty) * ((SELECT today_price FROM px) - SUM(qty*vest_price)/SUM(qty))) AS \"PNL if held\", (SUM(qty) * ((SELECT today_price FROM px) - MIN(sell_price))) AS \"missed by\" FROM matched GROUP BY sell_date ORDER BY sell_date"
|
||
}
|
||
]
|
||
}
|
||
],
|
||
"refresh": "5m",
|
||
"schemaVersion": 39,
|
||
"tags": [
|
||
"finance",
|
||
"personal",
|
||
"wealth"
|
||
],
|
||
"templating": {
|
||
"list": []
|
||
},
|
||
"time": {
|
||
"from": "now-180d",
|
||
"to": "now"
|
||
},
|
||
"timepicker": {},
|
||
"timezone": "browser",
|
||
"title": "Wealth",
|
||
"uid": "wealth",
|
||
"version": 1
|
||
}
|