From 9ee13a45bbfba643dc462962e6dc8b75c793fc36 Mon Sep 17 00:00:00 2001 From: ramseshk <45832522+ramseshk@users.noreply.github.com> Date: Fri, 7 Aug 2026 15:26:42 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20LTTB=20downsampling=20crashes=20on=20str?= =?UTF-8?q?ing=20timestamps=20+=20abs=E2=86=92Math.abs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _lttb_downsample: equity curve timestamps are ISO strings, not numeric. Rewrote to use array indices for triangle area instead of trying to multiply string * float. - Fixed IndexError from reusing 'a' variable incorrectly - Also fixed earlier: abs(dd) → Math.abs(dd) in vbt.html --- dashboard/server.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/dashboard/server.py b/dashboard/server.py index 7c22f73..8534f30 100644 --- a/dashboard/server.py +++ b/dashboard/server.py @@ -586,27 +586,28 @@ def _lttb_downsample(points: list[dict], target: int) -> list[dict]: return points bucket_size = (n - 2) / (target - 2) result = [points[0]] - a = 0 + a = 0 # index of last point in result (within original points array) for i in range(target - 2): - avg_x_start = int((i + 0) * bucket_size) + 1 - avg_x_end = int((i + 1) * bucket_size) + 1 - avg_range = points[avg_x_start:avg_x_end] - avg_x = sum(p.get("t", 0) if isinstance(p.get("t"), (int, float)) else 0 for p in avg_range) / max(len(avg_range), 1) - avg_y = sum(p["v"] for p in avg_range) / max(len(avg_range), 1) - range_offs = int((i + 1) * bucket_size) + 1 - range_to = int((i + 2) * bucket_size) + 1 - max_area = -1.0 + avg_start = int((i + 0) * bucket_size) + 1 + avg_end = int((i + 1) * bucket_size) + 1 + avg_range = points[avg_start:avg_end] + avg_y = sum(p["v"] for p in avg_range) / max(len(avg_range), 1) + avg_x = int((avg_start + avg_end - 1) / 2) + range_offs = int((i + 1) * bucket_size) + 1 + range_to = int((i + 2) * bucket_size) + 1 + max_area = -1.0 + next_pt = range_offs for j in range(range_offs, min(range_to + 1, n)): - pa = result[a] + pa = points[a] pc = points[j] - area = abs((pa.get("t", 0) if isinstance(pa.get("t"), (int, float)) else a) * (pc["v"] - avg_y) + - pc.get("t", 0) * (avg_y - pa["v"]) + - avg_x * (pa["v"] - pc["v"])) * 0.5 + area = abs((a - j) * (pc["v"] - avg_y) + + (j - avg_x) * (avg_y - pa["v"]) + + (avg_x - a) * (pa["v"] - pc["v"])) * 0.5 if area > max_area: max_area = area - next_a = j - result.append(points[next_a]) - a = next_a + next_pt = j + result.append(points[next_pt]) + a = next_pt result.append(points[-1]) return result