1 Downloading stock returns data

#install.packages("rstan")
#install.packages("astsa")
library("rstan")
library("astsa")
options(mc.cores=4)

# Daily closing prices of Germany DAX
price = EuStockMarkets[,4]
y     = diff(log(price))
y     = y - mean(y)
n     = length(y)

par(mfrow=c(1,1))
ts.plot(y,ylab="returns",main="Germany DAX")

2 SV-AR(1) model

For \(t=1,\ldots,n\), \[\begin{eqnarray*} y_t &=& \exp\{h_t/2\}\varepsilon_t\\ h_t &=& \mu+\phi (h_{t-1} - \mu)+\sigma u_t,\\ h_1 &\sim& N(\mu,\sigma^2/(1-\phi^2)). \end{eqnarray*}\] where \(\varepsilon_t\) are iid \(t_\nu(0,1)\) and \(u_t\) are iid \(N(0,1)\). The independent priors used are: \(\mu \sim N(0,10^2)\), \(\phi \sim N_{(-1,1)}(0.8,0.3^2)\), \(\sigma^2 \sim Gamma(0.5,0.5)\) and \(\nu \sim Gamma(1,0.05)\).

3 Stan model

3.1 Gaussian errors

# Filename: sv-g.stan
data {
  int<lower=0> n;   // # time points (equally spaced)
  vector[n] y;      // mean corrected return at time t
}

parameters {
  real mu;                     // mean log volatility
  real<lower=-1,upper=1> phi;  // persistence of volatility
  real<lower=0> sigma;         // white noise shock scale
  real<lower=2> nu;            // degrees of freedom
  vector[n] h;                 // log volatility at time t
}

model {
  phi ~ normal(0.8,0.3);
  sigma ~ gamma(0.5,0.5);
  mu ~ normal(0,10);
  nu ~ gamma(1,0.05);
  h[1] ~ normal(mu,sigma/sqrt(1-phi*phi));
  for (t in 2:n)
    h[t] ~ normal(mu+phi*(h[t-1]-mu),sigma);
  y ~ student_t(nu, 0.0, exp(h/2));
}

3.2 Student’s \(t\) errors

# Filename: sv-t.stan
data {
  int<lower=0> n;   // # time points (equally spaced)
  vector[n] y;      // mean corrected return at time t
}

parameters {
  real mu;                     // mean log volatility
  real<lower=-1,upper=1> phi;  // persistence of volatility
  real<lower=0> sigma;         // white noise shock scale
  vector[n] h;                 // log volatility at time t
}

model {
  phi ~ normal(0.8,0.3);
  sigma ~ gamma(0.5,0.5);
  mu ~ normal(0,10);
  h[1] ~ normal(mu,sigma/sqrt(1-phi*phi));
  for (t in 2:n)
    h[t] ~ normal(mu+phi*(h[t-1]-mu),sigma);
  y ~ normal(0.0,exp(h/2));
}

4 Running stan code

M  = 500

model.n = stan_model("sv-g.stan")
## Running /Library/Frameworks/R.framework/Resources/bin/R CMD SHLIB foo.c
## using C compiler: ‘Apple clang version 15.0.0 (clang-1500.0.40.1)’
## using SDK: ‘’
## clang -arch arm64 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG   -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/Rcpp/include/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/unsupported"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/BH/include" -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/src/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppParallel/include/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/rstan/include" -DEIGEN_NO_DEBUG  -DBOOST_DISABLE_ASSERTS  -DBOOST_PENDING_INTEGER_LOG2_HPP  -DSTAN_THREADS  -DUSE_STANC3 -DSTRICT_R_HEADERS  -DBOOST_PHOENIX_NO_VARIADIC_EXPRESSION  -D_HAS_AUTO_PTR_ETC=0  -include '/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim/fun/Eigen.hpp'  -D_REENTRANT -DRCPP_PARALLEL_USE_TBB=1   -I/opt/R/arm64/include    -fPIC  -falign-functions=64 -Wall -g -O2  -c foo.c -o foo.o
## In file included from <built-in>:1:
## In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim/fun/Eigen.hpp:22:
## In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/Dense:1:
## In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/Core:19:
## /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/src/Core/util/Macros.h:679:10: fatal error: 'cmath' file not found
## #include <cmath>
##          ^~~~~~~
## 1 error generated.
## make: *** [foo.o] Error 1
fit.g   = sampling(model.n,list(n=n,y=y),iter=M,chains=1)
## 
## SAMPLING FOR MODEL 'anon_model' NOW (CHAIN 1).
## Chain 1: 
## Chain 1: Gradient evaluation took 0.000226 seconds
## Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 2.26 seconds.
## Chain 1: Adjust your expectations accordingly!
## Chain 1: 
## Chain 1: 
## Chain 1: Iteration:   1 / 500 [  0%]  (Warmup)
## Chain 1: Iteration:  50 / 500 [ 10%]  (Warmup)
## Chain 1: Iteration: 100 / 500 [ 20%]  (Warmup)
## Chain 1: Iteration: 150 / 500 [ 30%]  (Warmup)
## Chain 1: Iteration: 200 / 500 [ 40%]  (Warmup)
## Chain 1: Iteration: 250 / 500 [ 50%]  (Warmup)
## Chain 1: Iteration: 251 / 500 [ 50%]  (Sampling)
## Chain 1: Iteration: 300 / 500 [ 60%]  (Sampling)
## Chain 1: Iteration: 350 / 500 [ 70%]  (Sampling)
## Chain 1: Iteration: 400 / 500 [ 80%]  (Sampling)
## Chain 1: Iteration: 450 / 500 [ 90%]  (Sampling)
## Chain 1: Iteration: 500 / 500 [100%]  (Sampling)
## Chain 1: 
## Chain 1:  Elapsed Time: 6.575 seconds (Warm-up)
## Chain 1:                7.361 seconds (Sampling)
## Chain 1:                13.936 seconds (Total)
## Chain 1:
model.t = stan_model("sv-t.stan")
## Running /Library/Frameworks/R.framework/Resources/bin/R CMD SHLIB foo.c
## using C compiler: ‘Apple clang version 15.0.0 (clang-1500.0.40.1)’
## using SDK: ‘’
## clang -arch arm64 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG   -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/Rcpp/include/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/unsupported"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/BH/include" -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/src/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppParallel/include/"  -I"/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/rstan/include" -DEIGEN_NO_DEBUG  -DBOOST_DISABLE_ASSERTS  -DBOOST_PENDING_INTEGER_LOG2_HPP  -DSTAN_THREADS  -DUSE_STANC3 -DSTRICT_R_HEADERS  -DBOOST_PHOENIX_NO_VARIADIC_EXPRESSION  -D_HAS_AUTO_PTR_ETC=0  -include '/Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim/fun/Eigen.hpp'  -D_REENTRANT -DRCPP_PARALLEL_USE_TBB=1   -I/opt/R/arm64/include    -fPIC  -falign-functions=64 -Wall -g -O2  -c foo.c -o foo.o
## In file included from <built-in>:1:
## In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/StanHeaders/include/stan/math/prim/fun/Eigen.hpp:22:
## In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/Dense:1:
## In file included from /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/Core:19:
## /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/library/RcppEigen/include/Eigen/src/Core/util/Macros.h:679:10: fatal error: 'cmath' file not found
## #include <cmath>
##          ^~~~~~~
## 1 error generated.
## make: *** [foo.o] Error 1
fit.t   = sampling(model.t,list(n=n,y=y),iter=M,chains=1)
## 
## SAMPLING FOR MODEL 'anon_model' NOW (CHAIN 1).
## Chain 1: 
## Chain 1: Gradient evaluation took 0.000303 seconds
## Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 3.03 seconds.
## Chain 1: Adjust your expectations accordingly!
## Chain 1: 
## Chain 1: 
## Chain 1: Iteration:   1 / 500 [  0%]  (Warmup)
## Chain 1: Iteration:  50 / 500 [ 10%]  (Warmup)
## Chain 1: Iteration: 100 / 500 [ 20%]  (Warmup)
## Chain 1: Iteration: 150 / 500 [ 30%]  (Warmup)
## Chain 1: Iteration: 200 / 500 [ 40%]  (Warmup)
## Chain 1: Iteration: 250 / 500 [ 50%]  (Warmup)
## Chain 1: Iteration: 251 / 500 [ 50%]  (Sampling)
## Chain 1: Iteration: 300 / 500 [ 60%]  (Sampling)
## Chain 1: Iteration: 350 / 500 [ 70%]  (Sampling)
## Chain 1: Iteration: 400 / 500 [ 80%]  (Sampling)
## Chain 1: Iteration: 450 / 500 [ 90%]  (Sampling)
## Chain 1: Iteration: 500 / 500 [100%]  (Sampling)
## Chain 1: 
## Chain 1:  Elapsed Time: 7.734 seconds (Warm-up)
## Chain 1:                6.858 seconds (Sampling)
## Chain 1:                14.592 seconds (Total)
## Chain 1:
params.g = extract(fit.g)
params.t = extract(fit.t)

qsd.g = t(apply(exp(params.g$h/2),2,quantile,c(0.025,0.5,0.975)))
qsd.t = t(apply(exp(params.t$h/2),2,quantile,c(0.025,0.5,0.975)))

5 Marginal posteriors of \((\mu,\phi,\sigma,\nu)\)

par(mfrow=c(2,4))
ts.plot(params.g$mu,xlab="Draws",main=expression(mu),ylab="",ylim=range(params.g$mu,params.t$mu))
lines(params.t$mu,col=2)
ts.plot(params.g$phi,xlab="Draws",main=expression(phi),ylab="",ylim=range(params.g$phi,params.t$phi))
lines(params.t$phi,col=2)
ts.plot(params.g$sigma,xlab="Draws",main=expression(sigma),ylab="",ylim=range(params.g$sigma,params.t$sigma))
lines(params.t$sigma,col=2)
ts.plot(params.t$nu,xlab="Iterations",main=expression(nu),ylab="")
boxplot(params.g$mu,params.t$mu,outline=FALSE,names=c("Gaussian","Student's t"),main=expression(mu))
boxplot(params.g$phi,params.t$phi,outline=FALSE,names=c("Gaussian","Student's t"),main=expression(phi))
boxplot(params.g$sigma,params.t$sigma,outline=FALSE,names=c("Gaussian","Student's t"),main=expression(sigma))
hist(params.t$nu,prob=TRUE,main=expression(nu),xlab="")

5.1 Posterior quantiles for \(\mu\)

tab = rbind(quantile(params.g$mu,c(0.01,0.05,0.5,0.95,0.99)),
quantile(params.t$mu,c(0.01,0.05,0.5,0.95,0.99)))
rownames(tab)=c("Gaussian","Student's t")
tab
##                    1%        5%       50%       95%       99%
## Gaussian    -10.07859 -10.01688 -9.827687 -9.642983 -9.538947
## Student's t -10.16613 -10.09410 -9.930063 -9.748884 -9.667854

5.2 Posterior quantiles for \(\phi\)

tab = rbind(quantile(params.g$phi,c(0.01,0.05,0.5,0.95,0.99)),
quantile(params.t$phi,c(0.01,0.05,0.5,0.95,0.99)))
rownames(tab)=c("Gaussian","Student's t")
tab
##                    1%        5%       50%       95%       99%
## Gaussian    0.9437874 0.9529665 0.9664373 0.9775090 0.9804357
## Student's t 0.9358860 0.9401383 0.9661100 0.9804359 0.9844241

5.3 Posterior quantiles for \(\sigma\)

tab = rbind(quantile(params.g$sigma,c(0.01,0.05,0.5,0.95,0.99)),
quantile(params.t$sigma,c(0.01,0.05,0.5,0.95,0.99)))
rownames(tab)=c("Gaussian","Student's t")
tab
##                    1%        5%       50%       95%       99%
## Gaussian    0.1306978 0.1364088 0.1518336 0.1813667 0.1898979
## Student's t 0.1149745 0.1183771 0.1528463 0.1946473 0.2083977

5.4 Posterior quantiles for \(\nu\)

quantile(params.t$nu,c(0.01,0.05,0.5,0.95,0.99))
##       1%       5%      50%      95%      99% 
## 10.00972 11.68812 20.81765 46.45052 66.84300

6 Posterior distribution of time-varying standard deviations

par(mfrow=c(1,1))
ts.plot(qsd.g[,2],ylim=range(qsd.g,qsd.t),ylab="Standard deviation")
lines(qsd.g[,1])
lines(qsd.g[,3])
lines(qsd.t[,1],col=2)
lines(qsd.t[,2],col=2)
lines(qsd.t[,3],col=2)
legend("top",legend=c("Gaussian errors","Student's t errors"),col=1:2,lwd=2,bty="n",lty=1)

LS0tCnRpdGxlOiAiU1Ygd2l0aCBHYXVzc2lhbiBvciBTdHVkZW50J3MgJHQkIGVycm9ycyIKc3VidGl0bGU6ICJIYW1pbHRvbmlhbiBNQyB2aWEgU1RBTiIKYXV0aG9yOiAiSGVkaWJlcnQgRi4gTG9wZXMiCmRhdGU6ICIxNC8wNi8yMDI1IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQotLS0KCgojIERvd25sb2FkaW5nICBzdG9jayByZXR1cm5zIGRhdGEKCmBgYHtyIGZpZy53aWR0aD04LGZpZy5oZWlnaHQ9NSxmaWcuYWxpZ249J2NlbnRlcicsbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI2luc3RhbGwucGFja2FnZXMoInJzdGFuIikKI2luc3RhbGwucGFja2FnZXMoImFzdHNhIikKbGlicmFyeSgicnN0YW4iKQpsaWJyYXJ5KCJhc3RzYSIpCm9wdGlvbnMobWMuY29yZXM9NCkKCiMgRGFpbHkgY2xvc2luZyBwcmljZXMgb2YgR2VybWFueSBEQVgKcHJpY2UgPSBFdVN0b2NrTWFya2V0c1ssNF0KeSAgICAgPSBkaWZmKGxvZyhwcmljZSkpCnkgICAgID0geSAtIG1lYW4oeSkKbiAgICAgPSBsZW5ndGgoeSkKCnBhcihtZnJvdz1jKDEsMSkpCnRzLnBsb3QoeSx5bGFiPSJyZXR1cm5zIixtYWluPSJHZXJtYW55IERBWCIpCmBgYAoKIyBTVi1BUigxKSBtb2RlbApGb3IgJHQ9MSxcbGRvdHMsbiQsClxiZWdpbntlcW5hcnJheSp9CnlfdCAmPSYgXGV4cFx7aF90LzJcfVx2YXJlcHNpbG9uX3RcXApoX3QgJj0mIFxtdStccGhpIChoX3t0LTF9IC0gXG11KStcc2lnbWEgdV90LFxcCmhfMSAmXHNpbSYgIE4oXG11LFxzaWdtYV4yLygxLVxwaGleMikpLgpcZW5ke2VxbmFycmF5Kn0Kd2hlcmUgJFx2YXJlcHNpbG9uX3QkIGFyZSBpaWQgJHRfXG51KDAsMSkkIGFuZCAkdV90JCBhcmUgaWlkICROKDAsMSkkLiAgVGhlIGluZGVwZW5kZW50IHByaW9ycyB1c2VkIGFyZTogJFxtdSBcc2ltIE4oMCwxMF4yKSQsICRccGhpIFxzaW0gTl97KC0xLDEpfSgwLjgsMC4zXjIpJCwgJFxzaWdtYV4yIFxzaW0gR2FtbWEoMC41LDAuNSkkIGFuZCAkXG51IFxzaW0gR2FtbWEoMSwwLjA1KSQuCgojIFN0YW4gbW9kZWwKCiMjIEdhdXNzaWFuIGVycm9ycwoKYGBge3IgZXZhbD1GQUxTRX0KIyBGaWxlbmFtZTogc3YtZy5zdGFuCmRhdGEgewogIGludDxsb3dlcj0wPiBuOyAgIC8vICMgdGltZSBwb2ludHMgKGVxdWFsbHkgc3BhY2VkKQogIHZlY3RvcltuXSB5OyAgICAgIC8vIG1lYW4gY29ycmVjdGVkIHJldHVybiBhdCB0aW1lIHQKfQoKcGFyYW1ldGVycyB7CiAgcmVhbCBtdTsgICAgICAgICAgICAgICAgICAgICAvLyBtZWFuIGxvZyB2b2xhdGlsaXR5CiAgcmVhbDxsb3dlcj0tMSx1cHBlcj0xPiBwaGk7ICAvLyBwZXJzaXN0ZW5jZSBvZiB2b2xhdGlsaXR5CiAgcmVhbDxsb3dlcj0wPiBzaWdtYTsgICAgICAgICAvLyB3aGl0ZSBub2lzZSBzaG9jayBzY2FsZQogIHJlYWw8bG93ZXI9Mj4gbnU7ICAgICAgICAgICAgLy8gZGVncmVlcyBvZiBmcmVlZG9tCiAgdmVjdG9yW25dIGg7ICAgICAgICAgICAgICAgICAvLyBsb2cgdm9sYXRpbGl0eSBhdCB0aW1lIHQKfQoKbW9kZWwgewogIHBoaSB+IG5vcm1hbCgwLjgsMC4zKTsKICBzaWdtYSB+IGdhbW1hKDAuNSwwLjUpOwogIG11IH4gbm9ybWFsKDAsMTApOwogIG51IH4gZ2FtbWEoMSwwLjA1KTsKICBoWzFdIH4gbm9ybWFsKG11LHNpZ21hL3NxcnQoMS1waGkqcGhpKSk7CiAgZm9yICh0IGluIDI6bikKICAgIGhbdF0gfiBub3JtYWwobXUrcGhpKihoW3QtMV0tbXUpLHNpZ21hKTsKICB5IH4gc3R1ZGVudF90KG51LCAwLjAsIGV4cChoLzIpKTsKfQpgYGAKCiMjIFN0dWRlbnQncyAkdCQgZXJyb3JzCgpgYGB7ciBldmFsPUZBTFNFfQojIEZpbGVuYW1lOiBzdi10LnN0YW4KZGF0YSB7CiAgaW50PGxvd2VyPTA+IG47ICAgLy8gIyB0aW1lIHBvaW50cyAoZXF1YWxseSBzcGFjZWQpCiAgdmVjdG9yW25dIHk7ICAgICAgLy8gbWVhbiBjb3JyZWN0ZWQgcmV0dXJuIGF0IHRpbWUgdAp9CgpwYXJhbWV0ZXJzIHsKICByZWFsIG11OyAgICAgICAgICAgICAgICAgICAgIC8vIG1lYW4gbG9nIHZvbGF0aWxpdHkKICByZWFsPGxvd2VyPS0xLHVwcGVyPTE+IHBoaTsgIC8vIHBlcnNpc3RlbmNlIG9mIHZvbGF0aWxpdHkKICByZWFsPGxvd2VyPTA+IHNpZ21hOyAgICAgICAgIC8vIHdoaXRlIG5vaXNlIHNob2NrIHNjYWxlCiAgdmVjdG9yW25dIGg7ICAgICAgICAgICAgICAgICAvLyBsb2cgdm9sYXRpbGl0eSBhdCB0aW1lIHQKfQoKbW9kZWwgewogIHBoaSB+IG5vcm1hbCgwLjgsMC4zKTsKICBzaWdtYSB+IGdhbW1hKDAuNSwwLjUpOwogIG11IH4gbm9ybWFsKDAsMTApOwogIGhbMV0gfiBub3JtYWwobXUsc2lnbWEvc3FydCgxLXBoaSpwaGkpKTsKICBmb3IgKHQgaW4gMjpuKQogICAgaFt0XSB+IG5vcm1hbChtdStwaGkqKGhbdC0xXS1tdSksc2lnbWEpOwogIHkgfiBub3JtYWwoMC4wLGV4cChoLzIpKTsKfQpgYGAKCgojIFJ1bm5pbmcgc3RhbiBjb2RlCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpNICA9IDUwMAoKbW9kZWwubiA9IHN0YW5fbW9kZWwoInN2LWcuc3RhbiIpCmZpdC5nICAgPSBzYW1wbGluZyhtb2RlbC5uLGxpc3Qobj1uLHk9eSksaXRlcj1NLGNoYWlucz0xKQoKbW9kZWwudCA9IHN0YW5fbW9kZWwoInN2LXQuc3RhbiIpCmZpdC50ICAgPSBzYW1wbGluZyhtb2RlbC50LGxpc3Qobj1uLHk9eSksaXRlcj1NLGNoYWlucz0xKQoKcGFyYW1zLmcgPSBleHRyYWN0KGZpdC5nKQpwYXJhbXMudCA9IGV4dHJhY3QoZml0LnQpCgpxc2QuZyA9IHQoYXBwbHkoZXhwKHBhcmFtcy5nJGgvMiksMixxdWFudGlsZSxjKDAuMDI1LDAuNSwwLjk3NSkpKQpxc2QudCA9IHQoYXBwbHkoZXhwKHBhcmFtcy50JGgvMiksMixxdWFudGlsZSxjKDAuMDI1LDAuNSwwLjk3NSkpKQpgYGAKCiMgTWFyZ2luYWwgcG9zdGVyaW9ycyBvZiAkKFxtdSxccGhpLFxzaWdtYSxcbnUpJAoKYGBge3IgZmlnLndpZHRoPTEyLGZpZy5oZWlnaHQ9OCxmaWcuYWxpZ249J2NlbnRlcicsbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGFyKG1mcm93PWMoMiw0KSkKdHMucGxvdChwYXJhbXMuZyRtdSx4bGFiPSJEcmF3cyIsbWFpbj1leHByZXNzaW9uKG11KSx5bGFiPSIiLHlsaW09cmFuZ2UocGFyYW1zLmckbXUscGFyYW1zLnQkbXUpKQpsaW5lcyhwYXJhbXMudCRtdSxjb2w9MikKdHMucGxvdChwYXJhbXMuZyRwaGkseGxhYj0iRHJhd3MiLG1haW49ZXhwcmVzc2lvbihwaGkpLHlsYWI9IiIseWxpbT1yYW5nZShwYXJhbXMuZyRwaGkscGFyYW1zLnQkcGhpKSkKbGluZXMocGFyYW1zLnQkcGhpLGNvbD0yKQp0cy5wbG90KHBhcmFtcy5nJHNpZ21hLHhsYWI9IkRyYXdzIixtYWluPWV4cHJlc3Npb24oc2lnbWEpLHlsYWI9IiIseWxpbT1yYW5nZShwYXJhbXMuZyRzaWdtYSxwYXJhbXMudCRzaWdtYSkpCmxpbmVzKHBhcmFtcy50JHNpZ21hLGNvbD0yKQp0cy5wbG90KHBhcmFtcy50JG51LHhsYWI9Ikl0ZXJhdGlvbnMiLG1haW49ZXhwcmVzc2lvbihudSkseWxhYj0iIikKYm94cGxvdChwYXJhbXMuZyRtdSxwYXJhbXMudCRtdSxvdXRsaW5lPUZBTFNFLG5hbWVzPWMoIkdhdXNzaWFuIiwiU3R1ZGVudCdzIHQiKSxtYWluPWV4cHJlc3Npb24obXUpKQpib3hwbG90KHBhcmFtcy5nJHBoaSxwYXJhbXMudCRwaGksb3V0bGluZT1GQUxTRSxuYW1lcz1jKCJHYXVzc2lhbiIsIlN0dWRlbnQncyB0IiksbWFpbj1leHByZXNzaW9uKHBoaSkpCmJveHBsb3QocGFyYW1zLmckc2lnbWEscGFyYW1zLnQkc2lnbWEsb3V0bGluZT1GQUxTRSxuYW1lcz1jKCJHYXVzc2lhbiIsIlN0dWRlbnQncyB0IiksbWFpbj1leHByZXNzaW9uKHNpZ21hKSkKaGlzdChwYXJhbXMudCRudSxwcm9iPVRSVUUsbWFpbj1leHByZXNzaW9uKG51KSx4bGFiPSIiKQpgYGAKCiMjIFBvc3RlcmlvciBxdWFudGlsZXMgZm9yICRcbXUkCgpgYGB7cn0KdGFiID0gcmJpbmQocXVhbnRpbGUocGFyYW1zLmckbXUsYygwLjAxLDAuMDUsMC41LDAuOTUsMC45OSkpLApxdWFudGlsZShwYXJhbXMudCRtdSxjKDAuMDEsMC4wNSwwLjUsMC45NSwwLjk5KSkpCnJvd25hbWVzKHRhYik9YygiR2F1c3NpYW4iLCJTdHVkZW50J3MgdCIpCnRhYgpgYGAKCiMjIFBvc3RlcmlvciBxdWFudGlsZXMgZm9yICRccGhpJAoKYGBge3J9CnRhYiA9IHJiaW5kKHF1YW50aWxlKHBhcmFtcy5nJHBoaSxjKDAuMDEsMC4wNSwwLjUsMC45NSwwLjk5KSksCnF1YW50aWxlKHBhcmFtcy50JHBoaSxjKDAuMDEsMC4wNSwwLjUsMC45NSwwLjk5KSkpCnJvd25hbWVzKHRhYik9YygiR2F1c3NpYW4iLCJTdHVkZW50J3MgdCIpCnRhYgpgYGAKCiMjIFBvc3RlcmlvciBxdWFudGlsZXMgZm9yICRcc2lnbWEkCgpgYGB7cn0KdGFiID0gcmJpbmQocXVhbnRpbGUocGFyYW1zLmckc2lnbWEsYygwLjAxLDAuMDUsMC41LDAuOTUsMC45OSkpLApxdWFudGlsZShwYXJhbXMudCRzaWdtYSxjKDAuMDEsMC4wNSwwLjUsMC45NSwwLjk5KSkpCnJvd25hbWVzKHRhYik9YygiR2F1c3NpYW4iLCJTdHVkZW50J3MgdCIpCnRhYgpgYGAKIyMgUG9zdGVyaW9yIHF1YW50aWxlcyBmb3IgJFxudSQKCmBgYHtyfQpxdWFudGlsZShwYXJhbXMudCRudSxjKDAuMDEsMC4wNSwwLjUsMC45NSwwLjk5KSkKYGBgCgoKIyBQb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIG9mIHRpbWUtdmFyeWluZyBzdGFuZGFyZCBkZXZpYXRpb25zCgpgYGB7ciBmaWcud2lkdGg9OCxmaWcuaGVpZ2h0PTYsZmlnLmFsaWduPSdjZW50ZXInLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBhcihtZnJvdz1jKDEsMSkpCnRzLnBsb3QocXNkLmdbLDJdLHlsaW09cmFuZ2UocXNkLmcscXNkLnQpLHlsYWI9IlN0YW5kYXJkIGRldmlhdGlvbiIpCmxpbmVzKHFzZC5nWywxXSkKbGluZXMocXNkLmdbLDNdKQpsaW5lcyhxc2QudFssMV0sY29sPTIpCmxpbmVzKHFzZC50WywyXSxjb2w9MikKbGluZXMocXNkLnRbLDNdLGNvbD0yKQpsZWdlbmQoInRvcCIsbGVnZW5kPWMoIkdhdXNzaWFuIGVycm9ycyIsIlN0dWRlbnQncyB0IGVycm9ycyIpLGNvbD0xOjIsbHdkPTIsYnR5PSJuIixsdHk9MSkKYGBgCg==