In [1]:
import numpy as np
import pandas as pd

%matplotlib inline

# generate a daily signal covering one year 2016 in a pandas dataframe
N = 360
df_train = pd.DataFrame({"Date" : pd.date_range(start="2016-01-25", periods=N, freq='D'),
                         "Signal" : (np.arange(N)//40 + np.arange(N) % 21 + np.random.randn(N))})

In [2]:
df_train.head(12)


Out[2]:
Date Signal
0 2016-01-25 1.436207
1 2016-01-26 -0.339352
2 2016-01-27 1.391167
3 2016-01-28 5.550326
4 2016-01-29 3.434334
5 2016-01-30 5.203728
6 2016-01-31 6.164420
7 2016-02-01 6.634344
8 2016-02-02 8.656479
9 2016-02-03 10.892104
10 2016-02-04 9.553648
11 2016-02-05 11.124479

In [3]:
df_train.tail(12)


Out[3]:
Date Signal
348 2017-01-07 19.841373
349 2017-01-08 20.897530
350 2017-01-09 22.650536
351 2017-01-10 22.417791
352 2017-01-11 22.822750
353 2017-01-12 23.847727
354 2017-01-13 25.678839
355 2017-01-14 27.094453
356 2017-01-15 28.295554
357 2017-01-16 9.360934
358 2017-01-17 8.413078
359 2017-01-18 9.210448

In [4]:
df_train.plot('Date' , ['Signal'])


Out[4]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f789c1db908>

In [5]:
import pyaf.ForecastEngine as autof
# create a forecast engine. This is the main object handling all the operations
lEngine = autof.cForecastEngine()

# get the best time series model for predicting one week
lEngine.train(iInputDS = df_train, iTime = 'Date', iSignal = 'Signal', iHorizon = 7);
lEngine.getModelInfo() # => relative error 7% (MAPE)


INFO:pyaf.std:START_TRAINING 'Signal'
INFO:pyaf.std:END_TRAINING_TIME_IN_SECONDS 'Signal' 3.4169421195983887
INFO:pyaf.std:TIME_DETAIL TimeVariable='Date' TimeMin=2016-01-25T00:00:00.000000 TimeMax=2016-11-01T00:00:00.000000 TimeDelta=<DateOffset: days=1> Estimation = (0 , 282) Validation = (282 , 353) Test = (353 , 360) Horizon=7
INFO:pyaf.std:SIGNAL_DETAIL_ORIG SignalVariable='Signal' Min=-0.33935182494219296 Max=28.941573004927022  Mean=13.944759665883332 StdDev=6.7549349144413355
INFO:pyaf.std:SIGNAL_DETAIL_TRANSFORMED TransformedSignalVariable='_Signal' Min=-0.33935182494219296 Max=28.941573004927022  Mean=13.944759665883332 StdDev=6.7549349144413355
INFO:pyaf.std:BEST_TRANSOFORMATION_TYPE '_'
INFO:pyaf.std:BEST_DECOMPOSITION  '_Signal_LinearTrend_residue_zeroCycle_residue_AR(64)' [LinearTrend + NoCycle + AR(64)]
INFO:pyaf.std:TREND_DETAIL '_Signal_LinearTrend' [LinearTrend]
INFO:pyaf.std:CYCLE_DETAIL '_Signal_LinearTrend_residue_zeroCycle' [NoCycle]
INFO:pyaf.std:AUTOREG_DETAIL '_Signal_LinearTrend_residue_zeroCycle_residue_AR(64)' [AR(64)]
INFO:pyaf.std:MODEL_MAPE MAPE_Fit=0.4087 MAPE_Forecast=0.0987 MAPE_Test=0.0271
INFO:pyaf.std:MODEL_SMAPE SMAPE_Fit=0.1362 SMAPE_Forecast=0.0984 SMAPE_Test=0.0261
INFO:pyaf.std:MODEL_MASE MASE_Fit=0.5068 MASE_Forecast=0.6649 MASE_Test=0.0657
INFO:pyaf.std:MODEL_L1 L1_Fit=1.1437930137516317 L1_Forecast=1.595662537261305 L1_Test=0.2751357303329571
INFO:pyaf.std:MODEL_L2 L2_Fit=1.6476964115418584 L2_Forecast=2.019247791605564 L2_Test=0.4067862971325673
INFO:pyaf.std:MODEL_COMPLEXITY 80
INFO:pyaf.std:AR_MODEL_DETAIL_START
INFO:pyaf.std:AR_MODEL_COEFF 1 _Signal_LinearTrend_residue_zeroCycle_residue_Lag21 0.7108400532436476
INFO:pyaf.std:AR_MODEL_COEFF 2 _Signal_LinearTrend_residue_zeroCycle_residue_Lag1 0.5741250809934642
INFO:pyaf.std:AR_MODEL_COEFF 3 _Signal_LinearTrend_residue_zeroCycle_residue_Lag22 -0.4699609759830834
INFO:pyaf.std:AR_MODEL_COEFF 4 _Signal_LinearTrend_residue_zeroCycle_residue_Lag4 -0.23708731169625058
INFO:pyaf.std:AR_MODEL_COEFF 5 _Signal_LinearTrend_residue_zeroCycle_residue_Lag3 0.2177333236242141
INFO:pyaf.std:AR_MODEL_COEFF 6 _Signal_LinearTrend_residue_zeroCycle_residue_Lag24 -0.20866885822050268
INFO:pyaf.std:AR_MODEL_COEFF 7 _Signal_LinearTrend_residue_zeroCycle_residue_Lag14 -0.1845580012895532
INFO:pyaf.std:AR_MODEL_COEFF 8 _Signal_LinearTrend_residue_zeroCycle_residue_Lag25 0.15155227084374148
INFO:pyaf.std:AR_MODEL_COEFF 9 _Signal_LinearTrend_residue_zeroCycle_residue_Lag18 -0.1508914341288538
INFO:pyaf.std:AR_MODEL_COEFF 10 _Signal_LinearTrend_residue_zeroCycle_residue_Lag33 0.14809535479228286
INFO:pyaf.std:AR_MODEL_DETAIL_END

In [ ]:


In [6]:
import warnings

with warnings.catch_warnings():
    warnings.simplefilter("error")
    lEngine.standardPlots()


INFO:pyaf.std:START_PLOTTING
INFO:pyaf.std:END_PLOTTING_TIME_IN_SECONDS 2.4246671199798584

In [7]:
# predict one week
df_forecast = lEngine.forecast(iInputDS = df_train, iHorizon = 7)
# list the columns of the forecast dataset
print(df_forecast.columns) #

# print the real forecasts
# Future dates : ['2017-01-19T00:00:00.000000000' '2017-01-20T00:00:00.000000000' '2017-01-21T00:00:00.000000000' '2017-01-22T00:00:00.000000000' '2017-01-23T00:00:00.000000000' '2017-01-24T00:00:00.000000000' '2017-01-25T00:00:00.000000000']
print(df_forecast['Date'].tail(7).values)

# signal forecast : [ 9.74934646  10.04419761  12.15136455  12.20369717  14.09607727 15.68086323  16.22296559]
print(df_forecast['Signal_Forecast'].tail(7).values)


INFO:pyaf.std:START_FORECASTING
INFO:pyaf.std:END_FORECAST_TIME_IN_SECONDS 0.7547671794891357
Index(['Date', 'Signal', '_Signal', 'row_number', 'Date_Normalized',
       '_Signal_LinearTrend', '_Signal_LinearTrend_residue',
       '_Signal_LinearTrend_residue_zeroCycle',
       '_Signal_LinearTrend_residue_zeroCycle_residue',
       '_Signal_LinearTrend_residue_zeroCycle_residue_AR(64)',
       '_Signal_LinearTrend_residue_zeroCycle_residue_AR(64)_residue',
       '_Signal_Trend', '_Signal_Trend_residue', '_Signal_Cycle',
       '_Signal_Cycle_residue', '_Signal_AR', '_Signal_AR_residue',
       '_Signal_TransformedForecast', 'Signal_Forecast',
       '_Signal_TransformedResidue', 'Signal_Residue',
       'Signal_Forecast_Lower_Bound', 'Signal_Forecast_Upper_Bound'],
      dtype='object')
['2017-01-19T00:00:00.000000000' '2017-01-20T00:00:00.000000000'
 '2017-01-21T00:00:00.000000000' '2017-01-22T00:00:00.000000000'
 '2017-01-23T00:00:00.000000000' '2017-01-24T00:00:00.000000000'
 '2017-01-25T00:00:00.000000000']
[ 9.67394248 11.12908439 14.58289525 14.81455664 16.38843671 17.5349585
 17.41766939]

In [ ]: