diff --git a/stacks/monitoring/modules/monitoring/dashboards/wealth.json b/stacks/monitoring/modules/monitoring/dashboards/wealth.json index 7e646e8f..9eb062a6 100644 --- a/stacks/monitoring/modules/monitoring/dashboards/wealth.json +++ b/stacks/monitoring/modules/monitoring/dashboards/wealth.json @@ -281,333 +281,6 @@ } ] }, - { - "id": 5, - "title": "Net worth \u2014 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 \u2212 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 \u2212 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 \u2014 total value", @@ -834,936 +507,6 @@ } ] }, - { - "id": 11, - "title": "12mo return", - "description": "Modified-Dietz return over the trailing 12 months: market_gain / (nw_12mo_ago + 0.5 \u00d7 contributions_12mo). Excludes new money in \u2014 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 \u2212 withdrawals) over the trailing 12 months. How much new money you put in \u2014 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 \u00a3 \u2014 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": "\u0394 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": "\u0394 1d (mkt)", - "description": "Pure market gain over the trailing window \u2014 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": "\u0394 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": "\u0394 7d (mkt)", - "description": "Pure market gain over the trailing window \u2014 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": "\u0394 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": "\u0394 30d (mkt)", - "description": "Pure market gain over the trailing window \u2014 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": "\u0394 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": "\u0394 90d (mkt)", - "description": "Pure market gain over the trailing window \u2014 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 \u00d7 contributions). Pure investment performance \u2014 excludes new contributions, so a \u00a3100k 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": 91 - }, - "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 \u2014 contributions vs market gain", - "description": "Each calendar year's net worth change split into 'new money in' (contributions \u2212 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": 102 - }, - "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)), daily AS (SELECT 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), year_end AS (SELECT DISTINCT ON (EXTRACT(YEAR FROM valuation_date)) EXTRACT(YEAR FROM valuation_date)::int AS yr, nw, contrib FROM daily ORDER BY EXTRACT(YEAR FROM valuation_date), valuation_date DESC), deltas AS (SELECT yr, nw, contrib, lag(nw) OVER (ORDER BY yr) AS prev_nw, lag(contrib) OVER (ORDER BY yr) AS prev_contrib FROM year_end) SELECT yr::text AS year, ROUND((contrib - prev_contrib)::numeric, 0) AS contributions, ROUND(((nw - prev_nw) - (contrib - prev_contrib))::numeric, 0) AS market_gain FROM deltas WHERE prev_nw IS NOT NULL ORDER BY yr" - } - ] - }, { "id": 25, "title": "Monthly contributions vs market gain", @@ -3151,6 +1894,289 @@ ] } ] + }, + { + "id": 9201, + "title": "Returns over time windows", + "description": "Replaces the 12mo + \u0394 stat cards. \u0394 all = total change; \u0394 market = change net of contributions; Return % = Modified-Dietz.", + "type": "table", + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "wealth-pg" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 201 + }, + "fieldConfig": { + "defaults": { + "custom": { + "align": "right" + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "\u0394 all (\u00a3)" + }, + "properties": [ + { + "id": "unit", + "value": "currencyGBP" + }, + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + }, + { + "id": "color", + "value": { + "mode": "continuous-RdYlGr" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "\u0394 market (\u00a3)" + }, + "properties": [ + { + "id": "unit", + "value": "currencyGBP" + }, + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + }, + { + "id": "color", + "value": { + "mode": "continuous-RdYlGr" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Return %" + }, + "properties": [ + { + "id": "unit", + "value": "percent" + }, + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + }, + { + "id": "color", + "value": { + "mode": "continuous-RdYlGr" + } + } + ] + } + ] + }, + "options": { + "cellHeight": "sm", + "footer": { + "show": false + } + }, + "targets": [ + { + "refId": "A", + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "wealth-pg" + }, + "format": "table", + "editorMode": "code", + "rawQuery": true, + "rawSql": "WITH active_count AS (SELECT COUNT(*) n FROM accounts), mc AS (SELECT MAX(valuation_date) d FROM (SELECT valuation_date, COUNT(*) c FROM dav_corrected GROUP BY valuation_date) x WHERE c>=(SELECT n FROM active_count)), latest AS (SELECT DISTINCT ON (account_id) account_id, total_value nw_now, net_contribution c_now FROM dav_corrected WHERE valuation_date<=(SELECT d FROM mc) ORDER BY account_id, valuation_date DESC), an AS (SELECT SUM(nw_now) nw_now, SUM(c_now) c_now FROM latest), w(label,ord,iv) AS (VALUES ('1d',1,interval '1 day'),('7d',2,interval '7 days'),('30d',3,interval '30 days'),('90d',4,interval '90 days'),('12mo',5,interval '12 months')), ago AS (SELECT wl.label, wl.ord, SUM(x.nw) nw_ago, SUM(x.c) c_ago FROM w wl CROSS JOIN latest l LEFT JOIN LATERAL (SELECT total_value nw, net_contribution c FROM dav_corrected dd WHERE dd.account_id=l.account_id AND dd.valuation_date<=(SELECT d FROM mc)-wl.iv ORDER BY dd.valuation_date DESC LIMIT 1) x ON true GROUP BY wl.label, wl.ord) SELECT a.label AS \"Window\", round((an.nw_now-a.nw_ago)::numeric,0) AS \"\u0394 all (\u00a3)\", round(((an.nw_now-a.nw_ago)-(an.c_now-a.c_ago))::numeric,0) AS \"\u0394 market (\u00a3)\", round((((an.nw_now-a.nw_ago)-(an.c_now-a.c_ago))/NULLIF(a.nw_ago+0.5*(an.c_now-a.c_ago),0)*100)::numeric,2) AS \"Return %\" FROM ago a CROSS JOIN an ORDER BY a.ord" + } + ] + }, + { + "id": 9202, + "title": "Net worth: contribution vs market value (+ growth)", + "description": "Merged: net contribution + market value (net worth) lines; Growth = the gap between them.", + "type": "timeseries", + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "wealth-pg" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 201 + }, + "fieldConfig": { + "defaults": { + "unit": "currencyGBP", + "decimals": 0, + "custom": { + "drawStyle": "line", + "lineWidth": 2, + "fillOpacity": 0, + "showPoints": "never" + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Growth" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 15 + }, + { + "id": "custom.lineWidth", + "value": 1 + } + ] + } + ] + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "calcs": [ + "last" + ] + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "refId": "A", + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "wealth-pg" + }, + "format": "time_series", + "editorMode": "code", + "rawQuery": true, + "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 (net worth)\", (SUM(total_value)-SUM(net_contribution)) AS \"Growth\" FROM dav_corrected WHERE $__timeFilter(valuation_date) AND valuation_date <= (SELECT d FROM max_complete) GROUP BY valuation_date ORDER BY valuation_date" + } + ] + }, + { + "id": 9203, + "title": "Yearly: contributions / market gain / return %", + "description": "Merged yearly view. Contributions + market gain as bars (left \u00a3 axis); return % as a line (right % axis). timeFrom=10y so it always shows full history.", + "type": "timeseries", + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "wealth-pg" + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 209 + }, + "fieldConfig": { + "defaults": { + "unit": "currencyGBP", + "decimals": 0, + "custom": { + "drawStyle": "bars", + "fillOpacity": 80, + "lineWidth": 1 + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Return %" + }, + "properties": [ + { + "id": "custom.drawStyle", + "value": "line" + }, + { + "id": "custom.lineWidth", + "value": 2 + }, + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "unit", + "value": "percent" + }, + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "custom.axisLabel", + "value": "Return %" + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "yellow" + } + } + ] + } + ] + }, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "calcs": [ + "last" + ] + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "refId": "A", + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "wealth-pg" + }, + "format": "time_series", + "editorMode": "code", + "rawQuery": true, + "rawSql": "WITH active_count AS (SELECT COUNT(*) n FROM accounts), mc AS (SELECT MAX(valuation_date) d FROM (SELECT valuation_date, COUNT(*) c FROM dav_corrected GROUP BY valuation_date) x WHERE c>=(SELECT n FROM active_count)), daily AS (SELECT valuation_date, SUM(total_value) nw, SUM(net_contribution) contrib FROM dav_corrected WHERE valuation_date<=(SELECT d FROM mc) GROUP BY valuation_date), ye AS (SELECT DISTINCT ON (date_trunc('year',valuation_date)) date_trunc('year',valuation_date)::date yr, nw, contrib FROM daily ORDER BY date_trunc('year',valuation_date), valuation_date DESC), dd AS (SELECT yr, nw, contrib, lag(nw) OVER (ORDER BY yr) pnw, lag(contrib) OVER (ORDER BY yr) pc FROM ye) SELECT yr::timestamp AS \"time\", round((contrib-pc)::numeric,0) AS \"Contributions\", round(((nw-pnw)-(contrib-pc))::numeric,0) AS \"Market gain\", round((((nw-pnw)-(contrib-pc))/NULLIF(pnw+0.5*(contrib-pc),0)*100)::numeric,2) AS \"Return %\" FROM dd WHERE pnw IS NOT NULL ORDER BY yr" + } + ], + "timeFrom": "10y" } ], "refresh": "5m",