Black Scholes Merton Model with Generalized Pareto Distribution as tail distribution in option pricing.

# USD/CAD Options Pricing with Black-Scholes and GPD Tails
# Install required packages if not already installed
# install.packages(c("quantmod", "evir", "MASS"))

library(quantmod)
library(evir)
library(MASS)
library(tidyverse)


# Step 1: Fetch USD/CAD data
cat("Fetching USD/CAD data...\n")
## Fetching USD/CAD data...
getSymbols("CADUSD=X", src = "yahoo", from = "2020-01-01", auto.assign = TRUE)
## [1] "CADUSD=X"
usdcad <- `CADUSD=X`
prices <- na.omit(Cl(usdcad))

# Calculate log returns
returns <- diff(log(prices))
returns <- na.omit(returns)

# Current spot price
S0 <- as.numeric(tail(prices, 1))
cat(sprintf("Current USD/CAD spot price: %.4f\n", S0))
## Current USD/CAD spot price: 0.7252
# Step 2: Fit Generalized Pareto Distribution to tails
cat("\nFitting GPD to tail distributions...\n")
## 
## Fitting GPD to tail distributions...
# Define threshold (95th percentile for right tail, 5th for left tail)
threshold_upper <- quantile(returns, 0.95)
threshold_lower <- quantile(returns, 0.05)

# Fit GPD to upper tail (for calls - right tail risk)
upper_exceedances <- returns[returns > threshold_upper] - threshold_upper
gpd_upper <- gpd(as.numeric(returns), threshold = as.numeric(threshold_upper))

# Fit GPD to lower tail (for puts - left tail risk)
lower_exceedances <- abs(returns[returns < threshold_lower] - threshold_lower)
gpd_lower <- gpd(-as.numeric(returns), threshold = -as.numeric(threshold_lower))

cat(sprintf("Upper tail threshold: %.6f\n", threshold_upper))
## Upper tail threshold: 0.006802
cat(sprintf(
  "GPD upper tail shape parameter (xi): %.4f\n",
  gpd_upper$par.ests[1]
))
## GPD upper tail shape parameter (xi): 0.2664
cat(sprintf(
  "GPD upper tail scale parameter (beta): %.6f\n",
  gpd_upper$par.ests[2]
))
## GPD upper tail scale parameter (beta): 0.002055
# Step 3: Calculate volatility incorporating tail behavior
# Standard volatility
vol_standard <- sd(returns) * sqrt(252)

# Adjusted volatility considering GPD tails
vol_adj <- sd(returns) * sqrt(252) * (1 + abs(gpd_upper$par.ests[1]) * 0.5)

cat(sprintf(
  "\nStandard volatility: %.4f (%.2f%%)\n",
  vol_standard,
  vol_standard * 100
))
## 
## Standard volatility: 0.0688 (6.88%)
cat(sprintf("GPD-adjusted volatility: %.4f (%.2f%%)\n", vol_adj, vol_adj * 100))
## GPD-adjusted volatility: 0.0779 (7.79%)
# Step 4: Black-Scholes with GPD adjustment
black_scholes_gpd <- function(S, K, T, r, sigma, type = "call", gpd_shape = 0) {
  # Adjust for tail risk
  tail_adj <- 1 + abs(gpd_shape) * sqrt(T)
  sigma_adj <- sigma * tail_adj

  d1 <- (log(S / K) + (r + 0.5 * sigma_adj^2) * T) / (sigma_adj * sqrt(T))
  d2 <- d1 - sigma_adj * sqrt(T)

  if (type == "call") {
    price <- S * pnorm(d1) - K * exp(-r * T) * pnorm(d2)
  } else {
    price <- K * exp(-r * T) * pnorm(-d2) - S * pnorm(-d1)
  }

  return(price)
}

# Step 5: Set parameters and calculate option prices
r <- 0.05 # Risk-free rate (5%)
T_values <- c(1 / 12, 3 / 12, 6 / 12, 1, 1.5, 2) # Time to maturity in years
K_values <- seq(S0 * 0.95, S0 * 1.05, length.out = 6) # Strike prices around spot

# Create results dataframe
results <- data.frame(
  Strike = numeric(),
  Maturity_Months = numeric(),
  Call_Price = numeric(),
  Put_Price = numeric(),
  Call_Standard = numeric(),
  Put_Standard = numeric()
)

cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("OPTIONS PRICING RESULTS\n")
## OPTIONS PRICING RESULTS
cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
# Calculate first 6 call and put prices
for (i in 1:6) {
  K <- K_values[i]
  T <- T_values[min(i, length(T_values))]

  # GPD-adjusted prices
  call_gpd <- black_scholes_gpd(
    S0,
    K,
    T,
    r,
    vol_adj,
    "call",
    gpd_upper$par.ests[1]
  )
  put_gpd <- black_scholes_gpd(
    S0,
    K,
    T,
    r,
    vol_adj,
    "put",
    gpd_lower$par.ests[1]
  )

  # Standard Black-Scholes for comparison
  call_std <- black_scholes_gpd(S0, K, T, r, vol_standard, "call", 0)
  put_std <- black_scholes_gpd(S0, K, T, r, vol_standard, "put", 0)

  results <- rbind(
    results,
    data.frame(
      Strike = K,
      Maturity_Months = T * 12,
      Call_Price = call_gpd,
      Put_Price = put_gpd,
      Call_Standard = call_std,
      Put_Standard = put_std
    )
  )
}

# Display results
print(results[, 1:4], row.names = FALSE)
##     Strike Maturity_Months Call_Price    Put_Price
##  0.6889350               1 0.03918897 5.039225e-05
##  0.7034389               3 0.03324351 2.359645e-03
##  0.7179427               6 0.03371090 7.628362e-03
##  0.7324466              12 0.04449009 1.367433e-02
##  0.7469505              18 0.05417635 1.838785e-02
##  0.7614544              24 0.06327560 2.229187e-02
cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
cat("COMPARISON: GPD-Adjusted vs Standard Black-Scholes\n")
## COMPARISON: GPD-Adjusted vs Standard Black-Scholes
cat("\n", strrep("=", 70), "\n")
## 
##  ======================================================================
results$Call_Diff_Pct <- ((results$Call_Price - results$Call_Standard) /
  results$Call_Standard) *
  100
results$Put_Diff_Pct <- ((results$Put_Price - results$Put_Standard) /
  results$Put_Standard) *
  100

print(
  results[, c("Strike", "Maturity_Months", "Call_Diff_Pct", "Put_Diff_Pct")],
  row.names = FALSE
)
##     Strike Maturity_Months Call_Diff_Pct Put_Diff_Pct
##  0.6889350               1     0.1373236    362.23009
##  0.7034389               3     4.7671427     90.79342
##  0.7179427               6    13.2845361     59.59883
##  0.7324466              12    20.3946395     61.18461
##  0.7469505              18    25.0833565     65.71610
##  0.7614544              24    28.5029061     70.97133
cat("\n\nInterpretation:\n")
## 
## 
## Interpretation:
cat(
  "- Positive difference % means GPD model prices options higher (accounts for tail risk)\n"
)
## - Positive difference % means GPD model prices options higher (accounts for tail risk)
cat("- The GPD adjustment captures fat-tail behavior in currency markets\n")
## - The GPD adjustment captures fat-tail behavior in currency markets
cat("- This is particularly important for out-of-the-money options\n")
## - This is particularly important for out-of-the-money options
## Histogram
returns_df <- data.frame(
  Date = index(returns),
  Returns = as.numeric(returns)
)

# Create histogram with density overlay
p <- ggplot(returns_df, aes(x = Returns)) +
  geom_histogram(
    aes(y = after_stat(density)),
    bins = 50,
    fill = "steelblue",
    alpha = 0.7,
    color = "white"
  ) +
  geom_density(color = "darkred", linewidth = 1.2) +
  geom_vline(
    xintercept = threshold_upper,
    linetype = "dashed",
    color = "darkgreen",
    linewidth = 0.8
  ) +
  geom_vline(
    xintercept = threshold_lower,
    linetype = "dashed",
    color = "darkgreen",
    linewidth = 0.8
  ) +
  labs(
    title = "USD/CAD Log Returns Distribution",
    subtitle = "Histogram with Kernel Density Estimate and GPD Thresholds",
    x = "Log Returns",
    y = "Density"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    plot.subtitle = element_text(hjust = 0.5, size = 10),
    panel.grid.minor = element_blank()
  )

print(p)

LS0tCnRpdGxlOiAiQlNNIE1vZGVsIHdpdGggR1BEIGFzIHRoZSB0YWlsIGRpc3RyaWJ1dGlvbiBpbiBvcHRpb24gcHJpY2luZyIKYXV0aG9yOiAiV2Fzc2ltIElzbWFpbCIKZGF0ZTogIjIwMjUtMTItMDEiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGhpZ2hsaWdodDogdGFuZ28KLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFKQpgYGAKCiMgQmxhY2sgU2Nob2xlcyBNZXJ0b24gTW9kZWwgd2l0aCBHZW5lcmFsaXplZCBQYXJldG8gRGlzdHJpYnV0aW9uIGFzIHRhaWwgZGlzdHJpYnV0aW9uIGluIG9wdGlvbiBwcmljaW5nLgoKYGBge3J9CiMgVVNEL0NBRCBPcHRpb25zIFByaWNpbmcgd2l0aCBCbGFjay1TY2hvbGVzIGFuZCBHUEQgVGFpbHMKIyBJbnN0YWxsIHJlcXVpcmVkIHBhY2thZ2VzIGlmIG5vdCBhbHJlYWR5IGluc3RhbGxlZAojIGluc3RhbGwucGFja2FnZXMoYygicXVhbnRtb2QiLCAiZXZpciIsICJNQVNTIikpCgpsaWJyYXJ5KHF1YW50bW9kKQpsaWJyYXJ5KGV2aXIpCmxpYnJhcnkoTUFTUykKbGlicmFyeSh0aWR5dmVyc2UpCgoKIyBTdGVwIDE6IEZldGNoIFVTRC9DQUQgZGF0YQpjYXQoIkZldGNoaW5nIFVTRC9DQUQgZGF0YS4uLlxuIikKZ2V0U3ltYm9scygiQ0FEVVNEPVgiLCBzcmMgPSAieWFob28iLCBmcm9tID0gIjIwMjAtMDEtMDEiLCBhdXRvLmFzc2lnbiA9IFRSVUUpCgp1c2RjYWQgPC0gYENBRFVTRD1YYApwcmljZXMgPC0gbmEub21pdChDbCh1c2RjYWQpKQoKIyBDYWxjdWxhdGUgbG9nIHJldHVybnMKcmV0dXJucyA8LSBkaWZmKGxvZyhwcmljZXMpKQpyZXR1cm5zIDwtIG5hLm9taXQocmV0dXJucykKCiMgQ3VycmVudCBzcG90IHByaWNlClMwIDwtIGFzLm51bWVyaWModGFpbChwcmljZXMsIDEpKQpjYXQoc3ByaW50ZigiQ3VycmVudCBVU0QvQ0FEIHNwb3QgcHJpY2U6ICUuNGZcbiIsIFMwKSkKCiMgU3RlcCAyOiBGaXQgR2VuZXJhbGl6ZWQgUGFyZXRvIERpc3RyaWJ1dGlvbiB0byB0YWlscwpjYXQoIlxuRml0dGluZyBHUEQgdG8gdGFpbCBkaXN0cmlidXRpb25zLi4uXG4iKQoKIyBEZWZpbmUgdGhyZXNob2xkICg5NXRoIHBlcmNlbnRpbGUgZm9yIHJpZ2h0IHRhaWwsIDV0aCBmb3IgbGVmdCB0YWlsKQp0aHJlc2hvbGRfdXBwZXIgPC0gcXVhbnRpbGUocmV0dXJucywgMC45NSkKdGhyZXNob2xkX2xvd2VyIDwtIHF1YW50aWxlKHJldHVybnMsIDAuMDUpCgojIEZpdCBHUEQgdG8gdXBwZXIgdGFpbCAoZm9yIGNhbGxzIC0gcmlnaHQgdGFpbCByaXNrKQp1cHBlcl9leGNlZWRhbmNlcyA8LSByZXR1cm5zW3JldHVybnMgPiB0aHJlc2hvbGRfdXBwZXJdIC0gdGhyZXNob2xkX3VwcGVyCmdwZF91cHBlciA8LSBncGQoYXMubnVtZXJpYyhyZXR1cm5zKSwgdGhyZXNob2xkID0gYXMubnVtZXJpYyh0aHJlc2hvbGRfdXBwZXIpKQoKIyBGaXQgR1BEIHRvIGxvd2VyIHRhaWwgKGZvciBwdXRzIC0gbGVmdCB0YWlsIHJpc2spCmxvd2VyX2V4Y2VlZGFuY2VzIDwtIGFicyhyZXR1cm5zW3JldHVybnMgPCB0aHJlc2hvbGRfbG93ZXJdIC0gdGhyZXNob2xkX2xvd2VyKQpncGRfbG93ZXIgPC0gZ3BkKC1hcy5udW1lcmljKHJldHVybnMpLCB0aHJlc2hvbGQgPSAtYXMubnVtZXJpYyh0aHJlc2hvbGRfbG93ZXIpKQoKY2F0KHNwcmludGYoIlVwcGVyIHRhaWwgdGhyZXNob2xkOiAlLjZmXG4iLCB0aHJlc2hvbGRfdXBwZXIpKQpjYXQoc3ByaW50ZigKICAiR1BEIHVwcGVyIHRhaWwgc2hhcGUgcGFyYW1ldGVyICh4aSk6ICUuNGZcbiIsCiAgZ3BkX3VwcGVyJHBhci5lc3RzWzFdCikpCmNhdChzcHJpbnRmKAogICJHUEQgdXBwZXIgdGFpbCBzY2FsZSBwYXJhbWV0ZXIgKGJldGEpOiAlLjZmXG4iLAogIGdwZF91cHBlciRwYXIuZXN0c1syXQopKQoKIyBTdGVwIDM6IENhbGN1bGF0ZSB2b2xhdGlsaXR5IGluY29ycG9yYXRpbmcgdGFpbCBiZWhhdmlvcgojIFN0YW5kYXJkIHZvbGF0aWxpdHkKdm9sX3N0YW5kYXJkIDwtIHNkKHJldHVybnMpICogc3FydCgyNTIpCgojIEFkanVzdGVkIHZvbGF0aWxpdHkgY29uc2lkZXJpbmcgR1BEIHRhaWxzCnZvbF9hZGogPC0gc2QocmV0dXJucykgKiBzcXJ0KDI1MikgKiAoMSArIGFicyhncGRfdXBwZXIkcGFyLmVzdHNbMV0pICogMC41KQoKY2F0KHNwcmludGYoCiAgIlxuU3RhbmRhcmQgdm9sYXRpbGl0eTogJS40ZiAoJS4yZiUlKVxuIiwKICB2b2xfc3RhbmRhcmQsCiAgdm9sX3N0YW5kYXJkICogMTAwCikpCmNhdChzcHJpbnRmKCJHUEQtYWRqdXN0ZWQgdm9sYXRpbGl0eTogJS40ZiAoJS4yZiUlKVxuIiwgdm9sX2Fkaiwgdm9sX2FkaiAqIDEwMCkpCgojIFN0ZXAgNDogQmxhY2stU2Nob2xlcyB3aXRoIEdQRCBhZGp1c3RtZW50CmJsYWNrX3NjaG9sZXNfZ3BkIDwtIGZ1bmN0aW9uKFMsIEssIFQsIHIsIHNpZ21hLCB0eXBlID0gImNhbGwiLCBncGRfc2hhcGUgPSAwKSB7CiAgIyBBZGp1c3QgZm9yIHRhaWwgcmlzawogIHRhaWxfYWRqIDwtIDEgKyBhYnMoZ3BkX3NoYXBlKSAqIHNxcnQoVCkKICBzaWdtYV9hZGogPC0gc2lnbWEgKiB0YWlsX2FkagoKICBkMSA8LSAobG9nKFMgLyBLKSArIChyICsgMC41ICogc2lnbWFfYWRqXjIpICogVCkgLyAoc2lnbWFfYWRqICogc3FydChUKSkKICBkMiA8LSBkMSAtIHNpZ21hX2FkaiAqIHNxcnQoVCkKCiAgaWYgKHR5cGUgPT0gImNhbGwiKSB7CiAgICBwcmljZSA8LSBTICogcG5vcm0oZDEpIC0gSyAqIGV4cCgtciAqIFQpICogcG5vcm0oZDIpCiAgfSBlbHNlIHsKICAgIHByaWNlIDwtIEsgKiBleHAoLXIgKiBUKSAqIHBub3JtKC1kMikgLSBTICogcG5vcm0oLWQxKQogIH0KCiAgcmV0dXJuKHByaWNlKQp9CgojIFN0ZXAgNTogU2V0IHBhcmFtZXRlcnMgYW5kIGNhbGN1bGF0ZSBvcHRpb24gcHJpY2VzCnIgPC0gMC4wNSAjIFJpc2stZnJlZSByYXRlICg1JSkKVF92YWx1ZXMgPC0gYygxIC8gMTIsIDMgLyAxMiwgNiAvIDEyLCAxLCAxLjUsIDIpICMgVGltZSB0byBtYXR1cml0eSBpbiB5ZWFycwpLX3ZhbHVlcyA8LSBzZXEoUzAgKiAwLjk1LCBTMCAqIDEuMDUsIGxlbmd0aC5vdXQgPSA2KSAjIFN0cmlrZSBwcmljZXMgYXJvdW5kIHNwb3QKCiMgQ3JlYXRlIHJlc3VsdHMgZGF0YWZyYW1lCnJlc3VsdHMgPC0gZGF0YS5mcmFtZSgKICBTdHJpa2UgPSBudW1lcmljKCksCiAgTWF0dXJpdHlfTW9udGhzID0gbnVtZXJpYygpLAogIENhbGxfUHJpY2UgPSBudW1lcmljKCksCiAgUHV0X1ByaWNlID0gbnVtZXJpYygpLAogIENhbGxfU3RhbmRhcmQgPSBudW1lcmljKCksCiAgUHV0X1N0YW5kYXJkID0gbnVtZXJpYygpCikKCmNhdCgiXG4iLCBzdHJyZXAoIj0iLCA3MCksICJcbiIpCgpjYXQoIk9QVElPTlMgUFJJQ0lORyBSRVNVTFRTXG4iKQpjYXQoIlxuIiwgc3RycmVwKCI9IiwgNzApLCAiXG4iKQoKIyBDYWxjdWxhdGUgZmlyc3QgNiBjYWxsIGFuZCBwdXQgcHJpY2VzCmZvciAoaSBpbiAxOjYpIHsKICBLIDwtIEtfdmFsdWVzW2ldCiAgVCA8LSBUX3ZhbHVlc1ttaW4oaSwgbGVuZ3RoKFRfdmFsdWVzKSldCgogICMgR1BELWFkanVzdGVkIHByaWNlcwogIGNhbGxfZ3BkIDwtIGJsYWNrX3NjaG9sZXNfZ3BkKAogICAgUzAsCiAgICBLLAogICAgVCwKICAgIHIsCiAgICB2b2xfYWRqLAogICAgImNhbGwiLAogICAgZ3BkX3VwcGVyJHBhci5lc3RzWzFdCiAgKQogIHB1dF9ncGQgPC0gYmxhY2tfc2Nob2xlc19ncGQoCiAgICBTMCwKICAgIEssCiAgICBULAogICAgciwKICAgIHZvbF9hZGosCiAgICAicHV0IiwKICAgIGdwZF9sb3dlciRwYXIuZXN0c1sxXQogICkKCiAgIyBTdGFuZGFyZCBCbGFjay1TY2hvbGVzIGZvciBjb21wYXJpc29uCiAgY2FsbF9zdGQgPC0gYmxhY2tfc2Nob2xlc19ncGQoUzAsIEssIFQsIHIsIHZvbF9zdGFuZGFyZCwgImNhbGwiLCAwKQogIHB1dF9zdGQgPC0gYmxhY2tfc2Nob2xlc19ncGQoUzAsIEssIFQsIHIsIHZvbF9zdGFuZGFyZCwgInB1dCIsIDApCgogIHJlc3VsdHMgPC0gcmJpbmQoCiAgICByZXN1bHRzLAogICAgZGF0YS5mcmFtZSgKICAgICAgU3RyaWtlID0gSywKICAgICAgTWF0dXJpdHlfTW9udGhzID0gVCAqIDEyLAogICAgICBDYWxsX1ByaWNlID0gY2FsbF9ncGQsCiAgICAgIFB1dF9QcmljZSA9IHB1dF9ncGQsCiAgICAgIENhbGxfU3RhbmRhcmQgPSBjYWxsX3N0ZCwKICAgICAgUHV0X1N0YW5kYXJkID0gcHV0X3N0ZAogICAgKQogICkKfQoKIyBEaXNwbGF5IHJlc3VsdHMKcHJpbnQocmVzdWx0c1ssIDE6NF0sIHJvdy5uYW1lcyA9IEZBTFNFKQoKY2F0KCJcbiIsIHN0cnJlcCgiPSIsIDcwKSwgIlxuIikKY2F0KCJDT01QQVJJU09OOiBHUEQtQWRqdXN0ZWQgdnMgU3RhbmRhcmQgQmxhY2stU2Nob2xlc1xuIikKY2F0KCJcbiIsIHN0cnJlcCgiPSIsIDcwKSwgIlxuIikKCnJlc3VsdHMkQ2FsbF9EaWZmX1BjdCA8LSAoKHJlc3VsdHMkQ2FsbF9QcmljZSAtIHJlc3VsdHMkQ2FsbF9TdGFuZGFyZCkgLwogIHJlc3VsdHMkQ2FsbF9TdGFuZGFyZCkgKgogIDEwMApyZXN1bHRzJFB1dF9EaWZmX1BjdCA8LSAoKHJlc3VsdHMkUHV0X1ByaWNlIC0gcmVzdWx0cyRQdXRfU3RhbmRhcmQpIC8KICByZXN1bHRzJFB1dF9TdGFuZGFyZCkgKgogIDEwMAoKcHJpbnQoCiAgcmVzdWx0c1ssIGMoIlN0cmlrZSIsICJNYXR1cml0eV9Nb250aHMiLCAiQ2FsbF9EaWZmX1BjdCIsICJQdXRfRGlmZl9QY3QiKV0sCiAgcm93Lm5hbWVzID0gRkFMU0UKKQoKY2F0KCJcblxuSW50ZXJwcmV0YXRpb246XG4iKQpjYXQoCiAgIi0gUG9zaXRpdmUgZGlmZmVyZW5jZSAlIG1lYW5zIEdQRCBtb2RlbCBwcmljZXMgb3B0aW9ucyBoaWdoZXIgKGFjY291bnRzIGZvciB0YWlsIHJpc2spXG4iCikKY2F0KCItIFRoZSBHUEQgYWRqdXN0bWVudCBjYXB0dXJlcyBmYXQtdGFpbCBiZWhhdmlvciBpbiBjdXJyZW5jeSBtYXJrZXRzXG4iKQpjYXQoIi0gVGhpcyBpcyBwYXJ0aWN1bGFybHkgaW1wb3J0YW50IGZvciBvdXQtb2YtdGhlLW1vbmV5IG9wdGlvbnNcbiIpCgoKIyMgSGlzdG9ncmFtCnJldHVybnNfZGYgPC0gZGF0YS5mcmFtZSgKICBEYXRlID0gaW5kZXgocmV0dXJucyksCiAgUmV0dXJucyA9IGFzLm51bWVyaWMocmV0dXJucykKKQoKIyBDcmVhdGUgaGlzdG9ncmFtIHdpdGggZGVuc2l0eSBvdmVybGF5CnAgPC0gZ2dwbG90KHJldHVybnNfZGYsIGFlcyh4ID0gUmV0dXJucykpICsKICBnZW9tX2hpc3RvZ3JhbSgKICAgIGFlcyh5ID0gYWZ0ZXJfc3RhdChkZW5zaXR5KSksCiAgICBiaW5zID0gNTAsCiAgICBmaWxsID0gInN0ZWVsYmx1ZSIsCiAgICBhbHBoYSA9IDAuNywKICAgIGNvbG9yID0gIndoaXRlIgogICkgKwogIGdlb21fZGVuc2l0eShjb2xvciA9ICJkYXJrcmVkIiwgbGluZXdpZHRoID0gMS4yKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSB0aHJlc2hvbGRfdXBwZXIsCiAgICBsaW5ldHlwZSA9ICJkYXNoZWQiLAogICAgY29sb3IgPSAiZGFya2dyZWVuIiwKICAgIGxpbmV3aWR0aCA9IDAuOAogICkgKwogIGdlb21fdmxpbmUoCiAgICB4aW50ZXJjZXB0ID0gdGhyZXNob2xkX2xvd2VyLAogICAgbGluZXR5cGUgPSAiZGFzaGVkIiwKICAgIGNvbG9yID0gImRhcmtncmVlbiIsCiAgICBsaW5ld2lkdGggPSAwLjgKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiVVNEL0NBRCBMb2cgUmV0dXJucyBEaXN0cmlidXRpb24iLAogICAgc3VidGl0bGUgPSAiSGlzdG9ncmFtIHdpdGggS2VybmVsIERlbnNpdHkgRXN0aW1hdGUgYW5kIEdQRCBUaHJlc2hvbGRzIiwKICAgIHggPSAiTG9nIFJldHVybnMiLAogICAgeSA9ICJEZW5zaXR5IgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiLCBzaXplID0gMTQpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCgpwcmludChwKQoKYGBgCg==