|
1 | 1 | import numpy as np |
2 | 2 | from numpy.typing import ArrayLike |
3 | 3 | from statsmodels.tsa.ar_model import AutoReg, ar_select_order |
| 4 | +from statsmodels.stats.diagnostic import acorr_ljungbox |
4 | 5 | from scipy.signal import lfilter |
5 | 6 | from pyhctsa.Operations.Correlation import AutoCorr |
6 | 7 | from scipy.stats import ks_1samp, norm, t |
7 | 8 | import numba |
8 | 9 | from typing import Union |
9 | | -from pyhctsa.Utilities.utils import ZScore |
10 | | -from statsmodels.stats.diagnostic import acorr_ljungbox |
| 10 | +from ..Utilities.utils import ZScore |
| 11 | +from ..Operations.Stationarity import SlidingWindow |
| 12 | +from ..Operations.Correlation import FirstCrossing, AutoCorr |
11 | 13 |
|
| 14 | +def LocalSimple(y, forecastMeth = 'mean', trainLength = 3): |
| 15 | + y = np.asarray(y) |
| 16 | + N = len(y) |
| 17 | + # % Do the local prediction |
| 18 | + if trainLength == 'ac': |
| 19 | + lp = FirstCrossing(y, 'ac', 0, 'discrete') |
| 20 | + else: |
| 21 | + lp = trainLength # the length of the subsegment preceeding to use to predict the subsequent value |
| 22 | + evalr = np.arange(lp, N) #range over which to evaluate the forecast |
| 23 | + if np.size(evalr) == 0: |
| 24 | + print("This time series is too short for forecasting") |
| 25 | + return np.nan |
| 26 | + res = np.zeros(len(evalr)) |
| 27 | + if forecastMeth == 'mean': |
| 28 | + for i in range(len(evalr)): |
| 29 | + res[i] = np.mean(y[evalr[i]-lp:evalr[i]]) - y[evalr[i]] # prediction - value |
| 30 | + elif forecastMeth == 'median': |
| 31 | + for i in range(len(evalr)): |
| 32 | + res[i] = np.median(y[evalr[i]-lp:evalr[i]]) - y[evalr[i]] # prediction - value |
| 33 | + elif forecastMeth == 'lfit': |
| 34 | + for i in range(len(evalr)): |
| 35 | + # Fit linear |
| 36 | + p = np.polyfit(np.arange(1, lp+1), y[evalr[i]-lp:evalr[i]], 1) |
| 37 | + res[i] = np.polyval(p, lp+1) - y[evalr[i]] # prediction - value |
| 38 | + else: |
| 39 | + raise ValueError(f"Unknown forecasting method: {forecastMeth}") |
| 40 | + |
| 41 | + #Output statistics on the residuals, res |
| 42 | + #% Mean residual (mean error/bias): |
| 43 | + out = {} |
| 44 | + out['meanerr'] = np.mean(res) |
| 45 | + #% Spread of residuals: |
| 46 | + out['stderr'] = np.std(res, ddof=1) |
| 47 | + out['meanabserr'] = np.mean(np.abs(res)) |
| 48 | + #% Stationarity of residuals: |
| 49 | + out['sws'] = SlidingWindow(res, 'std', 'std', 5, 1) # across five non-overlapping segments |
| 50 | + out['swm'] = SlidingWindow(res, 'mean', 'std', 5, 1) # across five non-overlapping segments |
| 51 | + #% TODO Normality of residuals: |
| 52 | + #% Autocorrelation structure of the residuals: |
| 53 | + out['ac1'] = AutoCorr(res, 1, 'Fourier')[0] |
| 54 | + out['ac2'] = AutoCorr(res, 2, 'Fourier')[0] |
| 55 | + out['taures'] = FirstCrossing(res, 'ac', 0, 'continuous') |
| 56 | + out['tauresrat'] = FirstCrossing(res, 'ac', 0, 'continuous')/FirstCrossing(y, 'ac', 0, 'continuous') |
| 57 | + |
| 58 | + return out |
12 | 59 |
|
13 | 60 | def ExpSmoothing(x : ArrayLike, ntrain : Union[None, int, float] = None, alpha : Union[str, float] = 'best') -> dict: |
14 | 61 | """ |
|
0 commit comments