@sipemu/anofox-forecast 0.4.4 → 0.4.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,6 @@
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.
3
+ WebAssembly bindings for [anofox-forecast](https://crates.io/crates/anofox-forecast), a comprehensive time series forecasting library with 40+ models, automatic model selection, probabilistic postprocessing, and more.
4
4
 
5
5
  ## Installation
6
6
 
@@ -109,9 +109,27 @@ const ts = TimeSeries.withTimestamps(
109
109
  | `MSTLForecasterWrapper` | MSTL decomposition | `seasonal_periods[]` |
110
110
  | `GARCHForecaster` | GARCH volatility model | `p`, `q` |
111
111
 
112
+ ### Auto Selection
113
+
114
+ | Forecaster | Description | Parameters |
115
+ |------------|-------------|------------|
116
+ | `AutoForecaster` | Best of ARIMA, ETS, Theta | - |
117
+ | `AutoEnsembleForecaster` | Ensemble of top-K models | - |
118
+
119
+ ### Orchestration
120
+
121
+ | Type | Description |
122
+ |------|-------------|
123
+ | `JsDataProfile` | Automated data profiling (stationarity, trend, quality) |
124
+ | `JsPipelineBuilder` | Declarative pipeline construction |
125
+ | `JsPipelineResult` | Pipeline result with forecast and diagnostics |
126
+ | `JsPipelineReport` | Structured multi-section report |
127
+ | `selectModels()` | Model recommendation from data profile |
128
+ | `explainResult()` | Human-readable result explanation |
129
+
112
130
  ## Prediction Intervals
113
131
 
114
- Some models support prediction intervals:
132
+ Most models support prediction intervals:
115
133
 
116
134
  ```javascript
117
135
  import { NaiveForecaster } from '@sipemu/anofox-forecast';
@@ -191,6 +209,163 @@ ETSForecaster.isValidSpec("M", "A", "M"); // true
191
209
  ETSForecaster.isValidSpec("M", "A", "A"); // false (unstable)
192
210
  ```
193
211
 
212
+ ## Probabilistic Postprocessing
213
+
214
+ Generate calibrated prediction intervals using conformal prediction, historical simulation, or normal approximation:
215
+
216
+ ```javascript
217
+ import { JsConformalPredictor, JsPointForecasts, JsPostProcessor } from '@sipemu/anofox-forecast';
218
+
219
+ // Conformal prediction intervals (distribution-free)
220
+ const predictor = new JsConformalPredictor(0.9); // 90% coverage
221
+ predictor.calibrate(forecasts, actuals);
222
+ const intervals = predictor.predictIntervals(newForecasts);
223
+ console.log('Lower:', intervals.lower);
224
+ console.log('Upper:', intervals.upper);
225
+
226
+ // Unified PostProcessor API
227
+ const processor = JsPostProcessor.conformal(0.95);
228
+ const trained = processor.train(forecasts, actuals);
229
+ const pi = processor.predictIntervals(trained, newForecasts);
230
+ ```
231
+
232
+ ### Available Methods
233
+ - `JsConformalPredictor` — distribution-free intervals (split, cross-val, jackknife+)
234
+ - `JsNormalPredictor` — Gaussian error assumption baseline
235
+ - `JsHistoricalSimulator` — non-parametric empirical error distribution
236
+ - `JsPostProcessor` — unified API wrapping all methods
237
+ - `JsBacktestConfig` / `JsBacktestResult` — rolling/expanding window backtesting
238
+
239
+ ## Orchestration / Agent Forecasting
240
+
241
+ Build autonomous forecasting pipelines with data profiling, multi-metric model selection, preprocessing, ensemble construction, and structured reporting:
242
+
243
+ ### Data Profiling
244
+
245
+ ```javascript
246
+ import { JsDataProfile } from '@sipemu/anofox-forecast';
247
+
248
+ // Profile a time series
249
+ const profile = JsDataProfile.fromSeries(ts);
250
+ console.log('Observations:', profile.nObservations);
251
+ console.log('Trend:', profile.trendDirection); // "Rising", "Falling", "Flat"
252
+ console.log('Stationary?', profile.isStationary);
253
+ console.log('Intermittent?', profile.isIntermittent);
254
+ console.log('Quality:', profile.qualityScore); // 0.0 to 1.0
255
+
256
+ // Full profile as JSON
257
+ const json = profile.toJSON();
258
+
259
+ // Profile raw values (no timestamps needed)
260
+ const profile2 = JsDataProfile.fromValues(new Float64Array([1, 2, 3, 4, 5]));
261
+ ```
262
+
263
+ ### Model Selection
264
+
265
+ ```javascript
266
+ import { JsDataProfile, selectModels } from '@sipemu/anofox-forecast';
267
+
268
+ const profile = JsDataProfile.fromSeries(ts);
269
+
270
+ // Get model recommendations based on data characteristics
271
+ const result = selectModels(profile);
272
+ console.log('Recommended:', result.recommended); // ["ARIMA", "ETS", "Naive", "SES"]
273
+ console.log('Reasoning:', result.reasoning); // ["High autocorrelation...", ...]
274
+
275
+ // Filter to available models
276
+ const filtered = selectModels(profile, ["Naive", "SES", "ARIMA"]);
277
+ ```
278
+
279
+ ### Pipeline Builder
280
+
281
+ ```javascript
282
+ import { JsPipelineBuilder } from '@sipemu/anofox-forecast';
283
+
284
+ // Build and execute a forecasting pipeline
285
+ const result = new JsPipelineBuilder()
286
+ .profile() // enable data profiling
287
+ .preprocess('auto') // auto Box-Cox + outlier treatment
288
+ .metric('auto') // data-aware metric selection
289
+ .ensemble('auto') // ensemble if MCS includes > 1 model
290
+ .addModel('Naive')
291
+ .addModel('SES')
292
+ .addModel('SMA')
293
+ .withFallback() // Naive → SMA fallback chain
294
+ .nonNegative() // clamp forecasts >= 0
295
+ .execute(ts, 12); // 12-step forecast
296
+
297
+ console.log('Model:', result.modelName);
298
+ console.log('Forecast:', result.forecast.values);
299
+ console.log('Decision log:', result.decisionLog);
300
+
301
+ // Access diagnostics
302
+ const profile = result.profile; // JsDataProfile or undefined
303
+ const mcs = result.modelConfidenceSet; // { included, pValue, singleWinner }
304
+ const scores = result.metricScores; // [{ model, score, components }]
305
+ const weights = result.ensembleWeights; // [{ model, weight }] or undefined
306
+ const preprocess = result.preprocessInfo; // { boxcoxLambda, outliersReplaced, stepsApplied }
307
+ ```
308
+
309
+ #### Builder Options
310
+
311
+ | Method | Options | Description |
312
+ |--------|---------|-------------|
313
+ | `profile()` | — | Enable data profiling |
314
+ | `preprocess(mode)` | `"auto"`, `"none"` | Preprocessing (Box-Cox, outlier replacement) |
315
+ | `metric(strategy)` | `"auto"`, `"mae"`, `"mse"`, `"rmse"`, `"smape"`, `"wape"`, `"mda"` | Metric for model ranking |
316
+ | `ensemble(mode)` | `"auto"`, `"none"`, `"mean"`, `"median"`, `"weighted"` | Ensemble construction |
317
+ | `addModel(name)` | `"Naive"`, `"SES"`, `"SMA"`, `"SMA3"`, `"SMA5"`, `"SMA10"`, `"SeasonalNaive"` | Register a model |
318
+ | `addSeasonalModel(name, period)` | — | Register a seasonal model |
319
+ | `selectModels(k)` | — | Select top-K models |
320
+ | `crossValidate(folds, horizon)` | — | Enable cross-validation |
321
+ | `withFallback()` | — | Enable fallback chain |
322
+ | `nonNegative()` | — | Clamp forecasts to non-negative |
323
+ | `seasonalPeriod(p)` | — | Set seasonal period hint |
324
+
325
+ ### Pipeline Report
326
+
327
+ ```javascript
328
+ // Generate a structured report
329
+ const report = result.report();
330
+ console.log(report.title); // "Pipeline Report: SES"
331
+ console.log(report.sectionCount); // number of sections
332
+ console.log(report.toString()); // full formatted text
333
+
334
+ // Report as JSON with typed sections
335
+ const json = report.toJSON();
336
+ // { title, sections: [{ heading, content: { type, ... } }] }
337
+ // Content types: "text", "keyValue" (with pairs), "table" (with headers + rows)
338
+ ```
339
+
340
+ ### Explain Result
341
+
342
+ ```javascript
343
+ import { explainResult } from '@sipemu/anofox-forecast';
344
+
345
+ // Generate a human-readable explanation
346
+ const brief = explainResult(result, 'brief');
347
+ console.log(brief.summary); // "Selected SES for 12-step forecast."
348
+
349
+ const detailed = explainResult(result, 'detailed');
350
+ console.log(detailed.summary);
351
+ detailed.sections.forEach(s => console.log(s.heading, s.content));
352
+ ```
353
+
354
+ ## Calendar Annotations
355
+
356
+ Add holidays and named regressors for models that support exogenous variables:
357
+
358
+ ```javascript
359
+ import { CalendarAnnotations } from '@sipemu/anofox-forecast';
360
+
361
+ const calendar = new CalendarAnnotations();
362
+ calendar.addHoliday(Date.parse('2024-12-25'));
363
+ calendar.addRegressor('temperature', new Float64Array([20, 22, 25, 23]));
364
+
365
+ ts.setCalendar(calendar);
366
+ model.fit(ts); // ARIMA, MFLES, etc. will automatically use the regressors
367
+ ```
368
+
194
369
  ## Browser Usage
195
370
 
196
371
  ```html
@@ -232,8 +407,8 @@ const forecast = model.predict(10);
232
407
  ## Limitations
233
408
 
234
409
  - The `parallel` feature from the Rust crate is not available in WASM
235
- - Postprocessing features (conformal prediction, IDR) are not yet exposed
236
- - Cross-validation utilities are not yet exposed
410
+ - IDR (Isotonic Distributional Regression) and QRA are not yet exposed in WASM
411
+ - Abstract storage (`PipelineStore`) is not exposed — use the report JSON output for persistence
237
412
 
238
413
  ## License
239
414