Time Series: ARIMA Modeling

Nigerian Deposit Money Banks Monthly Loan to Deposit Ratio (Jan. 2007 - April 2017)

The data source is from the Central Bank of Nigeria Statistics Database

Determining if the Time Series is Stationary

Using the R tsdisplay method, I generated the ACF and PACF plots. The ACF plots show a gradual decrease which implies that the time series is not stationary

tsdisplay(loan_to_deposit)

Determining the Differencing Order to Make Time Series Stationary

The original data contains trends. To convert the time series to a stationary time series I made use of the R diffs method. To determine the order of difference to apply I made use of the R forecast package method ndiffs, ndiffs(loan_to_deposit) = 1

level_of_difference <- ndiffs(loan_to_deposit)
diff_data <- diff(loan_to_deposit, level_of_difference)
plot(diff_data, ylab="first order difference loans-to-deposit")

tsdisplay(diff_data, main="first order differencing of loans-to-deposit ratio time series")

The ACF above shows that there is only one autocorrelation that is outside the 95% limit. Lets check the impact of a log transform of the first order difference of the time series if this would address this issue

level_of_difference <- ndiffs(log(loan_to_deposit))
diff_log_data <- diff(log(loan_to_deposit), level_of_difference)
plot(diff_log_data, ylab="first order difference log(loans-to-deposit)")

tsdisplay(diff_log_data, main="first order difference of log(loans-to-deposit) ratio time series")

The log transform of the first order difference of time series produces ACF that indicates that the difference log series is a white noise series.

The first order difference of the log transform of the data would be used to generate the arima model. R auto.arima method would be used that generates the p,d,q automatically

arima_fit <- auto.arima(diff_log_data, seasonal = FALSE)
arima_fit
Series: diff_log_data 
ARIMA(0,0,0) with non-zero mean 

Coefficients:
      intercept
         0.0015
s.e.     0.0071

sigma^2 estimated as 0.006225:  log likelihood=137.84
AIC=-271.68   AICc=-271.58   BIC=-266.06
plot(diff_log_data, main="ARMA(0,0,0) Modeling \n the difference time series of log of Loan-to-Deposit Ratio")
lines(fitted(arima_fit), col="red") 
legend("bottomright",c("data","ARIMA(0,0,0)"),col=c("black","red"),lty=c(1,1))

Applying the learning from the Forecasting Principle text with a difference series that is a white noise, the model for the original series,log(loan_to_deposit) would be \(y^'^~t~=0.0015+y~(t-1)~+e~t~\)

ARIMA Model using auto.arima for the log(loan_to_deposit) Time Series

arima_fit_auto <- auto.arima(log(loan_to_deposit))
summary(arima_fit_auto)
Series: log(loan_to_deposit) 
ARIMA(0,1,0) with drift         

Coefficients:
       drift
      0.0015
s.e.  0.0071

sigma^2 estimated as 0.006225:  log likelihood=137.84
AIC=-271.68   AICc=-271.58   BIC=-266.06

Training set error measures:
                       ME       RMSE        MAE         MPE     MAPE      MASE        ACF1
Training set 3.386398e-05 0.07858044 0.04448429 -0.02037677 1.103638 0.2131183 -0.09051223
plot(log(loan_to_deposit), main="ARMA(0,1,0) Modeling \n of the log of Loan-to-Deposit Ratio Time Seires")
lines(fitted(arima_fit_auto), col="red") 
legend("bottomleft",c("data","ARIMA(0,1,0)"),col=c("black","red"),lty=c(1,1))

Simple Exponential Smoothening Modeling using R SES the log(loan_to_deposit) Time Series

ses_model <- ses(log(loan_to_deposit))
summary(ses_model)

Forecast method: Simple exponential smoothing

Model Information:
ETS(A,N,N) 

Call:
 ses(x = log(loan_to_deposit)) 

  Smoothing parameters:
    alpha = 0.9087 

  Initial states:
    l = 4.1984 

  sigma:  0.0783

      AIC      AICc       BIC 
-30.07517 -29.97600 -24.43461 

Error measures:
                      ME       RMSE       MAE        MPE     MAPE      MASE         ACF1
Training set 0.001656168 0.07827393 0.0446254 0.01718334 1.107703 0.2137943 0.0002983321

Forecasts:
         Point Forecast    Lo 80    Hi 80    Lo 95    Hi 95
May 2017       4.385022 4.284710 4.485334 4.231608 4.538436
Jun 2017       4.385022 4.249481 4.520563 4.177730 4.592314
Jul 2017       4.385022 4.221681 4.548362 4.135214 4.634830
Aug 2017       4.385022 4.197969 4.572075 4.098949 4.671095
Sep 2017       4.385022 4.176941 4.593103 4.066789 4.703254
Oct 2017       4.385022 4.157851 4.612193 4.037594 4.732450
Nov 2017       4.385022 4.140246 4.629798 4.010669 4.759375
Dec 2017       4.385022 4.123824 4.646219 3.985555 4.784489
Jan 2018       4.385022 4.108376 4.661668 3.961929 4.808115
Feb 2018       4.385022 4.093746 4.676298 3.939554 4.830490
plot(log(loan_to_deposit), main="ETS(A,N,N) Modeling \n of the log of Loan-to-Deposit Ratio Time Seires")
lines(fitted(ses_model), col="red") 
legend("bottomright",c("data","ETS(A,N,N)"),col=c("black","red"),lty=c(1,1))

The SES model made use of ETS(A,N,N)

Comparing SES and ARIMA for the log(loan_to_deposit) Time Series

comparing the SES and ARIMA model using the AICc,
ARIMA model - ARIMA(0,1,0), AICc is -271.58 SES model - ETS(A,N,N) with an alpha of 0.9087, AICc is -29.976

The ARIMA model based on the AICc performed better in modeling the log(loan_to_deposit) time series. However plotting the residuals of the two models suggest that it does not seem the AICc are computed the same way. Because the plot show very little difference. However the difference in AICc of SES (-29.976) and ARIMA (-271.58) looks large.

Based on the residual plot below, the models seems to have very similar performance.

Comparing the Residuals of the SES and ARIMA model

 plot(residuals(arima_fit_auto), main="Comparing the Residuals of \nSES and ARIMA model", ylab="residual")
lines(residuals(ses_model), col="red")
legend("topleft",c("ARIMA(0,1,0)","ETS(A,N,N)"),col=c("black","red"),lty=c(1,1))

Plotting the log(loan_to_deposit), ARIMA(0,1,0) and ETS(A,N,N) on one plot

plot(log(loan_to_deposit), main="log(loan_to_deposit) time series, ARIMA(0,1,0) and ETS(A,N,N) models in one Plot")
lines(fitted(ses_model), col="red") 
lines(fitted(arima_fit_auto), col="blue") 
legend("bottomright",c("data","ETS(A,N,N)","ARIMA(0,1,0)"),col=c("black","red","blue"),lty=c(1,1))

Analysing the Residuals

An attempt is made to check if the residual is a white noise or not. This is done by ploting the ACF and PACF for each of the models - ARIMA and SES. The outcome of this plot show that both model produce residuals that are approximately white noise.

tsdisplay(arima_fit_auto$residuals, main="Analysis of ARIMA(0,1,0) Residual")

tsdisplay(ses_model$residuals, main="Analysis of ETS(A,N,N) Residuals")

LS0tDQp0aXRsZTogIkFwcGx5aW5nIEFSSU1BIE1vZGVsaW5nIHRvIFRpbWUgU2VyaWVzIg0KYXV0aG9yOiAiQWRlYmF5byBBZGVyaWJpZ2JlIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgZ2l0aHViX2RvY3VtZW50OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KIyMjVGltZSBTZXJpZXM6IEFSSU1BIE1vZGVsaW5nDQojIyNOaWdlcmlhbiBEZXBvc2l0IE1vbmV5IEJhbmtzIE1vbnRobHkgTG9hbiB0byBEZXBvc2l0IFJhdGlvIChKYW4uIDIwMDcgLSBBcHJpbCAyMDE3KSANClRoZSBkYXRhIHNvdXJjZSBpcyBmcm9tIHRoZSBbQ2VudHJhbCBCYW5rIG9mIE5pZ2VyaWEgU3RhdGlzdGljcyAgRGF0YWJhc2VdKGh0dHA6Ly9zdGF0aXN0aWNzLmNibi5nb3YubmcvY2JuLW9ubGluZXN0YXRzL0RhdGFCcm93c2VyLmFzcHgpDQoNCmBgYHtyICBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeSgiZm9yZWNhc3QiKQ0KbGlicmFyeSgiZnBwIikNCg0KYGBgDQoNCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQojZGF0YSBzb3VyY2UNCmRtYl9kYXRhIDwtIHJlYWQuY3N2KCJETUJfZGF0YS5jc3YiKQ0KDQojY29udmVydCBkYXRhIHRvIHRpbWUgc2VyaWVzDQp0c19kYXRhIDwtIHRzKGRtYl9kYXRhWywoMzo1KV0sZnJlcXVlbmN5PTEyLHN0YXJ0PWMoMjAwNywxKSkNCg0KI2xvYW5fdG9fZGVwb3NpdA0KbG9hbl90b19kZXBvc2l0IDwtIHRzX2RhdGFbLDFdDQpgYGANCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQojY3JlYXRlIGZpdA0KZml0IDwtIHN0bChsb2FuX3RvX2RlcG9zaXQsdC53aW5kb3c9MTUsIHMud2luZG93PSJwZXJpb2RpYyIsIHJvYnVzdD1UUlVFKQ0KYGBgDQoNCg0KYGBge3IgIGVjaG89RkFMU0V9DQojcGFyKGNleC5heGlzPTEuNSwgY2V4LmxhYj0xLjUpDQp0cy5wbG90KGxvYW5fdG9fZGVwb3NpdCx4bGFiPSJZZWFyIix5bGFiPSJMb2Fucy10by1EZXBvc2l0IFJhdGlvIixtYWluPSJNb250aGx5IExvYW4tdG8tRGVwb3NpdCBSYXRpbyAgZm9yIE5pZ2VyaWEgRGVwb3NpdCBNb25leSBCYW5rcyBcbiBKYW4uIDIwMDcgLSBBcHIuIDIwMTciKQ0KbGluZXMoZml0JHRpbWUuc2VyaWVzWywyXSxjb2w9InJlZCIseWxhYj0iVHJlbmQiKQ0KbGVnZW5kKCJib3R0b21yaWdodCIsYygiZGF0YSIsInRyZW5kIiksY29sPWMoImJsYWNrIiwicmVkIiksbHR5PWMoMSwxKSkNCmBgYA0KDQojIyNEZXRlcm1pbmluZyBpZiB0aGUgVGltZSBTZXJpZXMgaXMgU3RhdGlvbmFyeQ0KDQpVc2luZyB0aGUgUiAqKnRzZGlzcGxheSoqIG1ldGhvZCwgSSBnZW5lcmF0ZWQgdGhlIEFDRiBhbmQgUEFDRiBwbG90cy4gVGhlIEFDRiBwbG90cyBzaG93IGEgZ3JhZHVhbCBkZWNyZWFzZSB3aGljaCBpbXBsaWVzIHRoYXQgdGhlIHRpbWUgc2VyaWVzIGlzIG5vdCBzdGF0aW9uYXJ5DQoNCg0KYGBge3IgfQ0KdHNkaXNwbGF5KGxvYW5fdG9fZGVwb3NpdCkNCmBgYA0KDQoNCiMjIyNEZXRlcm1pbmluZyB0aGUgRGlmZmVyZW5jaW5nIE9yZGVyIHRvIE1ha2UgVGltZSBTZXJpZXMgU3RhdGlvbmFyeQ0KDQoNClRoZSBvcmlnaW5hbCBkYXRhIGNvbnRhaW5zIHRyZW5kcy4gVG8gY29udmVydCB0aGUgdGltZSBzZXJpZXMgdG8gYSBzdGF0aW9uYXJ5IHRpbWUgc2VyaWVzIEkgbWFkZSB1c2Ugb2YgdGhlICBSICAqKmRpZmZzKiogIG1ldGhvZC4gDQpUbyBkZXRlcm1pbmUgdGhlIG9yZGVyIG9mIGRpZmZlcmVuY2UgdG8gYXBwbHkgSSBtYWRlICB1c2Ugb2YgdGhlIFIgZm9yZWNhc3QgcGFja2FnZSBtZXRob2QgbmRpZmZzLCBuZGlmZnMobG9hbl90b19kZXBvc2l0KSA9IGByIG5kaWZmcyhsb2FuX3RvX2RlcG9zaXQpIGANCg0KDQpgYGB7ciB9DQpsZXZlbF9vZl9kaWZmZXJlbmNlIDwtIG5kaWZmcyhsb2FuX3RvX2RlcG9zaXQpDQpkaWZmX2RhdGEgPC0gZGlmZihsb2FuX3RvX2RlcG9zaXQsIGxldmVsX29mX2RpZmZlcmVuY2UpDQoNCnBsb3QoZGlmZl9kYXRhLCB5bGFiPSJmaXJzdCBvcmRlciBkaWZmZXJlbmNlIGxvYW5zLXRvLWRlcG9zaXQiKQ0KdHNkaXNwbGF5KGRpZmZfZGF0YSwgbWFpbj0iZmlyc3Qgb3JkZXIgZGlmZmVyZW5jaW5nIG9mIGxvYW5zLXRvLWRlcG9zaXQgcmF0aW8gdGltZSBzZXJpZXMiKQ0KDQpgYGANCg0KVGhlIEFDRiBhYm92ZSBzaG93cyB0aGF0IHRoZXJlIGlzIG9ubHkgb25lIGF1dG9jb3JyZWxhdGlvbiB0aGF0IGlzIG91dHNpZGUgdGhlIDk1JSBsaW1pdC4NCkxldHMgY2hlY2sgdGhlIGltcGFjdCBvZiBhIGxvZyB0cmFuc2Zvcm0gb2YgdGhlIGZpcnN0IG9yZGVyIGRpZmZlcmVuY2Ugb2YgdGhlIHRpbWUgc2VyaWVzIGlmIHRoaXMgd291bGQgYWRkcmVzcyB0aGlzIGlzc3VlDQoNCg0KYGBge3IgfQ0KbGV2ZWxfb2ZfZGlmZmVyZW5jZSA8LSBuZGlmZnMobG9nKGxvYW5fdG9fZGVwb3NpdCkpDQpkaWZmX2xvZ19kYXRhIDwtIGRpZmYobG9nKGxvYW5fdG9fZGVwb3NpdCksIGxldmVsX29mX2RpZmZlcmVuY2UpDQpwbG90KGRpZmZfbG9nX2RhdGEsIHlsYWI9ImZpcnN0IG9yZGVyIGRpZmZlcmVuY2UgbG9nKGxvYW5zLXRvLWRlcG9zaXQpIikNCnRzZGlzcGxheShkaWZmX2xvZ19kYXRhLCBtYWluPSJmaXJzdCBvcmRlciBkaWZmZXJlbmNlIG9mIGxvZyhsb2Fucy10by1kZXBvc2l0KSByYXRpbyB0aW1lIHNlcmllcyIpDQoNCmBgYA0KDQpUaGUgbG9nIHRyYW5zZm9ybSBvZiB0aGUgZmlyc3Qgb3JkZXIgZGlmZmVyZW5jZSBvZiB0aW1lIHNlcmllcyBwcm9kdWNlcyBBQ0YgdGhhdCBpbmRpY2F0ZXMgdGhhdCB0aGUgZGlmZmVyZW5jZSBsb2cgc2VyaWVzIGlzIGEgd2hpdGUgbm9pc2Ugc2VyaWVzLg0KDQoNCg0KVGhlIGZpcnN0IG9yZGVyIGRpZmZlcmVuY2Ugb2YgdGhlIGxvZyB0cmFuc2Zvcm0gb2YgdGhlIGRhdGEgd291bGQgYmUgdXNlZCB0byBnZW5lcmF0ZSB0aGUgYXJpbWEgbW9kZWwuDQpSICoqYXV0by5hcmltYSoqIG1ldGhvZCB3b3VsZCBiZSB1c2VkIHRoYXQgZ2VuZXJhdGVzIHRoZSBwLGQscSBhdXRvbWF0aWNhbGx5DQoNCmBgYHtyIH0NCmFyaW1hX2ZpdCA8LSBhdXRvLmFyaW1hKGRpZmZfbG9nX2RhdGEsIHNlYXNvbmFsID0gRkFMU0UpDQphcmltYV9maXQNCg0KDQpwbG90KGRpZmZfbG9nX2RhdGEsIG1haW49IkFSTUEoMCwwLDApIE1vZGVsaW5nIFxuIHRoZSBkaWZmZXJlbmNlIHRpbWUgc2VyaWVzIG9mIGxvZyBvZiBMb2FuLXRvLURlcG9zaXQgUmF0aW8iKQ0KbGluZXMoZml0dGVkKGFyaW1hX2ZpdCksIGNvbD0icmVkIikgDQpsZWdlbmQoImJvdHRvbXJpZ2h0IixjKCJkYXRhIiwiQVJJTUEoMCwwLDApIiksY29sPWMoImJsYWNrIiwicmVkIiksbHR5PWMoMSwxKSkNCmBgYA0KDQpBcHBseWluZyB0aGUgbGVhcm5pbmcgZnJvbSB0aGUgW0ZvcmVjYXN0aW5nIFByaW5jaXBsZSB0ZXh0XShodHRwczovL3d3dy5vdGV4dHMub3JnL2ZwcC84LzEpIHdpdGggYSBkaWZmZXJlbmNlIHNlcmllcyB0aGF0ICBpcyBhIHdoaXRlIG5vaXNlLCB0aGUgbW9kZWwgZm9yIHRoZSBvcmlnaW5hbCBzZXJpZXMsbG9nKGxvYW5fdG9fZGVwb3NpdCkgd291bGQgYmUgJHleJ15+dH49MC4wMDE1K3l+KHQtMSl+K2V+dH4kDQoNCiMjIyNBUklNQSBNb2RlbCB1c2luZyBhdXRvLmFyaW1hIGZvciB0aGUgbG9nKGxvYW5fdG9fZGVwb3NpdCkgVGltZSBTZXJpZXMNCmBgYHtyfQ0KYXJpbWFfZml0X2F1dG8gPC0gYXV0by5hcmltYShsb2cobG9hbl90b19kZXBvc2l0KSkNCnN1bW1hcnkoYXJpbWFfZml0X2F1dG8pDQoNCnBsb3QobG9nKGxvYW5fdG9fZGVwb3NpdCksIG1haW49IkFSTUEoMCwxLDApIE1vZGVsaW5nIFxuIG9mIHRoZSBsb2cgb2YgTG9hbi10by1EZXBvc2l0IFJhdGlvIFRpbWUgU2VpcmVzIikNCmxpbmVzKGZpdHRlZChhcmltYV9maXRfYXV0byksIGNvbD0icmVkIikgDQpsZWdlbmQoImJvdHRvbWxlZnQiLGMoImRhdGEiLCJBUklNQSgwLDEsMCkiKSxjb2w9YygiYmxhY2siLCJyZWQiKSxsdHk9YygxLDEpKQ0KYGBgDQoNCiMjIyNTaW1wbGUgRXhwb25lbnRpYWwgU21vb3RoZW5pbmcgTW9kZWxpbmcgdXNpbmcgUiBTRVMgIHRoZSBsb2cobG9hbl90b19kZXBvc2l0KSBUaW1lIFNlcmllcw0KYGBge3J9DQpzZXNfbW9kZWwgPC0gc2VzKGxvZyhsb2FuX3RvX2RlcG9zaXQpKQ0Kc3VtbWFyeShzZXNfbW9kZWwpDQoNCnBsb3QobG9nKGxvYW5fdG9fZGVwb3NpdCksIG1haW49IkVUUyhBLE4sTikgTW9kZWxpbmcgXG4gb2YgdGhlIGxvZyBvZiBMb2FuLXRvLURlcG9zaXQgUmF0aW8gVGltZSBTZWlyZXMiKQ0KbGluZXMoZml0dGVkKHNlc19tb2RlbCksIGNvbD0icmVkIikgDQpsZWdlbmQoImJvdHRvbXJpZ2h0IixjKCJkYXRhIiwiRVRTKEEsTixOKSIpLGNvbD1jKCJibGFjayIsInJlZCIpLGx0eT1jKDEsMSkpDQoNCmBgYA0KDQpUaGUgU0VTIG1vZGVsIG1hZGUgdXNlIG9mIEVUUyhBLE4sTikNCg0KIyMjQ29tcGFyaW5nIFNFUyBhbmQgQVJJTUEgZm9yIHRoZSBsb2cobG9hbl90b19kZXBvc2l0KSBUaW1lIFNlcmllcw0KY29tcGFyaW5nIHRoZSBTRVMgYW5kIEFSSU1BIG1vZGVsIHVzaW5nIHRoZSBBSUNjLCAgIA0KQVJJTUEgbW9kZWwgLSBBUklNQSgwLDEsMCksIEFJQ2MgaXMgLTI3MS41OCANClNFUyBtb2RlbCAtIEVUUyhBLE4sTikgd2l0aCBhbiBhbHBoYSBvZiAwLjkwODcsIEFJQ2MgaXMgLTI5Ljk3Ng0KDQpUaGUgQVJJTUEgbW9kZWwgYmFzZWQgb24gdGhlIEFJQ2MgcGVyZm9ybWVkIGJldHRlciBpbiBtb2RlbGluZyB0aGUgbG9nKGxvYW5fdG9fZGVwb3NpdCkgdGltZSBzZXJpZXMuICAgSG93ZXZlciBwbG90dGluZyB0aGUgcmVzaWR1YWxzIG9mIHRoZSB0d28gbW9kZWxzIHN1Z2dlc3QgdGhhdCBpdCBkb2VzIG5vdCBzZWVtIHRoZSBBSUNjIGFyZSBjb21wdXRlZCB0aGUgc2FtZSB3YXkuIEJlY2F1c2UgdGhlIHBsb3Qgc2hvdyB2ZXJ5IGxpdHRsZSBkaWZmZXJlbmNlLiAgSG93ZXZlciB0aGUgZGlmZmVyZW5jZSBpbiBBSUNjIG9mIFNFUyAoLTI5Ljk3NikgYW5kIEFSSU1BICgtMjcxLjU4KSBsb29rcyBsYXJnZS4NCg0KQmFzZWQgb24gdGhlIHJlc2lkdWFsIHBsb3QgYmVsb3csIHRoZSBtb2RlbHMgc2VlbXMgdG8gaGF2ZSB2ZXJ5IHNpbWlsYXIgcGVyZm9ybWFuY2UuDQoNCiMjIyNDb21wYXJpbmcgdGhlIFJlc2lkdWFscyBvZiB0aGUgU0VTIGFuZCBBUklNQSBtb2RlbA0KYGBge3J9DQogcGxvdChyZXNpZHVhbHMoYXJpbWFfZml0X2F1dG8pLCBtYWluPSJDb21wYXJpbmcgdGhlIFJlc2lkdWFscyBvZiBcblNFUyBhbmQgQVJJTUEgbW9kZWwiLCB5bGFiPSJyZXNpZHVhbCIpDQpsaW5lcyhyZXNpZHVhbHMoc2VzX21vZGVsKSwgY29sPSJyZWQiKQ0KbGVnZW5kKCJ0b3BsZWZ0IixjKCJBUklNQSgwLDEsMCkiLCJFVFMoQSxOLE4pIiksY29sPWMoImJsYWNrIiwicmVkIiksbHR5PWMoMSwxKSkNCmBgYA0KDQojIyMjUGxvdHRpbmcgdGhlIGxvZyhsb2FuX3RvX2RlcG9zaXQpLCBBUklNQSgwLDEsMCkgYW5kIEVUUyhBLE4sTikgb24gb25lIHBsb3QNCmBgYHtyfQ0KcGxvdChsb2cobG9hbl90b19kZXBvc2l0KSwgbWFpbj0ibG9nKGxvYW5fdG9fZGVwb3NpdCkgdGltZSBzZXJpZXMsIEFSSU1BKDAsMSwwKSBhbmQgRVRTKEEsTixOKSBtb2RlbHMgaW4gb25lIFBsb3QiKQ0KbGluZXMoZml0dGVkKHNlc19tb2RlbCksIGNvbD0icmVkIikgDQpsaW5lcyhmaXR0ZWQoYXJpbWFfZml0X2F1dG8pLCBjb2w9ImJsdWUiKSANCmxlZ2VuZCgiYm90dG9tcmlnaHQiLGMoImRhdGEiLCJFVFMoQSxOLE4pIiwiQVJJTUEoMCwxLDApIiksY29sPWMoImJsYWNrIiwicmVkIiwiYmx1ZSIpLGx0eT1jKDEsMSkpDQoNCmBgYA0KIyMjI0FuYWx5c2luZyB0aGUgUmVzaWR1YWxzDQpBbiBhdHRlbXB0IGlzIG1hZGUgdG8gY2hlY2sgaWYgdGhlIHJlc2lkdWFsIGlzIGEgd2hpdGUgbm9pc2Ugb3Igbm90LiAgVGhpcyBpcyBkb25lIGJ5IHBsb3RpbmcgdGhlIEFDRiBhbmQgUEFDRiBmb3IgZWFjaCBvZiB0aGUgbW9kZWxzIC0gQVJJTUEgYW5kIFNFUy4gIFRoZSBvdXRjb21lIG9mIHRoaXMgcGxvdCBzaG93IHRoYXQgYm90aCBtb2RlbCBwcm9kdWNlIHJlc2lkdWFscyB0aGF0IGFyZSBhcHByb3hpbWF0ZWx5IHdoaXRlIG5vaXNlLiAgDQoNCmBgYHtyfQ0KdHNkaXNwbGF5KGFyaW1hX2ZpdF9hdXRvJHJlc2lkdWFscywgbWFpbj0iQW5hbHlzaXMgb2YgQVJJTUEoMCwxLDApIFJlc2lkdWFsIikNCg0KdHNkaXNwbGF5KHNlc19tb2RlbCRyZXNpZHVhbHMsIG1haW49IkFuYWx5c2lzIG9mIEVUUyhBLE4sTikgUmVzaWR1YWxzIikNCmBgYA0KDQo=