@sipemu/anofox-forecast 0.5.1 → 0.7.6

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/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # @sipemu/anofox-forecast
2
2
 
3
- WebAssembly bindings for [anofox-forecast](https://crates.io/crates/anofox-forecast), a comprehensive time series forecasting library with 50+ models, automatic model selection, probabilistic postprocessing, and more.
3
+ WebAssembly bindings for the [anofox-forecast](https://crates.io/crates/anofox-forecast) time series forecasting library.
4
+
5
+ 40+ forecasting models, automatic model selection, probabilistic postprocessing, and more — running entirely in the browser via WebAssembly.
4
6
 
5
7
  ## Installation
6
8
 
@@ -8,337 +10,150 @@ WebAssembly bindings for [anofox-forecast](https://crates.io/crates/anofox-forec
8
10
  npm install @sipemu/anofox-forecast
9
11
  ```
10
12
 
11
- ## Usage
12
-
13
- ### Basic Example
13
+ ## Quick Start
14
14
 
15
15
  ```javascript
16
- import { TimeSeries, NaiveForecaster, ThetaForecaster } from '@sipemu/anofox-forecast';
16
+ import init, { TimeSeries, AutoForecaster, NaiveForecaster } from '@sipemu/anofox-forecast';
17
17
 
18
- // Create a time series from values
19
- const data = [10, 12, 15, 14, 18, 20, 22, 25, 24, 28];
20
- const ts = new TimeSeries(new Float64Array(data));
18
+ await init();
21
19
 
22
- // Create and fit a forecaster
23
- const model = new NaiveForecaster();
20
+ const ts = new TimeSeries(new Float64Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]));
21
+ const model = new AutoForecaster();
24
22
  model.fit(ts);
25
-
26
- // Generate predictions
27
23
  const forecast = model.predict(5);
28
- console.log('Predictions:', forecast.values);
24
+ console.log(forecast.values); // Float64Array with 5 predictions
29
25
  ```
30
26
 
31
- ### With Timestamps
32
-
33
- ```javascript
34
- import { TimeSeries } from '@sipemu/anofox-forecast';
35
-
36
- const values = [10, 12, 15, 14, 18];
37
- const timestamps = [
38
- Date.parse('2024-01-01'),
39
- Date.parse('2024-01-02'),
40
- Date.parse('2024-01-03'),
41
- Date.parse('2024-01-04'),
42
- Date.parse('2024-01-05'),
43
- ];
44
-
45
- const ts = TimeSeries.withTimestamps(
46
- new Float64Array(values),
47
- new Float64Array(timestamps)
48
- );
49
- ```
50
-
51
- ## Available Forecasters
52
-
53
- ### Baseline Models
54
-
55
- | Forecaster | Description | Parameters |
56
- |------------|-------------|------------|
57
- | `NaiveForecaster` | Last observation repeated | - |
58
- | `MeanForecaster` | Historical mean | - |
59
- | `SeasonalNaiveForecaster` | Same season from previous cycle | `period` |
60
- | `RandomWalkDriftForecaster` | Random walk with trend | - |
61
- | `SMAForecaster` | Simple Moving Average | `window` |
62
- | `WindowAverageForecaster` | Rolling window average | `window_size` |
63
- | `SeasonalWindowAverageForecaster` | Seasonal window average | `period`, `window` |
64
-
65
- ### Exponential Smoothing Models
66
-
67
- | Forecaster | Description | Parameters |
68
- |------------|-------------|------------|
69
- | `SESForecaster` | Simple Exponential Smoothing | `alpha` |
70
- | `HoltForecaster` | Holt Linear Trend (Double ES) | `alpha`, `beta` |
71
- | `HoltWintersForecaster` | Triple Exponential Smoothing | `alpha`, `beta`, `gamma`, `period` |
72
- | `SeasonalESForecaster` | Seasonal Exponential Smoothing | `period` |
73
- | `ETSForecaster` | ETS state-space model | `error`, `trend`, `seasonal`, `period` |
74
- | `AutoETSForecaster` | Automatic ETS selection | - |
75
-
76
- ### Theta Models
77
-
78
- | Forecaster | Description | Parameters |
79
- |------------|-------------|------------|
80
- | `ThetaForecaster` | Standard Theta method | - |
81
- | `OptimizedThetaForecaster` | Optimized Theta | - |
82
- | `DynamicThetaForecaster` | Dynamic coefficient updates | `alpha` |
83
- | `AutoThetaForecaster` | Automatic Theta selection | - |
84
-
85
- ### ARIMA Models
86
-
87
- | Forecaster | Description | Parameters |
88
- |------------|-------------|------------|
89
- | `ARIMAForecaster` | ARIMA | `p`, `d`, `q` |
90
- | `SARIMAForecaster` | Seasonal ARIMA | `p`, `d`, `q`, `P`, `D`, `Q`, `period` |
91
- | `AutoARIMAForecaster` | Automatic ARIMA selection | - |
92
-
93
- ### Intermittent Demand Models
94
-
95
- | Forecaster | Description | Parameters |
96
- |------------|-------------|------------|
97
- | `CrostonForecaster` | Croston's method | - |
98
- | `TSBForecaster` | Teunter-Syntetos-Babai | - |
99
- | `ADIDAForecaster` | Aggregate-Disaggregate approach | - |
100
- | `IMAPAForecaster` | Multiple Aggregation Prediction | - |
101
-
102
- ### Advanced Models
103
-
104
- | Forecaster | Description | Parameters |
105
- |------------|-------------|------------|
106
- | `TBATSForecaster` | TBATS (complex seasonality) | `seasonal_periods[]` |
107
- | `AutoTBATSForecaster` | Automatic TBATS | `seasonal_periods[]` |
108
- | `MFLESForecaster` | Multiple Frequency LOESS | `seasonal_periods[]` |
109
- | `MSTLForecasterWrapper` | MSTL decomposition | `seasonal_periods[]` |
110
- | `GARCHForecaster` | GARCH volatility model | `p`, `q` |
27
+ ## Available Models
111
28
 
112
29
  ### Auto Selection
113
-
114
- | Forecaster | Description | Parameters |
115
- |------------|-------------|------------|
116
- | `AutoForecaster` | Best of ARIMA, ETS, Theta | - |
117
- | `AutoEnsembleForecaster` | Ensemble of top-K models | - |
118
-
119
- ## Prediction Intervals
120
-
121
- Most models support prediction intervals:
122
-
123
- ```javascript
124
- import { NaiveForecaster } from '@sipemu/anofox-forecast';
125
-
126
- const model = new NaiveForecaster();
127
- model.fit(ts);
128
-
129
- // Get forecast with 95% prediction intervals
130
- const forecast = model.predictWithIntervals(5, 0.95);
131
-
132
- console.log('Point predictions:', forecast.values);
133
- console.log('Lower bound:', forecast.lower);
134
- console.log('Upper bound:', forecast.upper);
135
- ```
136
-
137
- ## API Reference
138
-
139
- ### TimeSeries
140
-
141
- - `new TimeSeries(values: Float64Array)` - Create from values
142
- - `TimeSeries.withTimestamps(values, timestamps)` - Create with timestamps (ms since epoch)
143
- - `ts.length` - Number of observations
144
- - `ts.values` - Get values as array
145
- - `ts.isEmpty()` - Check if empty
146
- - `ts.hasMissingValues()` - Check for NaN values
147
- - `ts.slice(start, end)` - Get a slice of the series
148
-
149
- ### Forecast
150
-
151
- - `forecast.horizon` - Number of predictions
152
- - `forecast.values` - Point predictions
153
- - `forecast.lower` - Lower prediction interval (if available)
154
- - `forecast.upper` - Upper prediction interval (if available)
155
- - `forecast.hasLower()` - Check if lower interval exists
156
- - `forecast.hasUpper()` - Check if upper interval exists
157
-
158
- ### ETS Model Specification
159
-
160
- For `ETSForecaster`, use string codes:
161
- - **Error**: `"A"` (additive) or `"M"` (multiplicative)
162
- - **Trend**: `"N"` (none), `"A"` (additive), or `"Ad"` (additive damped)
163
- - **Seasonal**: `"N"` (none), `"A"` (additive), or `"M"` (multiplicative)
164
-
165
- ```javascript
166
- // ETS(A,A,M) - Additive error, Additive trend, Multiplicative seasonal
167
- const ets = new ETSForecaster("A", "A", "M", 12);
168
- ```
169
-
170
- #### Standard ETS Notation
171
-
172
- You can also use standard ETS notation (following [FPP3 taxonomy](https://otexts.com/fpp3/taxonomy.html)):
173
-
174
- ```javascript
175
- // Create from notation string
176
- const model = ETSForecaster.fromNotation("AAA", 12); // Holt-Winters additive
177
- const model = ETSForecaster.fromNotation("MAM", 12); // Multiplicative Holt-Winters
178
- const model = ETSForecaster.fromNotation("AAdM", 12); // Damped trend, multiplicative seasonal
179
- ```
180
-
181
- Valid notation format: `ErrorTrendSeasonal`
182
- - First letter: Error (A or M)
183
- - Second letter(s): Trend (N, A, or Ad)
184
- - Third letter: Seasonal (N, A, or M)
185
-
186
- #### Model Validation
187
-
188
- Some ETS combinations are unstable and will throw an error:
189
- - `MAA` - Multiplicative error + Additive trend + Additive seasonal
190
- - `MAdA` - Multiplicative error + Damped trend + Additive seasonal
191
-
192
- You can check validity before creating:
193
-
194
- ```javascript
195
- // Check if a specification is valid
196
- ETSForecaster.isValidSpec("A", "A", "A"); // true
197
- ETSForecaster.isValidSpec("M", "A", "M"); // true
198
- ETSForecaster.isValidSpec("M", "A", "A"); // false (unstable)
199
- ```
30
+ - `AutoForecaster` — selects best model across ARIMA, ETS, and Theta families
31
+ - `AutoEnsembleForecaster` automatic ensemble of top-K models
32
+ - `AutoARIMAForecaster` — automatic ARIMA order selection
33
+ - `AutoETSForecaster` automatic ETS model selection
34
+ - `AutoThetaForecaster` automatic Theta variant selection
35
+ - `AutoTBATSForecaster` — automatic TBATS configuration
36
+
37
+ ### Exponential Smoothing
38
+ - `SESForecaster` Simple Exponential Smoothing
39
+ - `HoltForecaster` — Holt's Linear Trend
40
+ - `HoltWintersForecaster` — Holt-Winters (additive/multiplicative seasonality)
41
+ - `SeasonalESForecaster` Seasonal Exponential Smoothing
42
+ - `ETSForecaster` — Error-Trend-Seasonal state-space framework
43
+
44
+ ### ARIMA
45
+ - `ARIMAForecaster` — ARIMA(p,d,q) model
46
+
47
+ ### Theta
48
+ - `ThetaForecaster` — Standard Theta
49
+ - `OptimizedThetaForecaster` — Optimized Theta
50
+ - `DynamicThetaForecaster` — Dynamic Theta
51
+
52
+ ### Baseline
53
+ - `NaiveForecaster`, `MeanForecaster`, `SeasonalNaiveForecaster`
54
+ - `RandomWalkWithDriftForecaster`, `SMAForecaster`, `WindowAverageForecaster`
55
+ - `SeasonalWindowAverageForecaster`
56
+
57
+ ### Intermittent Demand
58
+ - `CrostonForecaster`, `ADIDAForecaster`, `TSBForecaster`, `IMAPAForecaster`
59
+
60
+ ### Complex Seasonality & Volatility
61
+ - `TBATSForecaster`, `MFLESForecaster`, `MSTLForecaster`
62
+ - `GARCHForecaster` volatility modeling
63
+
64
+ ### Ensemble
65
+ - `EnsembleForecaster` — combine multiple models
200
66
 
201
67
  ## Probabilistic Postprocessing
202
68
 
203
- Generate calibrated prediction intervals using conformal prediction, historical simulation, or normal approximation:
69
+ Generate calibrated prediction intervals using conformal prediction, historical simulation, or normal approximation.
204
70
 
205
71
  ```javascript
206
72
  import { JsConformalPredictor, JsPointForecasts, JsPostProcessor } from '@sipemu/anofox-forecast';
207
73
 
208
- // Conformal prediction intervals (distribution-free)
74
+ // Conformal prediction intervals
209
75
  const predictor = new JsConformalPredictor(0.9); // 90% coverage
210
76
  predictor.calibrate(forecasts, actuals);
211
77
  const intervals = predictor.predictIntervals(newForecasts);
212
- console.log('Lower:', intervals.lower);
213
- console.log('Upper:', intervals.upper);
78
+ console.log(intervals.lower); // Float64Array
79
+ console.log(intervals.upper); // Float64Array
214
80
 
215
81
  // Unified PostProcessor API
216
82
  const processor = JsPostProcessor.conformal(0.95);
217
83
  const trained = processor.train(forecasts, actuals);
218
84
  const pi = processor.predictIntervals(trained, newForecasts);
85
+
86
+ // Backtesting
87
+ const config = new JsBacktestConfig(50, 5, 7); // window=50, step=5, horizon=7
88
+ const result = backtestPostProcessor(processor, forecasts, actuals, config);
89
+ console.log(`Coverage: ${result.coverage}`);
219
90
  ```
220
91
 
221
- ### Available Methods
222
- - `JsConformalPredictor` — distribution-free intervals (split, cross-val, jackknife+)
92
+ ### Available Postprocessing Methods
93
+ - `JsConformalPredictor` — distribution-free prediction intervals (split, cross-val, jackknife+)
223
94
  - `JsNormalPredictor` — Gaussian error assumption baseline
224
95
  - `JsHistoricalSimulator` — non-parametric empirical error distribution
225
96
  - `JsPostProcessor` — unified API wrapping all methods
226
97
  - `JsBacktestConfig` / `JsBacktestResult` — rolling/expanding window backtesting
227
98
 
228
- ## Calendar Annotations
99
+ ## Common API Pattern
229
100
 
230
- Add holidays and named regressors for models that support exogenous variables:
101
+ All forecasters share the same interface:
231
102
 
232
103
  ```javascript
233
- import { CalendarAnnotations } from '@sipemu/anofox-forecast';
104
+ const model = new SomeForecaster(/* config */);
105
+ model.fit(timeSeries);
234
106
 
235
- const calendar = new CalendarAnnotations();
236
- calendar.addHoliday(Date.parse('2024-12-25'));
237
- calendar.addRegressor('temperature', new Float64Array([20, 22, 25, 23]));
107
+ // Point forecasts
108
+ const forecast = model.predict(horizon);
109
+ console.log(forecast.values);
238
110
 
239
- ts.setCalendar(calendar);
240
- model.fit(ts); // ARIMA, MFLES, etc. will automatically use the regressors
111
+ // With confidence intervals
112
+ const forecastCI = model.predictWithIntervals(horizon, 0.95);
113
+ console.log(forecastCI.lower);
114
+ console.log(forecastCI.upper);
241
115
  ```
242
116
 
243
- ## Browser Usage
244
-
245
- ```html
246
- <script type="module">
247
- import init, { TimeSeries, ThetaForecaster } from './anofox_forecast_js.js';
117
+ ## ETS Notation
248
118
 
249
- async function main() {
250
- await init();
251
-
252
- const data = new Float64Array([10, 12, 15, 14, 18, 20, 22, 25]);
253
- const ts = new TimeSeries(data);
254
-
255
- const model = new ThetaForecaster();
256
- model.fit(ts);
257
-
258
- const forecast = model.predict(5);
259
- console.log('Forecast:', forecast.values);
260
- }
261
-
262
- main();
263
- </script>
264
- ```
265
-
266
- ## Node.js Usage
119
+ Create ETS models using standard notation (A=Additive, M=Multiplicative, N=None):
267
120
 
268
121
  ```javascript
269
- import { TimeSeries, AutoARIMAForecaster } from '@sipemu/anofox-forecast';
270
-
271
- // Load your data
272
- const data = [/* your time series data */];
273
- const ts = new TimeSeries(new Float64Array(data));
274
-
275
- // Forecast with AutoARIMA
276
- const model = new AutoARIMAForecaster();
277
- model.fit(ts);
278
- const forecast = model.predict(10);
122
+ const ets = ETSForecaster.fromNotation('AAA', 12); // ETS(A,A,A) with period 12
123
+ ets.fit(ts);
124
+ const forecast = ets.predict(12);
279
125
  ```
280
126
 
281
- ## Calendar Feature Engineering
282
-
283
- ```javascript
284
- import { FeatureGenerator, generateFutureTimestamps } from '@sipemu/anofox-forecast';
285
-
286
- // Build a feature generator
287
- const gen = new FeatureGenerator();
288
- gen.fourier(7, 2); // weekly Fourier terms
289
- gen.cyclical('month'); // sin/cos month encoding
290
- gen.cyclical('day_of_week'); // sin/cos day-of-week
291
- gen.binary('weekend'); // 0/1 weekend indicator
292
- gen.binary('month_end'); // 0/1 month-end
293
- gen.advanced('days_in_month'); // 28-31
294
-
295
- // Generate features from timestamps (ms since epoch)
296
- const features = gen.generate(timestamps); // { month_sin: [...], weekend: [...], ... }
297
- const names = gen.featureNames();
298
-
299
- // Generate future timestamps (calendar-aware)
300
- const future = generateFutureTimestamps(lastTimestampMs, '1mo', 12); // monthly
301
- const weekly = generateFutureTimestamps(lastTimestampMs, '1w', 4); // weekly
302
-
303
- // Auto-infer from TimeSeries
304
- const futureTs = ts.futureTimestamps(12);
305
- ```
127
+ ## Calendar Annotations
306
128
 
307
- ## Bootstrap Prediction Intervals
129
+ Add holidays and named regressors for models that support exogenous variables:
308
130
 
309
131
  ```javascript
310
- import { JsBootstrapPredictor } from '@sipemu/anofox-forecast';
311
-
312
- const bp = new JsBootstrapPredictor(0.95);
313
- bp.nReplicates(1000);
314
- bp.seed(42);
315
-
316
- const result = bp.fit(fittedValues, actuals);
317
- const intervals = bp.predictIntervals(result, pointForecast);
318
- console.log(intervals.lower, intervals.upper);
132
+ const calendar = new CalendarAnnotations();
133
+ calendar.addHoliday(Date.parse('2024-12-25'));
134
+ calendar.addRegressor('temperature', new Float64Array([20, 22, 25, ...]));
319
135
 
320
- // Multi-quantile forecasts
321
- const quantiles = bp.predictQuantiles(result, pointForecast, [0.10, 0.25, 0.50, 0.75, 0.90]);
136
+ ts.setCalendar(calendar);
137
+ model.fit(ts); // ARIMA, MFLES, etc. will use the regressors
322
138
  ```
323
139
 
324
- ## Per-Step Conformal Prediction
140
+ ## TypeScript Support
325
141
 
326
- ```javascript
327
- // Per-horizon-step intervals (tighter at h=1, wider at h=12)
328
- const perStep = predictor.fitPerStep(foldForecasts, foldActuals);
329
- console.log(perStep.halfWidths); // different width per step
142
+ Full TypeScript definitions are included. Import types directly:
330
143
 
331
- const intervals = perStep.predictIntervals(pointForecast);
144
+ ```typescript
145
+ import { TimeSeries, Forecast, AutoForecaster } from '@sipemu/anofox-forecast';
332
146
 
333
- // Multi-quantile conformal forecasts
334
- const quantiles = predictor.predictQuantiles(result, pointForecast, [0.10, 0.50, 0.90]);
147
+ const ts: TimeSeries = new TimeSeries(new Float64Array([1, 2, 3]));
148
+ const forecast: Forecast = model.predict(5);
335
149
  ```
336
150
 
337
- ## Limitations
151
+ ## Links
338
152
 
339
- - The `parallel` feature from the Rust crate is not available in WASM
340
- - IDR (Isotonic Distributional Regression) and QRA are not yet exposed in WASM
341
- - RegressionForecaster (11 regression backends) is Rust-only (not yet in WASM)
153
+ - [Rust crate](https://crates.io/crates/anofox-forecast)
154
+ - [API documentation](https://docs.rs/anofox-forecast)
155
+ - [GitHub repository](https://github.com/sipemu/anofox-forecast)
156
+ - [DuckDB extension](https://github.com/DataZooDE/anofox-forecast)
342
157
 
343
158
  ## License
344
159