Submitted to: \(Chunhua Lan_{Associate Professor}\)


Assignment

Instruction, data and Guideline from the professor:

This project assignment is designed to verify the put-call parity of crude oil options on crude oil futures contracts, which are traded on Chicago Mercantile Exchange (CME), from 12/1/2020 throughout 3/10/2021,
for example. You can select different time periods of data. But, the time span for the data is no less than 40 trading days in general.
The contract specifications can be found at the website of CME. (FYI: The futures prices are available at the link
http:/www.cmegroup.com/trading/energy/crude-oil/light-sweet-crude.html The call and put option prices are available at the link
http://www.cmegroup.com/trading/energy/crude-oil/light-sweet-crude_quotes_globex_options.html.)

To verify the put-call parity,

  1. Through D2L, you can find the data (“WTI_Data.xlsx”) including futures prices and options prices on a daily basis.
    The last prices are associated with different contract maturities given in the first row of the spreadsheet “Futures”.
    The “WTI Crude Future Mar21”, for example, list future prices at the maturity of March 2021, which are used in this assignment.
    You are required to use three different contract maturities.

  2. Similarly, the “last” call and put prices are used in this assignment. To ensure that you use the correct prices, there are a few points that you should note: A spreadsheet “Calls-Apr”, for example, include call option prices for

  1. Type: American Options;
  2. Expiration: Apr 2021;
  3. Strike Rang: 63, 63.5, 64, …
    Note that you need to match strike prices for calls and puts when you apply the put-call parity.
  1. The interest rates uses US treasury bill interest rates with a maturity of 1, 2, 3, … months, depending on the maturities for your derivatives maturities. If an interest rate with a given maturity is not listed, 9-month rates for example, you can use 6-month and 12-month interest rates to interpolate.

  2. You are required to create a spreadsheet that contains date, futures price, call price, put price, strike price, expiration, interest rate, verify the parity, calculate C-P (difference between call and put prices).

  3. You are required to summarize the results presented in (4) in the following perspective: (a) potential arbitrage opportunities; (b) strategies exploiting arbitrage opportunities; (c) whether your strategies are practical and why?
    Submit a report including (5) along with (4).

Equation

Implementing Put-Call Parity

European Option:
The put-call parity relationship for options on futures is given by:

\(C - P = (F-K) e^{rT}\)

Where:

C = Call option price
P = Put option price
F = Futures price
K = Strike price
r = Risk-free interest rate (continuously compounded)
T = Time to maturity (in years)

Simulate Arbitrage Trades
When LHS>RHS:
Buy the put, sell the call, and buy the underlying asset.
When RHS>LHS:
Sell the put, buy the call, and short the underlying asset.

American Option:
For American options, especially those on dividend-paying stocks, the relationship is adjusted to account for potential early exercise and dividends.
The adjusted inequality for American options is:

\[S-K \le C-P \le S-K e^{-rT}\]

This inequality indicates that the difference between the call and put prices for American options lies between \(S-K\) and \(S-K e^{-rT}\).
The exact relationship depends on factors like dividends and the likelihood of early exercise.

Where:

C = Call option price
P = Put option price
S = Futures price
K = Strike price
r = Risk-free interest rate (continuously compounded)
T = Time to maturity (in years)

This approach allows us to assess whether the observed prices of American options fall within the expected theoretical bounds, considering the possibility of early exercise and other factors.

Additional Considerations for European Options:

Monitor Transaction Costs

  • Arbitrage opportunities are only viable if the potential profit exceeds transaction costs like brokerage fees, bid-ask spreads, and taxes Validate
  • Real-World Feasibility Ensure there are no market restrictions (e.g., short-selling restrictions or liquidity issues).
  • Check that the instruments involved can be executed simultaneously to avoid execution risk.

Tools and Techniques:
- Spreadsheets or Software: Automate calculations of parity equations.
- Quantitative Models: Use programming languages like Python or R to scan for opportunities in large datasets.
- Trading Platforms: Real-time alerts based on preset arbitrage conditions.

By systematically checking these conditions, you can identify and potentially exploit arbitrage opportunities effectively.

Additional Considerations for American Options:

  • Dividends: If the underlying asset pays dividends, the present value of expected dividends should be subtracted from the spot price in the Upper_Bound calculation to accurately reflect the asset’s value.

  • Market Conditions: The actual prices of American options may deviate from these theoretical bounds due to market conditions, liquidity, and other factors.

By implementing these adjustments, our analysis will better reflect the pricing dynamics of American options, acknowledging the complexities introduced by their early exercise feature.


Project #2

Verify the put-call parity

This Report is to verify the put-call parity for crude oil options on futures contracts traded on the Chicago Mercantile Exchange (CME) from 12/1/2020 through 3/10/2021.

For American-style options, the put-call parity relationship differs slightly because of the possibility of early exercise.
However, at maturity, early exercise becomes irrelevant as the options are exercised (or not) based solely on their intrinsic value. Thus, the relationship simplifies.

Why This Works
Because of, Early Exercise is Irrelevant at Maturity:

At maturity, the options are either exercised or expire worthless.
The potential for early exercise (a defining feature of American options) no longer applies.

So, On Maturity,
we are dealing with Intrinsic Value Only. So, Futures Price (F) converges with the spot price (S)

\[ C = max(0, F-K) \] \[ P=max(0, K - F) \]


Practical Considerations While the formula remains the same as for European options:

\[C - P = F - K\]


Data Preparation

Futures Prices:
We extracted daily futures prices for three different contract maturities (e.g., March 2021, April 2021, June 2021) from the “Futures” sheet in “WTI_Data-02.xlsx”.

At first, we manually clean the data in Excel then calculate the put-call parity using R language.

Options Prices:
Also extracted daily call and put option prices corresponding to the same maturities and matching strike prices from the respective sheets (e.g., “Calls_Puts_Apr” for April 2021).

Calculated Expirations:

The analysis covers the following expirations and strike prices:

April 30, 2021:

  • Strike Price: USD 64
  • Strike Price: USD 65

June 30, 2021:

  • Strike Price: USD 63
  • Strike Price: USD 63.5
  • Strike Price: USD 64

July 31, 2021:

  • Strike Price: USD 63
  • Strike Price: USD 63.5
  • Strike Price: USD 64
  • Strike Price: USD 64.5
  • Strike Price: USD 65


Maturity April21

# Read data from the Excel file
data_apr21 <- read_excel("WTI_Data-02.xlsx", sheet = "Calls_Puts_Apr")

# data_apr21$Date <- as.Date(data_apr21$Date, format = "%m/%d/%Y")
data_apr21$futures_apr <- as.numeric(data_apr21$futures_apr)
data_apr21$cp64 <- as.numeric(data_apr21$cp64)
data_apr21$pp64 <- as.numeric(data_apr21$pp64)
data_apr21$cp64.5 <- as.numeric(data_apr21$cp64.5)
data_apr21$pp64.5 <- as.numeric(data_apr21$pp64.5)
data_apr21$cp65 <- as.numeric(data_apr21$cp65)
data_apr21$pp65 <- as.numeric(data_apr21$pp65)

# Strike Price: USD 64
# Calculate parity deviation for American-style options
data_apr21 <- data_apr21 %>% 
  mutate(deviation64 = (cp64 - pp64) - (futures_apr - 64))

# Strike Price: USD 64.5
data_apr21 <- data_apr21 %>% 
  mutate(deviation64.5 = (cp64.5 - pp64.5) - (futures_apr - 64.5))

# Strike Price: USD 65
data_apr21 <- data_apr21 %>% 
  mutate(deviation65 = (cp65 - pp65) - (futures_apr - 65))

# Define transaction cost threshold
transaction_cost <- 0.05  # We can adjust as per market norms

# Identify arbitrage opportunities
data_apr21 <- data_apr21 %>% 
  mutate(arbitrage64 = abs(deviation64) > transaction_cost) %>% 
  mutate(arbitrage64.5 = abs(deviation64.5) > transaction_cost) %>% 
  mutate(arbitrage65 = abs(deviation65) > transaction_cost)

data_apr21 %>%
  head(10) %>%
  kable(
    format = "html",
    caption = "The data April 21 (Maturity) with arbitrage opportunities"
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = FALSE,
    position = "center"
  ) %>%
row_spec(0, background = "#D3D3D3", bold = TRUE)
The data April 21 (Maturity) with arbitrage opportunities
Date futures_apr cp64 pp64 cp64.5 pp64.5 cp65 pp65 deviation64 deviation64.5 deviation65 arbitrage64 arbitrage64.5 arbitrage65
3/16/2021 64.37 0.85 0.41 0.67 0.63 0.49 1.01 0.07 0.17 0.11 TRUE TRUE TRUE
3/15/2021 65.39 1.69 0.30 1.32 0.43 0.99 0.60 0.00 0.00 0.00 FALSE FALSE FALSE
3/12/2021 65.61 2.00 0.39 1.64 0.53 1.32 0.71 0.00 0.00 0.00 FALSE FALSE FALSE
3/11/2021 66.02 2.46 0.44 2.09 0.57 1.75 0.73 0.00 0.00 0.00 FALSE FALSE FALSE
3/10/2021 64.44 1.54 1.10 1.28 1.34 1.05 1.61 0.00 0.00 0.00 FALSE FALSE FALSE
3/9/2021 64.01 1.45 1.44 1.21 1.70 1.01 2.00 0.00 0.00 0.00 FALSE FALSE FALSE
3/8/2021 65.05 2.12 1.07 1.83 1.28 1.57 1.52 0.00 0.00 0.00 FALSE FALSE FALSE
3/5/2021 66.09 2.89 0.80 2.55 0.96 2.23 1.14 0.00 0.00 0.00 FALSE FALSE FALSE
3/4/2021 63.83 1.61 1.78 1.37 2.04 1.17 2.34 0.00 0.00 0.00 FALSE FALSE FALSE
3/3/2021 61.28 0.79 3.51 0.66 3.88 0.55 4.27 0.00 0.00 0.00 FALSE FALSE FALSE
# Combine data for all strikes into a single data frame
deviation_data_apr21 <- data.frame(
  Strike = rep(c(64, 64.5, 65), each = nrow(data_apr21)),
  ParityDeviation = c(data_apr21$deviation64, data_apr21$deviation64.5, 
                      data_apr21$deviation65))

# Plot deviations
ggplot(deviation_data_apr21, aes(x = Strike, y = ParityDeviation)) +
  geom_boxplot() +
  geom_hline(yintercept = c(-transaction_cost, transaction_cost), color = "red", linetype = "dashed") +
  labs(title = "Put-Call Parity Deviations April 21", y = "Parity Deviation", x = "Strike Price")

# Filter out rows with NA values in Parity Deviation
filtered_data <- deviation_data_apr21 %>%
  filter(!is.na(ParityDeviation))

# 1. Line Plot - Parity Deviation Trends by Strike Price
ggplot(filtered_data, aes(x = Strike, y = ParityDeviation)) +
  geom_line(color = "blue", size = 1) +
  geom_point(color = "darkblue", size = 2) +
  labs(
    title = "Parity Deviation Trends by Strike Price",
    x = "Strike Price",
    y = "Parity Deviation"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 12, face = "bold"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 10)
  )

# 2. Histogram - Distribution of Parity Deviations
ggplot(filtered_data, aes(x = ParityDeviation)) +
  geom_histogram(binwidth = 0.02, fill = "blue", color = "black", alpha = 0.7) +
  labs(
    title = "Distribution of Parity Deviations",
    x = "Parity Deviation",
    y = "Frequency"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 12, face = "bold"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 10)
  )

# 3. Boxplot - Parity Deviations by Strike Price
ggplot(filtered_data, aes(x = factor(Strike), y = ParityDeviation)) +
  geom_boxplot(fill = "lightblue", color = "darkblue", outlier.color = "red", outlier.size = 2) +
  labs(
    title = "Boxplot of Parity Deviations by Strike Price",
    x = "Strike Price",
    y = "Parity Deviation"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 12, face = "bold"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 10)
  )

Key Observations:
Distribution of Deviations:

Most deviations are close to zero, suggesting that the observed market prices align well with theoretical expectations.
Minimal deviations from the parity equation imply that the market efficiently prices options, leaving limited opportunities for arbitrage.

Strike Price Behavior:

The dataset includes multiple strike prices, allowing for a comparative analysis of deviations across various levels.
The magnitude and variability of deviations appear similar across strike prices, indicating consistent market dynamics.

Implications for Arbitrage:

Minor deviations within a narrow range suggest that transaction costs, bid-ask spreads, or other trading frictions likely outweigh potential arbitrage profits.
Observations align with the expectation of market efficiency, particularly in actively traded instruments like crude oil options.

Conclusion:
The analysis highlights that deviations from put-call parity are minimal and consistent across strike prices. This confirms that the crude oil options market at the Chicago Mercantile Exchange is highly efficient.

Opportunities for arbitrage are limited and likely offset by transaction costs. This reinforces the theoretical robustness of put-call parity and the practicality of its application in financial markets.

Maturity June21

# Read data from the Excel file
data_jun21 <- read_excel("WTI_Data-02.xlsx", sheet = "Calls_Puts_Jun")


# data_jun21$Date <- as.Date(data_jun21$Date, format = "%m/%d/%Y")
data_jun21$futures_jun <- as.numeric(data_jun21$futures_jun)
data_jun21$cp63 <- as.numeric(data_jun21$cp63)
data_jun21$pp63 <- as.numeric(data_jun21$pp63)
data_jun21$cp64 <- as.numeric(data_jun21$cp64)
data_jun21$pp64 <- as.numeric(data_jun21$pp64)
data_jun21$cp64.5 <- as.numeric(data_jun21$cp64.5)
data_jun21$pp64.5 <- as.numeric(data_jun21$pp64.5)
data_jun21$cp65 <- as.numeric(data_jun21$cp65)
data_jun21$pp65 <- as.numeric(data_jun21$pp65)
data_jun21$cp65.5 <- as.numeric(data_jun21$cp65.5)
data_jun21$pp65.5 <- as.numeric(data_jun21$pp65.5)
data_jun21$cp66 <- as.numeric(data_jun21$cp66)
data_jun21$pp66 <- as.numeric(data_jun21$pp66)

# Strike Price: USD 63
# Calculate parity deviation for American-style options
data_jun21 <- data_jun21 %>% 
  mutate(deviation63 = (cp63 - pp63) - (futures_jun - 63))

# Strike Price: USD 63.5
data_jun21 <- data_jun21 %>% 
  mutate(deviation63.5 = (cp63.5 - pp63.5) - (futures_jun - 63.5))

# Strike Price: USD 64
data_jun21 <- data_jun21 %>% 
  mutate(deviation64 = (cp64 - pp64) - (futures_jun - 64))

# Define transaction cost threshold
transaction_cost <- 0.05  # Adjust as per market norms

# Identify arbitrage opportunities
data_jun21 <- data_jun21 %>% 
  mutate(arbitrage63 = abs(deviation63) > transaction_cost) %>% 
  mutate(arbitrage63.5 = abs(deviation63.5) > transaction_cost) %>% 
  mutate(arbitrage64 = abs(deviation64) > transaction_cost)

data_jun21 %>%
  head(10) %>%
  kable(
    format = "html",
    caption = "The data June 21 (Maturity) with arbitrage opportunities"
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = FALSE,
    position = "center"
  ) %>%
row_spec(0, background = "#D3D3D3", bold = TRUE)
The data June 21 (Maturity) with arbitrage opportunities
Date futures_jun cp63 pp63 cp63.5 pp63.5 cp64 pp64 cp64.5 pp64.5 cp65 pp65 cp65.5 pp65.5 cp66 pp66 deviation63 deviation63.5 deviation64 arbitrage63 arbitrage63.5 arbitrage64
3/16/2021 64.32 4.82 3.14 4.53 3.35 4.25 3.57 3.99 3.81 3.74 4.06 3.50 4.32 3.26 4.58 0.36 0.36 0.36 TRUE TRUE TRUE
3/15/2021 65.20 5.16 2.96 4.87 3.17 4.58 3.38 4.31 3.61 4.05 3.85 3.80 4.10 3.56 4.36 0.00 0.00 0.00 FALSE FALSE FALSE
3/12/2021 65.36 5.25 2.89 4.95 3.09 4.66 3.30 4.39 3.53 4.13 3.77 3.88 4.02 3.63 4.27 0.00 0.00 0.00 FALSE FALSE FALSE
3/11/2021 65.66 5.50 2.84 5.20 3.04 4.91 3.25 4.62 3.46 4.35 3.69 4.09 3.93 3.85 4.19 0.00 0.00 0.00 FALSE FALSE FALSE
3/10/2021 64.09 4.47 3.38 4.20 3.61 3.94 3.85 3.70 4.11 3.46 4.37 3.24 4.65 3.02 4.93 0.00 0.00 0.00 FALSE FALSE FALSE
3/9/2021 63.69 4.30 3.61 4.04 3.85 3.79 4.10 3.55 4.36 3.32 4.63 3.10 4.91 2.90 5.21 0.00 0.00 0.00 FALSE FALSE FALSE
3/8/2021 64.52 4.74 3.22 4.46 3.44 4.20 3.68 3.94 3.92 3.69 4.17 3.46 4.44 3.23 4.71 0.00 0.00 0.00 FALSE FALSE FALSE
3/5/2021 65.45 5.41 2.96 5.11 3.16 4.82 3.37 4.54 3.59 4.28 3.83 4.02 4.07 3.77 4.32 0.00 0.00 0.00 FALSE FALSE FALSE
3/4/2021 63.15 3.93 3.78 3.67 4.02 3.43 4.28 3.20 4.55 2.98 4.83 2.77 5.12 2.57 5.42 0.00 0.00 0.00 FALSE FALSE FALSE
3/3/2021 60.69 2.79 5.10 2.59 5.40 2.41 5.72 2.23 6.04 2.07 6.38 1.92 NA 1.77 7.08 0.00 0.00 0.00 FALSE FALSE FALSE
# Combine data for all strikes into a single data frame
deviation_data_jun21 <- data.frame(
  Strike = rep(c(63, 63.5, 64), each = nrow(data_jun21)),
  ParityDeviation = c(data_jun21$deviation63, data_jun21$deviation63.5, 
                      data_jun21$deviation64))

# Plot deviations
ggplot(deviation_data_jun21, aes(x = Strike, y = ParityDeviation)) +
  geom_boxplot() +
  geom_hline(yintercept = c(-transaction_cost, transaction_cost), color = "red", linetype = "dashed") +
  labs(title = "Put-Call Parity Deviations June 21", y = "Parity Deviation", x = "Strike Price")

# Filter out rows with NA values in ParityDeviation
filtered_data <- deviation_data_jun21 %>%
  filter(!is.na(ParityDeviation))

# 1. Line Plot - Parity Deviation Trends by Strike Price
ggplot(filtered_data, aes(x = Strike, y = ParityDeviation)) +
  geom_line(color = "blue", size = 1) +
  geom_point(color = "darkblue", size = 2) +
  labs(
    title = "Parity Deviation Trends by Strike Price",
    x = "Strike Price",
    y = "Parity Deviation"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 12, face = "bold"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 10)
  )

# 2. Histogram - Distribution of Parity Deviations
ggplot(filtered_data, aes(x = ParityDeviation)) +
  geom_histogram(binwidth = 0.02, fill = "blue", color = "black", alpha = 0.7) +
  labs(
    title = "Distribution of Parity Deviations",
    x = "Parity Deviation",
    y = "Frequency"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 12, face = "bold"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 10)
  )

# 3. Boxplot - Parity Deviations by Strike Price
ggplot(filtered_data, aes(x = factor(Strike), y = ParityDeviation)) +
  geom_boxplot(fill = "lightblue", color = "darkblue", outlier.color = "red", outlier.size = 2) +
  labs(
    title = "Boxplot of Parity Deviations by Strike Price",
    x = "Strike Price",
    y = "Parity Deviation"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 12, face = "bold"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 10)
  )

Maturity July21

# Read data from the Excel file
data_jul21 <- read_excel("WTI_Data-02.xlsx", sheet = "Calls_Puts_Jul")

# data_jul21$Date <- as.Date(data_jul21$Date, format = "%m/%d/%Y")
data_jul21$futures_jul <- as.numeric(data_jul21$futures_jul)
data_jul21$cp63 <- as.numeric(data_jul21$cp63)
data_jul21$pp63 <- as.numeric(data_jul21$pp63)
data_jul21$cp63.5 <- as.numeric(data_jul21$cp63.5)
data_jul21$pp63.5 <- as.numeric(data_jul21$pp63.5)
data_jul21$cp64 <- as.numeric(data_jul21$cp64)
data_jul21$pp64 <- as.numeric(data_jul21$pp64)
data_jul21$cp64.5 <- as.numeric(data_jul21$cp64.5)
data_jul21$pp64.5 <- as.numeric(data_jul21$pp64.5)
data_jul21$cp65 <- as.numeric(data_jul21$cp65)
data_jul21$pp65 <- as.numeric(data_jul21$pp65)
data_jul21$cp65.5 <- as.numeric(data_jul21$cp65.5)
data_jul21$pp65.5 <- as.numeric(data_jul21$pp65.5)
data_jul21$cp66 <- as.numeric(data_jul21$cp66)
data_jul21$pp66 <- as.numeric(data_jul21$pp66)

data_jul21 <- data_jul21 %>% 
  mutate(deviation63 = (cp63 - pp63) - (futures_jul - 63))

# Strike Price: USD 63
# Calculate parity deviation for American-style options
data_jul21 <- data_jul21 %>% 
  mutate(deviation63 = (cp63 - pp63) - (futures_jul - 63))

# Strike Price: USD 63.5
data_jul21 <- data_jul21 %>% 
  mutate(deviation63.5 = (cp63.5 - pp63.5) - (futures_jul - 63.5))

# Strike Price: USD 64
data_jul21 <- data_jul21 %>% 
  mutate(deviation64 = (cp64 - pp64) - (futures_jul - 64))

# Strike Price: USD 64.5
data_jul21 <- data_jul21 %>% 
  mutate(deviation64.5 = (cp64.5 - pp64.5) - (futures_jul - 64.5))

# Strike Price: USD 65
data_jul21 <- data_jul21 %>% 
  mutate(deviation65 = (cp65 - pp65) - (futures_jul - 65))

# Define transaction cost threshold
transaction_cost <- 0.05  # We can adjust as per market norms

# Identify arbitrage opportunities
data_jul21 <- data_jul21 %>% 
  mutate(arbitrage63 = abs(deviation63) > transaction_cost) %>% 
  mutate(arbitrage63.5 = abs(deviation63.5) > transaction_cost) %>% 
  mutate(arbitrage64 = abs(deviation64) > transaction_cost)%>% 
  mutate(arbitrage64.5 = abs(deviation64.5) > transaction_cost)%>% 
  mutate(arbitrage65 = abs(deviation65) > transaction_cost)

data_jul21 %>%
  head(10) %>%
  kable(
    format = "html",
    caption = "The data july 21 (Maturity) with arbitrage opportunities"
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = FALSE,
    position = "center"
  ) %>%
row_spec(0, background = "#D3D3D3", bold = TRUE)
The data july 21 (Maturity) with arbitrage opportunities
Date futures_jul cp63 pp63 cp63.5 pp63.5 cp64 pp64 cp64.5 pp64.5 cp65 pp65 cp65.5 pp65.5 cp66 pp66 deviation63 deviation63.5 deviation64 deviation64.5 deviation65 arbitrage63 arbitrage63.5 arbitrage64 arbitrage64.5 arbitrage65
3/15/2021 63.87 5.68 3.97 5.41 4.20 5.14 4.43 4.88 4.67 4.63 4.92 4.39 5.18 4.15 5.44 0.84 0.84 0.84 0.84 0.84 TRUE TRUE TRUE TRUE TRUE
3/12/2021 64.71 5.72 3.88 5.44 4.10 5.17 4.33 4.91 4.57 4.66 4.82 4.42 5.08 4.18 5.34 0.13 0.13 0.13 0.13 0.13 TRUE TRUE TRUE TRUE TRUE
3/11/2021 64.84 5.91 3.80 5.63 4.02 5.35 4.24 5.08 4.48 4.83 4.72 4.58 4.97 4.34 5.23 0.27 0.27 0.27 0.26 0.27 TRUE TRUE TRUE TRUE TRUE
3/10/2021 65.11 4.91 4.33 4.65 4.57 4.40 4.82 4.16 5.08 3.94 5.36 3.72 5.64 3.51 5.93 -1.53 -1.53 -1.53 -1.53 -1.53 TRUE TRUE TRUE TRUE TRUE
3/9/2021 63.58 4.74 4.54 4.49 4.79 4.25 5.05 4.02 5.32 3.79 5.59 3.58 5.88 3.38 6.18 -0.38 -0.38 -0.38 -0.38 -0.38 TRUE TRUE TRUE TRUE TRUE
3/8/2021 63.20 5.09 4.15 4.82 4.38 4.56 4.62 4.31 4.87 4.07 5.13 3.84 5.40 3.62 5.68 0.74 0.74 0.74 0.74 0.74 TRUE TRUE TRUE TRUE TRUE
3/5/2021 63.94 5.69 3.88 5.41 4.10 5.13 4.32 4.87 4.56 4.61 4.80 4.36 5.05 4.12 5.31 0.87 0.87 0.87 0.87 0.87 TRUE TRUE TRUE TRUE TRUE
3/4/2021 64.81 4.23 4.71 3.99 4.97 3.76 5.24 3.54 5.52 3.32 5.80 3.12 6.10 2.92 6.40 -2.29 -2.29 -2.29 -2.29 -2.29 TRUE TRUE TRUE TRUE TRUE
3/3/2021 62.52 3.23 6.08 3.03 6.38 2.85 6.70 2.67 7.02 2.51 7.36 2.35 7.70 2.20 8.05 -2.37 -2.37 -2.37 -2.37 -2.37 TRUE TRUE TRUE TRUE TRUE
3/2/2021 60.15 2.62 6.97 2.46 7.30 2.29 7.64 2.14 7.99 2.00 8.35 1.87 8.71 1.74 9.09 -1.50 -1.49 -1.50 -1.50 -1.50 TRUE TRUE TRUE TRUE TRUE
# Combine data for all strikes into a single data frame
deviation_data_jul21 <- data.frame(
  Strike = rep(c(63, 63.5, 64, 64.5, 65), each = nrow(data_jul21)),
  ParityDeviation = c(data_jul21$deviation63, data_jul21$deviation63.5, 
                      data_jul21$deviation64, data_jul21$deviation64.5, 
                      data_jul21$deviation65)
)

# Plot deviations
ggplot(deviation_data_jul21, aes(x = Strike, y = ParityDeviation)) +
  geom_boxplot() +
  geom_hline(yintercept = c(-transaction_cost, transaction_cost), color = "red", linetype = "dashed") +
  labs(title = "Put-Call Parity Deviations July 21", y = "Parity Deviation", x = "Strike Price")

# Filter out rows with NA values in ParityDeviation
filtered_data <- deviation_data_jul21 %>%
  filter(!is.na(ParityDeviation))

# 1. Line Plot - Parity Deviation Trends by Strike Price
ggplot(filtered_data, aes(x = Strike, y = ParityDeviation)) +
  geom_line(color = "blue", size = 1) +
  geom_point(color = "darkblue", size = 2) +
  labs(
    title = "Parity Deviation Trends by Strike Price",
    x = "Strike Price",
    y = "Parity Deviation"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 12, face = "bold"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 10)
  )

# 2. Histogram - Distribution of Parity Deviations
ggplot(filtered_data, aes(x = ParityDeviation)) +
  geom_histogram(binwidth = 0.02, fill = "blue", color = "black", alpha = 0.7) +
  labs(
    title = "Distribution of Parity Deviations",
    x = "Parity Deviation",
    y = "Frequency"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 12, face = "bold"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 10)
  )

# 3. Boxplot - Parity Deviations by Strike Price
ggplot(filtered_data, aes(x = factor(Strike), y = ParityDeviation)) +
  geom_boxplot(fill = "lightblue", color = "darkblue", outlier.color = "red", outlier.size = 2) +
  labs(
    title = "Boxplot of Parity Deviations by Strike Price",
    x = "Strike Price",
    y = "Parity Deviation"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 12, face = "bold"),
    axis.title = element_text(size = 10),
    axis.text = element_text(size = 10)
  )

Conclusion from Results

By analyzing the flagged arbitrage opportunities and deviations:

If all deviations are within ±0.05, the market is arbitrage-free at the specified transaction cost.
If some deviations exceed ±0.05, those specific rows indicate potential arbitrage opportunities that can be exploited.

We Found 1 Arbitrage opportunity for the expiration April 21 & June 21. And several arbitrage opportunities for July 21.


*Submitted By:

Mohammad Hossein Ardestani
MQIM 3768677
Faculty of Management
University of New Brunswick
mhossein.ardestani@unb.ca

Md Mahmudul Hasan
MQIM 3760573
Faculty of Management
University of New Brunswick
mahmudul.hasan@unb.ca

LS0tDQp0aXRsZTogIjxzcGFuIHN0eWxlPSdmb250LXNpemU6MjRweDsnPlZlcmlmaWNhdGlvbiBvZiBQdXQtQ2FsbCBQYXJpdHkgZm9yIENydWRlIE9pbCBPcHRpb25zPC9zcGFuPiINCmF1dGhvcjogIkhvc3NlaW4gJiBIYXNhbiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGhpZ2hsaWdodDogemVuYnVybg0KICAgIHRvY19kZXB0aDogNA0KICAgIGRmX3ByaW50OiBrYWJsZQ0KICAgIHRoZW1lOiBsdW1lbg0KZGF0ZTogIk5vdmVtYmVyIDIzLCAyMDI0Ig0KLS0tDQoNCiMjIyMgKlN1Ym1pdHRlZCB0bzoqICRDaHVuaHVhIExhbl97QXNzb2NpYXRlIFByb2Zlc3Nvcn0kDQo8YnI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPiBib2R5LCB0ZCB7Zm9udC1zaXplOiAxNXB4O30gY29kZS5ye2ZvbnQtc2l6ZTogMTVweDt9IHByZSB7Zm9udC1zaXplOiAxNXB4fSA8L3N0eWxlPg0KPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0zLjcuMS5zbGltLm1pbi5qcyI+PC9zY3JpcHQ+DQo8c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+DQogICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkgew0KICAkKCdhJykuYXR0cigndGFyZ2V0JywgJ19ibGFuaycpOw0KICB9KTsNCjwvc2NyaXB0Pg0KPHN0eWxlPg0KLmJveGVkIHsNCiAgYmFja2dyb3VuZDogIzFDMUMxQzsNCiAgY29sb3I6ICNmZmZmZmY7DQogIGJvcmRlcjogMHB4IHNvbGlkICM2NDY0NjQ7DQogIG1hcmdpbjogMHB4IGF1dG87DQogIHdpZHRoOiBhdXRvOw0KICBwYWRkaW5nOiAxMHB4Ow0KICBib3JkZXItcmFkaXVzOiAwcHg7DQp9DQo8L3N0eWxlPg0KDQoNCiMgIHsudGFic2V0fQ0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KCWVjaG8gPSBUUlVFLA0KCW1lc3NhZ2UgPSBGQUxTRSwNCgl3YXJuaW5nID0gRkFMU0UNCikNCmBgYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFLCBwYWdlZC5wcmludD1GQUxTRX0NCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5cXVhbnQpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShtb21lbnRzKQ0KbGlicmFyeSh0aWJibGUpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeSh2YXJzKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KHRzZXJpZXMpDQpgYGANCg0KIyMgQXNzaWdubWVudA0KDQoqKkluc3RydWN0aW9uLCBkYXRhIGFuZCBHdWlkZWxpbmUgZnJvbSB0aGUgcHJvZmVzc29yOioqDQoNCjxwPlRoaXMgcHJvamVjdCBhc3NpZ25tZW50IGlzIGRlc2lnbmVkIHRvIHZlcmlmeSB0aGUgcHV0LWNhbGwgcGFyaXR5IG9mIGNydWRlIG9pbCBvcHRpb25zIG9uIGNydWRlIG9pbCBmdXR1cmVzIGNvbnRyYWN0cywgd2hpY2ggYXJlIHRyYWRlZCBvbiBDaGljYWdvIE1lcmNhbnRpbGUgRXhjaGFuZ2UgKENNRSksIGZyb20gMTIvMS8yMDIwIHRocm91Z2hvdXQgMy8xMC8yMDIxLFwNCmZvciBleGFtcGxlLiBZb3UgY2FuIHNlbGVjdCBkaWZmZXJlbnQgdGltZSBwZXJpb2RzIG9mIGRhdGEuIEJ1dCwgdGhlIHRpbWUgc3BhbiBmb3IgdGhlIGRhdGEgaXMgbm8gbGVzcyB0aGFuIDQwIHRyYWRpbmcgZGF5cyBpbiBnZW5lcmFsLlwNClRoZSBjb250cmFjdCBzcGVjaWZpY2F0aW9ucyBjYW4gYmUgZm91bmQgYXQgdGhlIHdlYnNpdGUgb2YgQ01FLiANCihGWUk6IFRoZSBmdXR1cmVzIHByaWNlcyBhcmUgYXZhaWxhYmxlIGF0IHRoZSBsaW5rXA0KaHR0cDovd3d3LmNtZWdyb3VwLmNvbS90cmFkaW5nL2VuZXJneS9jcnVkZS1vaWwvbGlnaHQtc3dlZXQtY3J1ZGUuaHRtbA0KVGhlIGNhbGwgYW5kIHB1dCBvcHRpb24gcHJpY2VzIGFyZSBhdmFpbGFibGUgYXQgdGhlIGxpbmtcDQpodHRwOi8vd3d3LmNtZWdyb3VwLmNvbS90cmFkaW5nL2VuZXJneS9jcnVkZS1vaWwvbGlnaHQtc3dlZXQtY3J1ZGVfcXVvdGVzX2dsb2JleF9vcHRpb25zLmh0bWwuKQ0KPC9wPg0KDQpUbyB2ZXJpZnkgdGhlIHB1dC1jYWxsIHBhcml0eSxcDQoNCjEuIFRocm91Z2ggRDJMLCB5b3UgY2FuIGZpbmQgdGhlIGRhdGEgKioo4oCcV1RJX0RhdGEueGxzeOKAnSkqKiBpbmNsdWRpbmcgZnV0dXJlcyBwcmljZXMgYW5kIG9wdGlvbnMgcHJpY2VzIG9uIGEgZGFpbHkgYmFzaXMuXA0KVGhlIGxhc3QgcHJpY2VzIGFyZSBhc3NvY2lhdGVkIHdpdGggZGlmZmVyZW50IGNvbnRyYWN0IG1hdHVyaXRpZXMgZ2l2ZW4gaW4gdGhlIGZpcnN0IHJvdyBvZiB0aGUgc3ByZWFkc2hlZXQg4oCcRnV0dXJlc+KAnS5cDQpUaGUg4oCcV1RJIENydWRlIEZ1dHVyZSBNYXIyMeKAnSwgZm9yIGV4YW1wbGUsIGxpc3QgZnV0dXJlIHByaWNlcyBhdCB0aGUgbWF0dXJpdHkgb2YgTWFyY2ggMjAyMSwgd2hpY2ggYXJlIHVzZWQgaW4gdGhpcyBhc3NpZ25tZW50LlwNCllvdSBhcmUgcmVxdWlyZWQgdG8gdXNlIHRocmVlIGRpZmZlcmVudCBjb250cmFjdCBtYXR1cml0aWVzLlwNCg0KMi4gU2ltaWxhcmx5LCB0aGUg4oCcbGFzdOKAnSBjYWxsIGFuZCBwdXQgcHJpY2VzIGFyZSB1c2VkIGluIHRoaXMgYXNzaWdubWVudC4gVG8gZW5zdXJlIHRoYXQgeW91IHVzZSB0aGUgY29ycmVjdCBwcmljZXMsIHRoZXJlIGFyZSBhIGZldyBwb2ludHMgdGhhdCB5b3Ugc2hvdWxkIG5vdGU6IEEgc3ByZWFkc2hlZXQg4oCcQ2FsbHMtQXBy4oCdLCBmb3IgZXhhbXBsZSwgaW5jbHVkZSBjYWxsIG9wdGlvbiBwcmljZXMgZm9yXA0KKGEpIFR5cGU6IEFtZXJpY2FuIE9wdGlvbnM7XA0KKGIpIEV4cGlyYXRpb246IEFwciAyMDIxO1wNCihjKSBTdHJpa2UgUmFuZzogNjMsIDYzLjUsIDY0LCAuLi4gXA0KTm90ZSB0aGF0IHlvdSBuZWVkIHRvICoqbWF0Y2ggc3RyaWtlIHByaWNlcyBmb3IgY2FsbHMgYW5kIHB1dHMgd2hlbiB5b3UgYXBwbHkgdGhlIHB1dC1jYWxsIHBhcml0eS4qKlwNCg0KMy4gVGhlIGludGVyZXN0IHJhdGVzIHVzZXMgVVMgdHJlYXN1cnkgYmlsbCBpbnRlcmVzdCByYXRlcyB3aXRoIGEgbWF0dXJpdHkgb2YgMSwgMiwgMywg4oCmIG1vbnRocywgZGVwZW5kaW5nIG9uIHRoZSBtYXR1cml0aWVzIGZvciB5b3VyIGRlcml2YXRpdmVzIG1hdHVyaXRpZXMuIElmIGFuIGludGVyZXN0IHJhdGUgd2l0aCBhIGdpdmVuIG1hdHVyaXR5IGlzIG5vdCBsaXN0ZWQsIDktbW9udGggcmF0ZXMgZm9yIGV4YW1wbGUsIHlvdSBjYW4gdXNlIDYtbW9udGggYW5kIDEyLW1vbnRoIGludGVyZXN0IHJhdGVzIHRvIGludGVycG9sYXRlLlwNCg0KNC4gWW91IGFyZSByZXF1aXJlZCB0byBjcmVhdGUgYSBzcHJlYWRzaGVldCB0aGF0IGNvbnRhaW5zIGRhdGUsIGZ1dHVyZXMgcHJpY2UsIGNhbGwgcHJpY2UsIHB1dCBwcmljZSwgc3RyaWtlIHByaWNlLCBleHBpcmF0aW9uLCBpbnRlcmVzdCByYXRlLCB2ZXJpZnkgdGhlIHBhcml0eSwgY2FsY3VsYXRlIEMtUCAoZGlmZmVyZW5jZSBiZXR3ZWVuIGNhbGwgYW5kIHB1dCBwcmljZXMpLlwNCg0KNS4gWW91IGFyZSByZXF1aXJlZCB0byBzdW1tYXJpemUgdGhlIHJlc3VsdHMgcHJlc2VudGVkIGluICg0KSBpbiB0aGUgZm9sbG93aW5nIHBlcnNwZWN0aXZlOiAoYSkgcG90ZW50aWFsIGFyYml0cmFnZSBvcHBvcnR1bml0aWVzOyAoYikgc3RyYXRlZ2llcyBleHBsb2l0aW5nIGFyYml0cmFnZSBvcHBvcnR1bml0aWVzOyAoYykgd2hldGhlciB5b3VyIHN0cmF0ZWdpZXMgYXJlIHByYWN0aWNhbCBhbmQgd2h5P1wNClN1Ym1pdCBhIHJlcG9ydCBpbmNsdWRpbmcgKDUpIGFsb25nIHdpdGggKDQpLlwNCg0KDQojIyBFcXVhdGlvbg0KDQoqKkltcGxlbWVudGluZyBQdXQtQ2FsbCBQYXJpdHkqKg0KDQo6Ojo6IHsuY29sdW1uc30NCg0KOjo6IHsuY29sdW1uIHdpZHRoPSI1MCUifQ0KKipFdXJvcGVhbiBPcHRpb246KipcDQpUaGUgcHV0LWNhbGwgcGFyaXR5IHJlbGF0aW9uc2hpcCBmb3Igb3B0aW9ucyBvbiBmdXR1cmVzIGlzIGdpdmVuIGJ5Og0KDQokQyAtIFAgPSAoRi1LKSBlXntyVH0kDQoNCg0KV2hlcmU6XA0KDQpDID0gQ2FsbCBvcHRpb24gcHJpY2VcDQpQID0gUHV0IG9wdGlvbiBwcmljZVwNCkYgPSBGdXR1cmVzIHByaWNlXA0KSyA9IFN0cmlrZSBwcmljZVwNCnIgPSBSaXNrLWZyZWUgaW50ZXJlc3QgcmF0ZSAoY29udGludW91c2x5IGNvbXBvdW5kZWQpXA0KVCA9IFRpbWUgdG8gbWF0dXJpdHkgKGluIHllYXJzKVwNCg0KKipTaW11bGF0ZSBBcmJpdHJhZ2UgVHJhZGVzKipcDQoqKldoZW4gTEhTPlJIUzoqKlwNCkJ1eSB0aGUgcHV0LCBzZWxsIHRoZSBjYWxsLCBhbmQgYnV5IHRoZSB1bmRlcmx5aW5nIGFzc2V0LlwNCioqV2hlbiBSSFM+TEhTOioqXA0KU2VsbCB0aGUgcHV0LCBidXkgdGhlIGNhbGwsIGFuZCBzaG9ydCB0aGUgdW5kZXJseWluZyBhc3NldC5cDQoNCjo6Og0KDQo6Ojogey5jb2x1bW4gd2lkdGg9IjUwJSJ9DQoNCioqQW1lcmljYW4gT3B0aW9uOioqXA0KRm9yIEFtZXJpY2FuIG9wdGlvbnMsIGVzcGVjaWFsbHkgdGhvc2Ugb24gZGl2aWRlbmQtcGF5aW5nIHN0b2NrcywgdGhlIHJlbGF0aW9uc2hpcCBpcyBhZGp1c3RlZCB0byBhY2NvdW50IGZvciBwb3RlbnRpYWwgZWFybHkgZXhlcmNpc2UgYW5kIGRpdmlkZW5kcy5cDQpUaGUgYWRqdXN0ZWQgaW5lcXVhbGl0eSBmb3IgQW1lcmljYW4gb3B0aW9ucyBpczoNCg0KJCRTLUsgXGxlIEMtUCBcbGUgUy1LIGVeey1yVH0kJA0KDQpUaGlzIGluZXF1YWxpdHkgaW5kaWNhdGVzIHRoYXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgY2FsbCBhbmQgcHV0IHByaWNlcyBmb3IgQW1lcmljYW4gb3B0aW9ucyBsaWVzIGJldHdlZW4gJFMtSyQgYW5kICRTLUsgZV57LXJUfSQuXA0KVGhlIGV4YWN0IHJlbGF0aW9uc2hpcCBkZXBlbmRzIG9uIGZhY3RvcnMgbGlrZSBkaXZpZGVuZHMgYW5kIHRoZSBsaWtlbGlob29kIG9mIGVhcmx5IGV4ZXJjaXNlLlwNCg0KV2hlcmU6XA0KDQpDID0gQ2FsbCBvcHRpb24gcHJpY2VcDQpQID0gUHV0IG9wdGlvbiBwcmljZVwNClMgPSBGdXR1cmVzIHByaWNlXA0KSyA9IFN0cmlrZSBwcmljZVwNCnIgPSBSaXNrLWZyZWUgaW50ZXJlc3QgcmF0ZSAoY29udGludW91c2x5IGNvbXBvdW5kZWQpXA0KVCA9IFRpbWUgdG8gbWF0dXJpdHkgKGluIHllYXJzKVwNCg0KVGhpcyBhcHByb2FjaCBhbGxvd3MgdXMgdG8gYXNzZXNzIHdoZXRoZXIgdGhlIG9ic2VydmVkIHByaWNlcyBvZiBBbWVyaWNhbiBvcHRpb25zIGZhbGwgd2l0aGluIHRoZSBleHBlY3RlZCB0aGVvcmV0aWNhbCBib3VuZHMsIGNvbnNpZGVyaW5nIHRoZSBwb3NzaWJpbGl0eSBvZiBlYXJseSBleGVyY2lzZSBhbmQgb3RoZXIgZmFjdG9ycy4NCjo6Og0KOjo6Og0KDQoqKkFkZGl0aW9uYWwgQ29uc2lkZXJhdGlvbnMgZm9yIEV1cm9wZWFuIE9wdGlvbnM6KipcDQoNCioqTW9uaXRvciBUcmFuc2FjdGlvbiBDb3N0cyoqXA0KDQogIC0gQXJiaXRyYWdlIG9wcG9ydHVuaXRpZXMgYXJlIG9ubHkgdmlhYmxlIGlmIHRoZSBwb3RlbnRpYWwgcHJvZml0IGV4Y2VlZHMgdHJhbnNhY3Rpb24gY29zdHMgbGlrZSBicm9rZXJhZ2UgZmVlcywgYmlkLWFzayBzcHJlYWRzLCBhbmQgdGF4ZXMgVmFsaWRhdGVcDQogIC0gUmVhbC1Xb3JsZCBGZWFzaWJpbGl0eSBFbnN1cmUgdGhlcmUgYXJlIG5vIG1hcmtldCByZXN0cmljdGlvbnMgKGUuZy4sIHNob3J0LXNlbGxpbmcgcmVzdHJpY3Rpb25zIG9yIGxpcXVpZGl0eSBpc3N1ZXMpLlwNCiAgLSBDaGVjayB0aGF0IHRoZSBpbnN0cnVtZW50cyBpbnZvbHZlZCBjYW4gYmUgZXhlY3V0ZWQgc2ltdWx0YW5lb3VzbHkgdG8gYXZvaWQgZXhlY3V0aW9uIHJpc2suXA0KDQoqKlRvb2xzIGFuZCBUZWNobmlxdWVzOioqXA0KICAtIFNwcmVhZHNoZWV0cyBvciBTb2Z0d2FyZTogQXV0b21hdGUgY2FsY3VsYXRpb25zIG9mIHBhcml0eSBlcXVhdGlvbnMuXA0KICAtIFF1YW50aXRhdGl2ZSBNb2RlbHM6IFVzZSBwcm9ncmFtbWluZyBsYW5ndWFnZXMgbGlrZSBQeXRob24gb3IgUiB0byBzY2FuIGZvciBvcHBvcnR1bml0aWVzIGluIGxhcmdlIGRhdGFzZXRzLlwNCiAgLSBUcmFkaW5nIFBsYXRmb3JtczogUmVhbC10aW1lIGFsZXJ0cyBiYXNlZCBvbiBwcmVzZXQgYXJiaXRyYWdlIGNvbmRpdGlvbnMuXA0KDQpCeSBzeXN0ZW1hdGljYWxseSBjaGVja2luZyB0aGVzZSBjb25kaXRpb25zLCB5b3UgY2FuIGlkZW50aWZ5IGFuZCBwb3RlbnRpYWxseSBleHBsb2l0IGFyYml0cmFnZSBvcHBvcnR1bml0aWVzIGVmZmVjdGl2ZWx5Lg0KDQoNCg0KDQoqKkFkZGl0aW9uYWwgQ29uc2lkZXJhdGlvbnMgZm9yIEFtZXJpY2FuIE9wdGlvbnM6KioNCg0KICArIERpdmlkZW5kczogSWYgdGhlIHVuZGVybHlpbmcgYXNzZXQgcGF5cyBkaXZpZGVuZHMsIHRoZSBwcmVzZW50IHZhbHVlIG9mIGV4cGVjdGVkIGRpdmlkZW5kcyBzaG91bGQgYmUgc3VidHJhY3RlZCBmcm9tIHRoZSBzcG90IHByaWNlIGluIHRoZSBVcHBlcl9Cb3VuZCBjYWxjdWxhdGlvbiB0byBhY2N1cmF0ZWx5IHJlZmxlY3QgdGhlIGFzc2V0J3MgdmFsdWUuXA0KDQogICsgTWFya2V0IENvbmRpdGlvbnM6IFRoZSBhY3R1YWwgcHJpY2VzIG9mIEFtZXJpY2FuIG9wdGlvbnMgbWF5IGRldmlhdGUgZnJvbSB0aGVzZSB0aGVvcmV0aWNhbCBib3VuZHMgZHVlIHRvIG1hcmtldCBjb25kaXRpb25zLCBsaXF1aWRpdHksIGFuZCBvdGhlciBmYWN0b3JzLlwNCg0KQnkgaW1wbGVtZW50aW5nIHRoZXNlIGFkanVzdG1lbnRzLCBvdXIgYW5hbHlzaXMgd2lsbCBiZXR0ZXIgcmVmbGVjdCB0aGUgcHJpY2luZyBkeW5hbWljcyBvZiBBbWVyaWNhbiBvcHRpb25zLCBhY2tub3dsZWRnaW5nIHRoZSBjb21wbGV4aXRpZXMgaW50cm9kdWNlZCBieSB0aGVpciBlYXJseSBleGVyY2lzZSBmZWF0dXJlLg0KDQoNCjxicj4NCg0KDQoNCiMjIFByb2plY3QgIzINCg0KDQoqKlZlcmlmeSB0aGUgcHV0LWNhbGwgcGFyaXR5KioNCg0KDQpUaGlzIFJlcG9ydCBpcyB0byB2ZXJpZnkgdGhlIHB1dC1jYWxsIHBhcml0eSBmb3IgY3J1ZGUgb2lsIG9wdGlvbnMgb24gZnV0dXJlcyBjb250cmFjdHMgdHJhZGVkIG9uIHRoZSBDaGljYWdvIE1lcmNhbnRpbGUgRXhjaGFuZ2UgKENNRSkgZnJvbSAxMi8xLzIwMjAgdGhyb3VnaCAzLzEwLzIwMjEuXA0KDQoNCkZvciAqKkFtZXJpY2FuLXN0eWxlIG9wdGlvbnMqKiwgdGhlIHB1dC1jYWxsIHBhcml0eSByZWxhdGlvbnNoaXAgZGlmZmVycyBzbGlnaHRseSBiZWNhdXNlIG9mIHRoZSBwb3NzaWJpbGl0eSBvZiBlYXJseSBleGVyY2lzZS5cDQpIb3dldmVyLCAqKmF0IG1hdHVyaXR5LCoqIGVhcmx5IGV4ZXJjaXNlIGJlY29tZXMgaXJyZWxldmFudCBhcyB0aGUgb3B0aW9ucyBhcmUgZXhlcmNpc2VkIChvciBub3QpIGJhc2VkIHNvbGVseSBvbiB0aGVpciBpbnRyaW5zaWMgdmFsdWUuIFRodXMsIHRoZSByZWxhdGlvbnNoaXAgc2ltcGxpZmllcy5cDQoNCioqV2h5IFRoaXMgV29ya3MqKlwNCkJlY2F1c2Ugb2YsIEVhcmx5IEV4ZXJjaXNlIGlzIElycmVsZXZhbnQgYXQgTWF0dXJpdHk6XA0KDQoqKkF0IG1hdHVyaXR5LCoqIHRoZSBvcHRpb25zIGFyZSBlaXRoZXIgZXhlcmNpc2VkIG9yIGV4cGlyZSB3b3J0aGxlc3MuXA0KVGhlIHBvdGVudGlhbCBmb3IgZWFybHkgZXhlcmNpc2UgKGEgZGVmaW5pbmcgZmVhdHVyZSBvZiBBbWVyaWNhbiBvcHRpb25zKSBubyBsb25nZXIgYXBwbGllcy5cDQoNClNvLCBPbiBNYXR1cml0eSxcDQp3ZSBhcmUgZGVhbGluZyB3aXRoICoqSW50cmluc2ljIFZhbHVlIE9ubHkqKi4gU28sICoqRnV0dXJlcyBQcmljZSAoRikgY29udmVyZ2VzIHdpdGggdGhlIHNwb3QgcHJpY2UgKFMpKioNCg0KDQokJCBDID0gbWF4KDAsIEYtSykgJCQNCiQkIFA9bWF4KDAsIEsgLSBGKSAkJA0KDQoNCjxicj4NCg0KKipQcmFjdGljYWwgQ29uc2lkZXJhdGlvbnMqKg0KV2hpbGUgdGhlIGZvcm11bGEgcmVtYWlucyB0aGUgc2FtZSBhcyBmb3IgRXVyb3BlYW4gb3B0aW9uczoNCg0KJCRDIC0gUCA9IEYgLSBLJCQNCg0KPGJyPg0KDQoqKkRhdGEgUHJlcGFyYXRpb24qKg0KDQoqKkZ1dHVyZXMgUHJpY2VzOioqXA0KV2UgZXh0cmFjdGVkIGRhaWx5IGZ1dHVyZXMgcHJpY2VzIGZvciB0aHJlZSBkaWZmZXJlbnQgY29udHJhY3QgbWF0dXJpdGllcyAoZS5nLiwgTWFyY2ggMjAyMSwgQXByaWwgMjAyMSwgSnVuZSAyMDIxKSBmcm9tIHRoZSAiRnV0dXJlcyIgc2hlZXQgaW4gKioiV1RJX0RhdGEtMDIueGxzeCIqKi5cDQoNCkF0IGZpcnN0LCB3ZSBtYW51YWxseSBjbGVhbiB0aGUgZGF0YSBpbiBFeGNlbCB0aGVuIGNhbGN1bGF0ZSB0aGUgcHV0LWNhbGwgcGFyaXR5IHVzaW5nIFIgbGFuZ3VhZ2UuXA0KDQoqKk9wdGlvbnMgUHJpY2VzOioqXA0KQWxzbyBleHRyYWN0ZWQgZGFpbHkgY2FsbCBhbmQgcHV0IG9wdGlvbiBwcmljZXMgY29ycmVzcG9uZGluZyB0byB0aGUgc2FtZSBtYXR1cml0aWVzIGFuZCBtYXRjaGluZyBzdHJpa2UgcHJpY2VzIGZyb20gdGhlIHJlc3BlY3RpdmUgc2hlZXRzIChlLmcuLCAiQ2FsbHNfUHV0c19BcHIiIGZvciBBcHJpbCAyMDIxKS5cDQo8YnI+DQoNCiMjIyBDYWxjdWxhdGVkIEV4cGlyYXRpb25zOg0KVGhlIGFuYWx5c2lzIGNvdmVycyB0aGUgZm9sbG93aW5nIGV4cGlyYXRpb25zIGFuZCBzdHJpa2UgcHJpY2VzOiAgDQoNCiMjIyMgQXByaWwgMzAsIDIwMjE6DQotICoqU3RyaWtlIFByaWNlOiBVU0QgNjQqKiAgDQotICoqU3RyaWtlIFByaWNlOiBVU0QgNjUqKg0KDQojIyMjIEp1bmUgMzAsIDIwMjE6DQotICoqU3RyaWtlIFByaWNlOiBVU0QgNjMqKiAgDQotICoqU3RyaWtlIFByaWNlOiBVU0QgNjMuNSoqICANCi0gKipTdHJpa2UgUHJpY2U6IFVTRCA2NCoqDQoNCiMjIyMgSnVseSAzMSwgMjAyMToNCi0gKipTdHJpa2UgUHJpY2U6IFVTRCA2MyoqICANCi0gKipTdHJpa2UgUHJpY2U6IFVTRCA2My41KiogIA0KLSAqKlN0cmlrZSBQcmljZTogVVNEIDY0KiogIA0KLSAqKlN0cmlrZSBQcmljZTogVVNEIDY0LjUqKiAgDQotICoqU3RyaWtlIFByaWNlOiBVU0QgNjUqKg0KDQoNCjxicj4NCg0KIyMgTWF0dXJpdHkgQXByaWwyMQ0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQ0KIyBSZWFkIGRhdGEgZnJvbSB0aGUgRXhjZWwgZmlsZQ0KZGF0YV9hcHIyMSA8LSByZWFkX2V4Y2VsKCJXVElfRGF0YS0wMi54bHN4Iiwgc2hlZXQgPSAiQ2FsbHNfUHV0c19BcHIiKQ0KDQojIGRhdGFfYXByMjEkRGF0ZSA8LSBhcy5EYXRlKGRhdGFfYXByMjEkRGF0ZSwgZm9ybWF0ID0gIiVtLyVkLyVZIikNCmRhdGFfYXByMjEkZnV0dXJlc19hcHIgPC0gYXMubnVtZXJpYyhkYXRhX2FwcjIxJGZ1dHVyZXNfYXByKQ0KZGF0YV9hcHIyMSRjcDY0IDwtIGFzLm51bWVyaWMoZGF0YV9hcHIyMSRjcDY0KQ0KZGF0YV9hcHIyMSRwcDY0IDwtIGFzLm51bWVyaWMoZGF0YV9hcHIyMSRwcDY0KQ0KZGF0YV9hcHIyMSRjcDY0LjUgPC0gYXMubnVtZXJpYyhkYXRhX2FwcjIxJGNwNjQuNSkNCmRhdGFfYXByMjEkcHA2NC41IDwtIGFzLm51bWVyaWMoZGF0YV9hcHIyMSRwcDY0LjUpDQpkYXRhX2FwcjIxJGNwNjUgPC0gYXMubnVtZXJpYyhkYXRhX2FwcjIxJGNwNjUpDQpkYXRhX2FwcjIxJHBwNjUgPC0gYXMubnVtZXJpYyhkYXRhX2FwcjIxJHBwNjUpDQoNCiMgU3RyaWtlIFByaWNlOiBVU0QgNjQNCiMgQ2FsY3VsYXRlIHBhcml0eSBkZXZpYXRpb24gZm9yIEFtZXJpY2FuLXN0eWxlIG9wdGlvbnMNCmRhdGFfYXByMjEgPC0gZGF0YV9hcHIyMSAlPiUgDQogIG11dGF0ZShkZXZpYXRpb242NCA9IChjcDY0IC0gcHA2NCkgLSAoZnV0dXJlc19hcHIgLSA2NCkpDQoNCiMgU3RyaWtlIFByaWNlOiBVU0QgNjQuNQ0KZGF0YV9hcHIyMSA8LSBkYXRhX2FwcjIxICU+JSANCiAgbXV0YXRlKGRldmlhdGlvbjY0LjUgPSAoY3A2NC41IC0gcHA2NC41KSAtIChmdXR1cmVzX2FwciAtIDY0LjUpKQ0KDQojIFN0cmlrZSBQcmljZTogVVNEIDY1DQpkYXRhX2FwcjIxIDwtIGRhdGFfYXByMjEgJT4lIA0KICBtdXRhdGUoZGV2aWF0aW9uNjUgPSAoY3A2NSAtIHBwNjUpIC0gKGZ1dHVyZXNfYXByIC0gNjUpKQ0KDQojIERlZmluZSB0cmFuc2FjdGlvbiBjb3N0IHRocmVzaG9sZA0KdHJhbnNhY3Rpb25fY29zdCA8LSAwLjA1ICAjIFdlIGNhbiBhZGp1c3QgYXMgcGVyIG1hcmtldCBub3Jtcw0KDQojIElkZW50aWZ5IGFyYml0cmFnZSBvcHBvcnR1bml0aWVzDQpkYXRhX2FwcjIxIDwtIGRhdGFfYXByMjEgJT4lIA0KICBtdXRhdGUoYXJiaXRyYWdlNjQgPSBhYnMoZGV2aWF0aW9uNjQpID4gdHJhbnNhY3Rpb25fY29zdCkgJT4lIA0KICBtdXRhdGUoYXJiaXRyYWdlNjQuNSA9IGFicyhkZXZpYXRpb242NC41KSA+IHRyYW5zYWN0aW9uX2Nvc3QpICU+JSANCiAgbXV0YXRlKGFyYml0cmFnZTY1ID0gYWJzKGRldmlhdGlvbjY1KSA+IHRyYW5zYWN0aW9uX2Nvc3QpDQoNCmRhdGFfYXByMjEgJT4lDQogIGhlYWQoMTApICU+JQ0KICBrYWJsZSgNCiAgICBmb3JtYXQgPSAiaHRtbCIsDQogICAgY2FwdGlvbiA9ICJUaGUgZGF0YSBBcHJpbCAyMSAoTWF0dXJpdHkpIHdpdGggYXJiaXRyYWdlIG9wcG9ydHVuaXRpZXMiDQogICkgJT4lDQogIGthYmxlX3N0eWxpbmcoDQogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLA0KICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwNCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiDQogICkgJT4lDQpyb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIiNEM0QzRDMiLCBib2xkID0gVFJVRSkNCmBgYA0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQ0KIyBDb21iaW5lIGRhdGEgZm9yIGFsbCBzdHJpa2VzIGludG8gYSBzaW5nbGUgZGF0YSBmcmFtZQ0KZGV2aWF0aW9uX2RhdGFfYXByMjEgPC0gZGF0YS5mcmFtZSgNCiAgU3RyaWtlID0gcmVwKGMoNjQsIDY0LjUsIDY1KSwgZWFjaCA9IG5yb3coZGF0YV9hcHIyMSkpLA0KICBQYXJpdHlEZXZpYXRpb24gPSBjKGRhdGFfYXByMjEkZGV2aWF0aW9uNjQsIGRhdGFfYXByMjEkZGV2aWF0aW9uNjQuNSwgDQogICAgICAgICAgICAgICAgICAgICAgZGF0YV9hcHIyMSRkZXZpYXRpb242NSkpDQoNCiMgUGxvdCBkZXZpYXRpb25zDQpnZ3Bsb3QoZGV2aWF0aW9uX2RhdGFfYXByMjEsIGFlcyh4ID0gU3RyaWtlLCB5ID0gUGFyaXR5RGV2aWF0aW9uKSkgKw0KICBnZW9tX2JveHBsb3QoKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGMoLXRyYW5zYWN0aW9uX2Nvc3QsIHRyYW5zYWN0aW9uX2Nvc3QpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGxhYnModGl0bGUgPSAiUHV0LUNhbGwgUGFyaXR5IERldmlhdGlvbnMgQXByaWwgMjEiLCB5ID0gIlBhcml0eSBEZXZpYXRpb24iLCB4ID0gIlN0cmlrZSBQcmljZSIpDQpgYGANCg0KYGBge3J9DQojIEZpbHRlciBvdXQgcm93cyB3aXRoIE5BIHZhbHVlcyBpbiBQYXJpdHkgRGV2aWF0aW9uDQpmaWx0ZXJlZF9kYXRhIDwtIGRldmlhdGlvbl9kYXRhX2FwcjIxICU+JQ0KICBmaWx0ZXIoIWlzLm5hKFBhcml0eURldmlhdGlvbikpDQoNCiMgMS4gTGluZSBQbG90IC0gUGFyaXR5IERldmlhdGlvbiBUcmVuZHMgYnkgU3RyaWtlIFByaWNlDQpnZ3Bsb3QoZmlsdGVyZWRfZGF0YSwgYWVzKHggPSBTdHJpa2UsIHkgPSBQYXJpdHlEZXZpYXRpb24pKSArDQogIGdlb21fbGluZShjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJkYXJrYmx1ZSIsIHNpemUgPSAyKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUGFyaXR5IERldmlhdGlvbiBUcmVuZHMgYnkgU3RyaWtlIFByaWNlIiwNCiAgICB4ID0gIlN0cmlrZSBQcmljZSIsDQogICAgeSA9ICJQYXJpdHkgRGV2aWF0aW9uIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQ0KICApDQoNCiMgMi4gSGlzdG9ncmFtIC0gRGlzdHJpYnV0aW9uIG9mIFBhcml0eSBEZXZpYXRpb25zDQpnZ3Bsb3QoZmlsdGVyZWRfZGF0YSwgYWVzKHggPSBQYXJpdHlEZXZpYXRpb24pKSArDQogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wMiwgZmlsbCA9ICJibHVlIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNykgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBQYXJpdHkgRGV2aWF0aW9ucyIsDQogICAgeCA9ICJQYXJpdHkgRGV2aWF0aW9uIiwNCiAgICB5ID0gIkZyZXF1ZW5jeSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkNCiAgKQ0KDQojIDMuIEJveHBsb3QgLSBQYXJpdHkgRGV2aWF0aW9ucyBieSBTdHJpa2UgUHJpY2UNCmdncGxvdChmaWx0ZXJlZF9kYXRhLCBhZXMoeCA9IGZhY3RvcihTdHJpa2UpLCB5ID0gUGFyaXR5RGV2aWF0aW9uKSkgKw0KICBnZW9tX2JveHBsb3QoZmlsbCA9ICJsaWdodGJsdWUiLCBjb2xvciA9ICJkYXJrYmx1ZSIsIG91dGxpZXIuY29sb3IgPSAicmVkIiwgb3V0bGllci5zaXplID0gMikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkJveHBsb3Qgb2YgUGFyaXR5IERldmlhdGlvbnMgYnkgU3RyaWtlIFByaWNlIiwNCiAgICB4ID0gIlN0cmlrZSBQcmljZSIsDQogICAgeSA9ICJQYXJpdHkgRGV2aWF0aW9uIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQ0KICApDQoNCmBgYA0KDQoNCioqS2V5IE9ic2VydmF0aW9uczoqKlwNCioqRGlzdHJpYnV0aW9uIG9mIERldmlhdGlvbnM6KipcDQoNCk1vc3QgZGV2aWF0aW9ucyBhcmUgY2xvc2UgdG8gemVybywgc3VnZ2VzdGluZyB0aGF0IHRoZSBvYnNlcnZlZCBtYXJrZXQgcHJpY2VzIGFsaWduIHdlbGwgd2l0aCB0aGVvcmV0aWNhbCBleHBlY3RhdGlvbnMuXA0KTWluaW1hbCBkZXZpYXRpb25zIGZyb20gdGhlIHBhcml0eSBlcXVhdGlvbiBpbXBseSB0aGF0IHRoZSBtYXJrZXQgZWZmaWNpZW50bHkgcHJpY2VzIG9wdGlvbnMsIGxlYXZpbmcgbGltaXRlZCBvcHBvcnR1bml0aWVzIGZvciBhcmJpdHJhZ2UuXA0KDQoqKlN0cmlrZSBQcmljZSBCZWhhdmlvcjoqKlwNCg0KVGhlIGRhdGFzZXQgaW5jbHVkZXMgbXVsdGlwbGUgc3RyaWtlIHByaWNlcywgYWxsb3dpbmcgZm9yIGEgY29tcGFyYXRpdmUgYW5hbHlzaXMgb2YgZGV2aWF0aW9ucyBhY3Jvc3MgdmFyaW91cyBsZXZlbHMuXA0KVGhlIG1hZ25pdHVkZSBhbmQgdmFyaWFiaWxpdHkgb2YgZGV2aWF0aW9ucyBhcHBlYXIgc2ltaWxhciBhY3Jvc3Mgc3RyaWtlIHByaWNlcywgaW5kaWNhdGluZyBjb25zaXN0ZW50IG1hcmtldCBkeW5hbWljcy5cDQoNCioqSW1wbGljYXRpb25zIGZvciBBcmJpdHJhZ2U6KipcDQoNCk1pbm9yIGRldmlhdGlvbnMgd2l0aGluIGEgbmFycm93IHJhbmdlIHN1Z2dlc3QgdGhhdCB0cmFuc2FjdGlvbiBjb3N0cywgYmlkLWFzayBzcHJlYWRzLCBvciBvdGhlciB0cmFkaW5nIGZyaWN0aW9ucyBsaWtlbHkgb3V0d2VpZ2ggcG90ZW50aWFsIGFyYml0cmFnZSBwcm9maXRzLlwNCk9ic2VydmF0aW9ucyBhbGlnbiB3aXRoIHRoZSBleHBlY3RhdGlvbiBvZiBtYXJrZXQgZWZmaWNpZW5jeSwgcGFydGljdWxhcmx5IGluIGFjdGl2ZWx5IHRyYWRlZCBpbnN0cnVtZW50cyBsaWtlIGNydWRlIG9pbCBvcHRpb25zLlwNCg0KDQoqKkNvbmNsdXNpb246KipcDQpUaGUgYW5hbHlzaXMgaGlnaGxpZ2h0cyB0aGF0IGRldmlhdGlvbnMgZnJvbSBwdXQtY2FsbCBwYXJpdHkgYXJlIG1pbmltYWwgYW5kIGNvbnNpc3RlbnQgYWNyb3NzIHN0cmlrZSBwcmljZXMuIFRoaXMgY29uZmlybXMgdGhhdCB0aGUgY3J1ZGUgb2lsIG9wdGlvbnMgbWFya2V0IGF0IHRoZSBDaGljYWdvIE1lcmNhbnRpbGUgRXhjaGFuZ2UgaXMgaGlnaGx5IGVmZmljaWVudC5cDQoNCk9wcG9ydHVuaXRpZXMgZm9yIGFyYml0cmFnZSBhcmUgbGltaXRlZCBhbmQgbGlrZWx5IG9mZnNldCBieSB0cmFuc2FjdGlvbiBjb3N0cy4gVGhpcyByZWluZm9yY2VzIHRoZSB0aGVvcmV0aWNhbCByb2J1c3RuZXNzIG9mIHB1dC1jYWxsIHBhcml0eSBhbmQgdGhlIHByYWN0aWNhbGl0eSBvZiBpdHMgYXBwbGljYXRpb24gaW4gZmluYW5jaWFsIG1hcmtldHMuXA0KDQoNCiMjIE1hdHVyaXR5IEp1bmUyMQ0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQ0KIyBSZWFkIGRhdGEgZnJvbSB0aGUgRXhjZWwgZmlsZQ0KZGF0YV9qdW4yMSA8LSByZWFkX2V4Y2VsKCJXVElfRGF0YS0wMi54bHN4Iiwgc2hlZXQgPSAiQ2FsbHNfUHV0c19KdW4iKQ0KDQoNCiMgZGF0YV9qdW4yMSREYXRlIDwtIGFzLkRhdGUoZGF0YV9qdW4yMSREYXRlLCBmb3JtYXQgPSAiJW0vJWQvJVkiKQ0KZGF0YV9qdW4yMSRmdXR1cmVzX2p1biA8LSBhcy5udW1lcmljKGRhdGFfanVuMjEkZnV0dXJlc19qdW4pDQpkYXRhX2p1bjIxJGNwNjMgPC0gYXMubnVtZXJpYyhkYXRhX2p1bjIxJGNwNjMpDQpkYXRhX2p1bjIxJHBwNjMgPC0gYXMubnVtZXJpYyhkYXRhX2p1bjIxJHBwNjMpDQpkYXRhX2p1bjIxJGNwNjQgPC0gYXMubnVtZXJpYyhkYXRhX2p1bjIxJGNwNjQpDQpkYXRhX2p1bjIxJHBwNjQgPC0gYXMubnVtZXJpYyhkYXRhX2p1bjIxJHBwNjQpDQpkYXRhX2p1bjIxJGNwNjQuNSA8LSBhcy5udW1lcmljKGRhdGFfanVuMjEkY3A2NC41KQ0KZGF0YV9qdW4yMSRwcDY0LjUgPC0gYXMubnVtZXJpYyhkYXRhX2p1bjIxJHBwNjQuNSkNCmRhdGFfanVuMjEkY3A2NSA8LSBhcy5udW1lcmljKGRhdGFfanVuMjEkY3A2NSkNCmRhdGFfanVuMjEkcHA2NSA8LSBhcy5udW1lcmljKGRhdGFfanVuMjEkcHA2NSkNCmRhdGFfanVuMjEkY3A2NS41IDwtIGFzLm51bWVyaWMoZGF0YV9qdW4yMSRjcDY1LjUpDQpkYXRhX2p1bjIxJHBwNjUuNSA8LSBhcy5udW1lcmljKGRhdGFfanVuMjEkcHA2NS41KQ0KZGF0YV9qdW4yMSRjcDY2IDwtIGFzLm51bWVyaWMoZGF0YV9qdW4yMSRjcDY2KQ0KZGF0YV9qdW4yMSRwcDY2IDwtIGFzLm51bWVyaWMoZGF0YV9qdW4yMSRwcDY2KQ0KDQojIFN0cmlrZSBQcmljZTogVVNEIDYzDQojIENhbGN1bGF0ZSBwYXJpdHkgZGV2aWF0aW9uIGZvciBBbWVyaWNhbi1zdHlsZSBvcHRpb25zDQpkYXRhX2p1bjIxIDwtIGRhdGFfanVuMjEgJT4lIA0KICBtdXRhdGUoZGV2aWF0aW9uNjMgPSAoY3A2MyAtIHBwNjMpIC0gKGZ1dHVyZXNfanVuIC0gNjMpKQ0KDQojIFN0cmlrZSBQcmljZTogVVNEIDYzLjUNCmRhdGFfanVuMjEgPC0gZGF0YV9qdW4yMSAlPiUgDQogIG11dGF0ZShkZXZpYXRpb242My41ID0gKGNwNjMuNSAtIHBwNjMuNSkgLSAoZnV0dXJlc19qdW4gLSA2My41KSkNCg0KIyBTdHJpa2UgUHJpY2U6IFVTRCA2NA0KZGF0YV9qdW4yMSA8LSBkYXRhX2p1bjIxICU+JSANCiAgbXV0YXRlKGRldmlhdGlvbjY0ID0gKGNwNjQgLSBwcDY0KSAtIChmdXR1cmVzX2p1biAtIDY0KSkNCg0KIyBEZWZpbmUgdHJhbnNhY3Rpb24gY29zdCB0aHJlc2hvbGQNCnRyYW5zYWN0aW9uX2Nvc3QgPC0gMC4wNSAgIyBBZGp1c3QgYXMgcGVyIG1hcmtldCBub3Jtcw0KDQojIElkZW50aWZ5IGFyYml0cmFnZSBvcHBvcnR1bml0aWVzDQpkYXRhX2p1bjIxIDwtIGRhdGFfanVuMjEgJT4lIA0KICBtdXRhdGUoYXJiaXRyYWdlNjMgPSBhYnMoZGV2aWF0aW9uNjMpID4gdHJhbnNhY3Rpb25fY29zdCkgJT4lIA0KICBtdXRhdGUoYXJiaXRyYWdlNjMuNSA9IGFicyhkZXZpYXRpb242My41KSA+IHRyYW5zYWN0aW9uX2Nvc3QpICU+JSANCiAgbXV0YXRlKGFyYml0cmFnZTY0ID0gYWJzKGRldmlhdGlvbjY0KSA+IHRyYW5zYWN0aW9uX2Nvc3QpDQoNCmRhdGFfanVuMjEgJT4lDQogIGhlYWQoMTApICU+JQ0KICBrYWJsZSgNCiAgICBmb3JtYXQgPSAiaHRtbCIsDQogICAgY2FwdGlvbiA9ICJUaGUgZGF0YSBKdW5lIDIxIChNYXR1cml0eSkgd2l0aCBhcmJpdHJhZ2Ugb3Bwb3J0dW5pdGllcyINCiAgKSAlPiUNCiAga2FibGVfc3R5bGluZygNCiAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksDQogICAgZnVsbF93aWR0aCA9IEZBTFNFLA0KICAgIHBvc2l0aW9uID0gImNlbnRlciINCiAgKSAlPiUNCnJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAiI0QzRDNEMyIsIGJvbGQgPSBUUlVFKQ0KDQpgYGANCg0KYGBge3IgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1GQUxTRX0NCiMgQ29tYmluZSBkYXRhIGZvciBhbGwgc3RyaWtlcyBpbnRvIGEgc2luZ2xlIGRhdGEgZnJhbWUNCmRldmlhdGlvbl9kYXRhX2p1bjIxIDwtIGRhdGEuZnJhbWUoDQogIFN0cmlrZSA9IHJlcChjKDYzLCA2My41LCA2NCksIGVhY2ggPSBucm93KGRhdGFfanVuMjEpKSwNCiAgUGFyaXR5RGV2aWF0aW9uID0gYyhkYXRhX2p1bjIxJGRldmlhdGlvbjYzLCBkYXRhX2p1bjIxJGRldmlhdGlvbjYzLjUsIA0KICAgICAgICAgICAgICAgICAgICAgIGRhdGFfanVuMjEkZGV2aWF0aW9uNjQpKQ0KDQojIFBsb3QgZGV2aWF0aW9ucw0KZ2dwbG90KGRldmlhdGlvbl9kYXRhX2p1bjIxLCBhZXMoeCA9IFN0cmlrZSwgeSA9IFBhcml0eURldmlhdGlvbikpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKC10cmFuc2FjdGlvbl9jb3N0LCB0cmFuc2FjdGlvbl9jb3N0KSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBsYWJzKHRpdGxlID0gIlB1dC1DYWxsIFBhcml0eSBEZXZpYXRpb25zIEp1bmUgMjEiLCB5ID0gIlBhcml0eSBEZXZpYXRpb24iLCB4ID0gIlN0cmlrZSBQcmljZSIpDQoNCmBgYA0KYGBge3J9DQojIEZpbHRlciBvdXQgcm93cyB3aXRoIE5BIHZhbHVlcyBpbiBQYXJpdHlEZXZpYXRpb24NCmZpbHRlcmVkX2RhdGEgPC0gZGV2aWF0aW9uX2RhdGFfanVuMjEgJT4lDQogIGZpbHRlcighaXMubmEoUGFyaXR5RGV2aWF0aW9uKSkNCg0KIyAxLiBMaW5lIFBsb3QgLSBQYXJpdHkgRGV2aWF0aW9uIFRyZW5kcyBieSBTdHJpa2UgUHJpY2UNCmdncGxvdChmaWx0ZXJlZF9kYXRhLCBhZXMoeCA9IFN0cmlrZSwgeSA9IFBhcml0eURldmlhdGlvbikpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiLCBzaXplID0gMSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gImRhcmtibHVlIiwgc2l6ZSA9IDIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJQYXJpdHkgRGV2aWF0aW9uIFRyZW5kcyBieSBTdHJpa2UgUHJpY2UiLA0KICAgIHggPSAiU3RyaWtlIFByaWNlIiwNCiAgICB5ID0gIlBhcml0eSBEZXZpYXRpb24iDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApDQogICkNCg0KIyAyLiBIaXN0b2dyYW0gLSBEaXN0cmlidXRpb24gb2YgUGFyaXR5IERldmlhdGlvbnMNCmdncGxvdChmaWx0ZXJlZF9kYXRhLCBhZXMoeCA9IFBhcml0eURldmlhdGlvbikpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjAyLCBmaWxsID0gImJsdWUiLCBjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC43KSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFBhcml0eSBEZXZpYXRpb25zIiwNCiAgICB4ID0gIlBhcml0eSBEZXZpYXRpb24iLA0KICAgIHkgPSAiRnJlcXVlbmN5Ig0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQ0KICApDQoNCiMgMy4gQm94cGxvdCAtIFBhcml0eSBEZXZpYXRpb25zIGJ5IFN0cmlrZSBQcmljZQ0KZ2dwbG90KGZpbHRlcmVkX2RhdGEsIGFlcyh4ID0gZmFjdG9yKFN0cmlrZSksIHkgPSBQYXJpdHlEZXZpYXRpb24pKSArDQogIGdlb21fYm94cGxvdChmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gImRhcmtibHVlIiwgb3V0bGllci5jb2xvciA9ICJyZWQiLCBvdXRsaWVyLnNpemUgPSAyKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQm94cGxvdCBvZiBQYXJpdHkgRGV2aWF0aW9ucyBieSBTdHJpa2UgUHJpY2UiLA0KICAgIHggPSAiU3RyaWtlIFByaWNlIiwNCiAgICB5ID0gIlBhcml0eSBEZXZpYXRpb24iDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApDQogICkNCg0KYGBgDQoNCg0KDQoNCiMjIE1hdHVyaXR5IEp1bHkyMQ0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQ0KIyBSZWFkIGRhdGEgZnJvbSB0aGUgRXhjZWwgZmlsZQ0KZGF0YV9qdWwyMSA8LSByZWFkX2V4Y2VsKCJXVElfRGF0YS0wMi54bHN4Iiwgc2hlZXQgPSAiQ2FsbHNfUHV0c19KdWwiKQ0KDQojIGRhdGFfanVsMjEkRGF0ZSA8LSBhcy5EYXRlKGRhdGFfanVsMjEkRGF0ZSwgZm9ybWF0ID0gIiVtLyVkLyVZIikNCmRhdGFfanVsMjEkZnV0dXJlc19qdWwgPC0gYXMubnVtZXJpYyhkYXRhX2p1bDIxJGZ1dHVyZXNfanVsKQ0KZGF0YV9qdWwyMSRjcDYzIDwtIGFzLm51bWVyaWMoZGF0YV9qdWwyMSRjcDYzKQ0KZGF0YV9qdWwyMSRwcDYzIDwtIGFzLm51bWVyaWMoZGF0YV9qdWwyMSRwcDYzKQ0KZGF0YV9qdWwyMSRjcDYzLjUgPC0gYXMubnVtZXJpYyhkYXRhX2p1bDIxJGNwNjMuNSkNCmRhdGFfanVsMjEkcHA2My41IDwtIGFzLm51bWVyaWMoZGF0YV9qdWwyMSRwcDYzLjUpDQpkYXRhX2p1bDIxJGNwNjQgPC0gYXMubnVtZXJpYyhkYXRhX2p1bDIxJGNwNjQpDQpkYXRhX2p1bDIxJHBwNjQgPC0gYXMubnVtZXJpYyhkYXRhX2p1bDIxJHBwNjQpDQpkYXRhX2p1bDIxJGNwNjQuNSA8LSBhcy5udW1lcmljKGRhdGFfanVsMjEkY3A2NC41KQ0KZGF0YV9qdWwyMSRwcDY0LjUgPC0gYXMubnVtZXJpYyhkYXRhX2p1bDIxJHBwNjQuNSkNCmRhdGFfanVsMjEkY3A2NSA8LSBhcy5udW1lcmljKGRhdGFfanVsMjEkY3A2NSkNCmRhdGFfanVsMjEkcHA2NSA8LSBhcy5udW1lcmljKGRhdGFfanVsMjEkcHA2NSkNCmRhdGFfanVsMjEkY3A2NS41IDwtIGFzLm51bWVyaWMoZGF0YV9qdWwyMSRjcDY1LjUpDQpkYXRhX2p1bDIxJHBwNjUuNSA8LSBhcy5udW1lcmljKGRhdGFfanVsMjEkcHA2NS41KQ0KZGF0YV9qdWwyMSRjcDY2IDwtIGFzLm51bWVyaWMoZGF0YV9qdWwyMSRjcDY2KQ0KZGF0YV9qdWwyMSRwcDY2IDwtIGFzLm51bWVyaWMoZGF0YV9qdWwyMSRwcDY2KQ0KDQpkYXRhX2p1bDIxIDwtIGRhdGFfanVsMjEgJT4lIA0KICBtdXRhdGUoZGV2aWF0aW9uNjMgPSAoY3A2MyAtIHBwNjMpIC0gKGZ1dHVyZXNfanVsIC0gNjMpKQ0KDQojIFN0cmlrZSBQcmljZTogVVNEIDYzDQojIENhbGN1bGF0ZSBwYXJpdHkgZGV2aWF0aW9uIGZvciBBbWVyaWNhbi1zdHlsZSBvcHRpb25zDQpkYXRhX2p1bDIxIDwtIGRhdGFfanVsMjEgJT4lIA0KICBtdXRhdGUoZGV2aWF0aW9uNjMgPSAoY3A2MyAtIHBwNjMpIC0gKGZ1dHVyZXNfanVsIC0gNjMpKQ0KDQojIFN0cmlrZSBQcmljZTogVVNEIDYzLjUNCmRhdGFfanVsMjEgPC0gZGF0YV9qdWwyMSAlPiUgDQogIG11dGF0ZShkZXZpYXRpb242My41ID0gKGNwNjMuNSAtIHBwNjMuNSkgLSAoZnV0dXJlc19qdWwgLSA2My41KSkNCg0KIyBTdHJpa2UgUHJpY2U6IFVTRCA2NA0KZGF0YV9qdWwyMSA8LSBkYXRhX2p1bDIxICU+JSANCiAgbXV0YXRlKGRldmlhdGlvbjY0ID0gKGNwNjQgLSBwcDY0KSAtIChmdXR1cmVzX2p1bCAtIDY0KSkNCg0KIyBTdHJpa2UgUHJpY2U6IFVTRCA2NC41DQpkYXRhX2p1bDIxIDwtIGRhdGFfanVsMjEgJT4lIA0KICBtdXRhdGUoZGV2aWF0aW9uNjQuNSA9IChjcDY0LjUgLSBwcDY0LjUpIC0gKGZ1dHVyZXNfanVsIC0gNjQuNSkpDQoNCiMgU3RyaWtlIFByaWNlOiBVU0QgNjUNCmRhdGFfanVsMjEgPC0gZGF0YV9qdWwyMSAlPiUgDQogIG11dGF0ZShkZXZpYXRpb242NSA9IChjcDY1IC0gcHA2NSkgLSAoZnV0dXJlc19qdWwgLSA2NSkpDQoNCiMgRGVmaW5lIHRyYW5zYWN0aW9uIGNvc3QgdGhyZXNob2xkDQp0cmFuc2FjdGlvbl9jb3N0IDwtIDAuMDUgICMgV2UgY2FuIGFkanVzdCBhcyBwZXIgbWFya2V0IG5vcm1zDQoNCiMgSWRlbnRpZnkgYXJiaXRyYWdlIG9wcG9ydHVuaXRpZXMNCmRhdGFfanVsMjEgPC0gZGF0YV9qdWwyMSAlPiUgDQogIG11dGF0ZShhcmJpdHJhZ2U2MyA9IGFicyhkZXZpYXRpb242MykgPiB0cmFuc2FjdGlvbl9jb3N0KSAlPiUgDQogIG11dGF0ZShhcmJpdHJhZ2U2My41ID0gYWJzKGRldmlhdGlvbjYzLjUpID4gdHJhbnNhY3Rpb25fY29zdCkgJT4lIA0KICBtdXRhdGUoYXJiaXRyYWdlNjQgPSBhYnMoZGV2aWF0aW9uNjQpID4gdHJhbnNhY3Rpb25fY29zdCklPiUgDQogIG11dGF0ZShhcmJpdHJhZ2U2NC41ID0gYWJzKGRldmlhdGlvbjY0LjUpID4gdHJhbnNhY3Rpb25fY29zdCklPiUgDQogIG11dGF0ZShhcmJpdHJhZ2U2NSA9IGFicyhkZXZpYXRpb242NSkgPiB0cmFuc2FjdGlvbl9jb3N0KQ0KDQpkYXRhX2p1bDIxICU+JQ0KICBoZWFkKDEwKSAlPiUNCiAga2FibGUoDQogICAgZm9ybWF0ID0gImh0bWwiLA0KICAgIGNhcHRpb24gPSAiVGhlIGRhdGEganVseSAyMSAoTWF0dXJpdHkpIHdpdGggYXJiaXRyYWdlIG9wcG9ydHVuaXRpZXMiDQogICkgJT4lDQogIGthYmxlX3N0eWxpbmcoDQogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLA0KICAgIGZ1bGxfd2lkdGggPSBGQUxTRSwNCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiDQogICkgJT4lDQpyb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIiNEM0QzRDMiLCBib2xkID0gVFJVRSkNCmBgYA0KDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQ0KIyBDb21iaW5lIGRhdGEgZm9yIGFsbCBzdHJpa2VzIGludG8gYSBzaW5nbGUgZGF0YSBmcmFtZQ0KZGV2aWF0aW9uX2RhdGFfanVsMjEgPC0gZGF0YS5mcmFtZSgNCiAgU3RyaWtlID0gcmVwKGMoNjMsIDYzLjUsIDY0LCA2NC41LCA2NSksIGVhY2ggPSBucm93KGRhdGFfanVsMjEpKSwNCiAgUGFyaXR5RGV2aWF0aW9uID0gYyhkYXRhX2p1bDIxJGRldmlhdGlvbjYzLCBkYXRhX2p1bDIxJGRldmlhdGlvbjYzLjUsIA0KICAgICAgICAgICAgICAgICAgICAgIGRhdGFfanVsMjEkZGV2aWF0aW9uNjQsIGRhdGFfanVsMjEkZGV2aWF0aW9uNjQuNSwgDQogICAgICAgICAgICAgICAgICAgICAgZGF0YV9qdWwyMSRkZXZpYXRpb242NSkNCikNCg0KIyBQbG90IGRldmlhdGlvbnMNCmdncGxvdChkZXZpYXRpb25fZGF0YV9qdWwyMSwgYWVzKHggPSBTdHJpa2UsIHkgPSBQYXJpdHlEZXZpYXRpb24pKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gYygtdHJhbnNhY3Rpb25fY29zdCwgdHJhbnNhY3Rpb25fY29zdCksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgbGFicyh0aXRsZSA9ICJQdXQtQ2FsbCBQYXJpdHkgRGV2aWF0aW9ucyBKdWx5IDIxIiwgeSA9ICJQYXJpdHkgRGV2aWF0aW9uIiwgeCA9ICJTdHJpa2UgUHJpY2UiKQ0KDQpgYGANCg0KDQpgYGB7cn0NCiMgRmlsdGVyIG91dCByb3dzIHdpdGggTkEgdmFsdWVzIGluIFBhcml0eURldmlhdGlvbg0KZmlsdGVyZWRfZGF0YSA8LSBkZXZpYXRpb25fZGF0YV9qdWwyMSAlPiUNCiAgZmlsdGVyKCFpcy5uYShQYXJpdHlEZXZpYXRpb24pKQ0KDQojIDEuIExpbmUgUGxvdCAtIFBhcml0eSBEZXZpYXRpb24gVHJlbmRzIGJ5IFN0cmlrZSBQcmljZQ0KZ2dwbG90KGZpbHRlcmVkX2RhdGEsIGFlcyh4ID0gU3RyaWtlLCB5ID0gUGFyaXR5RGV2aWF0aW9uKSkgKw0KICBnZW9tX2xpbmUoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxKSArDQogIGdlb21fcG9pbnQoY29sb3IgPSAiZGFya2JsdWUiLCBzaXplID0gMikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBhcml0eSBEZXZpYXRpb24gVHJlbmRzIGJ5IFN0cmlrZSBQcmljZSIsDQogICAgeCA9ICJTdHJpa2UgUHJpY2UiLA0KICAgIHkgPSAiUGFyaXR5IERldmlhdGlvbiINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkNCiAgKQ0KDQojIDIuIEhpc3RvZ3JhbSAtIERpc3RyaWJ1dGlvbiBvZiBQYXJpdHkgRGV2aWF0aW9ucw0KZ2dwbG90KGZpbHRlcmVkX2RhdGEsIGFlcyh4ID0gUGFyaXR5RGV2aWF0aW9uKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDIsIGZpbGwgPSAiYmx1ZSIsIGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjcpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUGFyaXR5IERldmlhdGlvbnMiLA0KICAgIHggPSAiUGFyaXR5IERldmlhdGlvbiIsDQogICAgeSA9ICJGcmVxdWVuY3kiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApDQogICkNCg0KIyAzLiBCb3hwbG90IC0gUGFyaXR5IERldmlhdGlvbnMgYnkgU3RyaWtlIFByaWNlDQpnZ3Bsb3QoZmlsdGVyZWRfZGF0YSwgYWVzKHggPSBmYWN0b3IoU3RyaWtlKSwgeSA9IFBhcml0eURldmlhdGlvbikpICsNCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3IgPSAiZGFya2JsdWUiLCBvdXRsaWVyLmNvbG9yID0gInJlZCIsIG91dGxpZXIuc2l6ZSA9IDIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJCb3hwbG90IG9mIFBhcml0eSBEZXZpYXRpb25zIGJ5IFN0cmlrZSBQcmljZSIsDQogICAgeCA9ICJTdHJpa2UgUHJpY2UiLA0KICAgIHkgPSAiUGFyaXR5IERldmlhdGlvbiINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkNCiAgKQ0KDQpgYGANCg0KDQoNCg0KKipDb25jbHVzaW9uIGZyb20gUmVzdWx0cyoqXA0KDQpCeSBhbmFseXppbmcgdGhlIGZsYWdnZWQgYXJiaXRyYWdlIG9wcG9ydHVuaXRpZXMgYW5kIGRldmlhdGlvbnM6XA0KDQpJZiBhbGwgZGV2aWF0aW9ucyBhcmUgd2l0aGluICoqwrEwLjA1KiosIHRoZSBtYXJrZXQgaXMgYXJiaXRyYWdlLWZyZWUgYXQgdGhlIHNwZWNpZmllZCB0cmFuc2FjdGlvbiBjb3N0LlwNCklmIHNvbWUgZGV2aWF0aW9ucyBleGNlZWQgKirCsTAuMDUqKiwgdGhvc2Ugc3BlY2lmaWMgcm93cyBpbmRpY2F0ZSBwb3RlbnRpYWwgYXJiaXRyYWdlIG9wcG9ydHVuaXRpZXMgdGhhdCBjYW4gYmUgZXhwbG9pdGVkLlwNCg0KV2UgRm91bmQgMSBBcmJpdHJhZ2Ugb3Bwb3J0dW5pdHkgZm9yIHRoZSBleHBpcmF0aW9uICoqQXByaWwgMjEqKiAmICoqSnVuZSAyMSoqLiBBbmQgKipzZXZlcmFsIGFyYml0cmFnZSBvcHBvcnR1bml0aWVzIGZvciBKdWx5IDIxKiouXA0KDQoNCjxicj4NCg0KIyMjIyAqU3VibWl0dGVkIEJ5Og0KDQo6Ojo6IHsuY29sdW1uc30NCjo6OiB7LmNvbHVtbiB3aWR0aD0iNTAlIn0NCjxzcGFuPiAgPHNwYW4gc3R5bGU9ImNvbG9yOiBTdGVlbGJsdWU7Ij4qKk1vaGFtbWFkIEhvc3NlaW4gQXJkZXN0YW5pKio8L3NwYW4+IFwNCk1RSU0gMzc2ODY3N1wNCkZhY3VsdHkgb2YgTWFuYWdlbWVudCBcDQpVbml2ZXJzaXR5IG9mIE5ldyBCcnVuc3dpY2sgXA0KbWhvc3NlaW4uYXJkZXN0YW5pXEB1bmIuY2FcDQoNCg0KOjo6DQo6Ojogey5jb2x1bW4gd2lkdGg9IjUwJSJ9DQo8c3Bhbj4gIDxzcGFuIHN0eWxlPSJjb2xvcjogU3RlZWxibHVlOyI+KipNZCBNYWhtdWR1bCBIYXNhbioqPC9zcGFuPiBcDQpNUUlNIDM3NjA1NzNcDQpGYWN1bHR5IG9mIE1hbmFnZW1lbnQgXA0KVW5pdmVyc2l0eSBvZiBOZXcgQnJ1bnN3aWNrIFwNCm1haG11ZHVsLmhhc2FuXEB1bmIuY2EgXA0KDQo6OjoNCjo6OjoNCg0K