pond-ts 0.48.0 → 0.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,7 +8,8 @@ The `@pond-ts` packages — `pond-ts`, `@pond-ts/react`, `@pond-ts/charts`,
8
8
  tag, so this file covers them all. Pre-1.0: minor bumps may include new features
9
9
  and type-level changes; patch bumps are strictly additive.
10
10
 
11
- [Unreleased]: https://github.com/pond-ts/pond/compare/v0.48.0...HEAD
11
+ [Unreleased]: https://github.com/pond-ts/pond/compare/v0.48.1...HEAD
12
+ [0.48.1]: https://github.com/pond-ts/pond/compare/v0.48.0...v0.48.1
12
13
  [0.48.0]: https://github.com/pond-ts/pond/compare/v0.47.0...v0.48.0
13
14
  [0.47.0]: https://github.com/pond-ts/pond/compare/v0.46.0...v0.47.0
14
15
  [0.46.0]: https://github.com/pjm17971/pond-ts/compare/v0.45.0...v0.46.0
@@ -47,6 +48,20 @@ and type-level changes; patch bumps are strictly additive.
47
48
 
48
49
  ## [Unreleased]
49
50
 
51
+ ## [0.48.1] — 2026-07-19
52
+
53
+ ### Fixed
54
+
55
+ - `smooth(column, 'loess', …)` is now numerically stable on absolute epoch-ms
56
+ timestamps. The local weighted regression is now conditioned on `x` centred at
57
+ the query point; previously the un-centred normal equations lost precision to
58
+ floating-point cancellation (anchors ~1.7e12 → `x²` terms ~3e24). Severity
59
+ scales with (anchor magnitude / window width)²: on finely-spaced series
60
+ (second-level cadence) the fit overshot wildly outside the data range instead
61
+ of smoothing, while coarser day-spaced series erred only subtly. Output is now
62
+ shift-invariant to the time origin. Series built from small integer anchors
63
+ (e.g. in unit tests) were unaffected, which is why this hid.
64
+
50
65
  ## [0.48.0] — 2026-07-17
51
66
 
52
67
  ### Added
@@ -187,10 +187,16 @@ function loessAt(x, anchors, values, span) {
187
187
  let sumWY = 0;
188
188
  let sumWXX = 0;
189
189
  let sumWXY = 0;
190
+ // Regress in local coordinates centred on the query point (`dx = pointX - x`).
191
+ // Anchors are typically absolute epoch-ms (~1.7e12), so accumulating
192
+ // `pointX * pointX` (~3e24) into the normal equations loses all precision to
193
+ // floating-point cancellation and the fit overshoots wildly. Centring keeps
194
+ // every term small; the fitted value at the query point is then just the
195
+ // intercept, since `dx = 0` there.
190
196
  for (let index = start; index < end; index++) {
191
- const pointX = anchors[index];
197
+ const dx = anchors[index] - x;
192
198
  const pointY = values[index];
193
- const distance = Math.abs(pointX - x);
199
+ const distance = Math.abs(dx);
194
200
  const ratio = distance / bandwidth;
195
201
  const weight = ratio >= 1 ? 0 : (1 - ratio ** 3) ** 3;
196
202
  if (weight === 0) {
@@ -198,10 +204,10 @@ function loessAt(x, anchors, values, span) {
198
204
  }
199
205
  weightedCount += 1;
200
206
  sumW += weight;
201
- sumWX += weight * pointX;
207
+ sumWX += weight * dx;
202
208
  sumWY += weight * pointY;
203
- sumWXX += weight * pointX * pointX;
204
- sumWXY += weight * pointX * pointY;
209
+ sumWXX += weight * dx * dx;
210
+ sumWXY += weight * dx * pointY;
205
211
  }
206
212
  if (weightedCount === 0 || sumW === 0) {
207
213
  return undefined;
@@ -210,9 +216,8 @@ function loessAt(x, anchors, values, span) {
210
216
  if (Math.abs(denominator) < Number.EPSILON) {
211
217
  return sumWY / sumW;
212
218
  }
213
- const intercept = (sumWY * sumWXX - sumWX * sumWXY) / denominator;
214
- const slope = (sumW * sumWXY - sumWX * sumWY) / denominator;
215
- return intercept + slope * x;
219
+ // Value at the query point: intercept + slope * dx, with dx = 0.
220
+ return (sumWY * sumWXX - sumWX * sumWXY) / denominator;
216
221
  }
217
222
  function lowerBound(values, target) {
218
223
  let low = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pond-ts",
3
- "version": "0.48.0",
3
+ "version": "0.48.1",
4
4
  "description": "TypeScript-first time series primitives",
5
5
  "license": "MIT",
6
6
  "repository": {