A look at various filter and smoothing models in R with libraries from mass(structT, tsSmooth, kalmanLike etc.),by Venables & Ripley. KFAS, Kalman Filter and Smoother for Exponential Family State Space Models,by Jounie Helske,and atsa from SHumway and Stoffer to accompany their book Data sets and scripts to accompany Time Series Analysis and Its Applications: With R Examples (4th ed), by R.H. Shumway and D.S. Stoffer. Springer Texts in Statisics. Rob Hyndmans forecast package.(now updated as fable in tidymodels)

[1] "^VIX"
fitvix <- StructTS(vix, "level")
fitvix

Call:
StructTS(x = vix, type = "level")

Variances:
  level  epsilon  
  2.413    1.164  
StructTS(x = vix, type = "level")

Call:
StructTS(x = vix, type = "level")

Variances:
  level  epsilon  
  2.413    1.164  
plot(vix, col = "blue")
lines(fitted(fitvix), lty ="dashed", lwd =2)

lines(tsSmooth(fitvix),lty = "dotted", lwd =2)

plot(forecast(fitvix))

# rearranged not reason for kalman est unfit ie. forecast command

#lines(kalman_est, lty = "dotted", ,lwd = 2, col = "yellow")
# the kalman est fit did not run, syntax or logic error, for reader to pursue, kalman fit below.
# an ARIMA fit
fit3 <- arima(vix, c(1, 1, 0))
predict(fit3, 12)
$pred
Time Series:
Start = 2022.8796142289 
End = 2022.90973120598 
Frequency = 365.2425 
 [1] 24.02898 24.02134 24.02336 24.02283
 [5] 24.02297 24.02293 24.02294 24.02294
 [9] 24.02294 24.02294 24.02294 24.02294

$se
Time Series:
Start = 2022.8796142289 
End = 2022.90973120598 
Frequency = 365.2425 
 [1] 2.096842 2.604237 3.104520 3.516523
 [5] 3.889381 4.228451 4.542537 4.836204
 [9] 5.113048 5.375649 5.626008 5.865690
## reconstruct this
pr <- KalmanForecast(12, fit3$model)
pr$pred + fit3$coef[4]
 [1] NA NA NA NA NA NA NA NA NA NA NA NA
sqrt(pr$var * fit3$sigma2)
 [1] 2.096842 2.604237 3.104520 3.516523
 [5] 3.889381 4.228451 4.542537 4.836204
 [9] 5.113048 5.375649 5.626008 5.865690
## and now do it year by year
mod <- fit3$model
for(y in 1:3) {
  pr <- KalmanForecast(4, mod, TRUE)
  print(list(pred = pr$pred + fit3$coef["intercept"],
             se = sqrt(pr$var * fit3$sigma2)))
  mod <- attr(pr, "mod")
}
$pred
[1] NA NA NA NA

$se
[1] 2.096842 2.604237 3.104520 3.516523

$pred
[1] NA NA NA NA

$se
[1] 3.889381 4.228451 4.542537 4.836204

$pred
[1] NA NA NA NA

$se
[1] 5.113048 5.375649 5.626008 5.865690
fit_kalman <- KalmanLike(vix, mod, nit = 0L, update = FALSE)
out <- KalmanSmooth(vix, mod, nit = 0L)
kalman_est <- out$smooth[ ,2]
plot.ts(vix)

plot(kalman_est, lty = "dashed", lwd = 2,col = "green")

vix <-  ts_timeSeries(vix)
histPlot(vix)

library(KFAS)
library(tseries)
library(timeSeries)
library(zoo)
library(quantmod)
library(forecast)

Start Kalman code with structural time series. Using KFAS library

getSymbols("SPY",  from = as.Date("2021-01-01"),
           end = as.Date("2022-10-31"),
           quote = "Close")
[1] "SPY"
cls <- SPY$SPY.Close



sp_r <- dailyReturn(SPY)

sp_r <- as.ts(sp_r)

fit_structural  <-  SSModel(sp_r ~ SSMtrend(1, Q = list(matrix(NA))), H = matrix(NA))

 fit_structural <- fitSSM(fit_structural, inits = c(0, 0),method = "BFGS")

 fit_structural$model["Q"]
, , 1

             [,1]
[1,] 3.508162e-10

Plot returns model and start price series model and plot.

plot(fit_structural$model)

NA


fit_structural2  <-  SSModel(cls ~ SSMtrend(1, Q = list(matrix(NA))), H = matrix(NA))
Warning: setting this dimension may lead to an invalid zoo objectWarning: setting this dimension may lead to an invalid zoo object
fit_structural2 <- fitSSM(fit_structural2, inits = c(0, 0),method = "BFGS")

fit_structural2$model["Q"]
, , 1

             [,1]
[1,] 5.191219e-12
str(fit_structural2$model$y)
 Time-Series [1:474, 1] from 1 to 474: 369 371 374 379 381 ...
 - attr(*, "index")= num [1:474] 1.61e+09 1.61e+09 1.61e+09 1.61e+09 1.61e+09 ...
  ..- attr(*, "tzone")= chr "UTC"
  ..- attr(*, "tclass")= chr "Date"
 - attr(*, "src")= chr "yahoo"
 - attr(*, "updated")= POSIXct[1:1], format:  ...
plot(fit_structural2$model$y)


plot(fit_structural2$model$y, cls)


plot((fit_structural2$model$y), lty = "dotted", lwd =2)



fit <- forecast(fit_structural2$model$y, h = 10 )
plot(fit)

kalman filter using atsa library.

library(quantmod)
library(tidyverse)
library(tsbox)
library(tidyquant)
library(forecast)

start downloading RF data stock ticker Regional Finance corp. base comparison naive model forecast.

rf_price <- tq_get("RF", from = "2020-01-01")

rf_ts <- as.ts(rf_price)



n_fc <- naive(
  rf_price$close,
  h = 10,
  level = c(80, 95),
  fan = FALSE,
  lambda = NULL,
  biasadj = FALSE,
  x = rf_price$close
)

autoplot(n_fc)

NA
NA
NA

start structts code

  fit <- StructTS(rf_price$close, type = "level")
#if (struct$code != 0) stop("optimizer did not converge")

smoothed <- tsSmooth(fit)
str(smoothed)
 Time-Series [1:727, 1] from 1 to 727: 17.1 16.8 16.6 16.4 16.5 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr "level"
#tsdiag(fit)

plot(rf_price$close, type = "l" , lwd =1)
lines(fitted(fit), lty = "dashed", lwd = 2, col = "green")
lines(tsSmooth(fit), lty ="dotted", lwd = 2, col = "blue")

plot(forecast(fit, h= 20))

NA
NA

start atsa code

library(astsa)

fit2 <- ssm(rf_price$close,A=1, alpha=.01, phi=1, sigw=.01, sigv=.1)
initial  value 34062.188799 
iter   2 value 3019.274455
iter   3 value 2739.621359
iter   4 value 2734.440614
iter   5 value 2734.306521
iter   6 value 2734.285794
iter   7 value 2734.251764
iter   8 value 2734.159321
iter   9 value 2734.020029
iter  10 value 2733.891035
iter  11 value 2431.772512
iter  12 value 2364.036048
iter  13 value 2244.024934
iter  14 value 2037.962713
iter  15 value 1888.963511
iter  16 value 1763.906884
iter  17 value 1704.698280
iter  18 value 1590.163090
iter  19 value 1502.535715
iter  20 value 1385.516543
iter  21 value 1194.683236
iter  22 value 1178.227716
iter  23 value 905.085614
iter  24 value 505.799424
iter  25 value 272.220675
iter  26 value 148.561118
iter  27 value 49.117765
iter  28 value -14.156880
iter  29 value -49.523492
iter  30 value -57.536101
iter  31 value -125.439876
iter  32 value -163.507674
iter  33 value -171.330783
iter  34 value -171.696825
iter  35 value -175.095062
iter  36 value -175.249986
iter  37 value -177.864860
iter  38 value -179.788364
iter  39 value -179.799725
iter  40 value -179.805357
iter  41 value -179.805874
iter  42 value -179.809292
iter  43 value -180.007659
iter  44 value -180.011473
iter  45 value -180.053510
iter  46 value -180.075863
iter  47 value -180.077005
iter  48 value -180.077169
iter  48 value -180.077170
iter  48 value -180.077170
final  value -180.077170 
converged
        estimate          SE
phi   0.99555157 0.003689686
alpha 0.08899968 0.069553448
sigw  0.45969564 0.021371139
sigv  0.08071906 0.052033219
tsplot(rf_price$close, col=4, type="o", pch=20, ylab="RF Price")
lines(fit2$Xs, col=6, lwd=2)
xx = c(time(fit2$Xs), rev(time(fit2$Xs)))
yy = c(fit2$Xs-2*sqrt(fit2$Ps), rev(fit2$Xs+2*sqrt(fit2$Ps)))
polygon(xx, yy, border=8, col=gray(.6, alpha=.25) )


num = COUNT(rf_price$close)


Linn  = function(para){
  phi = para[1]; sigw = para[2]; sigv = para[3]
  kf  = Kfilter0(num, rf_price$close, A=1, mu0=0, Sigma0=10, phi, sigw, sigv)
  return(kf$like)
}


# Estimation
init.par = c(.1, 1, 1)   # initial parameter values
(est = optim(init.par, Linn, gr=NULL, method="BFGS", hessian=TRUE, control=list(trace=1,REPORT=1)))
initial  value 58153.511326 
iter   2 value 8985.289029
iter   3 value 8983.344225
iter   4 value 8978.601561
iter   5 value 8973.824843
iter   6 value 8969.013554
iter   7 value 8964.167153
iter   8 value 8959.285064
iter   9 value 8954.366750
iter  10 value 8949.411630
iter  11 value 8944.419064
iter  12 value 8939.388464
iter  13 value 8934.319194
iter  14 value 8929.210628
iter  15 value 8924.062088
iter  16 value 8918.872927
iter  17 value 8913.642421
iter  18 value 8908.369858
iter  19 value 8903.054484
iter  20 value 8897.695571
iter  21 value 8892.292344
iter  22 value 8886.843985
iter  23 value 8881.349670
iter  24 value 8875.808544
iter  25 value 8870.219782
iter  26 value 8864.582429
iter  27 value 8858.895609
iter  28 value 8853.158352
iter  29 value 8847.369672
iter  30 value 8841.528567
iter  31 value 8835.633991
iter  32 value 8829.684863
iter  33 value 8823.680077
iter  34 value 8817.618500
iter  35 value 8811.498926
iter  36 value 8805.320124
iter  37 value 8799.080851
iter  38 value 8792.779782
iter  39 value 8786.415595
iter  40 value 8779.986869
iter  41 value 8773.492137
iter  42 value 8766.929922
iter  43 value 8760.298683
iter  44 value 8753.596784
iter  45 value 8746.822564
iter  46 value 8739.974291
iter  47 value 8733.050150
iter  48 value 8726.048292
iter  49 value 8718.966728
iter  50 value 8711.803474
iter  51 value 8704.556422
iter  52 value 8697.223378
iter  53 value 8689.802046
iter  54 value 8682.290050
iter  55 value 8674.684908
iter  56 value 8666.984045
iter  57 value 8659.184738
iter  58 value 8651.284159
iter  59 value 8643.279363
iter  60 value 8635.167251
iter  61 value 8626.944575
iter  62 value 8618.607931
iter  63 value 8610.153750
iter  64 value 8601.578323
iter  65 value 8592.877671
iter  66 value 8584.047690
iter  67 value 8575.084010
iter  68 value 8565.982016
iter  69 value 8556.736942
iter  70 value 8547.343634
iter  71 value 8537.796673
iter  72 value 8528.090352
iter  73 value 8518.218621
iter  74 value 8508.175046
iter  75 value 8497.952836
iter  76 value 8487.544709
iter  77 value 8476.942938
iter  78 value 8466.139298
iter  79 value 8455.125018
iter  80 value 8443.890691
iter  81 value 8432.426232
iter  82 value 8420.720826
iter  83 value 8408.762901
iter  84 value 8396.539923
iter  85 value 8384.038436
iter  86 value 8371.243830
iter  87 value 8358.140323
iter  88 value 8344.710776
iter  89 value 8330.936533
iter  90 value 8316.797196
iter  91 value 8302.270522
iter  92 value 8287.332082
iter  93 value 8271.954993
iter  94 value 8256.109582
iter  95 value 8239.762962
iter  96 value 8222.878669
iter  97 value 8205.415901
iter  98 value 8187.328996
iter  99 value 8168.566582
iter 100 value 8149.070508
final  value 8149.070508 
stopped after 100 iterations
$par
[1] 426.1884 510.7464 173.0802

$value
[1] 8149.071

$counts
function gradient 
     103      100 

$convergence
[1] 1

$message
NULL

$hessian
              [,1]         [,2]
[1,] -1.232593e-03 1.397552e-03
[2,]  1.397552e-03 2.807610e-03
[3,] -2.262368e-05 8.003553e-05
              [,3]
[1,] -2.262368e-05
[2,]  8.003553e-05
[3,] -2.170464e-02
SE = sqrt(diag(solve(est$hessian)))
Warning: NaNs produced
cbind(estimate=c(phi=est$par[1],sigw=est$par[2],sigv=est$par[3]), SE)
     estimate       SE
phi  426.1884      NaN
sigw 510.7464 15.08872
sigv 173.0802      NaN
ks =  Ksmooth0(num, rf_price$close, A=1,mu0=0, Sigma0=10, est$par[1], est$par[2], est$par[3])
tsplot(rf_price$close, type='o', col=4, pch=20)
lines(ks$xf, col=6, lwd=2)

NA
NA
NA
NA
NA
NA
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpBIGxvb2sgYXQgdmFyaW91cyBmaWx0ZXIgYW5kIHNtb290aGluZyBtb2RlbHMgaW4gUiB3aXRoIGxpYnJhcmllcyBmcm9tIG1hc3Moc3RydWN0VCwgdHNTbW9vdGgsIGthbG1hbkxpa2UgZXRjLiksYnkgVmVuYWJsZXMgJiBSaXBsZXkuIEtGQVMsIEthbG1hbiBGaWx0ZXIgYW5kIFNtb290aGVyIGZvciBFeHBvbmVudGlhbCBGYW1pbHkgU3RhdGUgU3BhY2UgTW9kZWxzLGJ5IEpvdW5pZSBIZWxza2UsYW5kIGF0c2EgZnJvbSBTSHVtd2F5IGFuZCBTdG9mZmVyIHRvIGFjY29tcGFueSB0aGVpciBib29rIERhdGEgc2V0cyBhbmQgc2NyaXB0cyB0byBhY2NvbXBhbnkgVGltZSBTZXJpZXMgQW5hbHlzaXMgYW5kIEl0cyBBcHBsaWNhdGlvbnM6IFdpdGggUiBFeGFtcGxlcyAoNHRoIGVkKSwgYnkgUi5ILiBTaHVtd2F5IGFuZCBELlMuIFN0b2ZmZXIuIFNwcmluZ2VyIFRleHRzIGluIFN0YXRpc2ljcy4gUm9iIEh5bmRtYW5zIGZvcmVjYXN0IHBhY2thZ2UuKG5vdyB1cGRhdGVkIGFzIGZhYmxlIGluIHRpZHltb2RlbHMpDQoNCmBgYHtyLCBlY2hvPUZBTFNFLGVycm9yPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHRpZHlxdWFudCkNCmxpYnJhcnkoZkJhc2ljcykNCmxpYnJhcnkoZm9yZWNhc3QpDQpsaWJyYXJ5KHRzYm94KQ0KDQoNCmBgYA0KDQpgYGB7cixlY2hvPUZBTFNFLGVycm9yPUZBTFNFfQ0Kc3RhcnRfZCA8LSBhcy5EYXRlKCIyMDE5LTEtMDEiKQ0KDQpnZXRTeW1ib2xzKCJeVklYIiwgZnJvbSA9IHN0YXJ0X2QpDQoNCiMgVFNfYm94IGNvbW1hbmQgbmV4dCBBZ25vc3RpYyB0aW1lc2VyaWVzIHBhY2thZ2UgY29udmVyc2lvbiB0byB0cyB0aW1lc2VyaWVzIFIgZGVmYXVsdCBuZWVkZWQgZm9yIHN0YXRzIGxpYiwgU3RydWN0VFMsIEthbG1hbkxpa2UgZXRjLg0Kdml4IDwtIFZJWCRWSVguQWRqdXN0ZWQNCnZpeCA8LSB0c190cyh2aXgpDQoNCiMgdGhlIGFib3ZlIGRpZmZlcmVudCBzYW1wbGVzIHdlcmUgdHJpYWwgdGVzdHMgZGF0YSB0eXBlcyBsZWZ0IGZvciByZXByb2R1Y2liaWxpdHksIHN5bWJvbCBjaGFuZ2VkIGZyb20gdml4IHRvIDIwMTcgdG8gXnZpeCAyMDE5LTIxDQoNCmBgYA0KDQpgYGB7cn0NCmZpdHZpeCA8LSBTdHJ1Y3RUUyh2aXgsICJsZXZlbCIpDQpmaXR2aXgNClN0cnVjdFRTKHggPSB2aXgsIHR5cGUgPSAibGV2ZWwiKQ0KDQpwbG90KHZpeCwgY29sID0gImJsdWUiKQ0KbGluZXMoZml0dGVkKGZpdHZpeCksIGx0eSA9ImRhc2hlZCIsIGx3ZCA9MikNCg0KbGluZXModHNTbW9vdGgoZml0dml4KSxsdHkgPSAiZG90dGVkIiwgbHdkID0yKQ0KcGxvdChmb3JlY2FzdChmaXR2aXgpKQ0KIyByZWFycmFuZ2VkIG5vdCByZWFzb24gZm9yIGthbG1hbiBlc3QgdW5maXQgaWUuIGZvcmVjYXN0IGNvbW1hbmQNCg0KI2xpbmVzKGthbG1hbl9lc3QsIGx0eSA9ICJkb3R0ZWQiLCAsbHdkID0gMiwgY29sID0gInllbGxvdyIpDQojIHRoZSBrYWxtYW4gZXN0IGZpdCBkaWQgbm90IHJ1biwgc3ludGF4IG9yIGxvZ2ljIGVycm9yLCBmb3IgcmVhZGVyIHRvIHB1cnN1ZSwga2FsbWFuIGZpdCBiZWxvdy4NCmBgYA0KDQpgYGB7cn0NCiMgYW4gQVJJTUEgZml0DQpmaXQzIDwtIGFyaW1hKHZpeCwgYygxLCAxLCAwKSkNCnByZWRpY3QoZml0MywgMTIpDQojIyByZWNvbnN0cnVjdCB0aGlzDQpwciA8LSBLYWxtYW5Gb3JlY2FzdCgxMiwgZml0MyRtb2RlbCkNCnByJHByZWQgKyBmaXQzJGNvZWZbNF0NCnNxcnQocHIkdmFyICogZml0MyRzaWdtYTIpDQojIyBhbmQgbm93IGRvIGl0IHllYXIgYnkgeWVhcg0KbW9kIDwtIGZpdDMkbW9kZWwNCmZvcih5IGluIDE6Mykgew0KICBwciA8LSBLYWxtYW5Gb3JlY2FzdCg0LCBtb2QsIFRSVUUpDQogIHByaW50KGxpc3QocHJlZCA9IHByJHByZWQgKyBmaXQzJGNvZWZbImludGVyY2VwdCJdLA0KICAgICAgICAgICAgIHNlID0gc3FydChwciR2YXIgKiBmaXQzJHNpZ21hMikpKQ0KICBtb2QgPC0gYXR0cihwciwgIm1vZCIpDQp9DQoNCmBgYA0KDQpgYGB7cn0NCmZpdF9rYWxtYW4gPC0gS2FsbWFuTGlrZSh2aXgsIG1vZCwgbml0ID0gMEwsIHVwZGF0ZSA9IEZBTFNFKQ0Kb3V0IDwtIEthbG1hblNtb290aCh2aXgsIG1vZCwgbml0ID0gMEwpDQprYWxtYW5fZXN0IDwtIG91dCRzbW9vdGhbICwyXQ0KcGxvdC50cyh2aXgpDQpwbG90KGthbG1hbl9lc3QsIGx0eSA9ICJkYXNoZWQiLCBsd2QgPSAyLGNvbCA9ICJncmVlbiIpDQp2aXggPC0gIHRzX3RpbWVTZXJpZXModml4KQ0KaGlzdFBsb3Qodml4KQ0KDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KEtGQVMpDQpsaWJyYXJ5KHRzZXJpZXMpDQpsaWJyYXJ5KHRpbWVTZXJpZXMpDQpsaWJyYXJ5KHpvbykNCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KDQoNCmBgYA0KDQpTdGFydCBLYWxtYW4gY29kZSB3aXRoIHN0cnVjdHVyYWwgdGltZSBzZXJpZXMuIFVzaW5nIEtGQVMgbGlicmFyeQ0KDQpgYGB7cn0NCmdldFN5bWJvbHMoIlNQWSIsICBmcm9tID0gYXMuRGF0ZSgiMjAyMS0wMS0wMSIpLA0KICAgICAgICAgICBlbmQgPSBhcy5EYXRlKCIyMDIyLTEwLTMxIiksDQogICAgICAgICAgIHF1b3RlID0gIkNsb3NlIikNCmNscyA8LSBTUFkkU1BZLkNsb3NlDQoNCg0KDQpzcF9yIDwtIGRhaWx5UmV0dXJuKFNQWSkNCg0Kc3BfciA8LSBhcy50cyhzcF9yKQ0KDQpmaXRfc3RydWN0dXJhbCAgPC0gIFNTTW9kZWwoc3BfciB+IFNTTXRyZW5kKDEsIFEgPSBsaXN0KG1hdHJpeChOQSkpKSwgSCA9IG1hdHJpeChOQSkpDQoNCiBmaXRfc3RydWN0dXJhbCA8LSBmaXRTU00oZml0X3N0cnVjdHVyYWwsIGluaXRzID0gYygwLCAwKSxtZXRob2QgPSAiQkZHUyIpDQoNCiBmaXRfc3RydWN0dXJhbCRtb2RlbFsiUSJdDQoNCmBgYA0KDQpQbG90IHJldHVybnMgbW9kZWwgYW5kIHN0YXJ0IHByaWNlIHNlcmllcyBtb2RlbCBhbmQgcGxvdC4NCg0KYGBge3J9DQpwbG90KGZpdF9zdHJ1Y3R1cmFsJG1vZGVsKQ0KDQpmaXRfc3RydWN0dXJhbDIgIDwtICBTU01vZGVsKGNscyB+IFNTTXRyZW5kKDEsIFEgPSBsaXN0KG1hdHJpeChOQSkpKSwgSCA9IG1hdHJpeChOQSkpDQoNCg0KZml0X3N0cnVjdHVyYWwyIDwtIGZpdFNTTShmaXRfc3RydWN0dXJhbDIsIGluaXRzID0gYygwLCAwKSxtZXRob2QgPSAiQkZHUyIpDQoNCmZpdF9zdHJ1Y3R1cmFsMiRtb2RlbFsiUSJdDQoNCnN0cihmaXRfc3RydWN0dXJhbDIkbW9kZWwkeSkNCg0KDQpwbG90KGZpdF9zdHJ1Y3R1cmFsMiRtb2RlbCR5KQ0KDQpwbG90KGZpdF9zdHJ1Y3R1cmFsMiRtb2RlbCR5LCBjbHMpDQoNCnBsb3QoKGZpdF9zdHJ1Y3R1cmFsMiRtb2RlbCR5KSwgbHR5ID0gImRvdHRlZCIsIGx3ZCA9MikNCg0KDQpmaXQgPC0gZm9yZWNhc3QoZml0X3N0cnVjdHVyYWwyJG1vZGVsJHksIGggPSAxMCApDQpwbG90KGZpdCkNCg0KYGBgDQoNCmthbG1hbiBmaWx0ZXIgdXNpbmcgYXRzYSBsaWJyYXJ5Lg0KDQpgYGB7cn0NCmxpYnJhcnkocXVhbnRtb2QpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkodHNib3gpDQpsaWJyYXJ5KHRpZHlxdWFudCkNCmxpYnJhcnkoZm9yZWNhc3QpDQoNCg0KYGBgDQoNCnN0YXJ0IGRvd25sb2FkaW5nIFJGIGRhdGEgc3RvY2sgdGlja2VyIFJlZ2lvbmFsIEZpbmFuY2UgY29ycC4gYmFzZSBjb21wYXJpc29uIG5haXZlIG1vZGVsIGZvcmVjYXN0Lg0KDQpgYGB7cn0NCnJmX3ByaWNlIDwtIHRxX2dldCgiUkYiLCBmcm9tID0gIjIwMjAtMDEtMDEiKQ0KDQpyZl90cyA8LSBhcy50cyhyZl9wcmljZSkNCg0KDQoNCm5fZmMgPC0gbmFpdmUoDQogIHJmX3ByaWNlJGNsb3NlLA0KICBoID0gMTAsDQogIGxldmVsID0gYyg4MCwgOTUpLA0KICBmYW4gPSBGQUxTRSwNCiAgbGFtYmRhID0gTlVMTCwNCiAgYmlhc2FkaiA9IEZBTFNFLA0KICB4ID0gcmZfcHJpY2UkY2xvc2UNCikNCg0KYXV0b3Bsb3Qobl9mYykNCg0KDQoNCmBgYA0KDQpzdGFydCBzdHJ1Y3R0cyBjb2RlDQoNCmBgYHtyfQ0KICBmaXQgPC0gU3RydWN0VFMocmZfcHJpY2UkY2xvc2UsIHR5cGUgPSAibGV2ZWwiKQ0KI2lmIChzdHJ1Y3QkY29kZSAhPSAwKSBzdG9wKCJvcHRpbWl6ZXIgZGlkIG5vdCBjb252ZXJnZSIpDQoNCnNtb290aGVkIDwtIHRzU21vb3RoKGZpdCkNCnN0cihzbW9vdGhlZCkNCg0KDQojdHNkaWFnKGZpdCkNCg0KcGxvdChyZl9wcmljZSRjbG9zZSwgdHlwZSA9ICJsIiAsIGx3ZCA9MSkNCmxpbmVzKGZpdHRlZChmaXQpLCBsdHkgPSAiZGFzaGVkIiwgbHdkID0gMiwgY29sID0gImdyZWVuIikNCmxpbmVzKHRzU21vb3RoKGZpdCksIGx0eSA9ImRvdHRlZCIsIGx3ZCA9IDIsIGNvbCA9ICJibHVlIikNCnBsb3QoZm9yZWNhc3QoZml0LCBoPSAyMCkpDQoNCg0KYGBgDQoNCnN0YXJ0IGF0c2EgY29kZQ0KDQpgYGB7cn0NCmxpYnJhcnkoYXN0c2EpDQoNCmZpdDIgPC0gc3NtKHJmX3ByaWNlJGNsb3NlLEE9MSwgYWxwaGE9LjAxLCBwaGk9MSwgc2lndz0uMDEsIHNpZ3Y9LjEpDQp0c3Bsb3QocmZfcHJpY2UkY2xvc2UsIGNvbD00LCB0eXBlPSJvIiwgcGNoPTIwLCB5bGFiPSJSRiBQcmljZSIpDQpsaW5lcyhmaXQyJFhzLCBjb2w9NiwgbHdkPTIpDQp4eCA9IGModGltZShmaXQyJFhzKSwgcmV2KHRpbWUoZml0MiRYcykpKQ0KeXkgPSBjKGZpdDIkWHMtMipzcXJ0KGZpdDIkUHMpLCByZXYoZml0MiRYcysyKnNxcnQoZml0MiRQcykpKQ0KcG9seWdvbih4eCwgeXksIGJvcmRlcj04LCBjb2w9Z3JheSguNiwgYWxwaGE9LjI1KSApDQoNCm51bSA9IENPVU5UKHJmX3ByaWNlJGNsb3NlKQ0KDQoNCkxpbm4gID0gZnVuY3Rpb24ocGFyYSl7DQogIHBoaSA9IHBhcmFbMV07IHNpZ3cgPSBwYXJhWzJdOyBzaWd2ID0gcGFyYVszXQ0KICBrZiAgPSBLZmlsdGVyMChudW0sIHJmX3ByaWNlJGNsb3NlLCBBPTEsIG11MD0wLCBTaWdtYTA9MTAsIHBoaSwgc2lndywgc2lndikNCiAgcmV0dXJuKGtmJGxpa2UpDQp9DQoNCg0KIyBFc3RpbWF0aW9uDQppbml0LnBhciA9IGMoLjEsIDEsIDEpICAgIyBpbml0aWFsIHBhcmFtZXRlciB2YWx1ZXMNCihlc3QgPSBvcHRpbShpbml0LnBhciwgTGlubiwgZ3I9TlVMTCwgbWV0aG9kPSJCRkdTIiwgaGVzc2lhbj1UUlVFLCBjb250cm9sPWxpc3QodHJhY2U9MSxSRVBPUlQ9MSkpKQ0KDQoNClNFID0gc3FydChkaWFnKHNvbHZlKGVzdCRoZXNzaWFuKSkpDQpjYmluZChlc3RpbWF0ZT1jKHBoaT1lc3QkcGFyWzFdLHNpZ3c9ZXN0JHBhclsyXSxzaWd2PWVzdCRwYXJbM10pLCBTRSkNCg0KDQprcyA9ICBLc21vb3RoMChudW0sIHJmX3ByaWNlJGNsb3NlLCBBPTEsbXUwPTAsIFNpZ21hMD0xMCwgZXN0JHBhclsxXSwgZXN0JHBhclsyXSwgZXN0JHBhclszXSkNCnRzcGxvdChyZl9wcmljZSRjbG9zZSwgdHlwZT0nbycsIGNvbD00LCBwY2g9MjApDQpsaW5lcyhrcyR4ZiwgY29sPTYsIGx3ZD0yKQ0KDQoNCg0KDQoNCg0KYGBgDQo=