Faire des prévisions de données revient à observer les valeurs passées, déterminer une dynamique, et tenter d’estimer les évolutions futures à partir du comportement passé de la série temporelle.

Il existe plusieurs moyens d’étudier la dynamique de la série. Tout d’abord, on peut étudier les cycles de la série, c’est notamment ce qui est fait pour étudier l’évolution du PIB qui est soumis à des cycles d’affaires (business cycles) plus ou moins longs. En fonction de l’état du cycle financier, on peut donc anticiper une hausse du PIB dans les périodes futures si le cycle est haussier, ou inversement anticiper une baisse du PIB si le cycle est plutôt baissier. On utilise ce moyen notamment pour faire des prévisions de long-terme (sur quelques années) avec des données à faible fréquence (notamment, des données annuelles ou trimestrielles).

Une méthode plus populaire et efficace (notamment quand on a des données de haute fréquence) est d’utiliser des modèles spécifiquement faits pour faire de la prévision. C’est le cas des Random Walks, des ETS (Exponential Smoothing State-Space) Models, des modèles ARIMA, ou des modèles (beaucoup) plus compliqués comme les transformations de Fourier.

On va étudier quelques une de ces méthodes ici.

data_schularick <- read_excel("C:/users/fkraus/Desktop/data_schularick.xlsx")
donnees_france <- data_schularick %>%
  filter(country=="France")%>%
  select(year, gdp)%>%
  mutate(gdp_growth = (log(gdp) - lag(log(gdp)))*100   )%>%
  na.omit()%>%
  filter(year >= 1950 & year < 2020)
head(donnees_france)

On a retiré 2020 qui est une année exceptionnelle, avec un choc purement exogène (donc impossible de le relier à des variations passées du PIB).

donnees_france %>%
  ggplot(aes(x=year, y=gdp_growth))+
  geom_line()

df <- donnees_france %>% arrange(year)

# Yearly time series
y_ts <- ts(
  df$gdp_growth,
  start     = min(df$year),
  frequency = 1        # yearly data
)

Filters

L’un des filtres les plus connus est le filtre Hodrick-Prescott, très utilisé dans la recherche.

HP <- hpfilter(y_ts,freq=1)

HP

Title:
 Hodrick-Prescott Filter 

Call:
 hpfilter(x = y_ts, freq = 1)

Method:
 hpfilter

Filter Type:
 lambda

Series:
 y_ts
HP_data <- data.frame(
  year = donnees_france$year, 
  gdp_growth = donnees_france$gdp_growth,
  trend = HP$trend[,1], 
  cycle = HP$cycle
  )

head(HP_data)
HP_data %>% ggplot(aes(x=year, y=gdp_growth))+
  geom_line()+
  geom_line(aes(y=trend), color="red", lty=2)

Note : Le filtre HP n’est pas le seul et unique filtre existant. Il existe les filtres Baxter-King, Butterworth, Christiano-Fitzgerald… Vous pouvez regarder dans le package mFilter les différents filtres, et les essayer.

Le filtre HP très critiqué. Notamment, Hamilton (2017) (NBER Working Paper de “Why you should never use the Hodrick Prescott filter”) défend l’idée que le filtre HP produit des séries biaisées, notamment au début et à la fin des observations. Il conseille d’utiliser une autre méthode, qui existe dans R au sein du package neverhpfilter :

require(neverhpfilter)
donnees_france$date <- as.Date(paste0(donnees_france$year, "-01-01"))



donnees_france_xts <- xts(donnees_france$gdp_growth, order.by=donnees_france$date)
  
not_hp <- yth_filter(donnees_france_xts, output=c("x", "cycle", "trend")) 
Avis : Your xts object doesn't have a dimnames attribute, aka names(your_xts) is NULL, which would've produced an error.
    Thus it has been given the name 'y' within the scope, and for the output, of this function.
plot(not_hp)

FORECASTS (ETS & ARIMA)

Prévisions in-sample

require(forecast)


fit_ets  <- ets(y_ts)

fit_arima <- auto.arima(y_ts)

out-sample forecast

fitted_ets   <- fitted(fit_ets)
fitted_arima <- fitted(fit_arima)
df_in_sample <- cbind(
  year         = as.numeric(time(y_ts)),
  gdp_growth       = as.numeric(y_ts),
  ets_fitted   = as.numeric(fitted_ets),
  arima_fitted = as.numeric(fitted_arima)
)
ggplot(df_in_sample, aes(x = year)) +
  geom_line(aes(y = gdp_growth), linetype = "solid") +
  geom_line(aes(y = ets_fitted), linetype = "dashed", color="red") +
  labs(
    title = "In-sample: actual vs ETS fitted",
    y = "Value"
  )

ggplot(df_in_sample, aes(x = year)) +
  geom_line(aes(y = gdp_growth), linetype = "solid") +
  geom_line(aes(y = arima_fitted), linetype = "dashed", color="red") +
  labs(
    title = "In-sample: actual vs ARIMA fitted",
    y = "Value"
  )

n <- length(y_ts)
h <- 15

y_train <- window(y_ts, end = time(y_ts)[n - h])

# Série de test = les 15 dernières années
y_test  <- window(y_ts, start = time(y_ts)[n - h + 1])

fit_ets_oos   <- ets(y_train)
fit_arima_oos <- auto.arima(y_train)

fc_ets_oos   <- forecast(fit_ets_oos,   h = h, level = c(80, 95))
fc_arima_oos <- forecast(fit_arima_oos, h = h, level = c(80, 95))
years_test <- as.numeric(time(y_test))

ets_insample <- data.frame(
  year         = years_test,
  gdp_growth       = as.numeric(y_test),
  ets_forecast = as.numeric(fc_ets_oos$mean),
  ets_lower_95   = fc_ets_oos$lower[, "95%"],
  ets_upper_95   = fc_ets_oos$upper[, "95%"]
)

arima_insample <- data.frame(
  year         = years_test,
  gdp_growth       = as.numeric(y_test),
  arima_forecast = as.numeric(fc_arima_oos$mean),
  arima_lower_95 = fc_arima_oos$lower[, "95%"],
  arima_upper_95 = fc_arima_oos$upper[, "95%"]
)
ggplot(ets_insample, aes(x = year)) +
  geom_line(aes(y = gdp_growth), linetype = "solid") +
  geom_line(aes(y = ets_forecast), linetype = "dashed") +
  geom_ribbon(aes(ymin = ets_lower_95, ymax = ets_upper_95),
              alpha = 0.2) +
  labs(
    title = "Out-of-sample: ETS forecast vs actual",
    y = "Value"
  )

La prévision avec ETS n’est pas très performante. En effet, on voit que l’évolution du PIB suite à la crise des Subprimes n’a pas pu être prise en compte par le modèle. Dans un certain sens, ce n’est pas “grave”, ça signifie que la crise de 2008 provient sûrement d’un choc exogène au système économique, qui ne peut pas être compris (uniquement) à partir des données passées. En revanche, comme de nombreux économistes l’ont défendu, les origines des crises sont souvent endogènes.

Par exemple, Minsky défend le fait que les crises se construisent dans les périodes de croissance économique prolongée, qui réduisent l’aversion au risque et poussent les individus à prendre des risques, jusqu’au “moment Minsky” où la confiance s’érode. Ainsi, un bon modèle de prévision serait capable de prendre en compte ce risque de retournement, avec un interval de confiance plus important.

ggplot(arima_insample, aes(x = year)) +
  geom_line(aes(y = gdp_growth), linetype = "solid") +
  geom_line(aes(y = arima_forecast), linetype = "dashed") +
  geom_ribbon(aes(ymin = arima_lower_95, ymax = arima_upper_95),
              alpha = 0.2) +
  labs(
    title = "Out-of-sample: ARIMA forecast vs actual",
    y = "Value"
  )

C’est le cas de la prévision avec Arima, qui contient l’évolution du PIB post-subprimes dans l’interval de confiance.

On peut à présent faire les prévisions out-sample, c’est-à-dire au delà de 2019.

h <- 5
fc_arima  <- forecast(fit_arima, h = h)
plot(fc_arima)

Avec le modèle ARIMA, on peut anticiper que la croissance du PIB va rester entre -3% et 7-8% jusqu’en 2024. Dans la réalité, la crise du Covid-19 (imprévisible) a plutôt créé une décroissance du PIB en 2020, et un rebond en 2021. En revanche, ces deux variations sont (plus ou moins) compris dans l’interval de confiance du modèle.

Aujourd’hui, les prévisions servent essentiellement a -faire des prévisions macroéconomique (PIB, inflation…) par les institutions internationales -faire des prévisions de prix d’actifs par les institutions financières

En revanche, ces institutions se tournent davantage vers des modèles de Machine Learning, qui vont comprendre la dynamique de la série et s’entraîner à mesure que les données s’actualisent.

LS0tDQp0aXRsZTogIlPDqWFuY2UgNiDDqWNvbm9tw6l0cmllIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQpGYWlyZSBkZXMgcHLDqXZpc2lvbnMgZGUgZG9ubsOpZXMgcmV2aWVudCDDoCBvYnNlcnZlciBsZXMgdmFsZXVycyBwYXNzw6llcywgZMOpdGVybWluZXIgdW5lIGR5bmFtaXF1ZSwgZXQgdGVudGVyIGQnZXN0aW1lciBsZXMgw6l2b2x1dGlvbnMgZnV0dXJlcyDDoCBwYXJ0aXIgZHUgY29tcG9ydGVtZW50IHBhc3PDqSBkZSBsYSBzw6lyaWUgdGVtcG9yZWxsZS4gDQoNCklsIGV4aXN0ZSBwbHVzaWV1cnMgbW95ZW5zIGQnw6l0dWRpZXIgbGEgZHluYW1pcXVlIGRlIGxhIHPDqXJpZS4gVG91dCBkJ2Fib3JkLCBvbiBwZXV0IMOpdHVkaWVyIGxlcyBjeWNsZXMgZGUgbGEgc8OpcmllLCBjJ2VzdCBub3RhbW1lbnQgY2UgcXVpIGVzdCBmYWl0IHBvdXIgw6l0dWRpZXIgbCfDqXZvbHV0aW9uIGR1IFBJQiBxdWkgZXN0IHNvdW1pcyDDoCBkZXMgY3ljbGVzIGQnYWZmYWlyZXMgKCpidXNpbmVzcyBjeWNsZXMqKSBwbHVzIG91IG1vaW5zIGxvbmdzLiBFbiBmb25jdGlvbiBkZSBsJ8OpdGF0IGR1IGN5Y2xlIGZpbmFuY2llciwgb24gcGV1dCBkb25jIGFudGljaXBlciB1bmUgaGF1c3NlIGR1IFBJQiBkYW5zIGxlcyBww6lyaW9kZXMgZnV0dXJlcyBzaSBsZSBjeWNsZSBlc3QgaGF1c3NpZXIsIG91IGludmVyc2VtZW50IGFudGljaXBlciB1bmUgYmFpc3NlIGR1IFBJQiBzaSBsZSBjeWNsZSBlc3QgcGx1dMO0dCBiYWlzc2llci4gT24gdXRpbGlzZSBjZSBtb3llbiBub3RhbW1lbnQgcG91ciBmYWlyZSBkZXMgcHLDqXZpc2lvbnMgZGUgbG9uZy10ZXJtZSAoc3VyIHF1ZWxxdWVzIGFubsOpZXMpIGF2ZWMgZGVzIGRvbm7DqWVzIMOgIGZhaWJsZSBmcsOpcXVlbmNlIChub3RhbW1lbnQsIGRlcyBkb25uw6llcyBhbm51ZWxsZXMgb3UgdHJpbWVzdHJpZWxsZXMpLg0KDQpVbmUgbcOpdGhvZGUgcGx1cyBwb3B1bGFpcmUgZXQgZWZmaWNhY2UgKG5vdGFtbWVudCBxdWFuZCBvbiBhIGRlcyBkb25uw6llcyBkZSBoYXV0ZSBmcsOpcXVlbmNlKSBlc3QgZCd1dGlsaXNlciBkZXMgbW9kw6hsZXMgc3DDqWNpZmlxdWVtZW50IGZhaXRzIHBvdXIgZmFpcmUgZGUgbGEgcHLDqXZpc2lvbi4gQydlc3QgbGUgY2FzIGRlcyBSYW5kb20gV2Fsa3MsIGRlcyBFVFMgKEV4cG9uZW50aWFsIFNtb290aGluZyBTdGF0ZS1TcGFjZSkgTW9kZWxzLCBkZXMgbW9kw6hsZXMgQVJJTUEsIG91IGRlcyBtb2TDqGxlcyAoYmVhdWNvdXApIHBsdXMgY29tcGxpcXXDqXMgY29tbWUgbGVzIHRyYW5zZm9ybWF0aW9ucyBkZSBGb3VyaWVyLg0KDQpPbiB2YSDDqXR1ZGllciBxdWVscXVlcyB1bmUgZGUgY2VzIG3DqXRob2RlcyBpY2kuDQoNCmBgYHtyfQ0KZGF0YV9zY2h1bGFyaWNrIDwtIHJlYWRfZXhjZWwoIkM6L3VzZXJzL2ZrcmF1cy9EZXNrdG9wL2RhdGFfc2NodWxhcmljay54bHN4IikNCmRvbm5lZXNfZnJhbmNlIDwtIGRhdGFfc2NodWxhcmljayAlPiUNCiAgZmlsdGVyKGNvdW50cnk9PSJGcmFuY2UiKSU+JQ0KICBzZWxlY3QoeWVhciwgZ2RwKSU+JQ0KICBtdXRhdGUoZ2RwX2dyb3d0aCA9IChsb2coZ2RwKSAtIGxhZyhsb2coZ2RwKSkpKjEwMCAgICklPiUNCiAgbmEub21pdCgpJT4lDQogIGZpbHRlcih5ZWFyID49IDE5NTAgJiB5ZWFyIDwgMjAyMCkNCmhlYWQoZG9ubmVlc19mcmFuY2UpDQpgYGANCk9uIGEgcmV0aXLDqSAyMDIwIHF1aSBlc3QgdW5lIGFubsOpZSBleGNlcHRpb25uZWxsZSwgYXZlYyB1biBjaG9jIHB1cmVtZW50IGV4b2fDqG5lIChkb25jIGltcG9zc2libGUgZGUgbGUgcmVsaWVyIMOgIGRlcyB2YXJpYXRpb25zIHBhc3PDqWVzIGR1IFBJQikuDQoNCg0KYGBge3J9DQpkb25uZWVzX2ZyYW5jZSAlPiUNCiAgZ2dwbG90KGFlcyh4PXllYXIsIHk9Z2RwX2dyb3d0aCkpKw0KICBnZW9tX2xpbmUoKQ0KYGBgDQoNCmBgYHtyfQ0KZGYgPC0gZG9ubmVlc19mcmFuY2UgJT4lIGFycmFuZ2UoeWVhcikNCg0KIyBZZWFybHkgdGltZSBzZXJpZXMNCnlfdHMgPC0gdHMoDQogIGRmJGdkcF9ncm93dGgsDQogIHN0YXJ0ICAgICA9IG1pbihkZiR5ZWFyKSwNCiAgZnJlcXVlbmN5ID0gMSAgICAgICAgIyB5ZWFybHkgZGF0YQ0KKQ0KYGBgDQoNCg0KIyBGaWx0ZXJzDQoNCkwndW4gZGVzIGZpbHRyZXMgbGVzIHBsdXMgY29ubnVzIGVzdCBsZSBmaWx0cmUgSG9kcmljay1QcmVzY290dCwgdHLDqHMgdXRpbGlzw6kgZGFucyBsYSByZWNoZXJjaGUuDQoNCmBgYHtyfQ0KSFAgPC0gaHBmaWx0ZXIoeV90cyxmcmVxPTEpDQoNCkhQDQpgYGANCmBgYHtyfQ0KSFBfZGF0YSA8LSBkYXRhLmZyYW1lKA0KICB5ZWFyID0gZG9ubmVlc19mcmFuY2UkeWVhciwgDQogIGdkcF9ncm93dGggPSBkb25uZWVzX2ZyYW5jZSRnZHBfZ3Jvd3RoLA0KICB0cmVuZCA9IEhQJHRyZW5kWywxXSwgDQogIGN5Y2xlID0gSFAkY3ljbGUNCiAgKQ0KDQpoZWFkKEhQX2RhdGEpDQpgYGANCg0KDQoNCmBgYHtyfQ0KSFBfZGF0YSAlPiUgZ2dwbG90KGFlcyh4PXllYXIsIHk9Z2RwX2dyb3d0aCkpKw0KICBnZW9tX2xpbmUoKSsNCiAgZ2VvbV9saW5lKGFlcyh5PXRyZW5kKSwgY29sb3I9InJlZCIsIGx0eT0yKQ0KYGBgDQoqTm90ZSA6IExlIGZpbHRyZSBIUCBuJ2VzdCBwYXMgbGUgc2V1bCBldCB1bmlxdWUgZmlsdHJlIGV4aXN0YW50LiBJbCBleGlzdGUgbGVzIGZpbHRyZXMgQmF4dGVyLUtpbmcsIEJ1dHRlcndvcnRoLCBDaHJpc3RpYW5vLUZpdHpnZXJhbGQuLi4gVm91cyBwb3V2ZXogcmVnYXJkZXIgZGFucyBsZSBwYWNrYWdlIG1GaWx0ZXIgbGVzIGRpZmbDqXJlbnRzIGZpbHRyZXMsIGV0IGxlcyBlc3NheWVyLiAqDQoNCkxlIGZpbHRyZSBIUCB0csOocyBjcml0aXF1w6kuIE5vdGFtbWVudCwgSGFtaWx0b24gKDIwMTcpIChOQkVSIFdvcmtpbmcgUGFwZXIgZGUgICJXaHkgeW91IHNob3VsZCBuZXZlciB1c2UgdGhlIEhvZHJpY2sgUHJlc2NvdHQgZmlsdGVyIikgZMOpZmVuZCBsJ2lkw6llIHF1ZSBsZSBmaWx0cmUgSFAgcHJvZHVpdCBkZXMgc8OpcmllcyBiaWFpc8OpZXMsIG5vdGFtbWVudCBhdSBkw6lidXQgZXQgw6AgbGEgZmluIGRlcyBvYnNlcnZhdGlvbnMuIElsIGNvbnNlaWxsZSBkJ3V0aWxpc2VyIHVuZSBhdXRyZSBtw6l0aG9kZSwgcXVpIGV4aXN0ZSBkYW5zIFIgYXUgc2VpbiBkdSBwYWNrYWdlIGBuZXZlcmhwZmlsdGVyYCA6DQoNCmBgYHtyfQ0KcmVxdWlyZShuZXZlcmhwZmlsdGVyKQ0KZG9ubmVlc19mcmFuY2UkZGF0ZSA8LSBhcy5EYXRlKHBhc3RlMChkb25uZWVzX2ZyYW5jZSR5ZWFyLCAiLTAxLTAxIikpDQoNCg0KDQpkb25uZWVzX2ZyYW5jZV94dHMgPC0geHRzKGRvbm5lZXNfZnJhbmNlJGdkcF9ncm93dGgsIG9yZGVyLmJ5PWRvbm5lZXNfZnJhbmNlJGRhdGUpDQogIA0Kbm90X2hwIDwtIHl0aF9maWx0ZXIoZG9ubmVlc19mcmFuY2VfeHRzLCBvdXRwdXQ9YygieCIsICJjeWNsZSIsICJ0cmVuZCIpKSANCg0KcGxvdChub3RfaHApDQoNCmBgYA0KDQogDQogDQogDQojIEZPUkVDQVNUUyAoRVRTICYgQVJJTUEpDQoNCiMgUHLDqXZpc2lvbnMgaW4tc2FtcGxlDQoNCmBgYHtyfQ0KcmVxdWlyZShmb3JlY2FzdCkNCg0KDQpmaXRfZXRzICA8LSBldHMoeV90cykNCg0KZml0X2FyaW1hIDwtIGF1dG8uYXJpbWEoeV90cykNCmBgYA0KDQojIG91dC1zYW1wbGUgZm9yZWNhc3QNCg0KYGBge3J9DQpmaXR0ZWRfZXRzICAgPC0gZml0dGVkKGZpdF9ldHMpDQpmaXR0ZWRfYXJpbWEgPC0gZml0dGVkKGZpdF9hcmltYSkNCmBgYA0KDQoNCmBgYHtyfQ0KZGZfaW5fc2FtcGxlIDwtIGNiaW5kKA0KICB5ZWFyICAgICAgICAgPSBhcy5udW1lcmljKHRpbWUoeV90cykpLA0KICBnZHBfZ3Jvd3RoICAgICAgID0gYXMubnVtZXJpYyh5X3RzKSwNCiAgZXRzX2ZpdHRlZCAgID0gYXMubnVtZXJpYyhmaXR0ZWRfZXRzKSwNCiAgYXJpbWFfZml0dGVkID0gYXMubnVtZXJpYyhmaXR0ZWRfYXJpbWEpDQopDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGZfaW5fc2FtcGxlLCBhZXMoeCA9IHllYXIpKSArDQogIGdlb21fbGluZShhZXMoeSA9IGdkcF9ncm93dGgpLCBsaW5ldHlwZSA9ICJzb2xpZCIpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gZXRzX2ZpdHRlZCksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yPSJyZWQiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiSW4tc2FtcGxlOiBhY3R1YWwgdnMgRVRTIGZpdHRlZCIsDQogICAgeSA9ICJWYWx1ZSINCiAgKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGRmX2luX3NhbXBsZSwgYWVzKHggPSB5ZWFyKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBnZHBfZ3Jvd3RoKSwgbGluZXR5cGUgPSAic29saWQiKSArDQogIGdlb21fbGluZShhZXMoeSA9IGFyaW1hX2ZpdHRlZCksIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yPSJyZWQiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiSW4tc2FtcGxlOiBhY3R1YWwgdnMgQVJJTUEgZml0dGVkIiwNCiAgICB5ID0gIlZhbHVlIg0KICApDQpgYGANCg0KDQpgYGB7cn0NCm4gPC0gbGVuZ3RoKHlfdHMpDQpoIDwtIDE1DQoNCnlfdHJhaW4gPC0gd2luZG93KHlfdHMsIGVuZCA9IHRpbWUoeV90cylbbiAtIGhdKQ0KDQojIFPDqXJpZSBkZSB0ZXN0ID0gbGVzIDE1IGRlcm5pw6hyZXMgYW5uw6llcw0KeV90ZXN0ICA8LSB3aW5kb3coeV90cywgc3RhcnQgPSB0aW1lKHlfdHMpW24gLSBoICsgMV0pDQoNCmZpdF9ldHNfb29zICAgPC0gZXRzKHlfdHJhaW4pDQpmaXRfYXJpbWFfb29zIDwtIGF1dG8uYXJpbWEoeV90cmFpbikNCg0KZmNfZXRzX29vcyAgIDwtIGZvcmVjYXN0KGZpdF9ldHNfb29zLCAgIGggPSBoLCBsZXZlbCA9IGMoODAsIDk1KSkNCmZjX2FyaW1hX29vcyA8LSBmb3JlY2FzdChmaXRfYXJpbWFfb29zLCBoID0gaCwgbGV2ZWwgPSBjKDgwLCA5NSkpDQoNCmBgYA0KDQoNCg0KYGBge3J9DQp5ZWFyc190ZXN0IDwtIGFzLm51bWVyaWModGltZSh5X3Rlc3QpKQ0KDQpldHNfaW5zYW1wbGUgPC0gZGF0YS5mcmFtZSgNCiAgeWVhciAgICAgICAgID0geWVhcnNfdGVzdCwNCiAgZ2RwX2dyb3d0aCAgICAgICA9IGFzLm51bWVyaWMoeV90ZXN0KSwNCiAgZXRzX2ZvcmVjYXN0ID0gYXMubnVtZXJpYyhmY19ldHNfb29zJG1lYW4pLA0KICBldHNfbG93ZXJfOTUgICA9IGZjX2V0c19vb3MkbG93ZXJbLCAiOTUlIl0sDQogIGV0c191cHBlcl85NSAgID0gZmNfZXRzX29vcyR1cHBlclssICI5NSUiXQ0KKQ0KDQphcmltYV9pbnNhbXBsZSA8LSBkYXRhLmZyYW1lKA0KICB5ZWFyICAgICAgICAgPSB5ZWFyc190ZXN0LA0KICBnZHBfZ3Jvd3RoICAgICAgID0gYXMubnVtZXJpYyh5X3Rlc3QpLA0KICBhcmltYV9mb3JlY2FzdCA9IGFzLm51bWVyaWMoZmNfYXJpbWFfb29zJG1lYW4pLA0KICBhcmltYV9sb3dlcl85NSA9IGZjX2FyaW1hX29vcyRsb3dlclssICI5NSUiXSwNCiAgYXJpbWFfdXBwZXJfOTUgPSBmY19hcmltYV9vb3MkdXBwZXJbLCAiOTUlIl0NCikNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGV0c19pbnNhbXBsZSwgYWVzKHggPSB5ZWFyKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBnZHBfZ3Jvd3RoKSwgbGluZXR5cGUgPSAic29saWQiKSArDQogIGdlb21fbGluZShhZXMoeSA9IGV0c19mb3JlY2FzdCksIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBldHNfbG93ZXJfOTUsIHltYXggPSBldHNfdXBwZXJfOTUpLA0KICAgICAgICAgICAgICBhbHBoYSA9IDAuMikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk91dC1vZi1zYW1wbGU6IEVUUyBmb3JlY2FzdCB2cyBhY3R1YWwiLA0KICAgIHkgPSAiVmFsdWUiDQogICkNCmBgYA0KTGEgcHLDqXZpc2lvbiBhdmVjIEVUUyBuJ2VzdCBwYXMgdHLDqHMgcGVyZm9ybWFudGUuIEVuIGVmZmV0LCBvbiB2b2l0IHF1ZSBsJ8Opdm9sdXRpb24gZHUgUElCIHN1aXRlIMOgIGxhIGNyaXNlIGRlcyBTdWJwcmltZXMgbidhIHBhcyBwdSDDqnRyZSBwcmlzZSBlbiBjb21wdGUgcGFyIGxlIG1vZMOobGUuIERhbnMgdW4gY2VydGFpbiBzZW5zLCBjZSBuJ2VzdCBwYXMgImdyYXZlIiwgw6dhIHNpZ25pZmllIHF1ZSBsYSBjcmlzZSBkZSAyMDA4IHByb3ZpZW50IHPDu3JlbWVudCBkJ3VuIGNob2MgZXhvZ8OobmUgYXUgc3lzdMOobWUgw6ljb25vbWlxdWUsIHF1aSBuZSBwZXV0IHBhcyDDqnRyZSBjb21wcmlzICh1bmlxdWVtZW50KSDDoCBwYXJ0aXIgZGVzIGRvbm7DqWVzIHBhc3PDqWVzLiBFbiByZXZhbmNoZSwgY29tbWUgZGUgbm9tYnJldXggw6ljb25vbWlzdGVzIGwnb250IGTDqWZlbmR1LCBsZXMgb3JpZ2luZXMgZGVzIGNyaXNlcyBzb250IHNvdXZlbnQgZW5kb2fDqG5lcy4gDQoNClBhciBleGVtcGxlLCBNaW5za3kgZMOpZmVuZCBsZSBmYWl0IHF1ZSBsZXMgY3Jpc2VzIHNlIGNvbnN0cnVpc2VudCBkYW5zIGxlcyBww6lyaW9kZXMgZGUgY3JvaXNzYW5jZSDDqWNvbm9taXF1ZSBwcm9sb25nw6llLCBxdWkgcsOpZHVpc2VudCBsJ2F2ZXJzaW9uIGF1IHJpc3F1ZSBldCBwb3Vzc2VudCBsZXMgaW5kaXZpZHVzIMOgIHByZW5kcmUgZGVzIHJpc3F1ZXMsIGp1c3F1J2F1ICJtb21lbnQgTWluc2t5IiBvw7kgbGEgY29uZmlhbmNlIHMnw6lyb2RlLiBBaW5zaSwgdW4gYm9uIG1vZMOobGUgZGUgcHLDqXZpc2lvbiBzZXJhaXQgY2FwYWJsZSBkZSBwcmVuZHJlIGVuIGNvbXB0ZSBjZSByaXNxdWUgZGUgcmV0b3VybmVtZW50LCBhdmVjIHVuIGludGVydmFsIGRlIGNvbmZpYW5jZSBwbHVzIGltcG9ydGFudC4NCg0KDQpgYGB7cn0NCmdncGxvdChhcmltYV9pbnNhbXBsZSwgYWVzKHggPSB5ZWFyKSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBnZHBfZ3Jvd3RoKSwgbGluZXR5cGUgPSAic29saWQiKSArDQogIGdlb21fbGluZShhZXMoeSA9IGFyaW1hX2ZvcmVjYXN0KSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGFyaW1hX2xvd2VyXzk1LCB5bWF4ID0gYXJpbWFfdXBwZXJfOTUpLA0KICAgICAgICAgICAgICBhbHBoYSA9IDAuMikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk91dC1vZi1zYW1wbGU6IEFSSU1BIGZvcmVjYXN0IHZzIGFjdHVhbCIsDQogICAgeSA9ICJWYWx1ZSINCiAgKQ0KYGBgDQoNCkMnZXN0IGxlIGNhcyBkZSBsYSBwcsOpdmlzaW9uIGF2ZWMgQXJpbWEsIHF1aSBjb250aWVudCBsJ8Opdm9sdXRpb24gZHUgUElCIHBvc3Qtc3VicHJpbWVzIGRhbnMgbCdpbnRlcnZhbCBkZSBjb25maWFuY2UuIA0KDQpPbiBwZXV0IMOgIHByw6lzZW50IGZhaXJlIGxlcyBwcsOpdmlzaW9ucyBvdXQtc2FtcGxlLCBjJ2VzdC3DoC1kaXJlIGF1IGRlbMOgIGRlIDIwMTkuDQoNCmBgYHtyfQ0KaCA8LSA1DQpmY19hcmltYSAgPC0gZm9yZWNhc3QoZml0X2FyaW1hLCBoID0gaCkNCmBgYA0KDQoNCg0KYGBge3J9DQpwbG90KGZjX2FyaW1hKQ0KYGBgDQpBdmVjIGxlIG1vZMOobGUgQVJJTUEsIG9uIHBldXQgYW50aWNpcGVyIHF1ZSBsYSBjcm9pc3NhbmNlIGR1IFBJQiB2YSByZXN0ZXIgZW50cmUgLTMlIGV0IDctOCUganVzcXUnZW4gMjAyNC4gRGFucyBsYSByw6lhbGl0w6ksIGxhIGNyaXNlIGR1IENvdmlkLTE5IChpbXByw6l2aXNpYmxlKSBhIHBsdXTDtHQgY3LDqcOpIHVuZSBkw6ljcm9pc3NhbmNlIGR1IFBJQiBlbiAyMDIwLCBldCB1biByZWJvbmQgZW4gMjAyMS4gRW4gcmV2YW5jaGUsIGNlcyBkZXV4IHZhcmlhdGlvbnMgc29udCAocGx1cyBvdSBtb2lucykgY29tcHJpcyBkYW5zIGwnaW50ZXJ2YWwgZGUgY29uZmlhbmNlIGR1IG1vZMOobGUuDQoNCkF1am91cmQnaHVpLCBsZXMgcHLDqXZpc2lvbnMgc2VydmVudCBlc3NlbnRpZWxsZW1lbnQgYSANCiAgLWZhaXJlIGRlcyBwcsOpdmlzaW9ucyBtYWNyb8OpY29ub21pcXVlIChQSUIsIGluZmxhdGlvbi4uLikgcGFyIGxlcyBpbnN0aXR1dGlvbnMgaW50ZXJuYXRpb25hbGVzDQogIC1mYWlyZSBkZXMgcHLDqXZpc2lvbnMgZGUgcHJpeCBkJ2FjdGlmcyBwYXIgbGVzIGluc3RpdHV0aW9ucyBmaW5hbmNpw6hyZXMNCiAgDQpFbiByZXZhbmNoZSwgY2VzIGluc3RpdHV0aW9ucyBzZSB0b3VybmVudCBkYXZhbnRhZ2UgdmVycyBkZXMgbW9kw6hsZXMgZGUgTWFjaGluZSBMZWFybmluZywgcXVpIHZvbnQgY29tcHJlbmRyZSBsYSBkeW5hbWlxdWUgZGUgbGEgc8OpcmllIGV0IHMnZW50cmHDrm5lciDDoCBtZXN1cmUgcXVlIGxlcyBkb25uw6llcyBzJ2FjdHVhbGlzZW50LiANCg0KDQoNCg0KDQo=