Abstract

Use an R Notebook for this challenge.

Design the best ARIMA/SARIMA model for the Mexican peso exchange rate (MX/USD). Download the exchange rate directly from the FRED Database (Federal reserve Bank of St. Louis).

Preparing my Workshop

Run the following R code to download the MX-USD exchange rate:

library(quantmod)
Loading required package: xts
Loading required package: zoo

Attaching package: ‘zoo’

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric

Loading required package: TTR
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
library(PerformanceAnalytics)

Attaching package: ‘PerformanceAnalytics’

The following object is masked from ‘package:graphics’:

    legend
getSymbols(Symbols="DEXMXUS", src="FRED")
‘getSymbols’ currently uses auto.assign=TRUE by default, but will
use auto.assign=FALSE in 0.5-0. You will still be able to use
‘loadSymbols’ to automatically load data. getOption("getSymbols.env")
and getOption("getSymbols.auto.assign") will still be checked for
alternate defaults.

This message is shown once per session and may be disabled by setting 
options("getSymbols.warning4.0"=FALSE). See ?getSymbols for details.
[1] "DEXMXUS"
DEXMXUS = DEXMXUS["2000-01-01/",]

You have to collapse the dataset from daily to monthly. Do the following:

mexrate = to.monthly(DEXMXUS)
Warning in to.period(x, "months", indexAt = indexAt, name = name, ...) :
  missing values removed from data
mexrate = Cl(mexrate)
colnames(mexrate)=c("exrate")

Once you have the monthlty exchange rate series, do the necessary steps to CALIBRATE the BEST arima/sarima model. You have to:

1.- In your R Notebook explain EACH STEP you need to do related to data management, statistical tests, ac/pac plots, residual tests, and arima models. 2.- You have to INTERPRET with your own words your LAST(SELECTED) ARIMA/SARIMA model 3.- Expand the dataset 21 months (up to Dec 2023), and do a forecast for the exchange rate. What is the expected exchange rate in Dec 2023? Do a plot for the exchange rate and the forecasted rate

Data management, statistical tests, ac/pac plots, residual tests, and arima models

library(readxl)
library(xts)
library(zoo)
library(tseries)

    ‘tseries’ version: 0.10-49

    ‘tseries’ is a package for time series analysis and
    computational finance.

    See ‘library(help="tseries")’ for details.
library(forecast)

I get the natural logarithm of all values:

lndexmus<- log(mexrate)

Now I graph log

plot(lndexmus)

IT SEEMS THAT THE SERIES ISN’T STATIONARY AND IT DOESN’T HAVE SEASONALITY SINCE THE MEAN OF THE SERIES CHANGES OVER TIME, AND THERE ARE NO CLEAR PEAKS IN THE SAME PERIODS OF THE YEAR.

s12.lnmexrate <- diff(lndexmus, lag=12)
s12.lnmexrate<- na.omit(s12.lnmexrate)
plot(s12.lnmexrate)

Dicky-Fuller test

adf.test(s12.lnmexrate, k = 0)

    Augmented Dickey-Fuller Test

data:  s12.lnmexrate
Dickey-Fuller = -3.8785, Lag order = 0, p-value =
0.01557
alternative hypothesis: stationary

I SEE THAT THE SERIES IS NOW STATIONARY, SINCE THE P-VALUE IS LESS THAN 0-05.

Calibrating the model

I will make the AC and PAC graphs to see the level of autocorrelation of the variable at certain lags:

library(astsa)
acf2(s12.lnmexrate,max.lag = 12)
     [,1]  [,2]  [,3]  [,4] [,5]  [,6]  [,7]  [,8]  [,9] [,10]
ACF  0.89  0.76  0.64  0.51 0.41  0.31  0.21  0.12  0.02 -0.06
PACF 0.89 -0.12 -0.05 -0.09 0.02 -0.06 -0.08 -0.04 -0.12 -0.01
     [,11] [,12]
ACF  -0.16 -0.25
PACF -0.21  0.00

THINKING THAT THIS MIGHT BE AN AR PROCESS, WE CAN TELL THAT THE ACF PLOT GRADUALLY DECREASES AND SIMULTANEOUSLY THE PACF HAS A SHARP DROP AFTER P SIGNIFICANT LAGS.

IN THE ACF PLOT WE SEE THAT THE AUTOCORRELATION BETWEEN LAG1 AND THE VARIABLE IS SEEN HAVING A CORRELATION OF ABOUT 0.9, AND THE AUTOCORRELATION BETWEEN LAG2 AND THE VARIABLE IS ABOUT 0.8. AFTER THIS LAG, THE FOLLOWING AUTOCORRELATIONS DECAY GRADUALLY, AND AFTER LAG8 ALL AUTOCORRELATIONS ARE NOT SIGNIFICANT.

IN THE PACF, AFTER THE 1ST LAG, THE AUTOCORRELATIONS CUT OFF DRASTICALLY. THE PATTERN OBSERVED IN THE ACF AND PACF IS A TYPICAL AR SIGNATURE; IN THIS CASE WE SELECT 1 TERM (P=1) SINCE THE PACF SHOWS THE FIRST AUTOCORRELATION AS POSITIVE AND SIGNIFICANT.

When finding an AR signature, we start setting the p according to the positive and significant autocorrelations in the PACF, and set the remaining the parameters equal to zero (q=0, P=0, and Q=0).

In this case, we can see in the ACF and PACF plots that lag 11 is significant and negative, but we can ignore this for now since it might show up when we check the errors of the first model.

Then I start adding only 1 AR term (p=1) and later see whether the model errors look like a white noise or whether I need to add more terms.

library(lmtest)
model1<-Arima(mexrate, order = c(1,0,0),
seasonal = list(order=c(0,1,0),period=12),
include.constant = TRUE,
lambda = 0)
coeftest(model1)

z test of coefficients:

       Estimate Std. Error z value Pr(>|z|)    
ar1   0.8837576  0.0285342 30.9719   <2e-16 ***
drift 0.0028429  0.0019308  1.4724   0.1409    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

I SEE THAT THE AR COEFFICIENT IS POSITIVE AND SIGNIFICANT AS EXPECTED ACCORDING TO THE PACF.

Now I can check whether the residuals of this model behave like a white noise:

Check residuals

“A white noise series is a time series variable that has no autocorrelations between any pair of lags, and also its mean is 0 and it is stationary. In other words, a white noise is a series that cannot be explained by any of its own past values or errors, since it is totally unpredictable.” (Dr. Dorantes, 2022)

The residuals series of a model (error series) is the difference between a real value of the variable and its predicted value using the model.

The residuals of the model are already calculated and stored in the Arima model R object in the residuals attribute:

lnmexrate_res <- model1$residuals

I get the ACF and PACF plots of these residuals to check for white noise or if the residuals still have significant autocorrelations with certain lags:

acf2(lnmexrate_res,max.lag = 12)
     [,1] [,2] [,3]  [,4] [,5] [,6]  [,7] [,8]  [,9] [,10]
ACF  0.11 0.03 0.05 -0.05 0.00 0.03 -0.03 0.04 -0.07  0.09
PACF 0.11 0.02 0.04 -0.07 0.01 0.03 -0.03 0.04 -0.08  0.11
     [,11] [,12]
ACF  -0.09 -0.48
PACF -0.12 -0.47

LAG 12 AUTOCORRELATION IS NEGATIVE AND SIGNIFICANT. THE REST OF THE LAG AUTOCORRELATIONS AREN’T.

IN THIS CASE WE WILL CONSIDER THE SIGNIFICANT AUTOCORRELATION OF LAG 12 IN THE ARIMA-SARIMA MODEL.

ACCORDING TO DR. NAU RECOMMENDATIONS, IF THE LAG IS NEGATIVE AND APPEARS IN BOTH ACF AND PACF AND DOESN’T FOLLOW AN AR SIGNATURE, THEN WE START INCLUDING AN MA TERM (Q=1) SINCE THE AUTOCORRELATION IS WITH LAG12 AND OUR DATA IS MONTHLY.

Then I modified the model and run it:

model2 <- Arima(mexrate, order = c(1,0,0),
seasonal = list(order=c(0,1,1),period=12),
include.constant = TRUE,
lambda = 0)
coeftest(model2)

z test of coefficients:

         Estimate  Std. Error  z value  Pr(>|z|)    
ar1    0.94095253  0.02237506  42.0536 < 2.2e-16 ***
sma1  -0.99998791  0.04727244 -21.1537 < 2.2e-16 ***
drift  0.00317518  0.00035704   8.8932 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

THE SEASONAL MA TERM IS NEGATIVE AND SIGNIFICANT AS EXPECTED. THEN, I GET THE RESIDUALS OF THIS MODEL AND CHECK WHETHER THE RESIDUALS SERIES LOOKS LIKE A WHITE NOISE SERIES.

lnmexrate_res2 <- model2$residuals

I get the ACF and PACF graphs to check whether these errors behave like a white noise:

acf2(lnmexrate_res2,max.lag = 12)
     [,1]  [,2]  [,3]  [,4] [,5] [,6]  [,7]  [,8]  [,9] [,10]
ACF   0.1 -0.02 -0.01 -0.08 0.01 0.03 -0.04 -0.01 -0.08  0.11
PACF  0.1 -0.03  0.00 -0.08 0.03 0.02 -0.04 -0.01 -0.08  0.13
     [,11] [,12]
ACF   0.01 -0.05
PACF -0.02 -0.05

Now the residuals series looks like a white noise series since non of the important Lags are significant. Then I keep this model and finish the calibration process.

INTERPRETATION of the final model:

FIRST, I HAVE TO CHECK WHAT IS THE VARIABLE OF STUDY (THE DEPENDENT VARIABLE). IN THIS CASE I AM MODELING THE ANNUAL DIFFERENCE OF THE LOG OF MEXICAN PESO EXCHANGE RATE (S12_LNMEXRATE), WHICH IS THE ANNUAL % CHANGE IN MONETARY RATES MONTH BY MONTH. THEN, I CAN INTERPRET THE MODEL AS FOLLOWS:

THE AR(1) TERM HAS A COEFFICIENT (PHI1) EQUAL TO 0.94095253, AND IT IS SIGNIFICANTLY GREATER THAN ZERO SINCE ITS P-VALUE<0.05. THEN I CAN SAY THAT THE ANNUAL % IN THE EXCHANGE RATE IS POSITIVELY AND SIGNIFICANTLY RELATED WITH ITS OWN ANNUAL % CHANGE OF THE PREVIOUS MONTHS. IN OTHER WORDS, FOR EACH 1% INCREASE IN ANNUAL % GROWTH OF THE PREVIOUS MONTH, THE CURRENT ANNUAL % CHANGE IN EXCHANGE RATES IS EXPECTED TO GROW IN ABOUT 0.94095253%.

THE CONSTANT PHI0 (OF DRIFT) IS POSITIVE BUT ISN’T REALLY SIGNIFICANT. THIS MEANS THAT THE ANNUAL % CHANGE IN RATES OF THE MEXICAN PESO ARE SLIGHTLY GROWING OVER TIME WITH AN AVERAGE ANNUAL GROWTH OF 0.00317518% (IT HAS A GROWING TENDENCY).

INTERPRETATION of the Seasonal MA term: THE ANNUAL % CHANGE IN RATES OF THE MEXICAN PESO IS NEGATIVELY RELATED TO THE SHOCK (ERROR) OF 12 MONTHS AGO. WHEN THE SHOCK IS NEGATIVE 12 MONTHS AGO, IT IS EXPECTED THAT THE ANNUAL % CHANGE IN RATES OF THE CURRENT MONTH WILL BE POSITIVE.

Forecast for the Exchange Rate

Expand the dataset 21 months (up to Dec 2023), and do a forecast for the exchange rate. What is the expected exchange rate in Dec 2023? Do a plot for the exchange rate and the forecasted rate

WITH THIS MODEL I SHALL DO A FORECAST FOR CHANGE IN THE MEXICAN PESO EXCHANGE RATE FOR THE NEXT 21 MONTHS. FOR THE LAST MODEL I WILL CONVERT THE ORIGINAL VARIABLE TO A TS R OBJECT TO HAVE A BETTER VISUALIZATION OF THE FORECAST:

mexrate.ts <- ts(coredata(mexrate),start=c(2000,1),frequency=12)
model2 <- Arima(mexrate.ts, order = c(1,0,0),
seasonal = list(order=c(0,1,1),period=12),
include.constant = TRUE,
lambda = 0)
forecast_mexrate <- forecast(model2, h=21)
autoplot(forecast_mexrate)

WE CAN SEE THE FORECAST FOR THE MEXICAN PESO EXCHANGE RATE, WHICH IS STORED AS AN ATTRIBUTE IN THE FORECAST_MEXRATE OBJECT:

forecast_mexrate$mean
          Jan      Feb      Mar      Apr      May      Jun
2022                            20.38147 20.58518 20.62783
2023 21.40718 21.43224 21.29827 21.26873 21.47559 21.51470
          Jul      Aug      Sep      Oct      Nov      Dec
2022 20.44389 20.77906 21.03587 21.08558 21.27813 21.38602
2023 21.31782 21.66251 21.92567 21.97316 22.16971 22.27825

THE EXCHANGE RATE FOR THE MEXICAN PESO EXPECTED FOR DECEMBER 2023 WILL SIT AT THE $22.27825 MARK. AS SEEN IN THE PLOT, THE TREND IS EXPECTED TO GO UPWARDS WITH A COUPLE OF DOWNWARD TRENDS FOR JULY AND AUGUST 2022.

Thank you

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKYXV0aG9yOiBTdGVmYW4gU2Nod2VpdHplciBBMDEyMDk3NTUKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojIEFic3RyYWN0ClVzZSBhbiBSIE5vdGVib29rIGZvciB0aGlzIGNoYWxsZW5nZS4KCkRlc2lnbiB0aGUgYmVzdCBBUklNQS9TQVJJTUEgbW9kZWwgZm9yIHRoZSBNZXhpY2FuIHBlc28gZXhjaGFuZ2UgcmF0ZSAoTVgvVVNEKS4gRG93bmxvYWQgdGhlIGV4Y2hhbmdlIHJhdGUgZGlyZWN0bHkgZnJvbSB0aGUgRlJFRCBEYXRhYmFzZSAoRmVkZXJhbCByZXNlcnZlIEJhbmsgb2YgU3QuIExvdWlzKS4gCgojIFByZXBhcmluZyBteSBXb3Jrc2hvcApSdW4gdGhlIGZvbGxvd2luZyBSIGNvZGUgdG8gZG93bmxvYWQgdGhlIE1YLVVTRCBleGNoYW5nZSByYXRlOgoKYGBge3J9CmxpYnJhcnkocXVhbnRtb2QpCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpCmdldFN5bWJvbHMoU3ltYm9scz0iREVYTVhVUyIsIHNyYz0iRlJFRCIpCkRFWE1YVVMgPSBERVhNWFVTWyIyMDAwLTAxLTAxLyIsXQpgYGAKCllvdSBoYXZlIHRvIGNvbGxhcHNlIHRoZSBkYXRhc2V0IGZyb20gZGFpbHkgdG8gbW9udGhseS4gRG8gdGhlIGZvbGxvd2luZzoKCmBgYHtyfQptZXhyYXRlID0gdG8ubW9udGhseShERVhNWFVTKQptZXhyYXRlID0gQ2wobWV4cmF0ZSkKY29sbmFtZXMobWV4cmF0ZSk9YygiZXhyYXRlIikKYGBgCk9uY2UgeW91IGhhdmUgdGhlIG1vbnRobHR5IGV4Y2hhbmdlIHJhdGUgc2VyaWVzLCBkbyB0aGUgbmVjZXNzYXJ5IHN0ZXBzIHRvIENBTElCUkFURSB0aGUgQkVTVCBhcmltYS9zYXJpbWEgbW9kZWwuIFlvdSBoYXZlIHRvOgoKMS4tIEluIHlvdXIgUiBOb3RlYm9vayBleHBsYWluIEVBQ0ggU1RFUCB5b3UgbmVlZCB0byBkbyByZWxhdGVkIHRvIGRhdGEgbWFuYWdlbWVudCwgc3RhdGlzdGljYWwgdGVzdHMsIGFjL3BhYyBwbG90cywgcmVzaWR1YWwgdGVzdHMsIGFuZCBhcmltYSBtb2RlbHMuCjIuLSBZb3UgaGF2ZSB0byBJTlRFUlBSRVQgd2l0aCB5b3VyIG93biB3b3JkcyB5b3VyIExBU1QoU0VMRUNURUQpIEFSSU1BL1NBUklNQSBtb2RlbAozLi0gRXhwYW5kIHRoZSBkYXRhc2V0IDIxIG1vbnRocyAodXAgdG8gRGVjIDIwMjMpLCBhbmQgZG8gYSBmb3JlY2FzdCBmb3IgdGhlIGV4Y2hhbmdlIHJhdGUuIFdoYXQgaXMgdGhlIGV4cGVjdGVkIGV4Y2hhbmdlIHJhdGUgaW4gRGVjIDIwMjM/IERvIGEgcGxvdCBmb3IgdGhlIGV4Y2hhbmdlIHJhdGUgYW5kIHRoZSBmb3JlY2FzdGVkIHJhdGUKCgojIyBEYXRhIG1hbmFnZW1lbnQsIHN0YXRpc3RpY2FsIHRlc3RzLCBhYy9wYWMgcGxvdHMsIHJlc2lkdWFsIHRlc3RzLCBhbmQgYXJpbWEgbW9kZWxzCgpgYGB7cn0KbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoeHRzKQpsaWJyYXJ5KHpvbykKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGZvcmVjYXN0KQpgYGAKCgpJIGdldCB0aGUgbmF0dXJhbCBsb2dhcml0aG0gb2YgYWxsIHZhbHVlczoKYGBge3J9CmxuZGV4bXVzPC0gbG9nKG1leHJhdGUpCmBgYAoKTm93IEkgZ3JhcGggbG9nCmBgYHtyfQpwbG90KGxuZGV4bXVzKQpgYGAKCklUIFNFRU1TIFRIQVQgVEhFIFNFUklFUyBJU04nVCBTVEFUSU9OQVJZIEFORCBJVCBET0VTTidUIEhBVkUgU0VBU09OQUxJVFkgU0lOQ0UgVEhFIE1FQU4gT0YgVEhFIFNFUklFUyBDSEFOR0VTIE9WRVIgVElNRSwgQU5EIFRIRVJFIEFSRSBOTyBDTEVBUiBQRUFLUyBJTiBUSEUgU0FNRSBQRVJJT0RTIE9GIFRIRSBZRUFSLgoKYGBge3J9CnMxMi5sbm1leHJhdGUgPC0gZGlmZihsbmRleG11cywgbGFnPTEyKQpzMTIubG5tZXhyYXRlPC0gbmEub21pdChzMTIubG5tZXhyYXRlKQpwbG90KHMxMi5sbm1leHJhdGUpCmBgYAoKIyBEaWNreS1GdWxsZXIgdGVzdAoKYGBge3J9CmFkZi50ZXN0KHMxMi5sbm1leHJhdGUsIGsgPSAwKQpgYGAKSSBTRUUgVEhBVCBUSEUgU0VSSUVTIElTIE5PVyBTVEFUSU9OQVJZLCBTSU5DRSBUSEUgUC1WQUxVRSBJUyBMRVNTIFRIQU4gMC0wNS4KCiMjIENhbGlicmF0aW5nIHRoZSBtb2RlbAoKSSB3aWxsIG1ha2UgdGhlIEFDIGFuZCBQQUMgZ3JhcGhzIHRvIHNlZSB0aGUgbGV2ZWwgb2YgYXV0b2NvcnJlbGF0aW9uIG9mIHRoZSB2YXJpYWJsZSBhdCBjZXJ0YWluIGxhZ3M6CgpgYGB7cn0KbGlicmFyeShhc3RzYSkKYWNmMihzMTIubG5tZXhyYXRlLG1heC5sYWcgPSAxMikKYGBgCgpUSElOS0lORyBUSEFUIFRISVMgTUlHSFQgQkUgQU4gQVIgUFJPQ0VTUywgV0UgQ0FOIFRFTEwgVEhBVCBUSEUgQUNGIFBMT1QgR1JBRFVBTExZIERFQ1JFQVNFUyBBTkQgU0lNVUxUQU5FT1VTTFkgVEhFIFBBQ0YgSEFTIEEgU0hBUlAgRFJPUCBBRlRFUiBQIFNJR05JRklDQU5UIExBR1MuCgpJTiBUSEUgQUNGIFBMT1QgV0UgU0VFIFRIQVQgVEhFIEFVVE9DT1JSRUxBVElPTiBCRVRXRUVOIExBRzEgQU5EIFRIRSBWQVJJQUJMRSBJUyBTRUVOIEhBVklORyBBIENPUlJFTEFUSU9OIE9GIEFCT1VUIDAuOSwgQU5EIFRIRSBBVVRPQ09SUkVMQVRJT04gQkVUV0VFTiBMQUcyIEFORCBUSEUgVkFSSUFCTEUgSVMgQUJPVVQgMC44LiBBRlRFUiBUSElTIExBRywgVEhFIEZPTExPV0lORyBBVVRPQ09SUkVMQVRJT05TIERFQ0FZIEdSQURVQUxMWSwgQU5EIEFGVEVSIExBRzggQUxMIEFVVE9DT1JSRUxBVElPTlMgQVJFIE5PVCBTSUdOSUZJQ0FOVC4gCgpJTiBUSEUgUEFDRiwgQUZURVIgVEhFIDFTVCBMQUcsIFRIRSBBVVRPQ09SUkVMQVRJT05TIENVVCBPRkYgRFJBU1RJQ0FMTFkuIFRIRSBQQVRURVJOIE9CU0VSVkVEIElOIFRIRSBBQ0YgQU5EIFBBQ0YgSVMgQSBUWVBJQ0FMIEFSIFNJR05BVFVSRTsgSU4gVEhJUyBDQVNFIFdFIFNFTEVDVCAxIFRFUk0gKFA9MSkgU0lOQ0UgVEhFIFBBQ0YgU0hPV1MgVEhFIEZJUlNUIEFVVE9DT1JSRUxBVElPTiBBUyBQT1NJVElWRSBBTkQgU0lHTklGSUNBTlQuCgpXaGVuIGZpbmRpbmcgYW4gQVIgc2lnbmF0dXJlLCB3ZSBzdGFydCBzZXR0aW5nIHRoZSBwIGFjY29yZGluZyB0byB0aGUgcG9zaXRpdmUgYW5kIHNpZ25pZmljYW50IGF1dG9jb3JyZWxhdGlvbnMgaW4gdGhlIFBBQ0YsIGFuZCBzZXQgdGhlIHJlbWFpbmluZyB0aGUgcGFyYW1ldGVycyBlcXVhbCB0byB6ZXJvIChxPTAsIFA9MCwgYW5kIFE9MCkuCgpJbiB0aGlzIGNhc2UsIHdlIGNhbiBzZWUgaW4gdGhlIEFDRiBhbmQgUEFDRiBwbG90cyB0aGF0IGxhZyAxMSBpcyBzaWduaWZpY2FudCBhbmQgbmVnYXRpdmUsIGJ1dCB3ZSBjYW4gaWdub3JlIHRoaXMgZm9yIG5vdyBzaW5jZSBpdCBtaWdodCBzaG93IHVwIHdoZW4gd2UgY2hlY2sgdGhlIGVycm9ycyBvZiB0aGUgZmlyc3QgbW9kZWwuCgpUaGVuIEkgc3RhcnQgYWRkaW5nIG9ubHkgMSBBUiB0ZXJtIChwPTEpIGFuZCBsYXRlciBzZWUgd2hldGhlciB0aGUgbW9kZWwgZXJyb3JzIGxvb2sgbGlrZSBhIHdoaXRlIG5vaXNlIG9yIHdoZXRoZXIgSSBuZWVkIHRvIGFkZCBtb3JlIHRlcm1zLgoKYGBge3J9CmxpYnJhcnkobG10ZXN0KQptb2RlbDE8LUFyaW1hKG1leHJhdGUsIG9yZGVyID0gYygxLDAsMCksCnNlYXNvbmFsID0gbGlzdChvcmRlcj1jKDAsMSwwKSxwZXJpb2Q9MTIpLAppbmNsdWRlLmNvbnN0YW50ID0gVFJVRSwKbGFtYmRhID0gMCkKY29lZnRlc3QobW9kZWwxKQpgYGAKSSBTRUUgVEhBVCBUSEUgQVIgQ09FRkZJQ0lFTlQgSVMgUE9TSVRJVkUgQU5EIFNJR05JRklDQU5UIEFTIEVYUEVDVEVEIEFDQ09SRElORyBUTyBUSEUgUEFDRi4KCk5vdyBJIGNhbiBjaGVjayB3aGV0aGVyIHRoZSByZXNpZHVhbHMgb2YgdGhpcyBtb2RlbCBiZWhhdmUgbGlrZSBhIHdoaXRlIG5vaXNlOgoKIyMgQ2hlY2sgcmVzaWR1YWxzCgoiQSB3aGl0ZSBub2lzZSBzZXJpZXMgaXMgYSB0aW1lIHNlcmllcyB2YXJpYWJsZSB0aGF0IGhhcyBubyBhdXRvY29ycmVsYXRpb25zIGJldHdlZW4gYW55IHBhaXIgb2YgbGFncywgYW5kIGFsc28gaXRzIG1lYW4gaXMgMCBhbmQgaXQgaXMgc3RhdGlvbmFyeS4gSW4gb3RoZXIgd29yZHMsIGEgd2hpdGUgbm9pc2UgaXMgYSBzZXJpZXMgdGhhdCBjYW5ub3QgYmUgZXhwbGFpbmVkIGJ5IGFueSBvZiBpdHMgb3duIHBhc3QgdmFsdWVzIG9yIGVycm9ycywgc2luY2UgaXQgaXMgdG90YWxseSB1bnByZWRpY3RhYmxlLiIgKERyLiBEb3JhbnRlcywgMjAyMikKClRoZSByZXNpZHVhbHMgc2VyaWVzIG9mIGEgbW9kZWwgKGVycm9yIHNlcmllcykgaXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBhIHJlYWwgdmFsdWUgb2YgdGhlIHZhcmlhYmxlIGFuZCBpdHMgcHJlZGljdGVkIHZhbHVlIHVzaW5nIHRoZSBtb2RlbC4KClRoZSByZXNpZHVhbHMgb2YgdGhlIG1vZGVsIGFyZSBhbHJlYWR5IGNhbGN1bGF0ZWQgYW5kIHN0b3JlZCBpbiB0aGUgQXJpbWEgbW9kZWwgUiBvYmplY3QgaW4gdGhlIHJlc2lkdWFscyBhdHRyaWJ1dGU6CgpgYGB7cn0KbG5tZXhyYXRlX3JlcyA8LSBtb2RlbDEkcmVzaWR1YWxzCmBgYAoKSSBnZXQgdGhlIEFDRiBhbmQgUEFDRiBwbG90cyBvZiB0aGVzZSByZXNpZHVhbHMgdG8gY2hlY2sgZm9yIHdoaXRlIG5vaXNlIG9yIGlmIHRoZSByZXNpZHVhbHMgc3RpbGwgaGF2ZSBzaWduaWZpY2FudCBhdXRvY29ycmVsYXRpb25zIHdpdGggY2VydGFpbiBsYWdzOgoKYGBge3J9CmFjZjIobG5tZXhyYXRlX3JlcyxtYXgubGFnID0gMTIpCmBgYApMQUcgMTIgQVVUT0NPUlJFTEFUSU9OIElTIE5FR0FUSVZFIEFORCBTSUdOSUZJQ0FOVC4gVEhFIFJFU1QgT0YgVEhFIExBRyBBVVRPQ09SUkVMQVRJT05TIEFSRU4nVC4KCklOIFRISVMgQ0FTRSBXRSBXSUxMIENPTlNJREVSIFRIRSBTSUdOSUZJQ0FOVCBBVVRPQ09SUkVMQVRJT04gT0YgTEFHIDEyIElOIFRIRSBBUklNQS1TQVJJTUEgTU9ERUwuCgpBQ0NPUkRJTkcgVE8gRFIuIE5BVSBSRUNPTU1FTkRBVElPTlMsIElGIFRIRSBMQUcgSVMgTkVHQVRJVkUgQU5EIEFQUEVBUlMgSU4gQk9USCBBQ0YgQU5EIFBBQ0YgQU5EIERPRVNOJ1QgRk9MTE9XIEFOIEFSIFNJR05BVFVSRSwgVEhFTiBXRSBTVEFSVCBJTkNMVURJTkcgQU4gTUEgVEVSTSAoUT0xKSBTSU5DRSBUSEUgQVVUT0NPUlJFTEFUSU9OIElTIFdJVEggTEFHMTIgQU5EIE9VUiBEQVRBIElTIE1PTlRITFkuCgpUaGVuIEkgbW9kaWZpZWQgdGhlIG1vZGVsIGFuZCBydW4gaXQ6CgpgYGB7cn0KbW9kZWwyIDwtIEFyaW1hKG1leHJhdGUsIG9yZGVyID0gYygxLDAsMCksCnNlYXNvbmFsID0gbGlzdChvcmRlcj1jKDAsMSwxKSxwZXJpb2Q9MTIpLAppbmNsdWRlLmNvbnN0YW50ID0gVFJVRSwKbGFtYmRhID0gMCkKY29lZnRlc3QobW9kZWwyKQpgYGAKVEhFIFNFQVNPTkFMIE1BIFRFUk0gSVMgTkVHQVRJVkUgQU5EIFNJR05JRklDQU5UIEFTIEVYUEVDVEVELiBUSEVOLCBJIEdFVCBUSEUgUkVTSURVQUxTIE9GIFRISVMgTU9ERUwgQU5EIENIRUNLIFdIRVRIRVIgVEhFIFJFU0lEVUFMUyBTRVJJRVMgTE9PS1MgTElLRSBBIFdISVRFIE5PSVNFIFNFUklFUy4KCmBgYHtyfQpsbm1leHJhdGVfcmVzMiA8LSBtb2RlbDIkcmVzaWR1YWxzCmBgYAoKSSBnZXQgdGhlIEFDRiBhbmQgUEFDRiBncmFwaHMgdG8gY2hlY2sgd2hldGhlciB0aGVzZSBlcnJvcnMgYmVoYXZlIGxpa2UgYSB3aGl0ZSBub2lzZToKCmBgYHtyfQphY2YyKGxubWV4cmF0ZV9yZXMyLG1heC5sYWcgPSAxMikKYGBgCk5vdyB0aGUgcmVzaWR1YWxzIHNlcmllcyBsb29rcyBsaWtlIGEgd2hpdGUgbm9pc2Ugc2VyaWVzIHNpbmNlIG5vbiBvZiB0aGUgaW1wb3J0YW50IExhZ3MgYXJlIHNpZ25pZmljYW50LiBUaGVuIEkga2VlcCB0aGlzIG1vZGVsIGFuZCBmaW5pc2ggdGhlIGNhbGlicmF0aW9uIHByb2Nlc3MuCgojIyBJTlRFUlBSRVRBVElPTiBvZiB0aGUgZmluYWwgbW9kZWw6CgpGSVJTVCwgSSBIQVZFIFRPIENIRUNLIFdIQVQgSVMgVEhFIFZBUklBQkxFIE9GIFNUVURZIChUSEUgREVQRU5ERU5UIFZBUklBQkxFKS4gSU4gVEhJUyBDQVNFIEkgQU0gTU9ERUxJTkcgVEhFIEFOTlVBTCBESUZGRVJFTkNFIE9GIFRIRSBMT0cgT0YgTUVYSUNBTiBQRVNPIEVYQ0hBTkdFIFJBVEUgKFMxMl9MTk1FWFJBVEUpLCBXSElDSCBJUyBUSEUgQU5OVUFMICUgQ0hBTkdFIElOIE1PTkVUQVJZIFJBVEVTIE1PTlRIIEJZIE1PTlRILiBUSEVOLCBJIENBTiBJTlRFUlBSRVQgVEhFIE1PREVMIEFTIEZPTExPV1M6CgpUSEUgQVIoMSkgVEVSTSBIQVMgQSBDT0VGRklDSUVOVCAoUEhJMSkgRVFVQUwgVE8gMC45NDA5NTI1MywgQU5EIElUIElTIFNJR05JRklDQU5UTFkgR1JFQVRFUiBUSEFOIFpFUk8gU0lOQ0UgSVRTIFAtVkFMVUU8MC4wNS4gVEhFTiBJIENBTiBTQVkgVEhBVCBUSEUgQU5OVUFMICUgSU4gVEhFIEVYQ0hBTkdFIFJBVEUgSVMgUE9TSVRJVkVMWSBBTkQgU0lHTklGSUNBTlRMWSBSRUxBVEVEIFdJVEggSVRTIE9XTiBBTk5VQUwgJSBDSEFOR0UgT0YgVEhFIFBSRVZJT1VTIE1PTlRIUy4gSU4gT1RIRVIgV09SRFMsIEZPUiBFQUNIIDElIElOQ1JFQVNFIElOIEFOTlVBTCAlIEdST1dUSCBPRiBUSEUgUFJFVklPVVMgTU9OVEgsIFRIRSBDVVJSRU5UIEFOTlVBTCAlIENIQU5HRSBJTiBFWENIQU5HRSBSQVRFUyBJUyBFWFBFQ1RFRCBUTyBHUk9XIElOIEFCT1VUIDAuOTQwOTUyNTMlLgoKVEhFIENPTlNUQU5UIFBISTAgKE9GIERSSUZUKSBJUyBQT1NJVElWRSBCVVQgSVNOJ1QgUkVBTExZIFNJR05JRklDQU5ULiBUSElTIE1FQU5TIFRIQVQgVEhFIEFOTlVBTCAlIENIQU5HRSBJTiBSQVRFUyBPRiBUSEUgTUVYSUNBTiBQRVNPIEFSRSBTTElHSFRMWSBHUk9XSU5HIE9WRVIgVElNRSBXSVRIIEFOIEFWRVJBR0UgQU5OVUFMIEdST1dUSCBPRiAwLjAwMzE3NTE4JSAoSVQgSEFTIEEgR1JPV0lORyBURU5ERU5DWSkuIAoKSU5URVJQUkVUQVRJT04gb2YgdGhlIFNlYXNvbmFsIE1BIHRlcm06ClRIRSBBTk5VQUwgJSBDSEFOR0UgSU4gUkFURVMgT0YgVEhFIE1FWElDQU4gUEVTTyBJUyBORUdBVElWRUxZIFJFTEFURUQgVE8gVEhFIFNIT0NLIChFUlJPUikgT0YgMTIgTU9OVEhTIEFHTy4gV0hFTiBUSEUgU0hPQ0sgSVMgTkVHQVRJVkUgMTIgTU9OVEhTIEFHTywgSVQgSVMgRVhQRUNURUQgVEhBVCBUSEUgQU5OVUFMICUgQ0hBTkdFIElOIFJBVEVTIE9GIFRIRSBDVVJSRU5UIE1PTlRIIFdJTEwgQkUgUE9TSVRJVkUuCgojIyBGb3JlY2FzdCBmb3IgdGhlIEV4Y2hhbmdlIFJhdGUKCkV4cGFuZCB0aGUgZGF0YXNldCAyMSBtb250aHMgKHVwIHRvIERlYyAyMDIzKSwgYW5kIGRvIGEgZm9yZWNhc3QgZm9yIHRoZSBleGNoYW5nZSByYXRlLiBXaGF0IGlzIHRoZSBleHBlY3RlZCBleGNoYW5nZSByYXRlIGluIERlYyAyMDIzPyBEbyBhIHBsb3QgZm9yIHRoZSBleGNoYW5nZSByYXRlIGFuZCB0aGUgZm9yZWNhc3RlZCByYXRlCgpXSVRIIFRISVMgTU9ERUwgSSBTSEFMTCBETyBBIEZPUkVDQVNUIEZPUiBDSEFOR0UgSU4gVEhFIE1FWElDQU4gUEVTTyBFWENIQU5HRSBSQVRFIEZPUiBUSEUgTkVYVCAyMSBNT05USFMuIEZPUiBUSEUgTEFTVCBNT0RFTCBJIFdJTEwgQ09OVkVSVCBUSEUgT1JJR0lOQUwgVkFSSUFCTEUgVE8gQSBUUyBSIE9CSkVDVCBUTyBIQVZFIEEgQkVUVEVSIFZJU1VBTElaQVRJT04gT0YgVEhFIEZPUkVDQVNUOgoKYGBge3J9Cm1leHJhdGUudHMgPC0gdHMoY29yZWRhdGEobWV4cmF0ZSksc3RhcnQ9YygyMDAwLDEpLGZyZXF1ZW5jeT0xMikKbW9kZWwyIDwtIEFyaW1hKG1leHJhdGUudHMsIG9yZGVyID0gYygxLDAsMCksCnNlYXNvbmFsID0gbGlzdChvcmRlcj1jKDAsMSwxKSxwZXJpb2Q9MTIpLAppbmNsdWRlLmNvbnN0YW50ID0gVFJVRSwKbGFtYmRhID0gMCkKZm9yZWNhc3RfbWV4cmF0ZSA8LSBmb3JlY2FzdChtb2RlbDIsIGg9MjEpCmF1dG9wbG90KGZvcmVjYXN0X21leHJhdGUpCmBgYAoKV0UgQ0FOIFNFRSBUSEUgRk9SRUNBU1QgRk9SIFRIRSBNRVhJQ0FOIFBFU08gRVhDSEFOR0UgUkFURSwgV0hJQ0ggSVMgU1RPUkVEIEFTIEFOIEFUVFJJQlVURSBJTiBUSEUgRk9SRUNBU1RfTUVYUkFURSBPQkpFQ1Q6CgpgYGB7cn0KZm9yZWNhc3RfbWV4cmF0ZSRtZWFuCmBgYAoKVEhFIEVYQ0hBTkdFIFJBVEUgRk9SIFRIRSBNRVhJQ0FOIFBFU08gRVhQRUNURUQgRk9SIERFQ0VNQkVSIDIwMjMgV0lMTCBTSVQgQVQgVEhFICQyMi4yNzgyNSBNQVJLLiBBUyBTRUVOIElOIFRIRSBQTE9ULCBUSEUgVFJFTkQgSVMgRVhQRUNURUQgVE8gR08gVVBXQVJEUyBXSVRIIEEgQ09VUExFIE9GIERPV05XQVJEIFRSRU5EUyBGT1IgSlVMWSBBTkQgQVVHVVNUIDIwMjIuIAoKVGhhbmsgeW91