<jupyter_start><jupyter_text>Data  Let's create some fake data first. It should contain trend, double seasonality and some noise.<jupyter_code>level = 50
n = 1400
period1 = 24
period2 = 24*7
H = 24
train_test_split_idx = 1000

ts = (level +
      trend(n, steepness=0.9) +
      seasonality(n, period1) +
      seasonality(n, period2))

sd = datetime(2019,2,1,0,0,0)

ts = pd.DataFrame(ts, index=pd.date_range(start=sd, end=sd + timedelta(days=ts.shape[0]-1), freq='1d'))

ts_train, ts_test = ts.iloc[:train_test_split_idx], ts.iloc[train_test_split_idx:]


ts_train.shape, ts_test.shape<jupyter_output><empty_output><jupyter_text>Here's what the data looks like. A slight upward trend can be observed.<jupyter_code>plt.plot(ts, linestyle='-');<jupyter_output><empty_output><jupyter_text>Baseline As we know, the data contains double seasonality. Still, let's compute both naive and snaive forecasts using a helper function:<jupyter_code>naive = NaiveForecastStrategy(ts, train_test_split_index=train_test_split_idx, freq=1).forecast(h=H).xarray()
snaive = SNaiveForecastStrategy(ts, train_test_split_index=train_test_split_idx, freq=24).forecast(h=H).xarray()

naive.mean_.shape, snaive.mean_.shape
target = xr_2d_factory(create_sliding_dataset(ts_test, h=H).squeeze(), 
                       start_date=ts_test.index[0], 
                       freq=ts_test.index.freq)

target.mean_.shape<jupyter_output><empty_output><jupyter_text>Just for the sake of demonstration, let's compare naive and snaive forecasts for out dataset:<jupyter_code>(TSMetrics(target, naive, snaive)
.for_horizons(0, 1, 5, 23)
.for_time_slices(time_slices.all, time_slices.weekend)
.with_description()
.with_metrics(mtx.MSE, mtx.MIS)
.with_predictions_plot()
.show())<jupyter_output><empty_output><jupyter_text>Of course, snaive forecast is much better. Let's set it as a baseline.  SARIMAX Basic Model Now we can use something more advanced. Let's assume we already did some kind of model properties selection (either AIC/BIC based, or CV/validation based).So our model is SARIMAX(2, 1, 1)x(1, 0, 1, 24).<jupyter_code>SARIMAX_DEF = {"order": (2, 1, 1), "seasonal_order": (1,0,1,24)}
model = sm.tsa.SARIMAX(ts_train, **SARIMAX_DEF)
model_fit = model.fit()
model_fit.summary()<jupyter_output><empty_output><jupyter_text>Now we can apply sliding window strategy and update the model using kalman filter smoothing:<jupyter_code>sm_seas = SMForecastStrategy(model_fit, SARIMAX_DEF).forecast(
    ts_test, test_exog=None, h=H
).xarray()

sm_seas.mean_.shape
SARIMAX_DEF = {"order": (2, 1, 1)}
model = sm.tsa.SARIMAX(ts_train, **SARIMAX_DEF)
model_fit = model.fit()

default = SMForecastStrategy(model_fit, SARIMAX_DEF).forecast(
    ts_test, test_exog=None, h=H
).xarray()

default.mean_.shape<jupyter_output><empty_output><jupyter_text>Now we can compare the model with snaive baseline:<jupyter_code>(
    TSMetrics(target, sm_seas, default)
    .use_reference(snaive)
    .for_horizons(0, 1, 5, 23)
    .for_time_slices(time_slices.all, time_slices.weekend)
    .with_description()
    .with_prediction_rankings(mtx.FVrMSE, mtx.FVrMIS)
    .with_predictions_plot()
    .show()
)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12162162162162163, 'fraction_numerical': 0.021684475172847266, 'mean_word_length': 5.859913793103448, 'pattern_counts': {'":': 3, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '446647', 'license': 'MIT', 'n_tokens_mistral': 1275, 'n_tokens_neox': 1203, 'n_words': 247, 'path': 'examples/basic_usage.ipynb', 'repo_name': 'vshulyak/ts-eval', 'size': '3182'}