@sipemu/anofox-forecast 0.5.1 → 0.8.0
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 +91 -276
- package/anofox_forecast_js.d.ts +916 -7
- package/anofox_forecast_js.js +3454 -934
- package/anofox_forecast_js_bg.wasm +0 -0
- package/package.json +20 -24
- package/anofox_forecast_js_bg.wasm.d.ts +0 -412
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)
|
|
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
|
-
##
|
|
12
|
-
|
|
13
|
-
### Basic Example
|
|
13
|
+
## Quick Start
|
|
14
14
|
|
|
15
15
|
```javascript
|
|
16
|
-
import { TimeSeries,
|
|
16
|
+
import init, { TimeSeries, AutoForecaster, NaiveForecaster } from '@sipemu/anofox-forecast';
|
|
17
17
|
|
|
18
|
-
|
|
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
|
-
|
|
23
|
-
const model = new
|
|
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(
|
|
24
|
+
console.log(forecast.values); // Float64Array with 5 predictions
|
|
29
25
|
```
|
|
30
26
|
|
|
31
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
- `
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
- `
|
|
145
|
-
- `
|
|
146
|
-
|
|
147
|
-
|
|
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
|
|
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(
|
|
213
|
-
console.log(
|
|
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
|
-
##
|
|
99
|
+
## Common API Pattern
|
|
229
100
|
|
|
230
|
-
|
|
101
|
+
All forecasters share the same interface:
|
|
231
102
|
|
|
232
103
|
```javascript
|
|
233
|
-
|
|
104
|
+
const model = new SomeForecaster(/* config */);
|
|
105
|
+
model.fit(timeSeries);
|
|
234
106
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
107
|
+
// Point forecasts
|
|
108
|
+
const forecast = model.predict(horizon);
|
|
109
|
+
console.log(forecast.values);
|
|
238
110
|
|
|
239
|
-
|
|
240
|
-
model.
|
|
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
|
-
##
|
|
244
|
-
|
|
245
|
-
```html
|
|
246
|
-
<script type="module">
|
|
247
|
-
import init, { TimeSeries, ThetaForecaster } from './anofox_forecast_js.js';
|
|
117
|
+
## ETS Notation
|
|
248
118
|
|
|
249
|
-
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
|
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
|
-
|
|
129
|
+
Add holidays and named regressors for models that support exogenous variables:
|
|
308
130
|
|
|
309
131
|
```javascript
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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
|
-
|
|
321
|
-
|
|
136
|
+
ts.setCalendar(calendar);
|
|
137
|
+
model.fit(ts); // ARIMA, MFLES, etc. will use the regressors
|
|
322
138
|
```
|
|
323
139
|
|
|
324
|
-
##
|
|
140
|
+
## TypeScript Support
|
|
325
141
|
|
|
326
|
-
|
|
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
|
-
|
|
144
|
+
```typescript
|
|
145
|
+
import { TimeSeries, Forecast, AutoForecaster } from '@sipemu/anofox-forecast';
|
|
332
146
|
|
|
333
|
-
|
|
334
|
-
const
|
|
147
|
+
const ts: TimeSeries = new TimeSeries(new Float64Array([1, 2, 3]));
|
|
148
|
+
const forecast: Forecast = model.predict(5);
|
|
335
149
|
```
|
|
336
150
|
|
|
337
|
-
##
|
|
151
|
+
## Links
|
|
338
152
|
|
|
339
|
-
-
|
|
340
|
-
-
|
|
341
|
-
-
|
|
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
|
|