From 726fb251822af8dc96cb897ec88d4f9aeda995a1 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Tue, 12 May 2026 19:22:43 +0000 Subject: [PATCH] monitoring(wealth): paint declining segments red on growth chart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirror the panel 5 treatment on panel 7 (Growth = market value − contribution). Second SQL column emits the growth value only when the point is part of a declining segment; field override paints it red with no fill, spanNulls=false. --- .../modules/monitoring/dashboards/wealth.json | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/stacks/monitoring/modules/monitoring/dashboards/wealth.json b/stacks/monitoring/modules/monitoring/dashboards/wealth.json index 399021a9..c5c11c8d 100644 --- a/stacks/monitoring/modules/monitoring/dashboards/wealth.json +++ b/stacks/monitoring/modules/monitoring/dashboards/wealth.json @@ -499,7 +499,7 @@ { "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.", + "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", @@ -546,6 +546,37 @@ "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 + } + ] } ] }, @@ -573,7 +604,7 @@ "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 valuation_date::timestamp AS \"time\", (SUM(total_value) - SUM(net_contribution)) AS growth FROM daily_account_valuation WHERE $__timeFilter(valuation_date) AND valuation_date <= (SELECT d FROM max_complete) GROUP BY valuation_date ORDER BY valuation_date" + "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) - SUM(net_contribution)) AS g 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, 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" } ] },