setup - libaries & custom functions
# libraries
library(tidyverse) # data wrangling & plotting
library(httr) # api get/post requests
# cnbc api function for later - pulls sector etfs
# data from this table [https://www.cnbc.com/sector-etfs/]
cnbc_api <- function(){
request <- GET("https://quote.cnbc.com/quote-html-webservice/restQuote/symbolType/symbol?symbols=XLE%7CXLF%7CXLU%7CXLI%7CGDX%7CXLK%7CXLV%7CXLY%7CXLP%7CXLB%7CXOP%7CIYR%7CXHB%7CITB%7CVNQ%7CGDXJ%7CIYE%7COIH%7CXME%7CXRT%7CSMH%7CIBB%7CKBE%7CKRE%7CXTL&requestMethod=itv&noform=1&partnerId=2&fund=1&exthrs=1&output=json&events=1")
if(status_code(request) == 200){
contents <- content(request)
cnbc_list <- contents[["FormattedQuoteResult"]][["FormattedQuote"]]
cnbc_data <- lapply(1:length(cnbc_list), function(x){
as.data.frame(cnbc_list[x])}) %>%
bind_rows(.)
return(cnbc_data)
} else {
message(sprintf("Status Code %s - No Data!", status_code(request)))
return()
}
}
setup - downloading cleaned data from other markdown
- option data (from orats), intended to be bare-bones so this can be
done with any api with option contract data
- price data (from yahoo)
# cleaned option data from orats
option_data <- readRDS(file = "data/clean_orats_core.rds")
# cleaned price data from yahoo
price_data <- readRDS(file = "data/clean_price_data.rds")
# samples of both tables
head(option_data, 3)
head(price_data, 3)
data prep - pulling sector etf tbl from cnbc
- will be using these etfs as benchmarks for the relative value
table
# pulling cnbc sector etf table, then displaying a sample
cnbc_tbl <- cnbc_api()
#sample
head(cnbc_tbl, 3)
# filtering for etfs whose data we have in our cleaned tables
etf_tbl <- cnbc_tbl %>%
select("ticker" = symbol,
name) %>%
filter(ticker %in% unique(price_data$ticker))
# sample of final etf table
head(etf_tbl, 3)
data prep - calculating price rate-of-change & preparing to calc
relative value table with energy tickers
- going to calculate a pearson correlation table (with energy tickers
& xle)
# calculating the log rate-of-change of adjclose prices
price_returns <- price_data %>%
group_by(ticker) %>%
arrange(ticker, date) %>%
mutate(price_change = round(log(adj_close/lag(adj_close)), 4)) %>%
ungroup()
# sample
head(price_returns, 3)
# going to filter for tickers that has sector = "Energy" and see how much data for all
# if one ticker has too few - it will tamper with the correlation range since the whole table will remove the data to be equal
price_returns %>%
filter(ticker %in% c(option_data[option_data$sector == "Energy",]$ticker, "XLE")) %>%
count(ticker) %>%
arrange(n)
# calculating pearson correlation with xle & all selected tickers
corr_tbl <- price_returns %>%
filter(ticker %in% c(option_data[option_data$sector == "Energy",]$ticker, "XLE")) %>%
pivot_wider(id_cols = date, names_from = ticker, values_from = price_change) %>%
drop_na() %>%
select(-date) %>%
as.matrix(.) %>%
cor(.) %>%
data.frame(
etf = "XLE",
ticker = row.names(.),
row.names = NULL) %>%
select(etf, ticker, "correlation" = XLE) %>%
arrange(desc(correlation))
# sample of correlation table
# etf = benchmark etf (xle)
# ticker = energy ticker
# correlation = pearson correlation between price log rate-of-change
head(corr_tbl, 3)
data prep - run simple linear regressions for coefficients of energy
tickers ~ xle
- creating “model table” with alpha & beta values
# preparing energy price tbl for the model calculation
energy_price_tbl <- price_returns %>%
filter(ticker %in% c(option_data[option_data$sector == "Energy",]$ticker, "XLE")) %>%
pivot_wider(id_cols = date, names_from = ticker, values_from = price_change) %>%
drop_na()
# sample
head(energy_price_tbl, 3)
# lapply loop to calculate the model of each ticker ~ xle
# binding data frame with their coefficients (alpha & beta)
model_tbl <- lapply(2:length(energy_price_tbl), function(x){
ticker <- names(energy_price_tbl)[x]
coefs <- coefficients(lm(energy_price_tbl[,ticker][[1]] ~ energy_price_tbl[,"XLE"][[1]]))
df <- data.frame(
etf = "XLE",
ticker = ticker,
alpha = coefs[1],
beta = coefs[2],
row.names = NULL)
return(df)}) %>%
bind_rows() %>%
mutate(across(alpha:beta, function(x) round(x, 4)))
# sample
head(model_tbl, 3)
data visualization - joined all tables into an “energy table”
- joined correlation, model & option data tables
- calculated the “iv forecast” with xle 1yr beta
- calculated the difference between the tickers current implied vol
& forecast across each monthly expiry
- graphed a visualization of the absolute difference
between implied vol & forecast vol
- arranged differenced values in descending order
- faceted the data into two plots, “front month” & “second
month”
- filled the column charts by correlation value to xle (the brighter
blue the column, the greater the correlation to xle)
- as expected, tickers least correlation to xle will have a greater
spread to our forecast iv
# joining all tables
# calculating forecast iv & difference between iv-forecast
energy_tbl <- left_join(corr_tbl, model_tbl, by = c("etf", "ticker")) %>%
left_join(option_data, by = "ticker") %>%
rename_all(~str_replace_all(., "atmivm", "iv")) %>%
mutate(across(starts_with("iv"), function(x) round(first(x) * beta, 2), .names = "{.col}_forecast"),
first_month = iv1 - iv1_forecast,
second_month = iv2 - iv2_forecast,
third_month = iv3 - iv3_forecast,
fourth_month = iv4 - iv4_forecast)
# sample
head(energy_tbl, 3)
# flipped column chart of the **absolute** difference between iv & forecast iv
# in descending order, only displaying the front 2 monthlies
energy_tbl %>%
pivot_longer(first_month:second_month) %>%
select(ticker, correlation, name, value) %>%
mutate(value = abs(value)) %>%
ggplot(aes(fct_reorder(ticker, value), value, fill = correlation)) +
geom_col() +
coord_flip() +
facet_wrap(~name, scales = "free") +
labs(title = "energy tickers: current implied vol & forecast implied vol absolute difference",
subtitle = "absolute difference between atm monthly iv & forecast iv (with xle beta 1year)",
x = "energy tickers", y = "absolute implied volatility difference",
caption = "the greater the difference, the hypothetically larger the inefficiency. compare the difference with the correlation to xle. only showcasing the front two monthly expiries.")

final table - energy table
- final table with all calculations from this exercise with tickers
from the energy sector
- again, there were pre-filtering done when cleaning data in another
markdown, refer to that for details
energy_tbl
LS0tDQp0aXRsZTogInJlbGF0aXZlIHZhbHVlIHNjYW5uZXIgZXhlcmNpc2UiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyMgc2V0dXAgLSBsaWJhcmllcyAmIGN1c3RvbSBmdW5jdGlvbnMNCg0KYGBge3Igd2FybmluZz1GQUxTRX0NCiMgbGlicmFyaWVzIA0KbGlicmFyeSh0aWR5dmVyc2UpICMgZGF0YSB3cmFuZ2xpbmcgJiBwbG90dGluZw0KbGlicmFyeShodHRyKSAjIGFwaSBnZXQvcG9zdCByZXF1ZXN0cw0KDQojIGNuYmMgYXBpIGZ1bmN0aW9uIGZvciBsYXRlciAtIHB1bGxzIHNlY3RvciBldGZzDQojIGRhdGEgZnJvbSB0aGlzIHRhYmxlIFtodHRwczovL3d3dy5jbmJjLmNvbS9zZWN0b3ItZXRmcy9dDQpjbmJjX2FwaSA8LSBmdW5jdGlvbigpew0KICByZXF1ZXN0IDwtIEdFVCgiaHR0cHM6Ly9xdW90ZS5jbmJjLmNvbS9xdW90ZS1odG1sLXdlYnNlcnZpY2UvcmVzdFF1b3RlL3N5bWJvbFR5cGUvc3ltYm9sP3N5bWJvbHM9WExFJTdDWExGJTdDWExVJTdDWExJJTdDR0RYJTdDWExLJTdDWExWJTdDWExZJTdDWExQJTdDWExCJTdDWE9QJTdDSVlSJTdDWEhCJTdDSVRCJTdDVk5RJTdDR0RYSiU3Q0lZRSU3Q09JSCU3Q1hNRSU3Q1hSVCU3Q1NNSCU3Q0lCQiU3Q0tCRSU3Q0tSRSU3Q1hUTCZyZXF1ZXN0TWV0aG9kPWl0diZub2Zvcm09MSZwYXJ0bmVySWQ9MiZmdW5kPTEmZXh0aHJzPTEmb3V0cHV0PWpzb24mZXZlbnRzPTEiKQ0KICANCiAgaWYoc3RhdHVzX2NvZGUocmVxdWVzdCkgPT0gMjAwKXsNCiAgICBjb250ZW50cyA8LSBjb250ZW50KHJlcXVlc3QpDQogICAgY25iY19saXN0IDwtIGNvbnRlbnRzW1siRm9ybWF0dGVkUXVvdGVSZXN1bHQiXV1bWyJGb3JtYXR0ZWRRdW90ZSJdXQ0KICAgIGNuYmNfZGF0YSA8LSBsYXBwbHkoMTpsZW5ndGgoY25iY19saXN0KSwgZnVuY3Rpb24oeCl7DQogICAgICBhcy5kYXRhLmZyYW1lKGNuYmNfbGlzdFt4XSl9KSAlPiUgDQogICAgICBiaW5kX3Jvd3MoLikNCiAgICANCiAgICByZXR1cm4oY25iY19kYXRhKQ0KICAgIA0KICB9IGVsc2Ugew0KICAgIG1lc3NhZ2Uoc3ByaW50ZigiU3RhdHVzIENvZGUgJXMgLSBObyBEYXRhISIsIHN0YXR1c19jb2RlKHJlcXVlc3QpKSkNCiAgICByZXR1cm4oKQ0KICB9DQp9DQpgYGANCg0KIyMjIHNldHVwIC0gZG93bmxvYWRpbmcgY2xlYW5lZCBkYXRhIGZyb20gb3RoZXIgbWFya2Rvd24NCi0gb3B0aW9uIGRhdGEgKGZyb20gb3JhdHMpLCBpbnRlbmRlZCB0byBiZSBiYXJlLWJvbmVzIHNvIHRoaXMgY2FuIGJlIGRvbmUgd2l0aCBhbnkgYXBpIHdpdGggb3B0aW9uIGNvbnRyYWN0IGRhdGENCi0gcHJpY2UgZGF0YSAoZnJvbSB5YWhvbykNCg0KYGBge3J9DQojIGNsZWFuZWQgb3B0aW9uIGRhdGEgZnJvbSBvcmF0cw0Kb3B0aW9uX2RhdGEgPC0gcmVhZFJEUyhmaWxlID0gImRhdGEvY2xlYW5fb3JhdHNfY29yZS5yZHMiKQ0KIyBjbGVhbmVkIHByaWNlIGRhdGEgZnJvbSB5YWhvbw0KcHJpY2VfZGF0YSA8LSByZWFkUkRTKGZpbGUgPSAiZGF0YS9jbGVhbl9wcmljZV9kYXRhLnJkcyIpDQoNCiMgc2FtcGxlcyBvZiBib3RoIHRhYmxlcw0KaGVhZChvcHRpb25fZGF0YSwgMykNCmhlYWQocHJpY2VfZGF0YSwgMykNCmBgYA0KDQojIyMgZGF0YSBwcmVwIC0gcHVsbGluZyBzZWN0b3IgZXRmIHRibCBmcm9tIGNuYmMNCi0gd2lsbCBiZSB1c2luZyB0aGVzZSBldGZzIGFzIGJlbmNobWFya3MgZm9yIHRoZSByZWxhdGl2ZSB2YWx1ZSB0YWJsZQ0KDQpgYGB7cn0NCiMgcHVsbGluZyBjbmJjIHNlY3RvciBldGYgdGFibGUsIHRoZW4gZGlzcGxheWluZyBhIHNhbXBsZQ0KY25iY190YmwgPC0gY25iY19hcGkoKQ0KDQojc2FtcGxlDQpoZWFkKGNuYmNfdGJsLCAzKQ0KDQojIGZpbHRlcmluZyBmb3IgZXRmcyB3aG9zZSBkYXRhIHdlIGhhdmUgaW4gb3VyIGNsZWFuZWQgdGFibGVzDQpldGZfdGJsIDwtIGNuYmNfdGJsICU+JQ0KICBzZWxlY3QoInRpY2tlciIgPSBzeW1ib2wsDQogICAgICAgICBuYW1lKSAlPiUNCiAgZmlsdGVyKHRpY2tlciAlaW4lIHVuaXF1ZShwcmljZV9kYXRhJHRpY2tlcikpDQoNCiMgc2FtcGxlIG9mIGZpbmFsIGV0ZiB0YWJsZQ0KaGVhZChldGZfdGJsLCAzKQ0KYGBgDQoNCiMjIyBkYXRhIHByZXAgLSBjYWxjdWxhdGluZyBwcmljZSByYXRlLW9mLWNoYW5nZSAmIHByZXBhcmluZyB0byBjYWxjIHJlbGF0aXZlIHZhbHVlIHRhYmxlIHdpdGggKiplbmVyZ3kqKiB0aWNrZXJzDQotIGdvaW5nIHRvIGNhbGN1bGF0ZSBhIHBlYXJzb24gY29ycmVsYXRpb24gdGFibGUgKHdpdGggZW5lcmd5IHRpY2tlcnMgJiB4bGUpDQoNCmBgYHtyfQ0KIyBjYWxjdWxhdGluZyB0aGUgbG9nIHJhdGUtb2YtY2hhbmdlIG9mIGFkamNsb3NlIHByaWNlcw0KcHJpY2VfcmV0dXJucyA8LSBwcmljZV9kYXRhICU+JQ0KICBncm91cF9ieSh0aWNrZXIpICU+JQ0KICBhcnJhbmdlKHRpY2tlciwgZGF0ZSkgJT4lDQogIG11dGF0ZShwcmljZV9jaGFuZ2UgPSByb3VuZChsb2coYWRqX2Nsb3NlL2xhZyhhZGpfY2xvc2UpKSwgNCkpICU+JQ0KICB1bmdyb3VwKCkNCg0KIyBzYW1wbGUNCmhlYWQocHJpY2VfcmV0dXJucywgMykNCg0KIyBnb2luZyB0byBmaWx0ZXIgZm9yIHRpY2tlcnMgdGhhdCBoYXMgc2VjdG9yID0gIkVuZXJneSIgYW5kIHNlZSBob3cgbXVjaCBkYXRhIGZvciBhbGwNCiMgaWYgb25lIHRpY2tlciBoYXMgdG9vIGZldyAtIGl0IHdpbGwgdGFtcGVyIHdpdGggdGhlIGNvcnJlbGF0aW9uIHJhbmdlIHNpbmNlIHRoZSB3aG9sZSB0YWJsZSB3aWxsIHJlbW92ZSB0aGUgZGF0YSB0byBiZSBlcXVhbA0KcHJpY2VfcmV0dXJucyAlPiUNCiAgZmlsdGVyKHRpY2tlciAlaW4lIGMob3B0aW9uX2RhdGFbb3B0aW9uX2RhdGEkc2VjdG9yID09ICJFbmVyZ3kiLF0kdGlja2VyLCAiWExFIikpICU+JQ0KICBjb3VudCh0aWNrZXIpICU+JQ0KICBhcnJhbmdlKG4pDQoNCiMgY2FsY3VsYXRpbmcgcGVhcnNvbiBjb3JyZWxhdGlvbiB3aXRoIHhsZSAmIGFsbCBzZWxlY3RlZCB0aWNrZXJzDQpjb3JyX3RibCA8LSBwcmljZV9yZXR1cm5zICU+JQ0KICBmaWx0ZXIodGlja2VyICVpbiUgYyhvcHRpb25fZGF0YVtvcHRpb25fZGF0YSRzZWN0b3IgPT0gIkVuZXJneSIsXSR0aWNrZXIsICJYTEUiKSkgJT4lDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBkYXRlLCBuYW1lc19mcm9tID0gdGlja2VyLCB2YWx1ZXNfZnJvbSA9IHByaWNlX2NoYW5nZSkgJT4lDQogIGRyb3BfbmEoKSAlPiUNCiAgc2VsZWN0KC1kYXRlKSAlPiUNCiAgYXMubWF0cml4KC4pICU+JQ0KICBjb3IoLikgJT4lDQogIGRhdGEuZnJhbWUoDQogICAgZXRmID0gIlhMRSIsDQogICAgdGlja2VyID0gcm93Lm5hbWVzKC4pLA0KICAgIHJvdy5uYW1lcyA9IE5VTEwpICU+JQ0KICBzZWxlY3QoZXRmLCB0aWNrZXIsICJjb3JyZWxhdGlvbiIgPSBYTEUpICU+JQ0KICBhcnJhbmdlKGRlc2MoY29ycmVsYXRpb24pKQ0KDQojIHNhbXBsZSBvZiBjb3JyZWxhdGlvbiB0YWJsZQ0KIyBldGYgPSBiZW5jaG1hcmsgZXRmICh4bGUpDQojIHRpY2tlciA9IGVuZXJneSB0aWNrZXINCiMgY29ycmVsYXRpb24gPSBwZWFyc29uIGNvcnJlbGF0aW9uIGJldHdlZW4gcHJpY2UgbG9nIHJhdGUtb2YtY2hhbmdlDQpoZWFkKGNvcnJfdGJsLCAzKQ0KYGBgDQoNCiMjIyBkYXRhIHByZXAgLSBydW4gc2ltcGxlIGxpbmVhciByZWdyZXNzaW9ucyBmb3IgY29lZmZpY2llbnRzIG9mIGVuZXJneSB0aWNrZXJzIH4geGxlDQotIGNyZWF0aW5nICJtb2RlbCB0YWJsZSIgd2l0aCBhbHBoYSAmIGJldGEgdmFsdWVzDQoNCmBgYHtyfQ0KIyBwcmVwYXJpbmcgZW5lcmd5IHByaWNlIHRibCBmb3IgdGhlIG1vZGVsIGNhbGN1bGF0aW9uDQplbmVyZ3lfcHJpY2VfdGJsIDwtIHByaWNlX3JldHVybnMgJT4lDQogIGZpbHRlcih0aWNrZXIgJWluJSBjKG9wdGlvbl9kYXRhW29wdGlvbl9kYXRhJHNlY3RvciA9PSAiRW5lcmd5IixdJHRpY2tlciwgIlhMRSIpKSAlPiUNCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGRhdGUsIG5hbWVzX2Zyb20gPSB0aWNrZXIsIHZhbHVlc19mcm9tID0gcHJpY2VfY2hhbmdlKSAlPiUNCiAgZHJvcF9uYSgpIA0KDQojIHNhbXBsZQ0KaGVhZChlbmVyZ3lfcHJpY2VfdGJsLCAzKQ0KDQojIGxhcHBseSBsb29wIHRvIGNhbGN1bGF0ZSB0aGUgbW9kZWwgb2YgZWFjaCB0aWNrZXIgfiB4bGUgDQojIGJpbmRpbmcgZGF0YSBmcmFtZSB3aXRoIHRoZWlyIGNvZWZmaWNpZW50cyAoYWxwaGEgJiBiZXRhKQ0KbW9kZWxfdGJsIDwtIGxhcHBseSgyOmxlbmd0aChlbmVyZ3lfcHJpY2VfdGJsKSwgZnVuY3Rpb24oeCl7DQogIHRpY2tlciA8LSBuYW1lcyhlbmVyZ3lfcHJpY2VfdGJsKVt4XQ0KICBjb2VmcyA8LSBjb2VmZmljaWVudHMobG0oZW5lcmd5X3ByaWNlX3RibFssdGlja2VyXVtbMV1dIH4gZW5lcmd5X3ByaWNlX3RibFssIlhMRSJdW1sxXV0pKQ0KICANCiAgZGYgPC0gZGF0YS5mcmFtZSgNCiAgICBldGYgPSAiWExFIiwNCiAgICB0aWNrZXIgPSB0aWNrZXIsDQogICAgYWxwaGEgPSBjb2Vmc1sxXSwNCiAgICBiZXRhID0gY29lZnNbMl0sDQogICAgcm93Lm5hbWVzID0gTlVMTCkNCiAgDQogIHJldHVybihkZil9KSAlPiUNCiAgYmluZF9yb3dzKCkgJT4lDQogIG11dGF0ZShhY3Jvc3MoYWxwaGE6YmV0YSwgZnVuY3Rpb24oeCkgcm91bmQoeCwgNCkpKQ0KDQojIHNhbXBsZQ0KaGVhZChtb2RlbF90YmwsIDMpDQpgYGANCg0KIyMjIGRhdGEgdmlzdWFsaXphdGlvbiAtIGpvaW5lZCBhbGwgdGFibGVzIGludG8gYW4gImVuZXJneSB0YWJsZSINCi0gam9pbmVkIGNvcnJlbGF0aW9uLCBtb2RlbCAmIG9wdGlvbiBkYXRhIHRhYmxlcw0KLSBjYWxjdWxhdGVkIHRoZSAiaXYgZm9yZWNhc3QiIHdpdGggeGxlIDF5ciBiZXRhDQotIGNhbGN1bGF0ZWQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdGlja2VycyBjdXJyZW50IGltcGxpZWQgdm9sICYgZm9yZWNhc3QgYWNyb3NzIGVhY2ggbW9udGhseSBleHBpcnkNCi0gZ3JhcGhlZCBhIHZpc3VhbGl6YXRpb24gb2YgdGhlICoqYWJzb2x1dGUqKiBkaWZmZXJlbmNlIGJldHdlZW4gaW1wbGllZCB2b2wgJiBmb3JlY2FzdCB2b2wNCiAgLSBhcnJhbmdlZCBkaWZmZXJlbmNlZCB2YWx1ZXMgaW4gZGVzY2VuZGluZyBvcmRlcg0KICAtIGZhY2V0ZWQgdGhlIGRhdGEgaW50byB0d28gcGxvdHMsICJmcm9udCBtb250aCIgJiAic2Vjb25kIG1vbnRoIg0KICAtIGZpbGxlZCB0aGUgY29sdW1uIGNoYXJ0cyBieSBjb3JyZWxhdGlvbiB2YWx1ZSB0byB4bGUgKHRoZSBicmlnaHRlciBibHVlIHRoZSBjb2x1bW4sIHRoZSBncmVhdGVyIHRoZSBjb3JyZWxhdGlvbiB0byB4bGUpDQogIC0gYXMgZXhwZWN0ZWQsIHRpY2tlcnMgbGVhc3QgY29ycmVsYXRpb24gdG8geGxlIHdpbGwgaGF2ZSBhIGdyZWF0ZXIgc3ByZWFkIHRvIG91ciBmb3JlY2FzdCBpdg0KDQpgYGB7ciBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9DQojIGpvaW5pbmcgYWxsIHRhYmxlcw0KIyBjYWxjdWxhdGluZyBmb3JlY2FzdCBpdiAmIGRpZmZlcmVuY2UgYmV0d2VlbiBpdi1mb3JlY2FzdA0KZW5lcmd5X3RibCA8LSBsZWZ0X2pvaW4oY29ycl90YmwsIG1vZGVsX3RibCwgYnkgPSBjKCJldGYiLCAidGlja2VyIikpICU+JQ0KICBsZWZ0X2pvaW4ob3B0aW9uX2RhdGEsIGJ5ID0gInRpY2tlciIpICU+JQ0KICByZW5hbWVfYWxsKH5zdHJfcmVwbGFjZV9hbGwoLiwgImF0bWl2bSIsICJpdiIpKSAlPiUNCiAgbXV0YXRlKGFjcm9zcyhzdGFydHNfd2l0aCgiaXYiKSwgZnVuY3Rpb24oeCkgcm91bmQoZmlyc3QoeCkgKiBiZXRhLCAyKSwgLm5hbWVzID0gInsuY29sfV9mb3JlY2FzdCIpLA0KICAgICAgICAgZmlyc3RfbW9udGggPSBpdjEgLSBpdjFfZm9yZWNhc3QsDQogICAgICAgICBzZWNvbmRfbW9udGggPSBpdjIgLSBpdjJfZm9yZWNhc3QsDQogICAgICAgICB0aGlyZF9tb250aCA9IGl2MyAtIGl2M19mb3JlY2FzdCwNCiAgICAgICAgIGZvdXJ0aF9tb250aCA9IGl2NCAtIGl2NF9mb3JlY2FzdCkNCg0KIyBzYW1wbGUNCmhlYWQoZW5lcmd5X3RibCwgMykNCg0KIyBmbGlwcGVkIGNvbHVtbiBjaGFydCBvZiB0aGUgKiphYnNvbHV0ZSoqIGRpZmZlcmVuY2UgYmV0d2VlbiBpdiAmIGZvcmVjYXN0IGl2DQojIGluIGRlc2NlbmRpbmcgb3JkZXIsIG9ubHkgZGlzcGxheWluZyB0aGUgZnJvbnQgMiBtb250aGxpZXMNCmVuZXJneV90YmwgJT4lDQogIHBpdm90X2xvbmdlcihmaXJzdF9tb250aDpzZWNvbmRfbW9udGgpICU+JQ0KICBzZWxlY3QodGlja2VyLCBjb3JyZWxhdGlvbiwgbmFtZSwgdmFsdWUpICU+JQ0KICBtdXRhdGUodmFsdWUgPSBhYnModmFsdWUpKSAlPiUNCiAgZ2dwbG90KGFlcyhmY3RfcmVvcmRlcih0aWNrZXIsIHZhbHVlKSwgdmFsdWUsIGZpbGwgPSBjb3JyZWxhdGlvbikpICsNCiAgZ2VvbV9jb2woKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIGZhY2V0X3dyYXAofm5hbWUsIHNjYWxlcyA9ICJmcmVlIikgKw0KICBsYWJzKHRpdGxlID0gImVuZXJneSB0aWNrZXJzOiBjdXJyZW50IGltcGxpZWQgdm9sICYgZm9yZWNhc3QgaW1wbGllZCB2b2wgYWJzb2x1dGUgZGlmZmVyZW5jZSIsDQogICAgICAgc3VidGl0bGUgPSAiYWJzb2x1dGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGF0bSBtb250aGx5IGl2ICYgZm9yZWNhc3QgaXYgKHdpdGggeGxlIGJldGEgMXllYXIpIiwNCiAgICAgICB4ID0gImVuZXJneSB0aWNrZXJzIiwgeSA9ICJhYnNvbHV0ZSBpbXBsaWVkIHZvbGF0aWxpdHkgZGlmZmVyZW5jZSIsDQogICAgICAgY2FwdGlvbiA9ICJ0aGUgZ3JlYXRlciB0aGUgZGlmZmVyZW5jZSwgdGhlIGh5cG90aGV0aWNhbGx5IGxhcmdlciB0aGUgaW5lZmZpY2llbmN5LiBjb21wYXJlIHRoZSBkaWZmZXJlbmNlIHdpdGggdGhlIGNvcnJlbGF0aW9uIHRvIHhsZS4gb25seSBzaG93Y2FzaW5nIHRoZSBmcm9udCB0d28gbW9udGhseSBleHBpcmllcy4iKQ0KYGBgDQoNCiMjIyBmaW5hbCB0YWJsZSAtIGVuZXJneSB0YWJsZQ0KLSBmaW5hbCB0YWJsZSB3aXRoIGFsbCBjYWxjdWxhdGlvbnMgZnJvbSB0aGlzIGV4ZXJjaXNlIHdpdGggdGlja2VycyBmcm9tIHRoZSBlbmVyZ3kgc2VjdG9yDQotIGFnYWluLCB0aGVyZSB3ZXJlIHByZS1maWx0ZXJpbmcgZG9uZSB3aGVuIGNsZWFuaW5nIGRhdGEgaW4gYW5vdGhlciBtYXJrZG93biwgcmVmZXIgdG8gdGhhdCBmb3IgZGV0YWlscw0KDQpgYGB7cn0NCmVuZXJneV90YmwNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K