- Tổng quan:
Sử dụng dữ liệu cổ phiếu DVN của PVIAM để vẽ ra những biểu đồ như:
Scatter Plot, Candlestick Charts, Bar Charts, Multi-line Chart. Bên cạnh
vẽ những biểu đồ trực quan hóa dữ liệu, tác giả cũng tiến hành sử dụng
ARIMA để tiến hành dự đoán giá trị của cổ phiếu.
Tiến hành:
2.1. Cài đặt Package và nhập dữ liệu PVIAM:
- Cài đặt Package
install.packages("knitr")
install.packages("plotly")
library(plotly)
install.packages("tq")
library(tq)
install.packages("quantmod")
library(quantmod)
install.packages("TTR")
library(TTR)
install.packages("ggplot2")
library(ggplot2)
library(ggplot2)
library(TTR)
library(magrittr)
# Các packages cần cài đặt
install.packages("knitr")
install.packages("plotly")
library(plotly)
install.packages("tq")
library(tq)
install.packages("quantmod")
library(quantmod)
install.packages("TTR")
library(TTR)
install.packages("ggplot2")
library(ggplot2)
library(ggplot2)
library(TTR)
library(magrittr)
- Nhập dữ liệu PVIAM:
#Import Data----
mydata <- read.csv("C:\\Users\\buith\\KPIM Joint Stock Company\\Business Intelligence - 4. Projects\\Research Portfolio Management Models\\R\\Data cổ phiếu PVI.csv")
mydata <- mydata[complete.cases(mydata$gia_mo_cua), ]
# Transform data----
mydata <- na.omit(mydata)
mydata$ngay <- as.Date(mydata$ngay, format = "%m/%d/%Y")
mydata$ma <- as.character(mydata$ma)
mydata$gia_mo_cua <- as.numeric(mydata$gia_mo_cua)
Warning: NAs introduced by coercion
mydata$gia_dong_cua <- as.numeric(mydata$gia_dong_cua)
mydata$khoi_luong_giao_dich_khop_lenh <- as.numeric(mydata$khoi_luong_giao_dich_khop_lenh)
mydata$gia_cao_nhat <- as.numeric(mydata$gia_cao_nhat)
mydata$gia_thap_nhat <- as.numeric(mydata$gia_thap_nhat)
mydata$gia_dieu_chinh <- as.numeric(mydata$gia_dieu_chinh)
Warning: NAs introduced by coercion
mydata$gia_tri_thay_doi <- as.numeric(mydata$gia_tri_thay_doi)
2.2. Lọc ra dữ liệu cổ phiếu DVN:
# Lọc dữ liệu DVN----
DVN <- mydata[mydata$ma == "DVN", ]
DVN <- na.omit(DVN)
DVN <- DVN[complete.cases(DVN$gia_tri_thay_doi), ]
2.3. Scattor Plot for DVN
plot(DVN$gia_dong_cua, main = "Closing Prices of DVN in 2022", ylab="DVN Close Price", x=DVN$ngay, xlab="Date")

2.4. Candlestick of DVN
DVN %>%
plot_ly(x = ~ngay, type = "candlestick",
open = ~gia_mo_cua, close = ~gia_dong_cua, high = ~gia_cao_nhat, low = ~gia_thap_nhat) %>%
layout(title = "Candlestick Chart for DVN",
xaxis = list(title = "Date"),
yaxis = list(title = "Price"))
2.5. Bar chart for DVN
DVN_bar <- DVN %>%
plot_ly(x = ~ngay, y = ~khoi_luong_giao_dich_khop_lenh, type = "bar",
marker = list(color = "#1f77b4")) %>%
layout(title = "DVN Daily Trading Volume", plot_bgcolor = "#e5ecf6",
xaxis = list(title = "Date"), yaxis = list(title = "Volume"))
DVN_bar
2.6. Multi-line Chart:
DVN$ma7 = SMA(DVN$gia_tri_thay_doi, n=7)
DVN$ma30 = SMA(DVN$gia_tri_thay_doi, n=30)
ggplot(data = DVN) +
geom_line(aes(x = ngay, y = gia_tri_thay_doi , color = "Daily Price")) +
geom_line(aes(x = ngay, y = ma7, color = "Weekly Moving Average")) +
geom_line(aes(x = ngay, y = ma30, color = "Monthly Moving Average")) +
ylab('DVN Stock Price') +
xlab('Time') +
labs(color = 'Trendline')

- Sử dụng mô hình ARIMA để dự báo giá đóng cửa của cổ phiếu DVN trong
60 ngày:
3.1. ADF Test:
print(adf.test(DVN$gia_dong_cua))
Augmented Dickey-Fuller Test
data: DVN$gia_dong_cua
Dickey-Fuller = -2.2199, Lag order = 6, p-value = 0.4832
alternative hypothesis: stationary
3.2. Decompose time series:
DVN$ma7 = SMA(DVN$gia_tri_thay_doi, n=7)
price_maDVN = ts(na.omit(DVN$ma7), frequency=30)
decomp = stl(price_maDVN, s.window="periodic", robust = TRUE)
plot(decomp)
par(mar=c(5,6,7,8))

df_DVN <- data.frame(date = index(DVN), DVN, row.names=NULL)
3.3. ACF test:
Acf(
df_DVN$gia_dong_cua,
lag.max = NULL,
type = c("correlation", "covariance", "partial"),
plot = TRUE,
na.action = na.contiguous,
demean = TRUE,
main = "ACF Series Plot"
)

3.4. PACF
# Partial Auto-correlation
Pacf(
df_DVN$gia_dong_cua,
lag.max = NULL,
plot = TRUE,
na.action = na.contiguous,
demean = TRUE,
main = "PACF Series Plot"
)

3.5. ARIMA model:
# ARIMA Model Fitting
modelfit <- auto.arima(df_DVN$gia_dong_cua, stepwise = TRUE, lambda = NULL)
modelfit
Series: df_DVN$gia_dong_cua
ARIMA(1,1,0)
Coefficients:
ar1
-0.1179
s.e. 0.0646
sigma^2 = 243294: log likelihood = -1881.63
AIC=3767.27 AICc=3767.32 BIC=3774.29
# Forecasting future prices
price_forecast <- forecast(modelfit, h=30)
plot(price_forecast)

- ARIMA dự đoán theo dữ liệu DVN từ năm 2017:
4.1. Import dữ liệu:
DVN2 <- read.csv("C:\\Users\\buith\\KPIM Joint Stock Company\\Business Intelligence - 4. Projects\\Research Portfolio Management Models\\R\\Dữ liệu DVN.csv")
4.2. Test ADF
print(adf.test(DVN2$gia_dong_cua))
Augmented Dickey-Fuller Test
data: DVN2$gia_dong_cua
Dickey-Fuller = -2.2053, Lag order = 10, p-value = 0.4914
alternative hypothesis: stationary
4.3. Decompose:
DVN2$ma7 = ma(DVN2$gia_tri_thay_doi, order=7)
DVN2$ma7[is.na(DVN2$ma7)] <- 0
price_ma <- ts(na.omit(DVN2$ma7), frequency=30)
decomp = stl(price_ma, s.window="periodic", robust = TRUE)
plot(decomp)

4.4. ACF Test
Acf(
series,
lag.max = NULL,
type = c("correlation", "covariance", "partial"),
plot = TRUE,
na.action = na.contiguous,
demean = TRUE,
main = "ACF Series Plot"
)

4.5. PACF test:
Pacf(
series,
lag.max = NULL,
plot = TRUE,
na.action = na.contiguous,
demean = TRUE,
main = "PACF Series Plot"
)

4.5. Forecasting:
modelfit <- auto.arima(DVN2$gia_dong_cua, stepwise = TRUE, lambda = NULL)
modelfit
Series: DVN2$gia_dong_cua
ARIMA(1,1,2)
Coefficients:
ar1 ma1 ma2
0.8857 -0.7681 -0.1495
s.e. 0.0566 0.0603 0.0276
sigma^2 = 280155: log likelihood = -10003.86
AIC=20015.72 AICc=20015.75 BIC=20036.4
price_forecast <- forecast(modelfit, h=60)
plot(price_forecast)

LS0tDQp0aXRsZTogQVJJTUEgTU9ETEUgRk9SIERWTiBTVE9DSw0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KMS4gIFThu5VuZyBxdWFuOg0KDQpT4butIGThu6VuZyBk4buvIGxp4buHdSBj4buVIHBoaeG6v3UgRFZOIGPhu6dhIFBWSUFNIMSR4buDIHbhur0gcmEgbmjhu69uZyBiaeG7g3UgxJHhu5MgbmjGsDogU2NhdHRlciBQbG90LCBDYW5kbGVzdGljayBDaGFydHMsIEJhciBDaGFydHMsIE11bHRpLWxpbmUgQ2hhcnQuIELDqm4gY+G6oW5oIHbhur0gbmjhu69uZyBiaeG7g3UgxJHhu5MgdHLhu7FjIHF1YW4gaMOzYSBk4buvIGxp4buHdSwgdMOhYyBnaeG6oyBjxaluZyB0aeG6v24gaMOgbmggc+G7rSBk4bulbmcgQVJJTUEgxJHhu4MgdGnhur9uIGjDoG5oIGThu7EgxJFvw6FuIGdpw6EgdHLhu4sgY+G7p2EgY+G7lSBwaGnhur91Lg0KDQpUaeG6v24gaMOgbmg6DQoNCjIuMS4gQ8OgaSDEkeG6t3QgUGFja2FnZSB2w6Agbmjhuq1wIGThu68gbGnhu4d1IFBWSUFNOg0KDQoxLiAgQ8OgaSDEkeG6t3QgUGFja2FnZQ0KDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCmluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQpsaWJyYXJ5KHBsb3RseSkNCmluc3RhbGwucGFja2FnZXMoInRxIikNCmxpYnJhcnkodHEpDQppbnN0YWxsLnBhY2thZ2VzKCJxdWFudG1vZCIpDQpsaWJyYXJ5KHF1YW50bW9kKQ0KaW5zdGFsbC5wYWNrYWdlcygiVFRSIikNCmxpYnJhcnkoVFRSKQ0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KFRUUikNCmxpYnJhcnkobWFncml0dHIpDQpgYGANCg0KYGBge3J9DQojIEPDoWMgcGFja2FnZXMgY+G6p24gY8OgaSDEkeG6t3QNCmluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCmluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQpsaWJyYXJ5KHBsb3RseSkNCmluc3RhbGwucGFja2FnZXMoInRxIikNCmxpYnJhcnkodHEpDQppbnN0YWxsLnBhY2thZ2VzKCJxdWFudG1vZCIpDQpsaWJyYXJ5KHF1YW50bW9kKQ0KaW5zdGFsbC5wYWNrYWdlcygiVFRSIikNCmxpYnJhcnkoVFRSKQ0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KFRUUikNCmxpYnJhcnkobWFncml0dHIpDQpgYGANCg0KMi4gIE5o4bqtcCBk4buvIGxp4buHdSBQVklBTToNCg0KYGBge3J9DQojSW1wb3J0IERhdGEtLS0tDQpteWRhdGEgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcYnVpdGhcXEtQSU0gSm9pbnQgU3RvY2sgQ29tcGFueVxcQnVzaW5lc3MgSW50ZWxsaWdlbmNlIC0gNC4gUHJvamVjdHNcXFJlc2VhcmNoIFBvcnRmb2xpbyBNYW5hZ2VtZW50IE1vZGVsc1xcUlxcRGF0YSBj4buVIHBoaeG6v3UgUFZJLmNzdiIpDQpteWRhdGEgPC0gbXlkYXRhW2NvbXBsZXRlLmNhc2VzKG15ZGF0YSRnaWFfbW9fY3VhKSwgXQ0KDQojIFRyYW5zZm9ybSBkYXRhLS0tLQ0KbXlkYXRhIDwtIG5hLm9taXQobXlkYXRhKQ0KbXlkYXRhJG5nYXkgPC0gYXMuRGF0ZShteWRhdGEkbmdheSwgZm9ybWF0ID0gIiVtLyVkLyVZIikNCm15ZGF0YSRtYSA8LSBhcy5jaGFyYWN0ZXIobXlkYXRhJG1hKQ0KbXlkYXRhJGdpYV9tb19jdWEgPC0gYXMubnVtZXJpYyhteWRhdGEkZ2lhX21vX2N1YSkNCm15ZGF0YSRnaWFfZG9uZ19jdWEgPC0gYXMubnVtZXJpYyhteWRhdGEkZ2lhX2RvbmdfY3VhKQ0KbXlkYXRhJGtob2lfbHVvbmdfZ2lhb19kaWNoX2tob3BfbGVuaCA8LSBhcy5udW1lcmljKG15ZGF0YSRraG9pX2x1b25nX2dpYW9fZGljaF9raG9wX2xlbmgpDQpteWRhdGEkZ2lhX2Nhb19uaGF0IDwtIGFzLm51bWVyaWMobXlkYXRhJGdpYV9jYW9fbmhhdCkNCm15ZGF0YSRnaWFfdGhhcF9uaGF0IDwtIGFzLm51bWVyaWMobXlkYXRhJGdpYV90aGFwX25oYXQpDQpteWRhdGEkZ2lhX2RpZXVfY2hpbmggPC0gYXMubnVtZXJpYyhteWRhdGEkZ2lhX2RpZXVfY2hpbmgpDQpteWRhdGEkZ2lhX3RyaV90aGF5X2RvaSA8LSBhcy5udW1lcmljKG15ZGF0YSRnaWFfdHJpX3RoYXlfZG9pKQ0KYGBgDQoNCjIuMi4gTOG7jWMgcmEgZOG7ryBsaeG7h3UgY+G7lSBwaGnhur91IERWTjoNCg0KYGBge3J9DQojIEzhu41jIGThu68gbGnhu4d1IERWTi0tLS0NCkRWTiA8LSBteWRhdGFbbXlkYXRhJG1hID09ICJEVk4iLCBdDQpEVk4gPC0gbmEub21pdChEVk4pDQpEVk4gPC0gRFZOW2NvbXBsZXRlLmNhc2VzKERWTiRnaWFfdHJpX3RoYXlfZG9pKSwgXQ0KYGBgDQoNCjIuMy4gU2NhdHRvciBQbG90IGZvciBEVk4NCg0KYGBge3J9DQpwbG90KERWTiRnaWFfZG9uZ19jdWEsIG1haW4gPSAiQ2xvc2luZyBQcmljZXMgb2YgRFZOIGluIDIwMjIiLCB5bGFiPSJEVk4gQ2xvc2UgUHJpY2UiLCB4PURWTiRuZ2F5LCB4bGFiPSJEYXRlIikNCmBgYA0KDQoyLjQuIENhbmRsZXN0aWNrIG9mIERWTg0KDQpgYGB7cn0NCkRWTiAlPiUNCiAgcGxvdF9seSh4ID0gfm5nYXksIHR5cGUgPSAiY2FuZGxlc3RpY2siLA0KICAgICAgICAgIG9wZW4gPSB+Z2lhX21vX2N1YSwgY2xvc2UgPSB+Z2lhX2RvbmdfY3VhLCBoaWdoID0gfmdpYV9jYW9fbmhhdCwgbG93ID0gfmdpYV90aGFwX25oYXQpICU+JQ0KICBsYXlvdXQodGl0bGUgPSAiQ2FuZGxlc3RpY2sgQ2hhcnQgZm9yIERWTiIsDQogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiRGF0ZSIpLA0KICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlByaWNlIikpDQpgYGANCg0KMi41LiBCYXIgY2hhcnQgZm9yIERWTg0KDQpgYGB7cn0NCkRWTl9iYXIgPC0gRFZOICU+JQ0KICBwbG90X2x5KHggPSB+bmdheSwgeSA9IH5raG9pX2x1b25nX2dpYW9fZGljaF9raG9wX2xlbmgsIHR5cGUgPSAiYmFyIiwgDQogICAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9ICIjMWY3N2I0IikpICU+JQ0KICBsYXlvdXQodGl0bGUgPSAiRFZOIERhaWx5IFRyYWRpbmcgVm9sdW1lIiwgcGxvdF9iZ2NvbG9yID0gIiNlNWVjZjYiLA0KICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIkRhdGUiKSwgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlZvbHVtZSIpKQ0KRFZOX2Jhcg0KYGBgDQoNCjIuNi4gTXVsdGktbGluZSBDaGFydDoNCg0KYGBge3J9DQpEVk4kbWE3ID0gU01BKERWTiRnaWFfdHJpX3RoYXlfZG9pLCBuPTcpDQpEVk4kbWEzMCA9IFNNQShEVk4kZ2lhX3RyaV90aGF5X2RvaSwgbj0zMCkNCmdncGxvdChkYXRhID0gRFZOKSArDQogIGdlb21fbGluZShhZXMoeCA9IG5nYXksIHkgPSBnaWFfdHJpX3RoYXlfZG9pICwgY29sb3IgPSAiRGFpbHkgUHJpY2UiKSkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBuZ2F5LCB5ID0gbWE3LCBjb2xvciA9ICJXZWVrbHkgTW92aW5nIEF2ZXJhZ2UiKSkgICsNCiAgZ2VvbV9saW5lKGFlcyh4ID0gbmdheSwgeSA9IG1hMzAsIGNvbG9yID0gIk1vbnRobHkgTW92aW5nIEF2ZXJhZ2UiKSkgICsNCiAgeWxhYignRFZOIFN0b2NrIFByaWNlJykgKw0KICB4bGFiKCdUaW1lJykgKw0KICBsYWJzKGNvbG9yID0gJ1RyZW5kbGluZScpDQpgYGANCg0KMy4gIFPhu60gZOG7pW5nIG3DtCBow6xuaCBBUklNQSDEkeG7gyBk4buxIGLDoW8gZ2nDoSDEkcOzbmcgY+G7rWEgY+G7p2EgY+G7lSBwaGnhur91IERWTiB0cm9uZyA2MCBuZ8OgeToNCg0KMy4xLiBBREYgVGVzdDpcDQoNCmBgYHtyfQ0KcHJpbnQoYWRmLnRlc3QoRFZOJGdpYV9kb25nX2N1YSkpDQoNCmBgYA0KDQozLjIuIERlY29tcG9zZSB0aW1lIHNlcmllczoNCg0KYGBge3J9DQpEVk4kbWE3ID0gU01BKERWTiRnaWFfdHJpX3RoYXlfZG9pLCBuPTcpDQpwcmljZV9tYURWTiA9IHRzKG5hLm9taXQoRFZOJG1hNyksIGZyZXF1ZW5jeT0zMCkNCmRlY29tcCA9IHN0bChwcmljZV9tYURWTiwgcy53aW5kb3c9InBlcmlvZGljIiwgcm9idXN0ID0gVFJVRSkNCnBsb3QoZGVjb21wKQ0KDQpwYXIobWFyPWMoNSw2LDcsOCkpDQpkZl9EVk4gPC0gZGF0YS5mcmFtZShkYXRlID0gaW5kZXgoRFZOKSwgRFZOLCByb3cubmFtZXM9TlVMTCkNCmBgYA0KDQozLjMuIEFDRiB0ZXN0OlwNCg0KYGBge3J9DQoNCkFjZigNCiAgZGZfRFZOJGdpYV9kb25nX2N1YSwNCiAgbGFnLm1heCA9IE5VTEwsDQogIHR5cGUgPSBjKCJjb3JyZWxhdGlvbiIsICJjb3ZhcmlhbmNlIiwgInBhcnRpYWwiKSwNCiAgcGxvdCA9IFRSVUUsDQogIG5hLmFjdGlvbiA9IG5hLmNvbnRpZ3VvdXMsDQogIGRlbWVhbiA9IFRSVUUsDQogIG1haW4gPSAiQUNGIFNlcmllcyBQbG90Ig0KKQ0KYGBgDQoNCjMuNC4gUEFDRg0KDQpgYGB7cn0NCiMgUGFydGlhbCBBdXRvLWNvcnJlbGF0aW9uDQpQYWNmKA0KICBkZl9EVk4kZ2lhX2RvbmdfY3VhLA0KICBsYWcubWF4ID0gTlVMTCwNCiAgcGxvdCA9IFRSVUUsDQogIG5hLmFjdGlvbiA9IG5hLmNvbnRpZ3VvdXMsDQogIGRlbWVhbiA9IFRSVUUsDQogIG1haW4gPSAiUEFDRiBTZXJpZXMgUGxvdCINCikNCg0KYGBgDQoNCjMuNS4gQVJJTUEgbW9kZWw6XA0KDQpgYGB7cn0NCiMgQVJJTUEgTW9kZWwgRml0dGluZw0KbW9kZWxmaXQgPC0gYXV0by5hcmltYShkZl9EVk4kZ2lhX2RvbmdfY3VhLCBzdGVwd2lzZSA9IFRSVUUsIGxhbWJkYSA9IE5VTEwpDQptb2RlbGZpdA0KYGBgDQoNCmBgYHtyfQ0KIyBGb3JlY2FzdGluZyBmdXR1cmUgcHJpY2VzDQpwcmljZV9mb3JlY2FzdCA8LSBmb3JlY2FzdChtb2RlbGZpdCwgaD0zMCkNCnBsb3QocHJpY2VfZm9yZWNhc3QpDQpgYGANCg0KNC4gIEFSSU1BIGThu7EgxJFvw6FuIHRoZW8gZOG7ryBsaeG7h3UgRFZOIHThu6sgbsSDbSAyMDE3Og0KDQo0LjEuIEltcG9ydCBk4buvIGxp4buHdToNCg0KYGBge3J9DQpEVk4yIDwtIHJlYWQuY3N2KCJDOlxcVXNlcnNcXGJ1aXRoXFxLUElNIEpvaW50IFN0b2NrIENvbXBhbnlcXEJ1c2luZXNzIEludGVsbGlnZW5jZSAtIDQuIFByb2plY3RzXFxSZXNlYXJjaCBQb3J0Zm9saW8gTWFuYWdlbWVudCBNb2RlbHNcXFJcXEThu68gbGnhu4d1IERWTi5jc3YiKQ0KDQpgYGANCg0KNC4yLiBUZXN0IEFERg0KDQpgYGB7cn0NCnByaW50KGFkZi50ZXN0KERWTjIkZ2lhX2RvbmdfY3VhKSkNCmBgYA0KDQo0LjMuIERlY29tcG9zZToNCg0KYGBge3J9DQpEVk4yJG1hNyA9IG1hKERWTjIkZ2lhX3RyaV90aGF5X2RvaSwgb3JkZXI9NykNCkRWTjIkbWE3W2lzLm5hKERWTjIkbWE3KV0gPC0gMA0KcHJpY2VfbWEgPC0gdHMobmEub21pdChEVk4yJG1hNyksIGZyZXF1ZW5jeT0zMCkNCg0KZGVjb21wID0gc3RsKHByaWNlX21hLCBzLndpbmRvdz0icGVyaW9kaWMiLCByb2J1c3QgPSBUUlVFKQ0KcGxvdChkZWNvbXApDQpgYGANCg0KNC40LiBBQ0YgVGVzdA0KDQpgYGB7cn0NCkFjZigNCiAgc2VyaWVzLA0KICBsYWcubWF4ID0gTlVMTCwNCiAgdHlwZSA9IGMoImNvcnJlbGF0aW9uIiwgImNvdmFyaWFuY2UiLCAicGFydGlhbCIpLA0KICBwbG90ID0gVFJVRSwNCiAgbmEuYWN0aW9uID0gbmEuY29udGlndW91cywNCiAgZGVtZWFuID0gVFJVRSwNCiAgbWFpbiA9ICJBQ0YgU2VyaWVzIFBsb3QiDQopDQpgYGANCg0KNC41LiBQQUNGIHRlc3Q6DQoNCmBgYHtyfQ0KUGFjZigNCiAgc2VyaWVzLA0KICBsYWcubWF4ID0gTlVMTCwNCiAgcGxvdCA9IFRSVUUsDQogIG5hLmFjdGlvbiA9IG5hLmNvbnRpZ3VvdXMsDQogIGRlbWVhbiA9IFRSVUUsDQogIG1haW4gPSAiUEFDRiBTZXJpZXMgUGxvdCINCikNCmBgYA0KDQo0LjUuIEZvcmVjYXN0aW5nOg0KDQpgYGB7cn0NCm1vZGVsZml0IDwtIGF1dG8uYXJpbWEoRFZOMiRnaWFfZG9uZ19jdWEsIHN0ZXB3aXNlID0gVFJVRSwgbGFtYmRhID0gTlVMTCkNCm1vZGVsZml0DQpwcmljZV9mb3JlY2FzdCA8LSBmb3JlY2FzdChtb2RlbGZpdCwgaD02MCkNCnBsb3QocHJpY2VfZm9yZWNhc3QpDQpgYGANCg==