Cointegration

Hai chuỗi thời gian đồng tích hợp (Cointegrated Time Series) ngụ ý rằng tồn tại một số nguyên nhân gốc (underlying forces) làm cho hai chuỗi thời gian có xu hướng biến động tương đồng nhau về dài hạn ngay cả khi nếu nhìn riêng lẻ thì chúng là các bước đi ngẫu nhiên (random walks).

Hamilton (1994) đưa ra mô tả về chuỗi đồng tích hợp như sau:

\[ x_{t} = x_{t - 1} + u_{t}\] \[ y_{t} = \gamma*x_{t} + v_{t}\]

Trong đó \(u_{t}\)\(v_{t}\) tuân theo N(0, 1).

Chúng ta có thể mô phỏng và hình ảnh hóa chuỗi đồng tích hợp như sau:

# A function for black theme: 
my_theme <- function(...) {
  theme(
    axis.line = element_blank(),  
    axis.text.x = element_text(color = "white", lineheight = 0.9),  
    axis.text.y = element_text(color = "white", lineheight = 0.9),  
    axis.ticks = element_line(color = "white", size  =  0.2),  
    axis.title.x = element_text(color = "white", margin = margin(0, 10, 0, 0)),  
    axis.title.y = element_text(color = "white", angle = 90, margin = margin(0, 10, 0, 0)),  
    axis.ticks.length = unit(0.3, "lines"),   
    legend.background = element_rect(color = NA, fill = "gray10"),  
    legend.key = element_rect(color = "white",  fill = "gray10"),  
    legend.key.size = unit(1.2, "lines"),  
    legend.key.height = NULL,  
    legend.key.width = NULL,      
    legend.text = element_text(color = "white"),  
    legend.title = element_text(face = "bold", hjust = 0, color = "white"),  
    legend.text.align = NULL,  
    legend.title.align = NULL,  
    legend.direction = "vertical",  
    legend.box = NULL, 
    panel.background = element_rect(fill = "gray10", color  =  NA),  
    panel.border = element_blank(),
    panel.grid.major = element_line(color = "grey35"),  
    panel.grid.minor = element_line(color = "grey20"),  
    panel.spacing = unit(0.5, "lines"),   
    strip.background = element_rect(fill = "grey30", color = "grey10"),  
    strip.text.x = element_text(color = "white"),  
    strip.text.y = element_text(color = "white", angle = -90),  
    plot.background = element_rect(color = "gray10", fill = "gray10"),  
    plot.title = element_text(color = "white", hjust = 0, lineheight = 1.25,
                              margin = margin(2, 2, 2, 2)),  
    plot.subtitle = element_text(color = "white", hjust = 0, margin = margin(2, 2, 2, 2)),  
    plot.caption = element_text(color = "white", hjust = 0),  
    plot.margin = unit(rep(1, 4), "lines"))
  
}

# Load some packages: 
library(tidyverse)
library(magrittr)

# Simulate two Cointegrated Time Series as proposed by Hamilton (1994): 
gamma <- 0.7

set.seed(29)
x <- rnorm(1000) %>% cumsum()
y <- gamma*x + rnorm(1000)

df <- data_frame(return = c(x, y), 
                 series = c(rep("X", 1000), rep("Y", 1000)), 
                 time = rep(1:1000, length.out = 2000))

# Visualize time series: 
df %>% 
  ggplot(aes(time, return, color = series)) + 
  geom_line() + 
  my_theme() + 
  scale_color_manual(values = c("cyan", "purple")) + 
  labs(x = NULL, y = NULL, 
       title = "Figure 1: An Example of Nonstationary/Cointegrated Time Series\nas proposed by Hamilton (1994)") 

Augmented Dickey Fuller Test

Từ hình 1 chúng ta có thể thấy hai chuỗi X và Y là các bước đi ngẫu nhiên. Chúng ta có thể kiểm định tính dừng (Stationary) của hai chuỗi này bằng kiểm định Augmented Dickey Fuller (ADF) test (1979):

## 
## ############################################### 
## # Augmented Dickey-Fuller Test Unit Root Test # 
## ############################################### 
## 
## Test regression none 
## 
## 
## Call:
## lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.2099 -0.7456 -0.0267  0.7259  3.1153 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)
## z.lag.1     0.0005076  0.0012061   0.421    0.674
## z.diff.lag -0.0207229  0.0317421  -0.653    0.514
## 
## Residual standard error: 1.072 on 996 degrees of freedom
## Multiple R-squared:  0.0005804,  Adjusted R-squared:  -0.001426 
## F-statistic: 0.2892 on 2 and 996 DF,  p-value: 0.7489
## 
## 
## Value of test-statistic is: 0.4209 
## 
## Critical values for test statistics: 
##       1pct  5pct 10pct
## tau1 -2.58 -1.95 -1.62
## 
## ############################################### 
## # Augmented Dickey-Fuller Test Unit Root Test # 
## ############################################### 
## 
## Test regression none 
## 
## 
## Call:
## lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -4.9905 -1.0595  0.0282  0.9996  4.0732 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## z.lag.1    -0.0005597  0.0024185  -0.231    0.817    
## z.diff.lag -0.4030040  0.0290357 -13.880   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.508 on 996 degrees of freedom
## Multiple R-squared:  0.1628, Adjusted R-squared:  0.1611 
## F-statistic: 96.81 on 2 and 996 DF,  p-value: < 2.2e-16
## 
## 
## Value of test-statistic is: -0.2314 
## 
## Critical values for test statistics: 
##       1pct  5pct 10pct
## tau1 -2.58 -1.95 -1.62

Các Test-statistics thu được lần lượt là 0.4209 và -0.2314 đều lớn hơn các Critical values tại tất cả các ngưỡng 1%, 5% và 10% nên chúng ta có thể nói rằng có bằng chứng thống kê cho thấy các chuỗi là không dừng.

Kế tiếp chúng ta xét chuỗi thời gian Z như sau:

\[ z_{t} = y_{t} - \gamma*x_{t} \]

Rồi kiểm định tính dừng cho chuỗi này bằng ADF Test:

## 
## ############################################### 
## # Augmented Dickey-Fuller Test Unit Root Test # 
## ############################################### 
## 
## Test regression none 
## 
## 
## Call:
## lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.2414 -0.7083 -0.0490  0.7102  3.0251 
## 
## Coefficients:
##            Estimate Std. Error t value Pr(>|t|)    
## z.lag.1    -0.94392    0.04419 -21.358   <2e-16 ***
## z.diff.lag -0.02848    0.03170  -0.898    0.369    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.037 on 996 degrees of freedom
## Multiple R-squared:  0.4859, Adjusted R-squared:  0.4849 
## F-statistic: 470.7 on 2 and 996 DF,  p-value: < 2.2e-16
## 
## 
## Value of test-statistic is: -21.3583 
## 
## Critical values for test statistics: 
##       1pct  5pct 10pct
## tau1 -2.58 -1.95 -1.62

Giá trị của Test-statistic là -21.3583 nhỏ hơn các Critical values tại tất cả các ngưỡng nên chúng ta có bằng chứng thống kê đủ mạnh để chấp nhận giả thuyết rằng chuỗi Z là dừng (Stationary).

Chúng ta có thể hình ảnh hóa chuỗi dừng Z này:

Chuỗi Z là dừng nên chúng ta có thể thấy rằng phân phối của chuỗi này có dạng hình chuông đối xứng:

Engle-Granger Method

Trong thực tế chúng ta không biết trước \(\gamma\) và chúng ta buộc phải ước lượng giá trị này bằng cách thực hiện hồi quy OLS (không có hệ số chặn) Y theo X rồi áp dụng kiểm định ADF cho phần dư. Cách thức này được mô tả trong các giáo trình Financial Econometrics là phương pháp kiểm định đồng tích hợp Engle-Granger (Engle-Granger method of testing cointegration).

Chúng ta thực hiện kiểm định Engle-Granger như sau:

## 
## Call:
## lm(formula = Y ~ X - 1, data = .)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.2121 -0.7075 -0.0430  0.7237  3.0939 
## 
## Coefficients:
##   Estimate Std. Error t value Pr(>|t|)    
## X 0.700745   0.001163   602.7   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.036 on 999 degrees of freedom
## Multiple R-squared:  0.9973, Adjusted R-squared:  0.9973 
## F-statistic: 3.633e+05 on 1 and 999 DF,  p-value: < 2.2e-16
## 
## ############################################### 
## # Augmented Dickey-Fuller Test Unit Root Test # 
## ############################################### 
## 
## Test regression none 
## 
## 
## Call:
## lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.2444 -0.6954 -0.0301  0.7329  3.0494 
## 
## Coefficients:
##            Estimate Std. Error t value Pr(>|t|)    
## z.lag.1    -0.94471    0.04421 -21.370   <2e-16 ***
## z.diff.lag -0.02807    0.03170  -0.886    0.376    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.036 on 996 degrees of freedom
## Multiple R-squared:  0.4861, Adjusted R-squared:  0.485 
## F-statistic:   471 on 2 and 996 DF,  p-value: < 2.2e-16
## 
## 
## Value of test-statistic is: -21.3698 
## 
## Critical values for test statistics: 
##       1pct  5pct 10pct
## tau1 -2.58 -1.95 -1.62

Giá trị của test này (là -21.3698) không khác biệt nhiều so với giá trị trước đó (-21.3583).

Economic Intuition behind Cointegrated Time Series

Các chuỗi đồng tích hợp (Cointegrated Time Series) ngụ ý rằng, ví dụ, cổ phiếu của các công ti trong cùng một ngành (như năng lượng) nên có xu hướng biến động tương tự như nhau về dài hạn hoặc spot price và forward price của một tài sản tài chính nên có biến thiên tương tự nhau.

References

  1. Dickey, D. A.; Fuller, W. A. (1979). “Distribution of the Estimators for Autoregressive Time Series with a Unit Root”. Journal of the American Statistical Association. 74 (366): 427–431.

  2. Hamilton, James D. (1994). Time Series Analysis, Princetown, New Jersey.

LS0tDQp0aXRsZTogIkNvaW50ZWdyYXRlZCBUaW1lIFNlcmllcyBhbmQgQXVnbWVudGVkIERpY2tleSBGdWxsZXIgVGVzdCIgDQpzdWJ0aXRsZTogIlNlbGYtdHJhaW5pbmcgUHJvamVjdCINCmF1dGhvcjogIk5ndXllbiBDaGkgRHVuZyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGhpZ2hsaWdodDogcHlnbWVudHMNCiAgICAjIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6ICJmbGF0bHkiDQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQotLS0NCg0KYGBge3Igc2V0dXAsaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KYGBgDQoNCiMgQ29pbnRlZ3JhdGlvbg0KDQpIYWkgY2h14buXaSB0aOG7nWkgZ2lhbiDEkeG7k25nIHTDrWNoIGjhu6NwIChDb2ludGVncmF0ZWQgVGltZSBTZXJpZXMpIG5n4bulIMO9IHLhurFuZyB04buTbiB04bqhaSBt4buZdCBz4buRIG5ndXnDqm4gbmjDom4gZ+G7kWMgKHVuZGVybHlpbmcgZm9yY2VzKSBsw6BtIGNobyBoYWkgY2h14buXaSB0aOG7nWkgZ2lhbiBjw7MgeHUgaMaw4bubbmcgYmnhur9uIMSR4buZbmcgdMawxqFuZyDEkeG7k25nIG5oYXUgduG7gSBkw6BpIGjhuqFuIG5nYXkgY+G6oyBraGkgbuG6v3UgbmjDrG4gcmnDqm5nIGzhursgdGjDrCBjaMO6bmcgbMOgIGPDoWMgYsaw4bubYyDEkWkgbmfhuqt1IG5oacOqbiAocmFuZG9tIHdhbGtzKS4gDQoNCkhhbWlsdG9uICgxOTk0KSDEkcawYSByYSBtw7QgdOG6oyB24buBIGNodeG7l2kgxJHhu5NuZyB0w61jaCBo4bujcCBuaMawIHNhdTogDQoNCiQkIHhfe3R9ID0geF97dCAtIDF9ICsgdV97dH0kJA0KJCQgeV97dH0gPSBcZ2FtbWEqeF97dH0gKyB2X3t0fSQkDQoNClRyb25nIMSRw7MgJHVfe3R9JCB2w6AgJHZfe3R9JCB0dcOibiB0aGVvIE4oMCwgMSkuIA0KDQpDaMO6bmcgdGEgY8OzIHRo4buDIG3DtCBwaOG7j25nIHbDoCBow6xuaCDhuqNuaCBow7NhIGNodeG7l2kgxJHhu5NuZyB0w61jaCBo4bujcCBuaMawIHNhdTogDQoNCg0KYGBge3J9DQojIEEgZnVuY3Rpb24gZm9yIGJsYWNrIHRoZW1lOiANCm15X3RoZW1lIDwtIGZ1bmN0aW9uKC4uLikgew0KICB0aGVtZSgNCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksICANCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJ3aGl0ZSIsIGxpbmVoZWlnaHQgPSAwLjkpLCAgDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiLCBsaW5laGVpZ2h0ID0gMC45KSwgIA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiLCBzaXplICA9ICAwLjIpLCAgDQogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIndoaXRlIiwgbWFyZ2luID0gbWFyZ2luKDAsIDEwLCAwLCAwKSksICANCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiLCBhbmdsZSA9IDkwLCBtYXJnaW4gPSBtYXJnaW4oMCwgMTAsIDAsIDApKSwgIA0KICAgIGF4aXMudGlja3MubGVuZ3RoID0gdW5pdCgwLjMsICJsaW5lcyIpLCAgIA0KICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gTkEsIGZpbGwgPSAiZ3JheTEwIiksICANCiAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGNvbG9yID0gIndoaXRlIiwgIGZpbGwgPSAiZ3JheTEwIiksICANCiAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDEuMiwgImxpbmVzIiksICANCiAgICBsZWdlbmQua2V5LmhlaWdodCA9IE5VTEwsICANCiAgICBsZWdlbmQua2V5LndpZHRoID0gTlVMTCwgICAgICANCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJ3aGl0ZSIpLCAgDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMCwgY29sb3IgPSAid2hpdGUiKSwgIA0KICAgIGxlZ2VuZC50ZXh0LmFsaWduID0gTlVMTCwgIA0KICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IE5VTEwsICANCiAgICBsZWdlbmQuZGlyZWN0aW9uID0gInZlcnRpY2FsIiwgIA0KICAgIGxlZ2VuZC5ib3ggPSBOVUxMLCANCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEwIiwgY29sb3IgID0gIE5BKSwgIA0KICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyZXkzNSIpLCAgDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmV5MjAiKSwgIA0KICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAuNSwgImxpbmVzIiksICAgDQogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyZXkzMCIsIGNvbG9yID0gImdyZXkxMCIpLCAgDQogICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIndoaXRlIiksICANCiAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiLCBhbmdsZSA9IC05MCksICANCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiZ3JheTEwIiwgZmlsbCA9ICJncmF5MTAiKSwgIA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiLCBoanVzdCA9IDAsIGxpbmVoZWlnaHQgPSAxLjI1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gbWFyZ2luKDIsIDIsIDIsIDIpKSwgIA0KICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiLCBoanVzdCA9IDAsIG1hcmdpbiA9IG1hcmdpbigyLCAyLCAyLCAyKSksICANCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiLCBoanVzdCA9IDApLCAgDQogICAgcGxvdC5tYXJnaW4gPSB1bml0KHJlcCgxLCA0KSwgImxpbmVzIikpDQogIA0KfQ0KDQojIExvYWQgc29tZSBwYWNrYWdlczogDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobWFncml0dHIpDQoNCiMgU2ltdWxhdGUgdHdvIENvaW50ZWdyYXRlZCBUaW1lIFNlcmllcyBhcyBwcm9wb3NlZCBieSBIYW1pbHRvbiAoMTk5NCk6IA0KZ2FtbWEgPC0gMC43DQoNCnNldC5zZWVkKDI5KQ0KeCA8LSBybm9ybSgxMDAwKSAlPiUgY3Vtc3VtKCkNCnkgPC0gZ2FtbWEqeCArIHJub3JtKDEwMDApDQoNCmRmIDwtIGRhdGFfZnJhbWUocmV0dXJuID0gYyh4LCB5KSwgDQogICAgICAgICAgICAgICAgIHNlcmllcyA9IGMocmVwKCJYIiwgMTAwMCksIHJlcCgiWSIsIDEwMDApKSwgDQogICAgICAgICAgICAgICAgIHRpbWUgPSByZXAoMToxMDAwLCBsZW5ndGgub3V0ID0gMjAwMCkpDQoNCiMgVmlzdWFsaXplIHRpbWUgc2VyaWVzOiANCmRmICU+JSANCiAgZ2dwbG90KGFlcyh0aW1lLCByZXR1cm4sIGNvbG9yID0gc2VyaWVzKSkgKyANCiAgZ2VvbV9saW5lKCkgKyANCiAgbXlfdGhlbWUoKSArIA0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiY3lhbiIsICJwdXJwbGUiKSkgKyANCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIA0KICAgICAgIHRpdGxlID0gIkZpZ3VyZSAxOiBBbiBFeGFtcGxlIG9mIE5vbnN0YXRpb25hcnkvQ29pbnRlZ3JhdGVkIFRpbWUgU2VyaWVzXG5hcyBwcm9wb3NlZCBieSBIYW1pbHRvbiAoMTk5NCkiKSANCmBgYA0KDQoNCiMgQXVnbWVudGVkIERpY2tleSBGdWxsZXIgVGVzdA0KDQpU4burIGjDrG5oIDEgY2jDum5nIHRhIGPDsyB0aOG7gyB0aOG6pXkgaGFpIGNodeG7l2kgWCB2w6AgWSBsw6AgY8OhYyBixrDhu5tjIMSRaSBuZ+G6q3Ugbmhpw6puLiBDaMO6bmcgdGEgY8OzIHRo4buDIGtp4buDbSDEkeG7i25oIHTDrW5oIGThu6tuZyAoU3RhdGlvbmFyeSkgY+G7p2EgaGFpIGNodeG7l2kgbsOgeSBi4bqxbmcga2nhu4NtIMSR4buLbmggQXVnbWVudGVkIERpY2tleSBGdWxsZXIgKEFERikgdGVzdCAoMTk3OSk6IA0KDQpgYGB7cn0NCiMgUGVyZm9ybSBBdWdtZW50ZWQgRGlja2V5IEZ1bGxlcjogDQoNCmxpYnJhcnkodXJjYSkNCg0KZGYgJT4lIA0KICBmaWx0ZXIoc2VyaWVzID09ICJYIikgJT4lIA0KICBwdWxsKHJldHVybikgJT4lIA0KICB1ci5kZih0eXBlID0gIm5vbmUiKSAlPiUgDQogIHN1bW1hcnkoKQ0KDQpkZiAlPiUgDQogIGZpbHRlcihzZXJpZXMgPT0gIlkiKSAlPiUgDQogIHB1bGwocmV0dXJuKSAlPiUgDQogIHVyLmRmKHR5cGUgPSAibm9uZSIpICU+JSANCiAgc3VtbWFyeSgpDQpgYGANCg0KQ8OhYyBUZXN0LXN0YXRpc3RpY3MgdGh1IMSRxrDhu6NjIGzhuqduIGzGsOG7o3QgbMOgIDAuNDIwOSB2w6AgLTAuMjMxNCDEkeG7gXUgbOG7m24gaMahbiBjw6FjIENyaXRpY2FsIHZhbHVlcyB04bqhaSB04bqldCBj4bqjIGPDoWMgbmfGsOG7oW5nIDElLCA1JSB2w6AgMTAlIG7Dqm4gY2jDum5nIHRhIGPDsyB0aOG7gyBuw7NpIHLhurFuZyBjw7MgYuG6sW5nIGNo4bupbmcgdGjhu5FuZyBrw6ogY2hvIHRo4bqleSBjw6FjIGNodeG7l2kgbMOgIGtow7RuZyBk4burbmcuIA0KDQoNCkvhur8gdGnhur9wIGNow7puZyB0YSB4w6l0IGNodeG7l2kgdGjhu51pIGdpYW4gWiBuaMawIHNhdTogDQoNCiQkIHpfe3R9ID0geV97dH0gLSBcZ2FtbWEqeF97dH0gJCQNCg0KUuG7k2kga2nhu4NtIMSR4buLbmggdMOtbmggZOG7q25nIGNobyBjaHXhu5dpIG7DoHkgYuG6sW5nIEFERiBUZXN0OiANCg0KYGBge3J9DQpkZiAlPiUgDQogIHNwcmVhZChrZXkgPSAic2VyaWVzIiwgdmFsdWUgPSAicmV0dXJuIikgJT4lIA0KICBtdXRhdGUoeiA9IFkgLSAwLjcqWCkgJT4lIA0KICBwdWxsKHopICU+JSANCiAgdXIuZGYodHlwZSA9ICJub25lIikgJT4lIA0KICBzdW1tYXJ5KCkNCmBgYA0KDQpHacOhIHRy4buLIGPhu6dhIFRlc3Qtc3RhdGlzdGljIGzDoCAtMjEuMzU4MyBuaOG7jyBoxqFuIGPDoWMgQ3JpdGljYWwgdmFsdWVzIHThuqFpIHThuqV0IGPhuqMgY8OhYyBuZ8aw4buhbmcgbsOqbiBjaMO6bmcgdGEgY8OzIGLhurFuZyBjaOG7qW5nIHRo4buRbmcga8OqIMSR4bunIG3huqFuaCDEkeG7gyBjaOG6pXAgbmjhuq1uIGdp4bqjIHRodXnhur90IHLhurFuZyBjaHXhu5dpIFogbMOgIGThu6tuZyAoU3RhdGlvbmFyeSkuIA0KDQoNCkNow7puZyB0YSBjw7MgdGjhu4MgaMOsbmgg4bqjbmggaMOzYSBjaHXhu5dpIGThu6tuZyBaIG7DoHk6IA0KDQpgYGB7cn0NCmRmICU+JSANCiAgc3ByZWFkKGtleSA9ICJzZXJpZXMiLCB2YWx1ZSA9ICJyZXR1cm4iKSAlPiUgDQogIG11dGF0ZSh6ID0gWSAtIGdhbW1hKlgpICU+JSANCiAgZ2dwbG90KGFlcyh0aW1lLCB6KSkgKyANCiAgbXlfdGhlbWUoKSArIA0KICBnZW9tX2xpbmUoY29sb3IgPSAiY3lhbiIpICsgDQogIGxhYnModGl0bGUgPSAiRmlndXJlIDI6IEFuIEV4YW1wbGUgb2YgU3RhdGlvbmFyeSBUaW1lIFNlcmllcyIsIA0KICAgICAgIHggPSBOVUxMLCB5ID0gTlVMTCkNCmBgYA0KDQpDaHXhu5dpIFogbMOgIGThu6tuZyBuw6puIGNow7puZyB0YSBjw7MgdGjhu4MgdGjhuqV5IHLhurFuZyBwaMOibiBwaOG7kWkgY+G7p2EgY2h14buXaSBuw6B5IGPDsyBk4bqhbmcgaMOsbmggY2h1w7RuZyDEkeG7kWkgeOG7qW5nOiANCg0KYGBge3J9DQpkZiAlPiUgDQogIHNwcmVhZChrZXkgPSAic2VyaWVzIiwgdmFsdWUgPSAicmV0dXJuIikgJT4lIA0KICBtdXRhdGUoeiA9IFkgLSBnYW1tYSpYKSAlPiUgDQogIGdncGxvdChhZXMoeikpICsgDQogIGdlb21fZGVuc2l0eShmaWxsID0gImN5YW4iLCBjb2xvciA9ICJjeWFuIiwgYWxwaGEgPSAwLjMpICsgDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBjb2xvciA9ICJwdXJwbGUiLCBmaWxsID0gInB1cnBsZSIsIGFscGhhID0gMC4zKSArIA0KICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgDQogICAgICAgdGl0bGUgPSAiRmlndXJlIDM6IERpc3RyaWJ1dGlvbiBvZiBTdGF0aW9uYXJ5IFRpbWUgU2VyaWVzIikgKyANCiAgbXlfdGhlbWUoKQ0KDQpgYGANCg0KDQojIEVuZ2xlLUdyYW5nZXIgTWV0aG9kDQoNClRyb25nIHRo4buxYyB04bq/IGNow7puZyB0YSBraMO0bmcgYmnhur90IHRyxrDhu5tjICRcZ2FtbWEkIHbDoCBjaMO6bmcgdGEgYnXhu5ljIHBo4bqjaSDGsOG7m2MgbMaw4bujbmcgZ2nDoSB0cuG7iyBuw6B5IGLhurFuZyBjw6FjaCB0aOG7sWMgaGnhu4duIGjhu5NpIHF1eSBPTFMgKGtow7RuZyBjw7MgaOG7hyBz4buRIGNo4bq3bikgWSB0aGVvIFggcuG7k2kgw6FwIGThu6VuZyBraeG7g20gxJHhu4tuaCBBREYgY2hvIHBo4bqnbiBkxrAuIEPDoWNoIHRo4bupYyBuw6B5IMSRxrDhu6NjIG3DtCB04bqjIHRyb25nIGPDoWMgZ2nDoW8gdHLDrG5oIEZpbmFuY2lhbCBFY29ub21ldHJpY3MgbMOgIHBoxrDGoW5nIHBow6FwIGtp4buDbSDEkeG7i25oIMSR4buTbmcgdMOtY2ggaOG7o3AgRW5nbGUtR3JhbmdlciAoRW5nbGUtR3JhbmdlciBtZXRob2Qgb2YgdGVzdGluZyBjb2ludGVncmF0aW9uKS4gDQoNCkNow7puZyB0YSB0aOG7sWMgaGnhu4duIGtp4buDbSDEkeG7i25oIEVuZ2xlLUdyYW5nZXIgbmjGsCBzYXU6IA0KDQpgYGB7cn0NCmRmICU+JSANCiAgc3ByZWFkKGtleSA9ICJzZXJpZXMiLCB2YWx1ZSA9ICJyZXR1cm4iKSAlPiUgDQogIGxtKFkgfiBYIC0gMSwgZGF0YSA9IC4pIC0+IG15X29scw0KDQpteV9vbHMgJT4lIHN1bW1hcnkoKQ0KDQpteV9vbHMkcmVzaWR1YWxzICU+JSANCiAgdXIuZGYodHlwZSA9ICJub25lIikgJT4lIA0KICBzdW1tYXJ5KCkNCmBgYA0KDQpHacOhIHRy4buLIGPhu6dhIHRlc3QgbsOgeSAobMOgIC0yMS4zNjk4KSBraMO0bmcga2jDoWMgYmnhu4d0IG5oaeG7gXUgc28gduG7m2kgZ2nDoSB0cuG7iyB0csaw4bubYyDEkcOzICgtMjEuMzU4MykuIA0KDQojIEVjb25vbWljIEludHVpdGlvbiBiZWhpbmQgQ29pbnRlZ3JhdGVkIFRpbWUgU2VyaWVzDQoNCkPDoWMgY2h14buXaSDEkeG7k25nIHTDrWNoIGjhu6NwIChDb2ludGVncmF0ZWQgVGltZSBTZXJpZXMpIG5n4bulIMO9IHLhurFuZywgdsOtIGThu6UsIGPhu5UgcGhp4bq/dSBj4bunYSBjw6FjIGPDtG5nIHRpIHRyb25nIGPDuW5nIG3hu5l0IG5nw6BuaCAobmjGsCBuxINuZyBsxrDhu6NuZykgbsOqbiBjw7MgeHUgaMaw4bubbmcgYmnhur9uIMSR4buZbmcgdMawxqFuZyB04buxIG5oxrAgbmhhdSB24buBIGTDoGkgaOG6oW4gaG/hurdjIHNwb3QgcHJpY2UgdsOgIGZvcndhcmQgcHJpY2UgY+G7p2EgbeG7mXQgdMOgaSBz4bqjbiB0w6BpIGNow61uaCBuw6puIGPDsyBiaeG6v24gdGhpw6puIHTGsMahbmcgdOG7sSBuaGF1LiANCg0KIyAgUmVmZXJlbmNlcw0KDQoxLiBEaWNrZXksIEQuIEEuOyBGdWxsZXIsIFcuIEEuICgxOTc5KS4gIkRpc3RyaWJ1dGlvbiBvZiB0aGUgRXN0aW1hdG9ycyBmb3IgQXV0b3JlZ3Jlc3NpdmUgVGltZSBTZXJpZXMgd2l0aCBhIFVuaXQgUm9vdCIuIEpvdXJuYWwgb2YgdGhlIEFtZXJpY2FuIFN0YXRpc3RpY2FsIEFzc29jaWF0aW9uLiA3NCAoMzY2KTogNDI34oCTNDMxLiANCg0KMi4gSGFtaWx0b24sIEphbWVzIEQuICgxOTk0KS4gVGltZSBTZXJpZXMgQW5hbHlzaXMsIFByaW5jZXRvd24sIE5ldyBKZXJzZXkuIA0KDQoNCg==