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==