About
In this worksheet we look at different distribution functions, sampling methods, and probability calculations. Next we consider a calculation of a Europen option using Monte Carlo simulation, and compare results to calculation using Black-Scholes.
Setup
Remember to always set your working directory to the source file location. Go to ‘Session’, scroll down to ‘Set Working Directory’, and click ‘To Source File Location’. Read carefully the below and follow the instructions to complete the tasks and answer any questions. Submit your work to RPubs as detailed in previous notes.
Note
Always read carefully the instructions on Sakai. For clarity, tasks/questions to be completed/answered are highlighted in red color (visible in preview) and numbered according to their particular placement in the task section. Quite often you will need to add your own code chunk.
Execute all code chunks, preview, publish, and submit link on Sakai follwoing the naming convention. Make sure to add comments to your code where appropriate. Use own language!
Task 1: Distribution, Sampling & Probability
#Install package quantmod
if(!require("quantmod",quietly = TRUE))
install.packages("quantmod",dependencies = TRUE, repos = "https://cloud.r-project.org")
Consider the free cash flow example with an estimated range set by a minimum of -$25M and maximum $275M. We start by generating a sample random set. Following is an example to generate a random set of 10 data points from a uniform distribution with probability \(\frac{1}{b-a}\), a minimum of a, and a maximum of b.
ud = runif(10, min=5, max=15) # runif is in reference to uniform distribution
# Other R functions needed for this task are hist(), mean(), sd(), punif(), runif(), pnorm(), and rnorm(). Check the Help command in R for more details about these functions.
##### 1A) Assuming a uniform probability distribution, generate a sample of 100 random observations (or deviates) representing the cash flows
ud = runif(100, min=-25000000, max=275000000)
Next we plot a histogram to describe the generated sample data, and calculate the mean and standard deviation of the sample using the proper R-functions
##### 1B) Plot a histogram and calculate the mean and standard deviation of your sample. Compare the mean and standard deviation of the sample to the theoretical values obtained using the proper formulas.
hist(ud)

mean(ud)
[1] 147903036
sd(ud)
[1] 92170972
Since it is a uniform probability distribution, we can know that a=-25, b=275 in the free cash flow example. Using the formula of to calculate the mean and standard deviation theoretically, we get:
mean=\(\frac{a+b}{2}\)=\(\frac{-25000000+275000000}{2}\)=125000000
standard deviation=\(\sqrt\frac{(b-a)^2}{12}\)=\(\sqrt\frac{(275000000-(-25000000))^2}{12}\)=86602540.38
Since the sample size is only 100, not large enough, there are certain differences in mean and standard deviation between the sample and theoretical values.
##### 1C) Repeat 1A & 1B above by increasing the sample size to 1000. Share your insights.
ud = runif(1000, min=-25000000, max=275000000)
hist(ud)

mean(ud)
[1] 124855334
sd(ud)
[1] 86058031
From the results we can see that, the mean and standard deviation of the sample with the size of 1000 is closer to the theoretical values. This means that as we increase the sample size, the discrete random generated sample approximates closer to the continuous uniform distribution.
Given the characteristics of a probability distribution we should be able to compute various probability scenarios using the proper functions in R.
##### 1D) Calculate the probability that the free cash flow is negative
punif(0, min = -25000000, max = 275000000, lower.tail = TRUE, log.p = FALSE)
[1] 0.08333333
We will now repeat the above exercises 1A, 1B, 1C using instead a normal distribution.
##### 1E) Repeat steps A-C for the case of a portfolio daily returns with normal probability distribution,a mean=1.2% and a standard deviation= 3.7%
nd=rnorm(100, mean=0.012, sd=0.037)
hist(nd)

mean(nd)
[1] 0.01100024
sd(nd)
[1] 0.0422672
nd=rnorm(1000, mean=0.012, sd=0.037)
hist(nd)

mean(nd)
[1] 0.01258229
sd(nd)
[1] 0.0368721
From the results we can see that, the mean and standard deviation of the sample with the size of 100 is 0.0110 and 0.04227, and the mean and standard deviation of the sample with the size of 1000 is 0.01258 and 0.03687, which is closer to the theoretical values. This means that as we increase the sample size, the discrete random generated sample approximates closer to the continuous normal distribution.
Similarly we should be able to compute various probability senarios with our obtained normal distribution.
##### 1F) Calculate the probability that returns will be negative using the values for mean and standard deviation as in 1E
pnorm(0, mean = 0.012, sd = 0.037, lower.tail = TRUE, log.p = FALSE)
[1] 0.3728463
##### 1G) Repeat the calculation in 1F using instead the standard Z-value. Share insights.
z=(0-0.012)/0.037
pnorm(z, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
[1] 0.3728463
Using instead the standard z-value, we get the same result as in 1F. This means that standardizing the normally distributed variable will not change the properties of it. Therefore, it would become easier to compare separate normal distributions with different mean and standard deviation.
Task 2: MC Simulation & European Option Pricing
Follow the Algorithm 5.2 example on p 167 (*) to calculate the price of a European option using a MC simulation. Note that the code in the book example is missing one detail and a correction. Those are left for your investigation.
##### 2A) Identify and explain the nature of the missing detail and the correction needed.
The missing detail is that we need to add S=S0 between the first and second for loops. Because when you finish one simulation, you need to reset the initial price to the underlying stock price. The correction is that the code for generating a random value from standard normal distribution should be rnorm(1, mean=0, sd=1) instead of rnorm(0,1).
Given the MC simulation we should be able to price a European option. Note the introduction of user defined function in the book. Below is an example of a user defined function and usage. The function returns the squared value.
myfunction <- function(x=2){
y=x^2
return(y)}
myfunction(x=5)
##### 2B) Use MC simulation to price a European Call option on a stock with initial price of $155, strike price $140, a time to expiration equal to six months, a risk-free interest rate of 2.5% and a volatility of 23%. Consider a number of periods n=100 and a number of simulations m=1000
optionvalue <- function( Type, S0, K, T, r, sigma, n, m, dt){
sum = 0;
for (i in 1 : m) { # number of simulated paths
S=S0
for (j in 1 : n) { # length of path
E = rnorm(1, mean=0, sd=1);
S = S + r * S * dt + sigma * S * sqrt(dt) * E; }
if (Type == "c" ){ payoff = max(S - K, 0) }
else if (Type == "p" ){ payoff = max(K - S, 0) }
else { payoff = max(S - K, 0) } # default
sum = sum + payoff }
OptionValue = (sum * exp(-r * T))/m;
return (OptionValue)}
optionvalue (Type = "c", S0 = 155, K = 140, T = 0.5,r = 0.025, sigma = 0.23, n = 100, m = 1000, dt = 0.5/100 )
[1] 20.42425
##### 2C) Write the mathematical representation of the discrete pricing equation modeled in the MC simulation. Explain what each variable in the equation represents, and provide the associated numerical value.
The mathematical representation of the discrete pricing equation modeled in the MC simulation is:
\(S_{t+\Delta_{t}}\) =\(S_{t}\) +r\(S_{t}\)\(\Delta_{t}\) +\(\sigma\)\(S_{t}\)\(\sqrt\Delta_{t}\)*\(\varepsilon_{t}\), \(\varepsilon_{t}\)~N(0, 1)
\(S_{t+\Delta_{t}}\) represents the underlying stock price next time period; \(S_{t}\) represents the underlying stock price this time period; r is the risk-free rate; \(\Delta_{t}\) represents the time periods and is equal to T/n, in which n represents the number of periods, and T is the expiration time; \(\sigma\) represents the volatility of the underlying stock price; \(\varepsilon_{t}\) is a random value generated from standard normal distribution.
From the example above, \(S_{0}\)=155, T=0.5, n=100, r=0.025, \(\Delta_{t}\)=T/n=0.005, \(\sigma\)=0.023, \(\varepsilon_{t}\) is selected randomly from standard normal distribution.
##### 2D) Compare the price obtained from the MC simulation to the option price using the Black-Scholes function pricing GBSOption(). Share insights.
library(fOptions)
GBSOption(TypeFlag = "c", S = 155, X = 140, Time = 1/2, r = 0.025, b = 0.025, sigma = 0.23)
Title:
Black Scholes Option Valuation
Call:
GBSOption(TypeFlag = "c", S = 155, X = 140, Time = 1/2, r = 0.025,
b = 0.025, sigma = 0.23)
Parameters:
Value:
TypeFlag c
S 155
X 140
Time 0.5
r 0.025
b 0.025
sigma 0.23
Option Price:
20.11899
Description:
Wed Jan 30 15:07:50 2019
The option price obtained from the MC simulation is 20.4243, while the option price using the Black-Scholes function is 20.1190. We can see that these two results are very close to each other. Because both MC simulation and Black-Sholes function assume that stock price follow the same geometric brown motion pattern, they are only different in solving the pricing problem. Therefore, their results should be the same or close to each other.
*http://computationalfinance.lsi.upc.edu
LS0tDQp0aXRsZTogIkZJTkM2MjEgV2ludGVyIDIwMTgtMTkgTGFiIFdvcmtzaGVldCAwNiINCmF1dGhvcjogIll1ZSBIdWFuZyINCmRhdGU6ICIxLzMwLzIwMTkiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0Kc3VidGl0bGU6IERpc3RyaWJ1dGlvbnMsIFNhbXBsaW5nIE1ldGhvZHMgJiBNb250ZSBDYXJsbyBTaW11bGF0aW9uICAoZmluYzYyMS1sYWIwNikNCi0tLQ0KDQojIyMgQWJvdXQNCg0KSW4gdGhpcyB3b3Jrc2hlZXQgd2UgbG9vayBhdCBkaWZmZXJlbnQgZGlzdHJpYnV0aW9uIGZ1bmN0aW9ucywgc2FtcGxpbmcgbWV0aG9kcywgYW5kIHByb2JhYmlsaXR5IGNhbGN1bGF0aW9ucy4gIE5leHQgd2UgY29uc2lkZXIgYSBjYWxjdWxhdGlvbiBvZiBhIEV1cm9wZW4gb3B0aW9uIHVzaW5nIE1vbnRlIENhcmxvIHNpbXVsYXRpb24sIGFuZCBjb21wYXJlIHJlc3VsdHMgdG8gY2FsY3VsYXRpb24gdXNpbmcgQmxhY2stU2Nob2xlcy4NCg0KIyMjIFNldHVwDQoNClJlbWVtYmVyIHRvIGFsd2F5cyBzZXQgeW91ciB3b3JraW5nIGRpcmVjdG9yeSB0byB0aGUgc291cmNlIGZpbGUgbG9jYXRpb24uIEdvIHRvICdTZXNzaW9uJywgc2Nyb2xsIGRvd24gdG8gJ1NldCBXb3JraW5nIERpcmVjdG9yeScsIGFuZCBjbGljayAnVG8gU291cmNlIEZpbGUgTG9jYXRpb24nLiBSZWFkIGNhcmVmdWxseSB0aGUgYmVsb3cgYW5kIGZvbGxvdyB0aGUgaW5zdHJ1Y3Rpb25zIHRvIGNvbXBsZXRlIHRoZSB0YXNrcyBhbmQgYW5zd2VyIGFueSBxdWVzdGlvbnMuICBTdWJtaXQgeW91ciB3b3JrIHRvIFJQdWJzIGFzIGRldGFpbGVkIGluIHByZXZpb3VzIG5vdGVzLiANCg0KIyMjIE5vdGUNCg0KQWx3YXlzIHJlYWQgY2FyZWZ1bGx5IHRoZSBpbnN0cnVjdGlvbnMgb24gU2FrYWkuICBGb3IgY2xhcml0eSwgdGFza3MvcXVlc3Rpb25zIHRvIGJlIGNvbXBsZXRlZC9hbnN3ZXJlZCBhcmUgaGlnaGxpZ2h0ZWQgaW4gcmVkIGNvbG9yICh2aXNpYmxlIGluIHByZXZpZXcpIGFuZCBudW1iZXJlZCBhY2NvcmRpbmcgdG8gdGhlaXIgcGFydGljdWxhciBwbGFjZW1lbnQgaW4gdGhlIHRhc2sgc2VjdGlvbi4gIFF1aXRlIG9mdGVuIHlvdSB3aWxsIG5lZWQgdG8gYWRkIHlvdXIgb3duIGNvZGUgY2h1bmsuDQoNCkV4ZWN1dGUgYWxsIGNvZGUgY2h1bmtzLCBwcmV2aWV3LCBwdWJsaXNoLCBhbmQgc3VibWl0IGxpbmsgb24gU2FrYWkgZm9sbHdvaW5nIHRoZSBuYW1pbmcgY29udmVudGlvbi4gTWFrZSBzdXJlIHRvIGFkZCBjb21tZW50cyB0byB5b3VyIGNvZGUgd2hlcmUgYXBwcm9wcmlhdGUuIFVzZSBvd24gbGFuZ3VhZ2UhDQoNCi0tLS0tLS0tLS0tLS0tDQoNCiMjIyBUYXNrIDE6IERpc3RyaWJ1dGlvbiwgU2FtcGxpbmcgJiBQcm9iYWJpbGl0eQ0KDQoNCmBgYHtyfQ0KI0luc3RhbGwgcGFja2FnZSBxdWFudG1vZCANCmlmKCFyZXF1aXJlKCJxdWFudG1vZCIscXVpZXRseSA9IFRSVUUpKQ0KICBpbnN0YWxsLnBhY2thZ2VzKCJxdWFudG1vZCIsZGVwZW5kZW5jaWVzID0gVFJVRSwgcmVwb3MgPSAiaHR0cHM6Ly9jbG91ZC5yLXByb2plY3Qub3JnIikNCmBgYA0KDQpDb25zaWRlciB0aGUgZnJlZSBjYXNoIGZsb3cgZXhhbXBsZSB3aXRoIGFuIGVzdGltYXRlZCByYW5nZSBzZXQgYnkgYSBtaW5pbXVtIG9mIC0kMjVNIGFuZCBtYXhpbXVtICQyNzVNLiBXZSBzdGFydCBieSBnZW5lcmF0aW5nIGEgc2FtcGxlIHJhbmRvbSBzZXQuIEZvbGxvd2luZyBpcyBhbiBleGFtcGxlIHRvIGdlbmVyYXRlIGEgcmFuZG9tIHNldCBvZiAxMCBkYXRhIHBvaW50cyBmcm9tIGEgdW5pZm9ybSBkaXN0cmlidXRpb24gd2l0aCBwcm9iYWJpbGl0eSAkXGZyYWN7MX17Yi1hfSQsIGEgbWluaW11bSBvZiBhLCBhbmQgYSBtYXhpbXVtIG9mIGIuDQoNCg0KDQpgYGB7cn0NCnVkID0gcnVuaWYoMTAsIG1pbj01LCBtYXg9MTUpICMgcnVuaWYgaXMgaW4gcmVmZXJlbmNlIHRvIHVuaWZvcm0gZGlzdHJpYnV0aW9uDQoNCiMgT3RoZXIgUiBmdW5jdGlvbnMgbmVlZGVkIGZvciB0aGlzIHRhc2sgYXJlIGhpc3QoKSwgbWVhbigpLCBzZCgpLCBwdW5pZigpLCBydW5pZigpLCAgcG5vcm0oKSwgYW5kIHJub3JtKCkuIENoZWNrIHRoZSBIZWxwIGNvbW1hbmQgaW4gUiBmb3IgbW9yZSBkZXRhaWxzIGFib3V0IHRoZXNlIGZ1bmN0aW9ucy4NCmBgYA0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDFBKSBBc3N1bWluZyBhIHVuaWZvcm0gcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uLCAgZ2VuZXJhdGUgYSBzYW1wbGUgb2YgMTAwIHJhbmRvbSBvYnNlcnZhdGlvbnMgKG9yIGRldmlhdGVzKSByZXByZXNlbnRpbmcgdGhlIGNhc2ggZmxvd3MNCjwvc3Bhbj4NCg0KYGBge3J9DQp1ZCA9IHJ1bmlmKDEwMCwgbWluPS0yNTAwMDAwMCwgbWF4PTI3NTAwMDAwMCkNCmBgYA0KDQpOZXh0IHdlIHBsb3QgYSBoaXN0b2dyYW0gdG8gZGVzY3JpYmUgdGhlIGdlbmVyYXRlZCBzYW1wbGUgZGF0YSwgYW5kIGNhbGN1bGF0ZSB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBzYW1wbGUgdXNpbmcgdGhlIHByb3BlciBSLWZ1bmN0aW9ucw0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDFCKSBQbG90IGEgaGlzdG9ncmFtIGFuZCBjYWxjdWxhdGUgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB5b3VyIHNhbXBsZS4gQ29tcGFyZSB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBzYW1wbGUgdG8gdGhlIHRoZW9yZXRpY2FsIHZhbHVlcyBvYnRhaW5lZCB1c2luZyB0aGUgcHJvcGVyIGZvcm11bGFzLiANCjwvc3Bhbj4NCg0KYGBge3J9DQpoaXN0KHVkKQ0KbWVhbih1ZCkNCnNkKHVkKQ0KYGBgDQpTaW5jZSBpdCBpcyBhIHVuaWZvcm0gcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uLCB3ZSBjYW4ga25vdyB0aGF0IGE9LTI1LCBiPTI3NSBpbiB0aGUgZnJlZSBjYXNoIGZsb3cgZXhhbXBsZS4gVXNpbmcgdGhlIGZvcm11bGEgb2YgdG8gY2FsY3VsYXRlIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gdGhlb3JldGljYWxseSwgd2UgZ2V0Og0KDQptZWFuPSRcZnJhY3thK2J9ezJ9JD0kXGZyYWN7LTI1MDAwMDAwKzI3NTAwMDAwMH17Mn0kPTEyNTAwMDAwMA0KDQpzdGFuZGFyZCBkZXZpYXRpb249JFxzcXJ0XGZyYWN7KGItYSleMn17MTJ9JD0kXHNxcnRcZnJhY3soMjc1MDAwMDAwLSgtMjUwMDAwMDApKV4yfXsxMn0kPTg2NjAyNTQwLjM4DQoNClNpbmNlIHRoZSBzYW1wbGUgc2l6ZSBpcyBvbmx5IDEwMCwgbm90IGxhcmdlIGVub3VnaCwgdGhlcmUgYXJlIGNlcnRhaW4gZGlmZmVyZW5jZXMgaW4gbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIGJldHdlZW4gdGhlIHNhbXBsZSBhbmQgdGhlb3JldGljYWwgdmFsdWVzLg0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDFDKSBSZXBlYXQgMUEgJiAxQiAgYWJvdmUgYnkgaW5jcmVhc2luZyB0aGUgc2FtcGxlIHNpemUgdG8gMTAwMC4gU2hhcmUgeW91ciBpbnNpZ2h0cy4NCjwvc3Bhbj4NCg0KYGBge3J9DQp1ZCA9IHJ1bmlmKDEwMDAsIG1pbj0tMjUwMDAwMDAsIG1heD0yNzUwMDAwMDApDQpoaXN0KHVkKQ0KbWVhbih1ZCkNCnNkKHVkKQ0KYGBgDQpGcm9tIHRoZSByZXN1bHRzIHdlIGNhbiBzZWUgdGhhdCwgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgc2FtcGxlIHdpdGggdGhlIHNpemUgb2YgMTAwMCBpcyBjbG9zZXIgdG8gdGhlIHRoZW9yZXRpY2FsIHZhbHVlcy4gVGhpcyBtZWFucyB0aGF0IGFzIHdlIGluY3JlYXNlIHRoZSBzYW1wbGUgc2l6ZSwgdGhlIGRpc2NyZXRlIHJhbmRvbSBnZW5lcmF0ZWQgc2FtcGxlIGFwcHJveGltYXRlcyBjbG9zZXIgdG8gdGhlIGNvbnRpbnVvdXMgdW5pZm9ybSBkaXN0cmlidXRpb24uDQoNCkdpdmVuIHRoZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgYSBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24gd2Ugc2hvdWxkIGJlIGFibGUgdG8gY29tcHV0ZSB2YXJpb3VzIHByb2JhYmlsaXR5IHNjZW5hcmlvcyB1c2luZyB0aGUgcHJvcGVyIGZ1bmN0aW9ucyBpbiBSLg0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDFEKSBDYWxjdWxhdGUgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIGZyZWUgY2FzaCBmbG93IGlzIG5lZ2F0aXZlDQo8L3NwYW4+DQoNCmBgYHtyfQ0KcHVuaWYoMCwgbWluID0gLTI1MDAwMDAwLCBtYXggPSAyNzUwMDAwMDAsIGxvd2VyLnRhaWwgPSBUUlVFLCBsb2cucCA9IEZBTFNFKQ0KYGBgDQoNCldlIHdpbGwgbm93IHJlcGVhdCB0aGUgYWJvdmUgZXhlcmNpc2VzIDFBLCAxQiwgMUMgdXNpbmcgaW5zdGVhZCBhIG5vcm1hbCBkaXN0cmlidXRpb24uIA0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDFFKSBSZXBlYXQgc3RlcHMgQS1DIGZvciB0aGUgY2FzZSBvZiBhIHBvcnRmb2xpbyBkYWlseSByZXR1cm5zIHdpdGggbm9ybWFsIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbixhIG1lYW49MS4yJSBhbmQgYSBzdGFuZGFyZCBkZXZpYXRpb249IDMuNyUNCjwvc3Bhbj4NCmBgYHtyfQ0KbmQ9cm5vcm0oMTAwLCBtZWFuPTAuMDEyLCBzZD0wLjAzNykNCmhpc3QobmQpDQptZWFuKG5kKQ0Kc2QobmQpDQpuZD1ybm9ybSgxMDAwLCBtZWFuPTAuMDEyLCBzZD0wLjAzNykNCmhpc3QobmQpDQptZWFuKG5kKQ0Kc2QobmQpDQpgYGANCkZyb20gdGhlIHJlc3VsdHMgd2UgY2FuIHNlZSB0aGF0LCB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBzYW1wbGUgd2l0aCB0aGUgc2l6ZSBvZiAxMDAgaXMgMC4wMTEwIGFuZCAwLjA0MjI3LCBhbmQgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgc2FtcGxlIHdpdGggdGhlIHNpemUgb2YgMTAwMCBpcyAwLjAxMjU4IGFuZCAwLjAzNjg3LCB3aGljaCBpcyBjbG9zZXIgdG8gdGhlIHRoZW9yZXRpY2FsIHZhbHVlcy4gVGhpcyBtZWFucyB0aGF0IGFzIHdlIGluY3JlYXNlIHRoZSBzYW1wbGUgc2l6ZSwgdGhlIGRpc2NyZXRlIHJhbmRvbSBnZW5lcmF0ZWQgc2FtcGxlIGFwcHJveGltYXRlcyBjbG9zZXIgdG8gdGhlIGNvbnRpbnVvdXMgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCg0KU2ltaWxhcmx5IHdlIHNob3VsZCBiZSBhYmxlIHRvIGNvbXB1dGUgdmFyaW91cyBwcm9iYWJpbGl0eSBzZW5hcmlvcyB3aXRoIG91ciBvYnRhaW5lZCBub3JtYWwgZGlzdHJpYnV0aW9uLg0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDFGKSBDYWxjdWxhdGUgdGhlIHByb2JhYmlsaXR5IHRoYXQgcmV0dXJucyB3aWxsIGJlIG5lZ2F0aXZlIHVzaW5nIHRoZSB2YWx1ZXMgZm9yIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBhcyBpbiAxRQ0KPC9zcGFuPg0KDQpgYGB7cn0NCnBub3JtKDAsIG1lYW4gPSAwLjAxMiwgc2QgPSAwLjAzNywgbG93ZXIudGFpbCA9IFRSVUUsIGxvZy5wID0gRkFMU0UpDQpgYGANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAxRykgUmVwZWF0IHRoZSBjYWxjdWxhdGlvbiBpbiAxRiB1c2luZyBpbnN0ZWFkIHRoZSBzdGFuZGFyZCBaLXZhbHVlLiBTaGFyZSBpbnNpZ2h0cy4NCjwvc3Bhbj4NCg0KYGBge3J9DQp6PSgwLTAuMDEyKS8wLjAzNw0KcG5vcm0oeiwgbWVhbiA9IDAsIHNkID0gMSwgbG93ZXIudGFpbCA9IFRSVUUsIGxvZy5wID0gRkFMU0UpDQpgYGANClVzaW5nIGluc3RlYWQgdGhlIHN0YW5kYXJkIHotdmFsdWUsIHdlIGdldCB0aGUgc2FtZSByZXN1bHQgYXMgaW4gMUYuIFRoaXMgbWVhbnMgdGhhdCBzdGFuZGFyZGl6aW5nIHRoZSBub3JtYWxseSBkaXN0cmlidXRlZCB2YXJpYWJsZSB3aWxsIG5vdCBjaGFuZ2UgdGhlIHByb3BlcnRpZXMgb2YgaXQuIFRoZXJlZm9yZSwgaXQgd291bGQgYmVjb21lIGVhc2llciB0byBjb21wYXJlIHNlcGFyYXRlIG5vcm1hbCBkaXN0cmlidXRpb25zIHdpdGggZGlmZmVyZW50IG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbi4NCg0KIyMjIFRhc2sgMjogTUMgU2ltdWxhdGlvbiAmIEV1cm9wZWFuIE9wdGlvbiBQcmljaW5nDQoNCkZvbGxvdyB0aGUgYCBBbGdvcml0aG0gNS4yIGV4YW1wbGUgb24gcCAxNjcgKCopYCB0byBjYWxjdWxhdGUgdGhlIHByaWNlIG9mIGEgRXVyb3BlYW4gb3B0aW9uIHVzaW5nIGEgTUMgc2ltdWxhdGlvbi4gTm90ZSB0aGF0IHRoZSBjb2RlIGluIHRoZSBib29rIGV4YW1wbGUgaXMgbWlzc2luZyBvbmUgZGV0YWlsIGFuZCBhIGNvcnJlY3Rpb24uIFRob3NlIGFyZSBsZWZ0IGZvciB5b3VyIGludmVzdGlnYXRpb24uIA0KDQo8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj4NCiMjIyMjIDJBKSBJZGVudGlmeSBhbmQgZXhwbGFpbiB0aGUgbmF0dXJlIG9mIHRoZSBtaXNzaW5nIGRldGFpbCBhbmQgdGhlIGNvcnJlY3Rpb24gbmVlZGVkLiAgICAgIA0KPC9zcGFuPg0KDQpUaGUgbWlzc2luZyBkZXRhaWwgaXMgdGhhdCB3ZSBuZWVkIHRvIGFkZCBTPVMwIGJldHdlZW4gdGhlIGZpcnN0IGFuZCBzZWNvbmQgZm9yIGxvb3BzLiBCZWNhdXNlIHdoZW4geW91IGZpbmlzaCBvbmUgc2ltdWxhdGlvbiwgeW91IG5lZWQgdG8gcmVzZXQgdGhlIGluaXRpYWwgcHJpY2UgdG8gdGhlIHVuZGVybHlpbmcgc3RvY2sgcHJpY2UuIFRoZSBjb3JyZWN0aW9uIGlzIHRoYXQgdGhlIGNvZGUgZm9yIGdlbmVyYXRpbmcgYSByYW5kb20gdmFsdWUgZnJvbSBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9uIHNob3VsZCBiZSBybm9ybSgxLCBtZWFuPTAsIHNkPTEpIGluc3RlYWQgb2Ygcm5vcm0oMCwxKS4NCg0KR2l2ZW4gdGhlIE1DIHNpbXVsYXRpb24gd2Ugc2hvdWxkIGJlIGFibGUgdG8gcHJpY2UgYSBFdXJvcGVhbiBvcHRpb24uICBOb3RlIHRoZSBpbnRyb2R1Y3Rpb24gb2YgdXNlciBkZWZpbmVkIGZ1bmN0aW9uIGluIHRoZSBib29rLg0KQmVsb3cgaXMgYW4gZXhhbXBsZSBvZiBhIHVzZXIgZGVmaW5lZCBmdW5jdGlvbiBhbmQgdXNhZ2UuICBUaGUgZnVuY3Rpb24gcmV0dXJucyB0aGUgc3F1YXJlZCB2YWx1ZS4NCg0KYGBge3J9DQpteWZ1bmN0aW9uIDwtIGZ1bmN0aW9uKHg9Mil7DQogIHk9eF4yDQpyZXR1cm4oeSl9DQoNCm15ZnVuY3Rpb24oeD01KQ0KYGBgDQoNCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQojIyMjIyAyQikgVXNlIE1DIHNpbXVsYXRpb24gdG8gcHJpY2UgYSBFdXJvcGVhbiBDYWxsIG9wdGlvbiBvbiBhIHN0b2NrIHdpdGggaW5pdGlhbCBwcmljZSBvZiAkMTU1LCBzdHJpa2UgcHJpY2UgJDE0MCwgYSB0aW1lIHRvIGV4cGlyYXRpb24gZXF1YWwgdG8gc2l4IG1vbnRocywgYSByaXNrLWZyZWUgaW50ZXJlc3QgcmF0ZSBvZiAyLjUlIGFuZCBhIHZvbGF0aWxpdHkgb2YgMjMlLiBDb25zaWRlciBhIG51bWJlciBvZiBwZXJpb2RzIG49MTAwIGFuZCBhIG51bWJlciBvZiBzaW11bGF0aW9ucyBtPTEwMDANCjwvc3Bhbj4NCg0KYGBge3J9DQpvcHRpb252YWx1ZSA8LSBmdW5jdGlvbiggVHlwZSwgUzAsIEssIFQsIHIsIHNpZ21hLCBuLCBtLCBkdCl7DQpzdW0gPSAwOw0KZm9yIChpIGluIDEgOiBtKSB7ICMgbnVtYmVyIG9mIHNpbXVsYXRlZCBwYXRocw0KICBTPVMwDQpmb3IgKGogaW4gMSA6IG4pIHsgIyBsZW5ndGggb2YgcGF0aA0KRSA9IHJub3JtKDEsIG1lYW49MCwgc2Q9MSk7DQpTID0gUyArIHIgKiBTICogZHQgKyBzaWdtYSAqIFMgKiBzcXJ0KGR0KSAqIEU7IH0NCmlmIChUeXBlID09ICJjIiApeyBwYXlvZmYgPSBtYXgoUyA/Pz8gSywgMCkgfQ0KZWxzZSBpZiAoVHlwZSA9PSAicCIgKXsgcGF5b2ZmID0gbWF4KEsgPz8/IFMsIDApIH0NCmVsc2UgeyBwYXlvZmYgPSBtYXgoUyA/Pz8gSywgMCkgfSAjIGRlZmF1bHQNCnN1bSA9IHN1bSArIHBheW9mZiB9DQpPcHRpb25WYWx1ZSA9IChzdW0gKiBleHAoPz8/ciAqIFQpKS9tOw0KcmV0dXJuIChPcHRpb25WYWx1ZSl9DQoNCm9wdGlvbnZhbHVlIChUeXBlID0gImMiLCBTMCA9IDE1NSwgSyA9IDE0MCwgVCA9IDAuNSxyID0gMC4wMjUsIHNpZ21hID0gMC4yMywgbiA9IDEwMCwgbSA9IDEwMDAsIGR0ID0gMC41LzEwMCApDQpgYGANCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+DQogICMjIyMjIDJDKSBXcml0ZSB0aGUgbWF0aGVtYXRpY2FsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkaXNjcmV0ZSBwcmljaW5nIGVxdWF0aW9uIG1vZGVsZWQgaW4gdGhlIE1DIHNpbXVsYXRpb24uIEV4cGxhaW4gd2hhdCBlYWNoIHZhcmlhYmxlIGluIHRoZSBlcXVhdGlvbiByZXByZXNlbnRzLCBhbmQgcHJvdmlkZSB0aGUgYXNzb2NpYXRlZCBudW1lcmljYWwgdmFsdWUuDQo8L3NwYW4+DQoNClRoZSBtYXRoZW1hdGljYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIGRpc2NyZXRlIHByaWNpbmcgZXF1YXRpb24gbW9kZWxlZCBpbiB0aGUgTUMgc2ltdWxhdGlvbiBpczoNCg0KJFNfe3QrXERlbHRhX3t0fX0kID0kU197dH0kICtyKiRTX3t0fSQqJFxEZWx0YV97dH0kICskXHNpZ21hJCokU197dH0kKiRcc3FydFxEZWx0YV97dH0kKiRcdmFyZXBzaWxvbl97dH0kLA0KJFx2YXJlcHNpbG9uX3t0fSR+TigwLCAxKQ0KDQokU197dCtcRGVsdGFfe3R9fSQgcmVwcmVzZW50cyB0aGUgdW5kZXJseWluZyBzdG9jayBwcmljZSBuZXh0IHRpbWUgcGVyaW9kOyAkU197dH0kIHJlcHJlc2VudHMgdGhlIHVuZGVybHlpbmcgc3RvY2sgcHJpY2UgdGhpcyB0aW1lIHBlcmlvZDsgciBpcyB0aGUgcmlzay1mcmVlIHJhdGU7ICRcRGVsdGFfe3R9JCByZXByZXNlbnRzIHRoZSB0aW1lIHBlcmlvZHMgYW5kIGlzIGVxdWFsIHRvIFQvbiwgaW4gd2hpY2ggbiByZXByZXNlbnRzIHRoZSBudW1iZXIgb2YgcGVyaW9kcywgYW5kIFQgaXMgdGhlIGV4cGlyYXRpb24gdGltZTsgJFxzaWdtYSQgcmVwcmVzZW50cyB0aGUgdm9sYXRpbGl0eSBvZiB0aGUgdW5kZXJseWluZyBzdG9jayBwcmljZTsgJFx2YXJlcHNpbG9uX3t0fSQgaXMgYSByYW5kb20gdmFsdWUgZ2VuZXJhdGVkIGZyb20gc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCg0KRnJvbSB0aGUgZXhhbXBsZSBhYm92ZSwgJFNfezB9JD0xNTUsIFQ9MC41LCBuPTEwMCwgcj0wLjAyNSwgJFxEZWx0YV97dH0kPVQvbj0wLjAwNSwgJFxzaWdtYSQ9MC4wMjMsICRcdmFyZXBzaWxvbl97dH0kIGlzIHNlbGVjdGVkIHJhbmRvbWx5IGZyb20gc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCg0KPHNwYW4gc3R5bGU9ImNvbG9yOnJlZCI+ICAgIA0KIyMjIyMgMkQpIENvbXBhcmUgdGhlIHByaWNlIG9idGFpbmVkIGZyb20gdGhlIE1DIHNpbXVsYXRpb24gdG8gdGhlIG9wdGlvbiBwcmljZSB1c2luZyB0aGUgQmxhY2stU2Nob2xlcyBmdW5jdGlvbiBwcmljaW5nIEdCU09wdGlvbigpLiBTaGFyZSBpbnNpZ2h0cy4NCjwvc3Bhbj4NCg0KYGBge3J9DQpsaWJyYXJ5KGZPcHRpb25zKQ0KR0JTT3B0aW9uKFR5cGVGbGFnID0gImMiLCBTID0gMTU1LCBYID0gMTQwLCBUaW1lID0gMS8yLCByID0gMC4wMjUsIGIgPSAwLjAyNSwgc2lnbWEgPSAwLjIzKQ0KYGBgDQpUaGUgb3B0aW9uIHByaWNlIG9idGFpbmVkIGZyb20gdGhlIE1DIHNpbXVsYXRpb24gaXMgMjAuNDI0Mywgd2hpbGUgdGhlIG9wdGlvbiBwcmljZSB1c2luZyB0aGUgQmxhY2stU2Nob2xlcyBmdW5jdGlvbiBpcyAyMC4xMTkwLiBXZSBjYW4gc2VlIHRoYXQgdGhlc2UgdHdvIHJlc3VsdHMgYXJlIHZlcnkgY2xvc2UgdG8gZWFjaCBvdGhlci4gQmVjYXVzZSBib3RoIE1DIHNpbXVsYXRpb24gYW5kIEJsYWNrLVNob2xlcyBmdW5jdGlvbiBhc3N1bWUgdGhhdCBzdG9jayBwcmljZSBmb2xsb3cgdGhlIHNhbWUgZ2VvbWV0cmljIGJyb3duIG1vdGlvbiBwYXR0ZXJuLCB0aGV5IGFyZSBvbmx5IGRpZmZlcmVudCBpbiBzb2x2aW5nIHRoZSBwcmljaW5nIHByb2JsZW0uIFRoZXJlZm9yZSwgdGhlaXIgcmVzdWx0cyBzaG91bGQgYmUgdGhlIHNhbWUgb3IgY2xvc2UgdG8gZWFjaCBvdGhlci4NCg0KKltodHRwOi8vY29tcHV0YXRpb25hbGZpbmFuY2UubHNpLnVwYy5lZHUgXShodHRwOi8vY29tcHV0YXRpb25hbGZpbmFuY2UubHNpLnVwYy5lZHUpDQo=