Analýza makroekonomických ukazovateľov

Úvod do problému, stanovenie hypotéz

Rozhodla som sa modelovať hodnotu akciového indexu (Stock Index Value) v závislosti od makroekonomických premenných: inflácie (Inflation Rate (%)), rastu HDP (GDP Growth Rate (%)), nezamestnanosti (Unemployment Rate (%)), a úrokovej sadzby (Interest Rate (%)).

Pracovná hypotéza predpokladá:

  • Inflation Rate (%) – negatívny vplyv na akciový index.

  • GDP Growth Rate (%) – pozitívny vplyv.

  • Unemployment Rate (%) – negatívny vplyv.

  • Interest Rate (%) – negatívny vplyv.

Cieľom analýzy je overiť, ktoré premenné štatisticky významne ovplyvňujú Stock Index Value a posúdiť vhodnosť lineárneho regresného modelu.

Načítanie knižníc

library(zoo)
library(tseries)
library(lmtest)
library(sandwich)
library(car)
library(carData)
library(cowplot)
library(ggplot2)
rm(list=ls())

Načitanie dát

data <- read.csv("economic_indicators_dataset_2010_2023.csv")

Výber premennych

macro <- data[, c("Inflation.Rate....",
                  "GDP.Growth.Rate....",
                  "Unemployment.Rate....",
                  "Interest.Rate....",
                  "Stock.Index.Value")]

summary(macro)
 Inflation.Rate.... GDP.Growth.Rate.... Unemployment.Rate.... Interest.Rate.... Stock.Index.Value
 Min.   :0.000      Min.   :-5.000      Min.   : 2.000        Min.   :-0.980    Min.   : 1017    
 1st Qu.:2.525      1st Qu.:-1.170      1st Qu.: 4.258        1st Qu.: 2.027    1st Qu.:11588    
 Median :5.205      Median : 2.580      Median : 6.865        Median : 4.975    Median :20996    
 Mean   :5.085      Mean   : 2.415      Mean   : 6.907        Mean   : 4.698    Mean   :20926    
 3rd Qu.:7.710      3rd Qu.: 5.445      3rd Qu.: 9.502        3rd Qu.: 7.353    3rd Qu.:30825    
 Max.   :9.990      Max.   : 9.930      Max.   :11.970        Max.   :10.000    Max.   :39982    

Imputácia mediánov

column_medians <- sapply(macro, median, na.rm = TRUE)

macro_imp <- macro
for (col in names(macro)) {
  macro_imp[[col]][is.na(macro_imp[[col]])] <- column_medians[col]
}

macro <- macro_imp

Boxploty

num_plots <- length(names(macro))
par(mfrow = c(2, 3))
par(mar = c(4, 4, 2, 1))

for (col in names(macro)) {
  boxplot(macro[[col]], main = col, xlab = "Hodnota", col = "lightblue")
}

mtext("Boxploty makroekonomických premenných", outer = TRUE, cex = 1.4, font = 2)
par(mfrow = c(1, 1))

Teraz sme:

  • Skontrolovali štruktúru dát.

  • Vybrali relevantné premenné.

  • Doplnili chýbajúce hodnoty mediánmi.

  • Vykreslili boxploty pre jednotlivé premenné, aby sme identifikovali potenciálne odľahlé hodnoty.

Pozorovania ukázali, že väčšina dát je v očakávanom rozsahu. Inflácia a úroková sadzba majú mierne rozšírené rozptýlenie, ale nie je extrémne.

Lineárna regresia – model 1

model <- lm(Stock.Index.Value ~ Inflation.Rate.... +
              GDP.Growth.Rate.... +
              Unemployment.Rate.... +
              Interest.Rate....,
            data = macro)

summary(model)

Call:
lm(formula = Stock.Index.Value ~ Inflation.Rate.... + GDP.Growth.Rate.... + 
    Unemployment.Rate.... + Interest.Rate...., data = macro)

Residuals:
     Min       1Q   Median       3Q      Max 
-20623.1  -9434.3    104.2   9972.6  19610.5 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)    
(Intercept)           23055.78    1678.73  13.734   <2e-16 ***
Inflation.Rate....      -37.23     167.90  -0.222    0.825    
GDP.Growth.Rate....     -26.39     121.94  -0.216    0.829    
Unemployment.Rate....  -152.38     166.52  -0.915    0.361    
Interest.Rate....      -175.40     157.57  -1.113    0.266    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 11090 on 495 degrees of freedom
Multiple R-squared:  0.00455,   Adjusted R-squared:  -0.003494 
F-statistic: 0.5656 on 4 and 495 DF,  p-value: 0.6877

Lineárny model odhadovaný pre Stock Index Value na základe premenných Inflation Rate, GDP Growth Rate, Unemployment Rate a Interest Rate ukazuje, že žiadna z vysvetľujúcich premenných nie je štatisticky významná. Intercept je vysoko významný, ale všetky koeficienty ostatných premenných majú p-hodnoty výrazne vyššie ako 0,05. Hodnota R-squared je extrémne nízka (0,00455), čo naznačuje, že model nevysvetľuje variabilitu Stock Index Value.

Reziduá modelu sa pohybujú približne medzi −20623 a +19610 a ich medián je veľmi blízko nule, čo naznačuje stredné centrovanie reziduí.

Diagnostické grafy pre model 1

par(mfrow = c(2, 2))
plot(model)
mtext("Diagnostické grafy regresného modelu", outer = TRUE, cex = 1.2, font = 2)
par(mfrow = c(1, 1))

Residuals vs Fitted

  • Väčšina reziduí je rozptýlená okolo nuly bez výrazného systematického skreslenia, aj keď vidíme niektoré extrémne body.

Q-Q plot

  • Reziduá sú približne normálne rozložené, hoci na okrajoch grafu možno pozorovať mierne odchýlky – niekoľko extrémnych hodnôt.

Scale-Location

  • Variancia reziduí je relatívne stabilná; nie sú výrazné známky heteroskedasticity.

Residuals vs Leverage

  • Väčšina bodov má nízku páku a štandardizované reziduá sa pohybujú medzi −2 a +2. Žiadne pozorovanie nevybočuje výrazne z Cookovej vzdialenosti.

Jarque–Bera test normality

residuals_model <- residuals(model)
jb_test <- jarque.bera.test(residuals_model)
jb_test

    Jarque Bera Test

data:  residuals_model
X-squared = 26.622, df = 2, p-value = 1.656e-06

Hodnota testu JB = 26,622 s p-hodnotou 1,656e-06 naznačuje, že reziduá nie sú úplne normálne rozložené. Odchýlky môžu byť spôsobené extrémnymi hodnotami alebo špičatými rozdeleniami.

Outlier test

outlier_test <- outlierTest(model)
outlier_test
No Studentized residuals with Bonferroni p < 0.05
Largest |rstudent|:

Jedno pozorovanie bolo označené ako potenciálny odľahlý bod (rstudent = −1,8766), ale p-hodnota po Bonferroni korekcii nie je k dispozícii. Tento bod môže mierne ovplyvniť odhad koeficientov.

Heteroskedasticita – grafy pre model 1

p1 <- ggplot(macro, aes(x = GDP.Growth.Rate...., y = resid(model)^2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "GDP Growth (%)",
       y = "Reziduá²",
       title = "Reziduá² vs GDP Growth") +
  theme_minimal()

p2 <- ggplot(macro, aes(x = Inflation.Rate...., y = resid(model)^2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "Inflation Rate (%)",
       y = "Reziduá²",
       title = "Reziduá² vs Inflation") +
  theme_minimal()

plot_grid(p1, p2)

Na grafoch “Reziduá vs GDP Growth” a “Reziduá vs Inflation” môžeme pozorovať, že ružová vyhladená krivka zostáva relatívne plochá a rozptyl reziduí sa s hodnotami premenných výrazne nemení. Menšie kolísanie naznačuje len slabé náznaky heteroskedasticity, ktoré však nie sú výrazné. Celkovo možno teda usúdiť, že v modeli sa heteroskedasticita výrazne nevyskytuje a rozptyl náhodnej zložky zostáva približne konštantný.

Oprava modelu (model 2) + vylúčenie problem

shift <- abs(min(macro$GDP.Growth.Rate...., na.rm = TRUE)) + 0.01

model2 <- lm(Stock.Index.Value ~
               I(log(GDP.Growth.Rate.... + shift)) +
               Unemployment.Rate.... +
               Interest.Rate....,
             data = macro)

summary(model2)

Call:
lm(formula = Stock.Index.Value ~ I(log(GDP.Growth.Rate.... + 
    shift)) + Unemployment.Rate.... + Interest.Rate...., data = macro)

Residuals:
     Min       1Q   Median       3Q      Max 
-20968.9  -9345.4    -62.7   9908.4  19840.0 

Coefficients:
                                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)                          23669.9     1683.6  14.059   <2e-16 ***
I(log(GDP.Growth.Rate.... + shift))   -517.9      533.4  -0.971    0.332    
Unemployment.Rate....                 -148.3      166.2  -0.892    0.373    
Interest.Rate....                     -174.3      157.2  -1.109    0.268    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 11060 on 496 degrees of freedom
Multiple R-squared:  0.006244,  Adjusted R-squared:  0.0002336 
F-statistic: 1.039 on 3 and 496 DF,  p-value: 0.375

Po logaritmickej transformácii GDP Growth Rate a odstránení Inflation Rate model ukazuje podobný obraz: žiadna z premenných (okrem interceptu) nie je štatisticky významná. Koeficienty sú stále nízke a p-hodnoty vyššie než 0,05. R-squared je veľmi nízke (0,0062), čo znamená, že model stále nevysvetľuje variabilitu Stock Index Value.

Reziduá sú podobne rozptýlené a medián je blízko nuly.

Diagnostické grafy pre model 2

par(mfrow = c(2, 2))
plot(model2)
mtext("Diagnostické grafy - Model 2 (log GDP)", outer = TRUE, cex = 1.2, font = 2)
par(mfrow = c(1, 1))

Residuals vs Fitted

  • Podobne ako pri model 1, reziduá sú rozptýlené okolo nuly, bez výrazných systematických odchýlok.

Q-Q plot

  • Reziduá sú približne normálne rozložené, mierne odchýlky na okrajoch.

Scale-Location

  • Variancia reziduí je stabilná, nenaznačuje heteroskedasticitu.

Residuals vs Leverage

  • Väčšina bodov má nízku páku, žiadne výrazne ovplyvňujúce pozorovanie.

Heteroskedasticita – grafy pre model 2

p3 <- ggplot(macro, aes(x = log(GDP.Growth.Rate.... + 1), y = resid(model2)^2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "log(GDP Growth)",
       y = "Reziduá²",
       title = "Reziduá² vs log(GDP Growth)") +
  theme_minimal()

p4 <- ggplot(macro, aes(x = Unemployment.Rate...., y = resid(model2)^2)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE, color = "red") +
  labs(x = "Unemployment Rate (%)",
       y = "Reziduá²",
       title = "Reziduá² vs Unemployment") +
  theme_minimal()

plot_grid(p3, p4)

Po logaritmickej transformácii premennej GDP Growth sa ružová krivka vyrovnala a rozptyl reziduí sa stal rovnomernejším, čo naznačuje, že transformácia znížila heteroskedasticitu. Premenná Unemployment Rate nevykazuje viditeľné známky heteroskedasticity, takže celkovo možno povedať, že nový model má stabilnejší rozptyl reziduí a lepšiu štruktúru ako pôvodný.

Breusch-Pagan test pre model 1 aj model 2

bptest(model)

    studentized Breusch-Pagan test

data:  model
BP = 2.9462, df = 4, p-value = 0.5669
bptest(model2)

    studentized Breusch-Pagan test

data:  model2
BP = 2.3352, df = 3, p-value = 0.5058
  • Pre model 1: BP = 2,9462, p = 0,5669
  • Pre model 2: BP = 2,3352, p = 0,5058

Výsledky Breusch–Paganovho testu pre model 1 (p = 0.5669) aj model 2 (p = 0.5058) naznačujú, že nemáme dostatok dôkazov na zamietnutie nulovej hypotézy homoskedasticity. Rozptyl rezíduí sa javí ako približne konštantný a nevykazuje systematickú závislosť od vysvetľujúcich premenných.

Z toho možno konštatovať, že reziduá oboch modelov spĺňajú predpoklad homoskedasticity, čo indikuje, že odhady regresných koeficientov sú efektívne a nie je potrebné aplikovať korekcie na heteroskedasticitu.

LS0tDQp0aXRsZTogIsOabG9oYV82Ig0KYXV0aG9yOiAiWXVsaWlhIEx5c3l0c2lhIg0KZGF0ZTogIk5vdmVtYmVyIDIwMjUiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdGhlbWU6IHVuaXRlZA0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgcGRmX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KZWRpdG9yX29wdGlvbnM6DQogIG1hcmtkb3duOg0KICAgIHdyYXA6IDcyDQotLS0NCg0KIyBBbmFsw716YSBtYWtyb2Vrb25vbWlja8O9Y2ggdWthem92YXRlxL5vdg0KDQojIyDDmnZvZCBkbyBwcm9ibMOpbXUsIHN0YW5vdmVuaWUgaHlwb3TDqXoNCg0KUm96aG9kbGEgc29tIHNhIG1vZGVsb3ZhxaUgaG9kbm90dSBha2Npb3bDqWhvIGluZGV4dSAoU3RvY2sgSW5kZXggVmFsdWUpIHYgesOhdmlzbG9zdGkgb2QgbWFrcm9la29ub21pY2vDvWNoIHByZW1lbm7DvWNoOiBpbmZsw6FjaWUgKEluZmxhdGlvbiBSYXRlICglKSksIHJhc3R1IEhEUCAoR0RQIEdyb3d0aCBSYXRlICglKSksIG5lemFtZXN0bmFub3N0aSAoVW5lbXBsb3ltZW50IFJhdGUgKCUpKSwgYSDDunJva292ZWogc2FkemJ5IChJbnRlcmVzdCBSYXRlICglKSkuDQoNClByYWNvdm7DoSBoeXBvdMOpemEgcHJlZHBva2xhZMOhOg0KDQotIEluZmxhdGlvbiBSYXRlICglKSDigJMgbmVnYXTDrXZueSB2cGx5diBuYSBha2Npb3bDvSBpbmRleC4NCg0KLSBHRFAgR3Jvd3RoIFJhdGUgKCUpIOKAkyBwb3ppdMOtdm55IHZwbHl2Lg0KDQotIFVuZW1wbG95bWVudCBSYXRlICglKSDigJMgbmVnYXTDrXZueSB2cGx5di4NCg0KLSBJbnRlcmVzdCBSYXRlICglKSDigJMgbmVnYXTDrXZueSB2cGx5di4NCg0KQ2llxL5vbSBhbmFsw716eSBqZSBvdmVyacWlLCBrdG9yw6kgcHJlbWVubsOpIMWhdGF0aXN0aWNreSB2w716bmFtbmUgb3ZwbHl2xYh1asO6IFN0b2NrIEluZGV4IFZhbHVlIGEgcG9zw7pkacWlIHZob2Rub3PFpSBsaW5lw6FybmVobyByZWdyZXNuw6lobyBtb2RlbHUuDQoNCiMjIE5hxI3DrXRhbmllIGtuacW+bsOtYw0KDQpgYGB7cn0NCmxpYnJhcnkoem9vKQ0KbGlicmFyeSh0c2VyaWVzKQ0KbGlicmFyeShsbXRlc3QpDQpsaWJyYXJ5KHNhbmR3aWNoKQ0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KGNhckRhdGEpDQpsaWJyYXJ5KGNvd3Bsb3QpDQpsaWJyYXJ5KGdncGxvdDIpDQpybShsaXN0PWxzKCkpDQpgYGANCg0KIyMgTmHEjWl0YW5pZSBkw6F0DQoNCmBgYHtyfQ0KZGF0YSA8LSByZWFkLmNzdigiZWNvbm9taWNfaW5kaWNhdG9yc19kYXRhc2V0XzIwMTBfMjAyMy5jc3YiKQ0KYGBgDQoNCiMjIFbDvWJlciBwcmVtZW5ueWNoDQoNCmBgYHtyfQ0KbWFjcm8gPC0gZGF0YVssIGMoIkluZmxhdGlvbi5SYXRlLi4uLiIsDQogICAgICAgICAgICAgICAgICAiR0RQLkdyb3d0aC5SYXRlLi4uLiIsDQogICAgICAgICAgICAgICAgICAiVW5lbXBsb3ltZW50LlJhdGUuLi4uIiwNCiAgICAgICAgICAgICAgICAgICJJbnRlcmVzdC5SYXRlLi4uLiIsDQogICAgICAgICAgICAgICAgICAiU3RvY2suSW5kZXguVmFsdWUiKV0NCg0Kc3VtbWFyeShtYWNybykNCmBgYA0KDQojIyBJbXB1dMOhY2lhIG1lZGnDoW5vdg0KDQpgYGB7cn0NCmNvbHVtbl9tZWRpYW5zIDwtIHNhcHBseShtYWNybywgbWVkaWFuLCBuYS5ybSA9IFRSVUUpDQoNCm1hY3JvX2ltcCA8LSBtYWNybw0KZm9yIChjb2wgaW4gbmFtZXMobWFjcm8pKSB7DQogIG1hY3JvX2ltcFtbY29sXV1baXMubmEobWFjcm9faW1wW1tjb2xdXSldIDwtIGNvbHVtbl9tZWRpYW5zW2NvbF0NCn0NCg0KbWFjcm8gPC0gbWFjcm9faW1wDQpgYGANCg0KIyMgQm94cGxvdHkNCg0KYGBge3J9DQpudW1fcGxvdHMgPC0gbGVuZ3RoKG5hbWVzKG1hY3JvKSkNCnBhcihtZnJvdyA9IGMoMiwgMykpDQpwYXIobWFyID0gYyg0LCA0LCAyLCAxKSkNCg0KZm9yIChjb2wgaW4gbmFtZXMobWFjcm8pKSB7DQogIGJveHBsb3QobWFjcm9bW2NvbF1dLCBtYWluID0gY29sLCB4bGFiID0gIkhvZG5vdGEiLCBjb2wgPSAibGlnaHRibHVlIikNCn0NCg0KbXRleHQoIkJveHBsb3R5IG1ha3JvZWtvbm9taWNrw71jaCBwcmVtZW5uw71jaCIsIG91dGVyID0gVFJVRSwgY2V4ID0gMS40LCBmb250ID0gMikNCnBhcihtZnJvdyA9IGMoMSwgMSkpDQpgYGANClRlcmF6IHNtZToNCg0KLSBTa29udHJvbG92YWxpIMWhdHJ1a3TDunJ1IGTDoXQuDQoNCi0gVnlicmFsaSByZWxldmFudG7DqSBwcmVtZW5uw6kuDQoNCi0gRG9wbG5pbGkgY2jDvWJhasO6Y2UgaG9kbm90eSBtZWRpw6FubWkuDQoNCi0gVnlrcmVzbGlsaSBib3hwbG90eSBwcmUgamVkbm90bGl2w6kgcHJlbWVubsOpLCBhYnkgc21lIGlkZW50aWZpa292YWxpIHBvdGVuY2nDoWxuZSBvZMS+YWhsw6kgaG9kbm90eS4NCg0KUG96b3JvdmFuaWEgdWvDoXphbGksIMW+ZSB2w6TEjcWhaW5hIGTDoXQgamUgdiBvxI1ha8OhdmFub20gcm96c2FodS4gSW5mbMOhY2lhIGEgw7pyb2tvdsOhIHNhZHpiYSBtYWrDuiBtaWVybmUgcm96xaHDrXJlbsOpIHJvenB0w71sZW5pZSwgYWxlIG5pZSBqZSBleHRyw6ltbmUuDQoNCiMjIExpbmXDoXJuYSByZWdyZXNpYSDigJMgbW9kZWwgMQ0KDQpgYGB7cn0NCm1vZGVsIDwtIGxtKFN0b2NrLkluZGV4LlZhbHVlIH4gSW5mbGF0aW9uLlJhdGUuLi4uICsNCiAgICAgICAgICAgICAgR0RQLkdyb3d0aC5SYXRlLi4uLiArDQogICAgICAgICAgICAgIFVuZW1wbG95bWVudC5SYXRlLi4uLiArDQogICAgICAgICAgICAgIEludGVyZXN0LlJhdGUuLi4uLA0KICAgICAgICAgICAgZGF0YSA9IG1hY3JvKQ0KDQpzdW1tYXJ5KG1vZGVsKQ0KYGBgDQpMaW5lw6FybnkgbW9kZWwgb2RoYWRvdmFuw70gcHJlIFN0b2NrIEluZGV4IFZhbHVlIG5hIHrDoWtsYWRlIHByZW1lbm7DvWNoIEluZmxhdGlvbiBSYXRlLCBHRFAgR3Jvd3RoIFJhdGUsIFVuZW1wbG95bWVudCBSYXRlIGEgSW50ZXJlc3QgUmF0ZSB1a2F6dWplLCDFvmUgxb5pYWRuYSB6IHZ5c3ZldMS+dWrDumNpY2ggcHJlbWVubsO9Y2ggbmllIGplIMWhdGF0aXN0aWNreSB2w716bmFtbsOhLiBJbnRlcmNlcHQgamUgdnlzb2tvIHbDvXpuYW1uw70sIGFsZSB2xaFldGt5IGtvZWZpY2llbnR5IG9zdGF0bsO9Y2ggcHJlbWVubsO9Y2ggbWFqw7ogcC1ob2Rub3R5IHbDvXJhem5lIHZ5xaHFoWllIGFrbyAwLDA1LiBIb2Rub3RhIFItc3F1YXJlZCBqZSBleHRyw6ltbmUgbsOtemthICgwLDAwNDU1KSwgxI1vIG5hem5hxI11amUsIMW+ZSBtb2RlbCBuZXZ5c3ZldMS+dWplIHZhcmlhYmlsaXR1IFN0b2NrIEluZGV4IFZhbHVlLg0KDQpSZXppZHXDoSBtb2RlbHUgc2EgcG9oeWJ1asO6IHByaWJsacW+bmUgbWVkemkg4oiSMjA2MjMgYSArMTk2MTAgYSBpY2ggbWVkacOhbiBqZSB2ZcS+bWkgYmzDrXprbyBudWxlLCDEjW8gbmF6bmHEjXVqZSBzdHJlZG7DqSBjZW50cm92YW5pZSByZXppZHXDrS4NCg0KIyMgRGlhZ25vc3RpY2vDqSBncmFmeSBwcmUgbW9kZWwgMQ0KDQpgYGB7cn0NCnBhcihtZnJvdyA9IGMoMiwgMikpDQpwbG90KG1vZGVsKQ0KbXRleHQoIkRpYWdub3N0aWNrw6kgZ3JhZnkgcmVncmVzbsOpaG8gbW9kZWx1Iiwgb3V0ZXIgPSBUUlVFLCBjZXggPSAxLjIsIGZvbnQgPSAyKQ0KcGFyKG1mcm93ID0gYygxLCAxKSkNCmBgYA0KDQojIyMjIFJlc2lkdWFscyB2cyBGaXR0ZWQNCg0KLSBWw6TEjcWhaW5hIHJlemlkdcOtIGplIHJvenB0w71sZW7DoSBva29sbyBudWx5IGJleiB2w71yYXpuw6lobyBzeXN0ZW1hdGlja8OpaG8gc2tyZXNsZW5pYSwgYWoga2XEjyB2aWTDrW1lIG5pZWt0b3LDqSBleHRyw6ltbmUgYm9keS4NCg0KIyMjIyBRLVEgcGxvdCANCg0KLSBSZXppZHXDoSBzw7ogcHJpYmxpxb5uZSBub3Jtw6FsbmUgcm96bG/FvmVuw6ksIGhvY2kgbmEgb2tyYWpvY2ggZ3JhZnUgbW/Fvm5vIHBvem9yb3ZhxaUgbWllcm5lIG9kY2jDvWxreSDigJMgbmlla2/EvmtvIGV4dHLDqW1ueWNoIGhvZG7DtHQuDQoNCiMjIyMgU2NhbGUtTG9jYXRpb24NCg0KLSBWYXJpYW5jaWEgcmV6aWR1w60gamUgcmVsYXTDrXZuZSBzdGFiaWxuw6E7IG5pZSBzw7ogdsO9cmF6bsOpIHpuw6Fta3kgaGV0ZXJvc2tlZGFzdGljaXR5Lg0KDQojIyMjIFJlc2lkdWFscyB2cyBMZXZlcmFnZQ0KDQotIFbDpMSNxaFpbmEgYm9kb3YgbcOhIG7DrXprdSBww6FrdSBhIMWhdGFuZGFyZGl6b3ZhbsOpIHJlemlkdcOhIHNhIHBvaHlidWrDuiBtZWR6aSDiiJIyIGEgKzIuIMW9aWFkbmUgcG96b3JvdmFuaWUgbmV2eWJvxI11amUgdsO9cmF6bmUgeiBDb29rb3ZlaiB2emRpYWxlbm9zdGkuDQoNCiMjIEphcnF1ZeKAk0JlcmEgdGVzdCBub3JtYWxpdHkNCg0KYGBge3J9DQpyZXNpZHVhbHNfbW9kZWwgPC0gcmVzaWR1YWxzKG1vZGVsKQ0KamJfdGVzdCA8LSBqYXJxdWUuYmVyYS50ZXN0KHJlc2lkdWFsc19tb2RlbCkNCmpiX3Rlc3QNCmBgYA0KSG9kbm90YSB0ZXN0dSBKQiA9IDI2LDYyMiBzIHAtaG9kbm90b3UgMSw2NTZlLTA2IG5hem5hxI11amUsIMW+ZSByZXppZHXDoSBuaWUgc8O6IMO6cGxuZSBub3Jtw6FsbmUgcm96bG/FvmVuw6kuIE9kY2jDvWxreSBtw7TFvnUgYnnFpSBzcMO0c29iZW7DqSBleHRyw6ltbnltaSBob2Rub3RhbWkgYWxlYm8gxaFwacSNYXTDvW1pIHJvemRlbGVuaWFtaS4NCg0KIyMgT3V0bGllciB0ZXN0DQoNCmBgYHtyfQ0Kb3V0bGllcl90ZXN0IDwtIG91dGxpZXJUZXN0KG1vZGVsKQ0Kb3V0bGllcl90ZXN0DQpgYGANCg0KSmVkbm8gcG96b3JvdmFuaWUgYm9sbyBvem5hxI1lbsOpIGFrbyBwb3RlbmNpw6Fsbnkgb2TEvmFobMO9IGJvZCAocnN0dWRlbnQgPSDiiJIxLDg3NjYpLCBhbGUgcC1ob2Rub3RhIHBvIEJvbmZlcnJvbmkga29yZWtjaWkgbmllIGplIGsgZGlzcG96w61jaWkuIFRlbnRvIGJvZCBtw7TFvmUgbWllcm5lIG92cGx5dm5pxaUgb2RoYWQga29lZmljaWVudG92Lg0KDQojIyBIZXRlcm9za2VkYXN0aWNpdGEg4oCTIGdyYWZ5IHByZSBtb2RlbCAxDQoNCmBgYHtyfQ0KcDEgPC0gZ2dwbG90KG1hY3JvLCBhZXMoeCA9IEdEUC5Hcm93dGguUmF0ZS4uLi4sIHkgPSByZXNpZChtb2RlbCleMikpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQiKSArDQogIGxhYnMoeCA9ICJHRFAgR3Jvd3RoICglKSIsDQogICAgICAgeSA9ICJSZXppZHXDocKyIiwNCiAgICAgICB0aXRsZSA9ICJSZXppZHXDocKyIHZzIEdEUCBHcm93dGgiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpwMiA8LSBnZ3Bsb3QobWFjcm8sIGFlcyh4ID0gSW5mbGF0aW9uLlJhdGUuLi4uLCB5ID0gcmVzaWQobW9kZWwpXjIpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHggPSAiSW5mbGF0aW9uIFJhdGUgKCUpIiwNCiAgICAgICB5ID0gIlJlemlkdcOhwrIiLA0KICAgICAgIHRpdGxlID0gIlJlemlkdcOhwrIgdnMgSW5mbGF0aW9uIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KcGxvdF9ncmlkKHAxLCBwMikNCmBgYA0KTmEgZ3JhZm9jaCAiUmV6aWR1w6EgdnMgR0RQIEdyb3d0aCIgYSAiUmV6aWR1w6EgdnMgSW5mbGF0aW9uIiBtw7TFvmVtZSBwb3pvcm92YcWlLCDFvmUgcnXFvm92w6EgdnlobGFkZW7DoSBrcml2a2Egem9zdMOhdmEgcmVsYXTDrXZuZSBwbG9jaMOhIGEgcm96cHR5bCByZXppZHXDrSBzYSBzIGhvZG5vdGFtaSBwcmVtZW5uw71jaCB2w71yYXpuZSBuZW1lbsOtLiBNZW7FoWllIGtvbMOtc2FuaWUgbmF6bmHEjXVqZSBsZW4gc2xhYsOpIG7DoXpuYWt5IGhldGVyb3NrZWRhc3RpY2l0eSwga3RvcsOpIHbFoWFrIG5pZSBzw7ogdsO9cmF6bsOpLiBDZWxrb3ZvIG1vxb5ubyB0ZWRhIHVzw7pkacWlLCDFvmUgdiBtb2RlbGkgc2EgaGV0ZXJvc2tlZGFzdGljaXRhIHbDvXJhem5lIG5ldnlza3l0dWplIGEgcm96cHR5bCBuw6Fob2RuZWogemxvxb5reSB6b3N0w6F2YSBwcmlibGnFvm5lIGtvbsWhdGFudG7DvS4NCg0KIyMgT3ByYXZhIG1vZGVsdSAobW9kZWwgMikgKyB2eWzDusSNZW5pZSBwcm9ibGVtDQoNCmBgYHtyfQ0Kc2hpZnQgPC0gYWJzKG1pbihtYWNybyRHRFAuR3Jvd3RoLlJhdGUuLi4uLCBuYS5ybSA9IFRSVUUpKSArIDAuMDENCg0KbW9kZWwyIDwtIGxtKFN0b2NrLkluZGV4LlZhbHVlIH4NCiAgICAgICAgICAgICAgIEkobG9nKEdEUC5Hcm93dGguUmF0ZS4uLi4gKyBzaGlmdCkpICsNCiAgICAgICAgICAgICAgIFVuZW1wbG95bWVudC5SYXRlLi4uLiArDQogICAgICAgICAgICAgICBJbnRlcmVzdC5SYXRlLi4uLiwNCiAgICAgICAgICAgICBkYXRhID0gbWFjcm8pDQoNCnN1bW1hcnkobW9kZWwyKQ0KYGBgDQpQbyBsb2dhcml0bWlja2VqIHRyYW5zZm9ybcOhY2lpIEdEUCBHcm93dGggUmF0ZSBhIG9kc3Ryw6FuZW7DrSBJbmZsYXRpb24gUmF0ZSBtb2RlbCB1a2F6dWplIHBvZG9ibsO9IG9icmF6OiDFvmlhZG5hIHogcHJlbWVubsO9Y2ggKG9rcmVtIGludGVyY2VwdHUpIG5pZSBqZSDFoXRhdGlzdGlja3kgdsO9em5hbW7DoS4gS29lZmljaWVudHkgc8O6IHN0w6FsZSBuw616a2UgYSBwLWhvZG5vdHkgdnnFocWhaWUgbmXFviAwLDA1LiBSLXNxdWFyZWQgamUgdmXEvm1pIG7DrXprZSAoMCwwMDYyKSwgxI1vIHpuYW1lbsOhLCDFvmUgbW9kZWwgc3TDoWxlIG5ldnlzdmV0xL51amUgdmFyaWFiaWxpdHUgU3RvY2sgSW5kZXggVmFsdWUuDQoNClJlemlkdcOhIHPDuiBwb2RvYm5lIHJvenB0w71sZW7DqSBhIG1lZGnDoW4gamUgYmzDrXprbyBudWx5Lg0KDQojIyBEaWFnbm9zdGlja8OpIGdyYWZ5IHByZSBtb2RlbCAyDQoNCmBgYHtyfQ0KcGFyKG1mcm93ID0gYygyLCAyKSkNCnBsb3QobW9kZWwyKQ0KbXRleHQoIkRpYWdub3N0aWNrw6kgZ3JhZnkgLSBNb2RlbCAyIChsb2cgR0RQKSIsIG91dGVyID0gVFJVRSwgY2V4ID0gMS4yLCBmb250ID0gMikNCnBhcihtZnJvdyA9IGMoMSwgMSkpDQpgYGANCiMjIyMgUmVzaWR1YWxzIHZzIEZpdHRlZA0KDQotIFBvZG9ibmUgYWtvIHByaSBtb2RlbCAxLCByZXppZHXDoSBzw7ogcm96cHTDvWxlbsOpIG9rb2xvIG51bHksIGJleiB2w71yYXpuw71jaCBzeXN0ZW1hdGlja8O9Y2ggb2RjaMO9bG9rLg0KDQojIyMjIFEtUSBwbG90DQoNCi0gUmV6aWR1w6Egc8O6IHByaWJsacW+bmUgbm9ybcOhbG5lIHJvemxvxb5lbsOpLCBtaWVybmUgb2RjaMO9bGt5IG5hIG9rcmFqb2NoLg0KDQojIyMjIFNjYWxlLUxvY2F0aW9uDQoNCi0gVmFyaWFuY2lhIHJlemlkdcOtIGplIHN0YWJpbG7DoSwgbmVuYXpuYcSNdWplIGhldGVyb3NrZWRhc3RpY2l0dS4NCg0KIyMjIyBSZXNpZHVhbHMgdnMgTGV2ZXJhZ2UNCg0KLSBWw6TEjcWhaW5hIGJvZG92IG3DoSBuw616a3UgcMOha3UsIMW+aWFkbmUgdsO9cmF6bmUgb3ZwbHl2xYh1asO6Y2UgcG96b3JvdmFuaWUuDQoNCiMjIEhldGVyb3NrZWRhc3RpY2l0YSDigJMgZ3JhZnkgcHJlIG1vZGVsIDINCg0KYGBge3J9DQpwMyA8LSBnZ3Bsb3QobWFjcm8sIGFlcyh4ID0gbG9nKEdEUC5Hcm93dGguUmF0ZS4uLi4gKyAxKSwgeSA9IHJlc2lkKG1vZGVsMileMikpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQiKSArDQogIGxhYnMoeCA9ICJsb2coR0RQIEdyb3d0aCkiLA0KICAgICAgIHkgPSAiUmV6aWR1w6HCsiIsDQogICAgICAgdGl0bGUgPSAiUmV6aWR1w6HCsiB2cyBsb2coR0RQIEdyb3d0aCkiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpwNCA8LSBnZ3Bsb3QobWFjcm8sIGFlcyh4ID0gVW5lbXBsb3ltZW50LlJhdGUuLi4uLCB5ID0gcmVzaWQobW9kZWwyKV4yKSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC42KSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZCIpICsNCiAgbGFicyh4ID0gIlVuZW1wbG95bWVudCBSYXRlICglKSIsDQogICAgICAgeSA9ICJSZXppZHXDocKyIiwNCiAgICAgICB0aXRsZSA9ICJSZXppZHXDocKyIHZzIFVuZW1wbG95bWVudCIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCnBsb3RfZ3JpZChwMywgcDQpDQpgYGANClBvIGxvZ2FyaXRtaWNrZWogdHJhbnNmb3Jtw6FjaWkgcHJlbWVubmVqIEdEUCBHcm93dGggc2EgcnXFvm92w6Ega3JpdmthIHZ5cm92bmFsYSBhIHJvenB0eWwgcmV6aWR1w60gc2Egc3RhbCByb3Zub21lcm5lasWhw61tLCDEjW8gbmF6bmHEjXVqZSwgxb5lIHRyYW5zZm9ybcOhY2lhIHpuw63FvmlsYSBoZXRlcm9za2VkYXN0aWNpdHUuIA0KUHJlbWVubsOhIFVuZW1wbG95bWVudCBSYXRlIG5ldnlrYXp1amUgdmlkaXRlxL5uw6kgem7DoW1reSBoZXRlcm9za2VkYXN0aWNpdHksIHRha8W+ZSBjZWxrb3ZvIG1vxb5ubyBwb3ZlZGHFpSwgxb5lIG5vdsO9IG1vZGVsIG3DoSBzdGFiaWxuZWrFocOtIHJvenB0eWwgcmV6aWR1w60gYSBsZXDFoWl1IMWhdHJ1a3TDunJ1IGFrbyBww7R2b2Ruw70uDQoNCiMjIEJyZXVzY2gtUGFnYW4gdGVzdCBwcmUgbW9kZWwgMSBhaiBtb2RlbCAyDQoNCmBgYHtyfQ0KYnB0ZXN0KG1vZGVsKQ0KYnB0ZXN0KG1vZGVsMikNCmBgYA0KLSBQcmUgbW9kZWwgMTogQlAgPSAyLDk0NjIsIHAgPSAwLDU2NjkNCi0gUHJlIG1vZGVsIDI6IEJQID0gMiwzMzUyLCBwID0gMCw1MDU4DQoNClbDvXNsZWRreSBCcmV1c2No4oCTUGFnYW5vdmhvIHRlc3R1IHByZSBtb2RlbCAxIChwID0gMC41NjY5KSBhaiBtb2RlbCAyIChwID0gMC41MDU4KSBuYXpuYcSNdWrDuiwgxb5lIG5lbcOhbWUgZG9zdGF0b2sgZMO0a2F6b3YgbmEgemFtaWV0bnV0aWUgbnVsb3ZlaiBoeXBvdMOpenkgaG9tb3NrZWRhc3RpY2l0eS4gUm96cHR5bCByZXrDrWR1w60gc2EgamF2w60gYWtvIHByaWJsacW+bmUga29uxaF0YW50bsO9IGEgbmV2eWthenVqZSBzeXN0ZW1hdGlja8O6IHrDoXZpc2xvc8WlIG9kIHZ5c3ZldMS+dWrDumNpY2ggcHJlbWVubsO9Y2guDQoNClogdG9obyBtb8W+bm8ga29uxaF0YXRvdmHFpSwgxb5lIHJlemlkdcOhIG9ib2NoIG1vZGVsb3Ygc3DEusWIYWrDuiBwcmVkcG9rbGFkIGhvbW9za2VkYXN0aWNpdHksIMSNbyBpbmRpa3VqZSwgxb5lIG9kaGFkeSByZWdyZXNuw71jaCBrb2VmaWNpZW50b3Ygc8O6IGVmZWt0w612bmUgYSBuaWUgamUgcG90cmVibsOpIGFwbGlrb3ZhxaUga29yZWtjaWUgbmEgaGV0ZXJvc2tlZGFzdGljaXR1Lg0KDQoNCg0KDQoNCiA=