def theta_f(series, n_periods=1): """ Original Theta forecast, as described by A&N. Args: - Series(PD Series): series to compute forecsat on - n_periods(int): number of periods to forecast Notes: When Alpha = 0.0, actually return 0.2 as according to the R forecasting library """ is_seasonal, inferred_freq = Utilities.check_seasonality(series) if is_seasonal: series_copy = series.copy(deep=True) decomposition = Utilities.decompose(series, period=inferred_freq) seasonal = decomposition.seasonal series = decomposition.trend + decomposition.resid n = len(series) forc, alpha = Statistical.ses_f(series, alpha, n_periods) if not alpha: alpha = 0.2 ts_vals = series.to_numpy() b = linregress(np.arange(len(ts_vals)), ts_vals)[0] drift = (0.5 * b) * (np.arange(n_periods) + 1 / alpha - ((1 - alpha)**n) / alpha) forc[-n_periods:] += drift if is_seasonal: f_len = len(forc) forc[-n_periods:] += (seasonal[-inferred_freq:] * np.trunc(1 + n_periods / inferred_freq) )[:n_periods].to_numpy() forc[:-n_periods] += seasonal.to_numpy() return forc
def holt_winters_f(series, slen, alpha, beta, gamma, n_preds): """ holt winters additive seasonal forecast returns fully smoothed exponential forecast TODO could possibly return timeseries + forecasted values """ expS1 = list(series.index) result = [] seasonals = Utilities.initial_seasonal_components(series, slen) for i in range(len(series) + n_preds): if i == 0: smooth = series[0] trend = Utilities.initial_trend(series, slen) result.append(series[0]) elif i >= len(series): m = i - len(series) + 1 result.append((smooth + m * trend) + seasonals[i % slen]) else: val = series[i] last_smooth, smooth = smooth, alpha * ( val - seasonals[i % slen]) + (1 - alpha) * (smooth + trend) trend = beta * (smooth - last_smooth) + (1 - beta) * trend seasonals[i % slen] = gamma * (val - smooth) + ( 1 - gamma) * seasonals[i % slen] result.append(smooth + trend + seasonals[i % slen]) forecast_dates = Utilities.find_next_forecastdates(series, n_periods) expS1.append(forecast_date) return pd.Series(result, index=expS1)
def moving_average_forecast_n_periods_old(series, window_size, n_periods, start_date, verbose=True): """Moving Average Forecast for number of periods. Args: series -- pandas series object window_size -- sliding window size n_periods -- number of periods start_date -- start date for the series """ # Get forecast for 1 value result_series = Utilities.average_forecast_one_period( series[-window_size:]) # input series input_series = result_series # remaining n-1 periods for ii in range(n_periods): result_series = Utilities.average_forecast_one_period( input_series[-window_size:]) input_series = pd.concat( [input_series, result_series[len(result_series) - 1:]]) return input_series
def holts_linear_f(series, alpha, beta, n_periods=1, mult_or_add=True): """Holts Linear Trend Forecast or Double Exponential Smoothing Forecast Args: series: pandas series object alpha: level smoothing factor beta: trend speed control factor mult_or_add: if True perform holts multiplicative smoothing, else perform holts additive smoothing """ expS1 = list(series.index) result = [series[0]] for n in range(1, len(series) + n_periods): if n == 1: level, trend = series[0], series[1] - series[0] if n >= len(series): value = result[-1] else: value = series[n] last_level, level = level, alpha * value + (1 - alpha) * (level + trend) trend = beta * (level - last_level) + (1 - beta) * trend if (mult_or_add): if (n <= len(series)): result.append(level * trend) else: result.append(level * trend * (n - len(series))) else: if (n <= len(series)): result.append(level * trend) else: result.append(level + (trend * (n - len(series)))) forecast_dates = Utilities.find_next_forecastdates(series, n_periods) expS1.append(forecast_date) return pd.Series(result, index=expS1)
def naive_f(series, n_periods): """naive forecasting for n periods Args: series(pandas data frame) -- time series to perform forecast on. n_periods(int): number of periods """ myseries = series.dropna(how='all') values = [myseries[-1]] * n_periods return Utilities.addPeriodsToSeries(myseries, values)
def moving_average_forecast(series, window_size, n_periods=1): """Moving Average Forecast. Args: series - pandas series object window - sliding window size Returns: """ result_series = Utilities.average_forecast_one_period( series[-window_size:]) return result_series
def weighted_avg_f(series, weights, n_periods=1): """Weighted Average Forecast. Args: series(pandas data frame) -- time series to perform forecast on weights(list): list of weights to use when computing weighted avg """ result = 0.0 weights.reverse() itr = len(weights) if len(weights) < len(series) else len(series) for n in range(itr): result += series[-n - 1] * weights[n] return Utilities.addPeriodsToSeries(series, result)