@@ -1104,3 +1104,104 @@ def test_multistep(analytical_model_spec):
1104
1104
rv_ri = fcasts_ri .residual_variance
1105
1105
assert_frame_equal (rv , rv_ri .iloc [- 1 :])
1106
1106
assert rv_ri .shape == (SP500 .shape [0 ], 10 )
1107
+
1108
+
1109
+ def test_forecast_exog_single_exog ():
1110
+ rg = np .random .default_rng (0 )
1111
+ y = rg .standard_normal (100 )
1112
+ x = pd .DataFrame (rg .standard_normal ((100 , 1 )), columns = ["x" ])
1113
+ x_oos = rg .standard_normal ((1 , 5 ))
1114
+ mod = ARX (y , x = x , lags = 1 )
1115
+ res = mod .fit ()
1116
+ # Direct forecast
1117
+ c , p , b , _ = res .params
1118
+ oos = np .zeros ((1 , 5 ))
1119
+ oos [0 , 0 ] = c + p * y [- 1 ] + b * x_oos [0 , 0 ]
1120
+ oos [0 , 1 ] = c + p * oos [0 , 0 ] + b * x_oos [0 , 1 ]
1121
+ oos [0 , 2 ] = c + p * oos [0 , 1 ] + b * x_oos [0 , 2 ]
1122
+ oos [0 , 3 ] = c + p * oos [0 , 2 ] + b * x_oos [0 , 3 ]
1123
+ oos [0 , 4 ] = c + p * oos [0 , 3 ] + b * x_oos [0 , 4 ]
1124
+ fcast = res .forecast (horizon = 5 , x = x_oos )
1125
+ assert_allclose (oos , fcast .mean )
1126
+
1127
+ x_oos2 = np .tile (x_oos , (100 , 1 ))
1128
+ fcast2 = res .forecast (horizon = 5 , x = x_oos2 )
1129
+ assert_allclose (fcast .mean , fcast2 .mean )
1130
+
1131
+ x_oos3 = np .tile (x_oos , (1 , 100 , 1 ))
1132
+ fcast3 = res .forecast (horizon = 5 , x = x_oos3 )
1133
+ assert_allclose (fcast .mean , fcast3 .mean )
1134
+
1135
+ x_oos4 = {"x" : x_oos }
1136
+ fcast4 = res .forecast (horizon = 5 , x = x_oos4 )
1137
+ assert_allclose (fcast .mean , fcast4 .mean )
1138
+
1139
+
1140
+ def test_forecast_exog_multi_exog ():
1141
+ rg = np .random .default_rng (0 )
1142
+ y = rg .standard_normal (100 )
1143
+ x = pd .DataFrame (rg .standard_normal ((100 , 2 )), columns = ["x1" , "x2" ])
1144
+ x_oos = rg .standard_normal ((2 , 1 , 5 ))
1145
+ mod = ARX (y , x = x , lags = 1 )
1146
+ res = mod .fit ()
1147
+
1148
+ c , p , b1 , b2 , _ = res .params
1149
+ oos = np .zeros ((1 , 5 ))
1150
+ oos [0 , 0 ] = c + p * y [- 1 ] + b1 * x_oos [0 , 0 , 0 ] + b2 * x_oos [1 , 0 , 0 ]
1151
+ oos [0 , 1 ] = c + p * oos [0 , 0 ] + b1 * x_oos [0 , 0 , 1 ] + b2 * x_oos [1 , 0 , 1 ]
1152
+ oos [0 , 2 ] = c + p * oos [0 , 1 ] + b1 * x_oos [0 , 0 , 2 ] + b2 * x_oos [1 , 0 , 2 ]
1153
+ oos [0 , 3 ] = c + p * oos [0 , 2 ] + b1 * x_oos [0 , 0 , 3 ] + b2 * x_oos [1 , 0 , 3 ]
1154
+ oos [0 , 4 ] = c + p * oos [0 , 3 ] + b1 * x_oos [0 , 0 , 4 ] + b2 * x_oos [1 , 0 , 4 ]
1155
+
1156
+ fcast = res .forecast (horizon = 5 , x = x_oos )
1157
+ assert_allclose (oos , fcast .mean )
1158
+
1159
+ x_oos2 = np .tile (x_oos , (100 , 1 ))
1160
+ fcast2 = res .forecast (horizon = 5 , x = x_oos2 )
1161
+ assert_allclose (fcast .mean , fcast2 .mean )
1162
+
1163
+ x_oos3 = {"x1" : x_oos [0 ], "x2" : x_oos [1 ]}
1164
+ fcast3 = res .forecast (horizon = 5 , x = x_oos3 )
1165
+ assert_allclose (fcast .mean , fcast3 .mean )
1166
+
1167
+
1168
+ def test_forecast_exog_single_exog_limited_sample ():
1169
+ rg = np .random .default_rng (0 )
1170
+ y = rg .standard_normal (100 )
1171
+ x = pd .DataFrame (rg .standard_normal ((100 , 1 )), columns = ["x" ])
1172
+ x_oos = rg .standard_normal ((3 , 5 ))
1173
+ mod = ARX (y , x = x , lags = 1 )
1174
+ res = mod .fit (first_obs = 0 , last_obs = 98 )
1175
+ oos = np .zeros ((3 , 5 ))
1176
+ # Direct forecast
1177
+ c , p , b , _ = res .params
1178
+ for idx in range (3 ):
1179
+ oos [idx , 0 ] = c + p * y [(- 3 + idx )] + b * x_oos [idx , 0 ]
1180
+ oos [idx , 1 ] = c + p * oos [idx , 0 ] + b * x_oos [idx , 1 ]
1181
+ oos [idx , 2 ] = c + p * oos [idx , 1 ] + b * x_oos [idx , 2 ]
1182
+ oos [idx , 3 ] = c + p * oos [idx , 2 ] + b * x_oos [idx , 3 ]
1183
+ oos [idx , 4 ] = c + p * oos [idx , 3 ] + b * x_oos [idx , 4 ]
1184
+ fcast = res .forecast (horizon = 5 , x = x_oos )
1185
+ assert_allclose (oos , fcast .mean )
1186
+
1187
+ x_oos2 = np .concatenate ([np .zeros ((97 , 5 )), x_oos ], axis = 0 )
1188
+ fcast2 = res .forecast (horizon = 5 , x = x_oos2 )
1189
+ assert_allclose (fcast .mean , fcast2 .mean )
1190
+
1191
+ x_oos3 = x_oos2 [None , :, :]
1192
+ fcast3 = res .forecast (horizon = 5 , x = x_oos3 )
1193
+ assert_allclose (fcast .mean , fcast3 .mean )
1194
+
1195
+ x_oos4 = {"x" : x_oos }
1196
+ fcast4 = res .forecast (horizon = 5 , x = x_oos4 )
1197
+ assert_allclose (fcast .mean , fcast4 .mean )
1198
+
1199
+
1200
+ def test_forecast_simulation_horizon_1 ():
1201
+ rg = np .random .default_rng (0 )
1202
+ y = rg .standard_normal (100 )
1203
+ x = pd .DataFrame (rg .standard_normal ((100 , 1 )), columns = ["x" ])
1204
+ mod = ARX (y , x = x , lags = 1 )
1205
+ res = mod .fit (first_obs = 0 , last_obs = 98 )
1206
+ res .forecast (start = 1 , x = x , method = "simulation" , simulations = 2 )
1207
+ res .forecast (start = 1 , x = x , method = "simulation" , simulations = 1 )
0 commit comments