Student Details
Chandangowda Maruvanahalli Shivaramu (s4063920)
Problem Statement
For a six-year period (2018–2024), the S&P 500 stock market index
and Bitcoin prices are analyzed for patterns and statistical features in
this report. Descriptive statistics are being thoroughly analyzed in
order to comprehend the central patterns and variability of both
datasets. By computing and showing correlation coefficients every six
months, the analysis delves deeper into the datasets trends and examines
the relationship between them. In conclusion, this study evaluates
whether formal tests and visual inspection are used to determine whether
the prices of Bitcoin and the S&P 500 follow a normal distribution.
The analysis’s conclusions shed light on how these two financial
instruments behave and interact, facilitating data-driven
decision-making.
Load Packages
library(ggplot2)
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(lubridate)
Attaching package: ‘lubridate’
The following objects are masked from ‘package:base’:
date, intersect, setdiff, union
library(readr)
library(stats)
Data
The S&P 500 index and Bitcoin historical prices from 2018 to 2024
are the datasets used in this analysis. The read_csv() function was used
to import the data, and the Date columns were then formatted
appropriately for additional analysis. A preview of the two datasets was
shown to ensure that the data was properly imported and prepared for
further work.
# Through R function called ‘read.csv’ which comes under 'readr' library, we are reading the csv files
sp_500_dataframe <- read_csv("/Users/chandangowda/Desktop/S&P 500-1.csv", show_col_types = FALSE)
btcoin_dataframe <- read_csv("/Users/chandangowda/Desktop/BTC-USD-1.csv", show_col_types = FALSE)
# Converting 'Date' column to date format
sp_500_dataframe$Date <- dmy(sp_500_dataframe$Date)
btcoin_dataframe$Date <- dmy(btcoin_dataframe$Date)
# Removing commas in 'Price' column and converting it to numeric
sp_500_dataframe$Price <- as.numeric(gsub(",", "", sp_500_dataframe$Price))
# head() function is used to display starting few rows of data
head(sp_500_dataframe)
head(btcoin_dataframe)
Task 1
In this task, descriptive statistics are calculated for both the
S&P 500 and Bitcoin datasets. For the purpose of comprehending the
central tendencies and variability in each dataset, critical metrics
such as mean, median, mode, range, standard deviation, and interquartile
range (IQR) are calculated. A comparative table is created to highlight
the differences in these metrics between the two financial instruments,
providing a basis for further analysis.
# Descriptive statistics for S&P 500 dataset
sp_500_mean <- mean(sp_500_dataframe$Price, na.rm = TRUE)
sp_500_median <- median(sp_500_dataframe$Price, na.rm = TRUE)
sp_500_mode <- as.numeric(names(sort(table(sp_500_dataframe$Price), decreasing=TRUE)[1]))
sp_500_range <- range(sp_500_dataframe$Price, na.rm = TRUE)
sp_500_sd <- sd(sp_500_dataframe$Price, na.rm = TRUE)
sp_500_min <- min(sp_500_dataframe$Price, na.rm = TRUE)
sp_500_max <- max(sp_500_dataframe$Price, na.rm = TRUE)
sp_500_first_quantile <- quantile(sp_500_dataframe$Price, 0.25, na.rm = TRUE)
sp_500_last_quantile <- quantile(sp_500_dataframe$Price, 0.75, na.rm = TRUE)
sp_500_iqr <- IQR(sp_500_dataframe$Price, na.rm = TRUE)
# Descriptive statistics for Bitcoin dataset
btcoin_mean <- mean(btcoin_dataframe$`Adj Close`, na.rm = TRUE)
btcoin_median <- median(btcoin_dataframe$`Adj Close`, na.rm = TRUE)
btcoin_mode <- as.numeric(names(sort(table(btcoin_dataframe$`Adj Close`), decreasing=TRUE)[1]))
btcoin_range <- range(btcoin_dataframe$`Adj Close`, na.rm = TRUE)
btcoin_sd <- sd(btcoin_dataframe$`Adj Close`, na.rm = TRUE)
btcoin_min <- min(btcoin_dataframe$`Adj Close`, na.rm = TRUE)
btcoin_max <- max(btcoin_dataframe$`Adj Close`, na.rm = TRUE)
btcoin_first_quantile <- quantile(btcoin_dataframe$`Adj Close`, 0.25, na.rm = TRUE)
btcoin_last_quantile <- quantile(btcoin_dataframe$`Adj Close`, 0.75, na.rm = TRUE)
btcoin_iqr <- IQR(btcoin_dataframe$`Adj Close`, na.rm = TRUE)
# Combining both statistics for comparison
comparative_statistics <- data.frame(
statistics_type = c("Mean", "Median", "Mode", "Range", "Standard Deviation", "Min", "Max", "First Quantile (Q1)", "Third Quantile (Q3)", "IQR"),
sp_500_data = c(sp_500_mean, sp_500_median, sp_500_mode, paste(sp_500_range, collapse = " - "), sp_500_sd, sp_500_min, sp_500_max, sp_500_first_quantile, sp_500_last_quantile, sp_500_iqr),
btcoin_data = c(btcoin_mean, btcoin_median, btcoin_mode, paste(btcoin_range, collapse = " - "), btcoin_sd, btcoin_min, btcoin_max, btcoin_first_quantile, btcoin_last_quantile, btcoin_iqr)
)
# Displaying the combined statistics
comparative_statistics
Task 2
In this task, line plots are used to show the price trends of Bitcoin
and the S&P 500 over a six-year period, making it easy to compare
their movements. Additionally, the correlation between the two datasets
is calculated every six months to explore any potential relationship
between them. Plotting the correlation values over time demonstrates the
evolution of the link between Bitcoin and the S&P 500.
# Plotting the S&P 500 data trend
ggplot(sp_500_dataframe, aes(x = Date, y = Price)) +
geom_line(color = "pink") +
labs(title = "S&P 500 Stocks Trend",
x = "Date",
y = "Price")

# Plotting the Bitcoin data trend
ggplot(btcoin_dataframe, aes(x = Date, y = `Adj Close`)) +
geom_line(color = "skyblue") +
labs(title = "Bitcoin Trend",
x = "Date",
y = "Price (USD)")

# Calculating correlation every six months and plotting it
# Merging both the datasets
merged_dataframe <- merge(sp_500_dataframe, btcoin_dataframe, by = "Date", all = TRUE)
# Creating a new column for 6-month duration
merged_dataframe <- merged_dataframe %>%
mutate(six_month_duration = floor_date(Date, "6 months"))
# Calculating the correlation for each 6-month duration
correlation_data <- merged_dataframe %>%
group_by(six_month_duration) %>%
summarize(correlation = cor(`Adj Close`, Price, use = "complete.obs"))
# Plotting the correlation
ggplot(correlation_data, aes(x = six_month_duration, y = correlation)) +
geom_line(color = "purple") +
labs(title = "Correlation data of S&P 500 and Bitcoin prices (every six months)",
x = "Date",
y = "Correlation")

Task 3
In this task, the correlation between the S&P 500 and Bitcoin
prices is calculated to explore the relationship between the two
datasets. To measure the strength of this association, the correlation
coefficient is calculated after any missing values have been eliminated.
In order to show the general direction and strength of the association
between the S&P 500 and Bitcoin values, a linear trend line is added
to a scatter plot that is created to represent the correlation.
# Removing the rows with missing values from the merged dataframe
clean_dataframe <- merged_dataframe %>%
filter(!is.na(Price) & !is.na(`Adj Close`))
# Computing the correlation coefficient between both datasets
sp_btcoin_correlation_coefficient <- cor(clean_dataframe$`Adj Close`, clean_dataframe$Price, use = "complete.obs")
# Creating a scatter plot to visualize the correlation
ggplot(clean_dataframe, aes(x = Price, y = `Adj Close`)) +
geom_point(color = "black", alpha = 0.5) + # Scatter plot points
geom_smooth(method = "lm", color = "green", se = FALSE) + # Add linear trend line
labs(title = paste("Correlation visualization between S&P 500 and Bitcoin Prices"),
x = "S&P 500 Price",
y = "Bitcoin Price") +
theme_minimal()

# Displaying the correlation coefficient
sp_btcoin_correlation_coefficient
[1] 0.8976749
Task 4
This task evaluates whether the S&P 500 and Bitcoin datasets
follow a normal distribution. Histograms and Q-Q plots are used in the
study to visually check the data and evaluate its distribution and form.
To officially test for normality, the Shapiro-Wilk test is also run on
both datasets. Further statistical analysis is guided by the results,
which shed light on the distribution characteristics of the S&P 500
and Bitcoin values.
# Normal Distribution Analysis
# Visually inspecting by generating histogram for S&P 500
ggplot(sp_500_dataframe, aes(x = Price)) +
geom_histogram(binwidth = 150, fill = "green", color = "black") +
labs(title = "Distribution of S&P 500 Price", x = "S&P 500 Price", y = "Frequency") +
theme_minimal()

# Q-Q Plot for S&P 500
ggplot(sp_500_dataframe, aes(sample = Price)) +
stat_qq() +
stat_qq_line() +
labs(title = "Q-Q Plot for S&P 500 Price", x = "Theoretical Quantiles", y = "Sample Quantiles") +
theme_minimal()

# Visually inspecting by generating histogram for Bitcoin
ggplot(btcoin_dataframe, aes(x = `Adj Close`)) +
geom_histogram(binwidth = 2500, fill = "red", color = "black") +
labs(title = "Distribution of Bitcoin Price", x = "Bitcoin Price (Adj Close)", y = "Frequency") +
theme_minimal()

# Q-Q Plot for Bitcoin
ggplot(btcoin_dataframe, aes(sample = `Adj Close`)) +
stat_qq() +
stat_qq_line() +
labs(title = "Q-Q Plot for Bitcoin Price", x = "Theoretical Quantiles", y = "Sample Quantiles") +
theme_minimal()

# Shapiro-Wilk Test for Normality
# Shapiro-Wilk test for S&P 500
sp_500_testing <- shapiro.test(sp_500_dataframe$Price)
# Shapiro-Wilk test for Bitcoin
btcoin_testing <- shapiro.test(btcoin_dataframe$`Adj Close`)
# Displaying the results of the Shapiro-Wilk test
sp_500_testing
Shapiro-Wilk normality test
data: sp_500_dataframe$Price
W = 0.961, p-value < 2.2e-16
btcoin_testing
Shapiro-Wilk normality test
data: btcoin_dataframe$`Adj Close`
W = 0.90984, p-value < 2.2e-16
LS0tCnRpdGxlOiAiTUFUSDEzMjQgQXNzaWdubWVudCAxIgpzdWJ0aXRsZTogU3RhdGlzdGljYWwgYW5hbHlzaXMgb2YgU1BfNTAwIGFuZCBCaXRjb2luIGRhdGEgb2YgNiB5ZWFycyAoZnJvbSAyMDE4IHRvIDIwMjQpCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKIyMgU3R1ZGVudCBEZXRhaWxzCgpDaGFuZGFuZ293ZGEgTWFydXZhbmFoYWxsaSBTaGl2YXJhbXUgKHM0MDYzOTIwKQoKIyMgUHJvYmxlbSBTdGF0ZW1lbnQKCkZvciBhIHNpeC15ZWFyIHBlcmlvZCAoMjAxOOKAkzIwMjQpLCB0aGUgUyZQIDUwMCBzdG9jayBtYXJrZXQgaW5kZXggYW5kIEJpdGNvaW4gcHJpY2VzIGFyZSBhbmFseXplZCBmb3IgcGF0dGVybnMgYW5kIHN0YXRpc3RpY2FsIGZlYXR1cmVzIGluIHRoaXMgcmVwb3J0LiBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGFyZSBiZWluZyB0aG9yb3VnaGx5IGFuYWx5emVkIGluIG9yZGVyIHRvIGNvbXByZWhlbmQgdGhlIGNlbnRyYWwgcGF0dGVybnMgYW5kIHZhcmlhYmlsaXR5IG9mIGJvdGggZGF0YXNldHMuIEJ5IGNvbXB1dGluZyBhbmQgc2hvd2luZyBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgZXZlcnkgc2l4IG1vbnRocywgdGhlIGFuYWx5c2lzIGRlbHZlcyBkZWVwZXIgaW50byB0aGUgZGF0YXNldHMgdHJlbmRzIGFuZCBleGFtaW5lcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlbS4gSW4gY29uY2x1c2lvbiwgdGhpcyBzdHVkeSBldmFsdWF0ZXMgd2hldGhlciBmb3JtYWwgdGVzdHMgYW5kIHZpc3VhbCBpbnNwZWN0aW9uIGFyZSB1c2VkIHRvIGRldGVybWluZSB3aGV0aGVyIHRoZSBwcmljZXMgb2YgQml0Y29pbiBhbmQgdGhlIFMmUCA1MDAgZm9sbG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gVGhlIGFuYWx5c2lzJ3MgY29uY2x1c2lvbnMgc2hlZCBsaWdodCBvbiBob3cgdGhlc2UgdHdvIGZpbmFuY2lhbCBpbnN0cnVtZW50cyBiZWhhdmUgYW5kIGludGVyYWN0LCBmYWNpbGl0YXRpbmcgZGF0YS1kcml2ZW4gZGVjaXNpb24tbWFraW5nLgoKIyMgTG9hZCBQYWNrYWdlcwoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoc3RhdHMpCmBgYAoKIyMgRGF0YQoKVGhlIFMmUCA1MDAgaW5kZXggYW5kIEJpdGNvaW4gaGlzdG9yaWNhbCBwcmljZXMgZnJvbSAyMDE4IHRvIDIwMjQgYXJlIHRoZSBkYXRhc2V0cyB1c2VkIGluIHRoaXMgYW5hbHlzaXMuIFRoZSByZWFkX2NzdigpIGZ1bmN0aW9uIHdhcyB1c2VkIHRvIGltcG9ydCB0aGUgZGF0YSwgYW5kIHRoZSBEYXRlIGNvbHVtbnMgd2VyZSB0aGVuIGZvcm1hdHRlZCBhcHByb3ByaWF0ZWx5IGZvciBhZGRpdGlvbmFsIGFuYWx5c2lzLiBBIHByZXZpZXcgb2YgdGhlIHR3byBkYXRhc2V0cyB3YXMgc2hvd24gdG8gZW5zdXJlIHRoYXQgdGhlIGRhdGEgd2FzIHByb3Blcmx5IGltcG9ydGVkIGFuZCBwcmVwYXJlZCBmb3IgZnVydGhlciB3b3JrLgoKYGBge3J9CiMgVGhyb3VnaCBSIGZ1bmN0aW9uIGNhbGxlZCDigJhyZWFkLmNzduKAmSB3aGljaCBjb21lcyB1bmRlciAncmVhZHInIGxpYnJhcnksIHdlIGFyZSByZWFkaW5nIHRoZSBjc3YgZmlsZXMKc3BfNTAwX2RhdGFmcmFtZSA8LSByZWFkX2NzdigiL1VzZXJzL2NoYW5kYW5nb3dkYS9EZXNrdG9wL1MmUCA1MDAtMS5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQpidGNvaW5fZGF0YWZyYW1lIDwtIHJlYWRfY3N2KCIvVXNlcnMvY2hhbmRhbmdvd2RhL0Rlc2t0b3AvQlRDLVVTRC0xLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpCgojIENvbnZlcnRpbmcgJ0RhdGUnIGNvbHVtbiB0byBkYXRlIGZvcm1hdApzcF81MDBfZGF0YWZyYW1lJERhdGUgPC0gZG15KHNwXzUwMF9kYXRhZnJhbWUkRGF0ZSkKYnRjb2luX2RhdGFmcmFtZSREYXRlIDwtIGRteShidGNvaW5fZGF0YWZyYW1lJERhdGUpCgojIFJlbW92aW5nIGNvbW1hcyBpbiAnUHJpY2UnIGNvbHVtbiBhbmQgY29udmVydGluZyBpdCB0byBudW1lcmljCnNwXzUwMF9kYXRhZnJhbWUkUHJpY2UgPC0gYXMubnVtZXJpYyhnc3ViKCIsIiwgIiIsIHNwXzUwMF9kYXRhZnJhbWUkUHJpY2UpKQoKIyBoZWFkKCkgZnVuY3Rpb24gaXMgdXNlZCB0byBkaXNwbGF5IHN0YXJ0aW5nIGZldyByb3dzIG9mIGRhdGEKaGVhZChzcF81MDBfZGF0YWZyYW1lKQpoZWFkKGJ0Y29pbl9kYXRhZnJhbWUpCmBgYAoKIyMgVGFzayAxCgpJbiB0aGlzIHRhc2ssIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgYXJlIGNhbGN1bGF0ZWQgZm9yIGJvdGggdGhlIFMmUCA1MDAgYW5kIEJpdGNvaW4gZGF0YXNldHMuIEZvciB0aGUgcHVycG9zZSBvZiBjb21wcmVoZW5kaW5nIHRoZSBjZW50cmFsIHRlbmRlbmNpZXMgYW5kIHZhcmlhYmlsaXR5IGluIGVhY2ggZGF0YXNldCwgY3JpdGljYWwgbWV0cmljcyBzdWNoIGFzIG1lYW4sIG1lZGlhbiwgbW9kZSwgcmFuZ2UsIHN0YW5kYXJkIGRldmlhdGlvbiwgYW5kIGludGVycXVhcnRpbGUgcmFuZ2UgKElRUikgYXJlIGNhbGN1bGF0ZWQuIEEgY29tcGFyYXRpdmUgdGFibGUgaXMgY3JlYXRlZCB0byBoaWdobGlnaHQgdGhlIGRpZmZlcmVuY2VzIGluIHRoZXNlIG1ldHJpY3MgYmV0d2VlbiB0aGUgdHdvIGZpbmFuY2lhbCBpbnN0cnVtZW50cywgcHJvdmlkaW5nIGEgYmFzaXMgZm9yIGZ1cnRoZXIgYW5hbHlzaXMuCgpgYGB7cn0KIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciBTJlAgNTAwIGRhdGFzZXQKc3BfNTAwX21lYW4gPC0gbWVhbihzcF81MDBfZGF0YWZyYW1lJFByaWNlLCBuYS5ybSA9IFRSVUUpCnNwXzUwMF9tZWRpYW4gPC0gbWVkaWFuKHNwXzUwMF9kYXRhZnJhbWUkUHJpY2UsIG5hLnJtID0gVFJVRSkKc3BfNTAwX21vZGUgPC0gYXMubnVtZXJpYyhuYW1lcyhzb3J0KHRhYmxlKHNwXzUwMF9kYXRhZnJhbWUkUHJpY2UpLCBkZWNyZWFzaW5nPVRSVUUpWzFdKSkKc3BfNTAwX3JhbmdlIDwtIHJhbmdlKHNwXzUwMF9kYXRhZnJhbWUkUHJpY2UsIG5hLnJtID0gVFJVRSkKc3BfNTAwX3NkIDwtIHNkKHNwXzUwMF9kYXRhZnJhbWUkUHJpY2UsIG5hLnJtID0gVFJVRSkKc3BfNTAwX21pbiA8LSBtaW4oc3BfNTAwX2RhdGFmcmFtZSRQcmljZSwgbmEucm0gPSBUUlVFKQpzcF81MDBfbWF4IDwtIG1heChzcF81MDBfZGF0YWZyYW1lJFByaWNlLCBuYS5ybSA9IFRSVUUpCnNwXzUwMF9maXJzdF9xdWFudGlsZSA8LSBxdWFudGlsZShzcF81MDBfZGF0YWZyYW1lJFByaWNlLCAwLjI1LCBuYS5ybSA9IFRSVUUpCnNwXzUwMF9sYXN0X3F1YW50aWxlIDwtIHF1YW50aWxlKHNwXzUwMF9kYXRhZnJhbWUkUHJpY2UsIDAuNzUsIG5hLnJtID0gVFJVRSkKc3BfNTAwX2lxciA8LSBJUVIoc3BfNTAwX2RhdGFmcmFtZSRQcmljZSwgbmEucm0gPSBUUlVFKQoKIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciBCaXRjb2luIGRhdGFzZXQKYnRjb2luX21lYW4gPC0gbWVhbihidGNvaW5fZGF0YWZyYW1lJGBBZGogQ2xvc2VgLCBuYS5ybSA9IFRSVUUpCmJ0Y29pbl9tZWRpYW4gPC0gbWVkaWFuKGJ0Y29pbl9kYXRhZnJhbWUkYEFkaiBDbG9zZWAsIG5hLnJtID0gVFJVRSkKYnRjb2luX21vZGUgPC0gYXMubnVtZXJpYyhuYW1lcyhzb3J0KHRhYmxlKGJ0Y29pbl9kYXRhZnJhbWUkYEFkaiBDbG9zZWApLCBkZWNyZWFzaW5nPVRSVUUpWzFdKSkKYnRjb2luX3JhbmdlIDwtIHJhbmdlKGJ0Y29pbl9kYXRhZnJhbWUkYEFkaiBDbG9zZWAsIG5hLnJtID0gVFJVRSkKYnRjb2luX3NkIDwtIHNkKGJ0Y29pbl9kYXRhZnJhbWUkYEFkaiBDbG9zZWAsIG5hLnJtID0gVFJVRSkKYnRjb2luX21pbiA8LSBtaW4oYnRjb2luX2RhdGFmcmFtZSRgQWRqIENsb3NlYCwgbmEucm0gPSBUUlVFKQpidGNvaW5fbWF4IDwtIG1heChidGNvaW5fZGF0YWZyYW1lJGBBZGogQ2xvc2VgLCBuYS5ybSA9IFRSVUUpCmJ0Y29pbl9maXJzdF9xdWFudGlsZSAgPC0gcXVhbnRpbGUoYnRjb2luX2RhdGFmcmFtZSRgQWRqIENsb3NlYCwgMC4yNSwgbmEucm0gPSBUUlVFKQpidGNvaW5fbGFzdF9xdWFudGlsZSA8LSBxdWFudGlsZShidGNvaW5fZGF0YWZyYW1lJGBBZGogQ2xvc2VgLCAwLjc1LCBuYS5ybSA9IFRSVUUpCmJ0Y29pbl9pcXIgPC0gSVFSKGJ0Y29pbl9kYXRhZnJhbWUkYEFkaiBDbG9zZWAsIG5hLnJtID0gVFJVRSkKCiMgQ29tYmluaW5nIGJvdGggc3RhdGlzdGljcyBmb3IgY29tcGFyaXNvbgpjb21wYXJhdGl2ZV9zdGF0aXN0aWNzIDwtIGRhdGEuZnJhbWUoCiAgc3RhdGlzdGljc190eXBlID0gYygiTWVhbiIsICJNZWRpYW4iLCAiTW9kZSIsICJSYW5nZSIsICJTdGFuZGFyZCBEZXZpYXRpb24iLCAiTWluIiwgIk1heCIsICJGaXJzdCBRdWFudGlsZSAoUTEpIiwgIlRoaXJkIFF1YW50aWxlIChRMykiLCAiSVFSIiksCiAgc3BfNTAwX2RhdGEgPSBjKHNwXzUwMF9tZWFuLCBzcF81MDBfbWVkaWFuLCBzcF81MDBfbW9kZSwgcGFzdGUoc3BfNTAwX3JhbmdlLCBjb2xsYXBzZSA9ICIgLSAiKSwgc3BfNTAwX3NkLCBzcF81MDBfbWluLCBzcF81MDBfbWF4LCBzcF81MDBfZmlyc3RfcXVhbnRpbGUsIHNwXzUwMF9sYXN0X3F1YW50aWxlLCBzcF81MDBfaXFyKSwKICBidGNvaW5fZGF0YSA9IGMoYnRjb2luX21lYW4sIGJ0Y29pbl9tZWRpYW4sIGJ0Y29pbl9tb2RlLCBwYXN0ZShidGNvaW5fcmFuZ2UsIGNvbGxhcHNlID0gIiAtICIpLCBidGNvaW5fc2QsIGJ0Y29pbl9taW4sIGJ0Y29pbl9tYXgsIGJ0Y29pbl9maXJzdF9xdWFudGlsZSwgYnRjb2luX2xhc3RfcXVhbnRpbGUsIGJ0Y29pbl9pcXIpCikKCiMgRGlzcGxheWluZyB0aGUgY29tYmluZWQgc3RhdGlzdGljcwpjb21wYXJhdGl2ZV9zdGF0aXN0aWNzCmBgYAoKIyMgVGFzayAyCgpJbiB0aGlzIHRhc2ssIGxpbmUgcGxvdHMgYXJlIHVzZWQgdG8gc2hvdyB0aGUgcHJpY2UgdHJlbmRzIG9mIEJpdGNvaW4gYW5kIHRoZSBTJlAgNTAwIG92ZXIgYSBzaXgteWVhciBwZXJpb2QsIG1ha2luZyBpdCBlYXN5IHRvIGNvbXBhcmUgdGhlaXIgbW92ZW1lbnRzLiBBZGRpdGlvbmFsbHksIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB0d28gZGF0YXNldHMgaXMgY2FsY3VsYXRlZCBldmVyeSBzaXggbW9udGhzIHRvIGV4cGxvcmUgYW55IHBvdGVudGlhbCByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVtLiBQbG90dGluZyB0aGUgY29ycmVsYXRpb24gdmFsdWVzIG92ZXIgdGltZSBkZW1vbnN0cmF0ZXMgdGhlIGV2b2x1dGlvbiBvZiB0aGUgbGluayBiZXR3ZWVuIEJpdGNvaW4gYW5kIHRoZSBTJlAgNTAwLgoKYGBge3J9CiMgUGxvdHRpbmcgdGhlIFMmUCA1MDAgZGF0YSB0cmVuZApnZ3Bsb3Qoc3BfNTAwX2RhdGFmcmFtZSwgYWVzKHggPSBEYXRlLCB5ID0gUHJpY2UpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gInBpbmsiKSArCiAgbGFicyh0aXRsZSA9ICJTJlAgNTAwIFN0b2NrcyBUcmVuZCIsCiAgICAgICB4ID0gIkRhdGUiLAogICAgICAgeSA9ICJQcmljZSIpCmBgYAoKYGBge3J9CiMgUGxvdHRpbmcgdGhlIEJpdGNvaW4gZGF0YSB0cmVuZApnZ3Bsb3QoYnRjb2luX2RhdGFmcmFtZSwgYWVzKHggPSBEYXRlLCB5ID0gYEFkaiBDbG9zZWApKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gInNreWJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJCaXRjb2luIFRyZW5kIiwKICAgICAgIHggPSAiRGF0ZSIsCiAgICAgICB5ID0gIlByaWNlIChVU0QpIikKYGBgCgpgYGB7cn0KIyBDYWxjdWxhdGluZyBjb3JyZWxhdGlvbiBldmVyeSBzaXggbW9udGhzIGFuZCBwbG90dGluZyBpdAoKIyBNZXJnaW5nIGJvdGggdGhlIGRhdGFzZXRzCm1lcmdlZF9kYXRhZnJhbWUgPC0gbWVyZ2Uoc3BfNTAwX2RhdGFmcmFtZSwgYnRjb2luX2RhdGFmcmFtZSwgYnkgPSAiRGF0ZSIsIGFsbCA9IFRSVUUpCgojIENyZWF0aW5nIGEgbmV3IGNvbHVtbiBmb3IgNi1tb250aCBkdXJhdGlvbgptZXJnZWRfZGF0YWZyYW1lIDwtIG1lcmdlZF9kYXRhZnJhbWUgJT4lCiAgbXV0YXRlKHNpeF9tb250aF9kdXJhdGlvbiA9IGZsb29yX2RhdGUoRGF0ZSwgIjYgbW9udGhzIikpCgojIENhbGN1bGF0aW5nIHRoZSBjb3JyZWxhdGlvbiBmb3IgZWFjaCA2LW1vbnRoIGR1cmF0aW9uCmNvcnJlbGF0aW9uX2RhdGEgPC0gbWVyZ2VkX2RhdGFmcmFtZSAlPiUKICBncm91cF9ieShzaXhfbW9udGhfZHVyYXRpb24pICU+JQogIHN1bW1hcml6ZShjb3JyZWxhdGlvbiA9IGNvcihgQWRqIENsb3NlYCwgUHJpY2UsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKSkKCiMgUGxvdHRpbmcgdGhlIGNvcnJlbGF0aW9uCmdncGxvdChjb3JyZWxhdGlvbl9kYXRhLCBhZXMoeCA9IHNpeF9tb250aF9kdXJhdGlvbiwgeSA9IGNvcnJlbGF0aW9uKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJwdXJwbGUiKSArCiAgbGFicyh0aXRsZSA9ICJDb3JyZWxhdGlvbiBkYXRhIG9mIFMmUCA1MDAgYW5kIEJpdGNvaW4gcHJpY2VzIChldmVyeSBzaXggbW9udGhzKSIsCiAgICAgICB4ID0gIkRhdGUiLAogICAgICAgeSA9ICJDb3JyZWxhdGlvbiIpCmBgYAoKIyMgVGFzayAzCgpJbiB0aGlzIHRhc2ssIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBTJlAgNTAwIGFuZCBCaXRjb2luIHByaWNlcyBpcyBjYWxjdWxhdGVkIHRvIGV4cGxvcmUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB0d28gZGF0YXNldHMuIFRvIG1lYXN1cmUgdGhlIHN0cmVuZ3RoIG9mIHRoaXMgYXNzb2NpYXRpb24sIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBpcyBjYWxjdWxhdGVkIGFmdGVyIGFueSBtaXNzaW5nIHZhbHVlcyBoYXZlIGJlZW4gZWxpbWluYXRlZC4gSW4gb3JkZXIgdG8gc2hvdyB0aGUgZ2VuZXJhbCBkaXJlY3Rpb24gYW5kIHN0cmVuZ3RoIG9mIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSBTJlAgNTAwIGFuZCBCaXRjb2luIHZhbHVlcywgYSBsaW5lYXIgdHJlbmQgbGluZSBpcyBhZGRlZCB0byBhIHNjYXR0ZXIgcGxvdCB0aGF0IGlzIGNyZWF0ZWQgdG8gcmVwcmVzZW50IHRoZSBjb3JyZWxhdGlvbi4KCmBgYHtyfQojIFJlbW92aW5nIHRoZSByb3dzIHdpdGggbWlzc2luZyB2YWx1ZXMgZnJvbSB0aGUgbWVyZ2VkIGRhdGFmcmFtZQpjbGVhbl9kYXRhZnJhbWUgPC0gbWVyZ2VkX2RhdGFmcmFtZSAlPiUKICBmaWx0ZXIoIWlzLm5hKFByaWNlKSAmICFpcy5uYShgQWRqIENsb3NlYCkpCgojIENvbXB1dGluZyB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgYmV0d2VlbiBib3RoIGRhdGFzZXRzCnNwX2J0Y29pbl9jb3JyZWxhdGlvbl9jb2VmZmljaWVudCA8LSBjb3IoY2xlYW5fZGF0YWZyYW1lJGBBZGogQ2xvc2VgLCBjbGVhbl9kYXRhZnJhbWUkUHJpY2UsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQoKIyBDcmVhdGluZyBhIHNjYXR0ZXIgcGxvdCB0byB2aXN1YWxpemUgdGhlIGNvcnJlbGF0aW9uCmdncGxvdChjbGVhbl9kYXRhZnJhbWUsIGFlcyh4ID0gUHJpY2UsIHkgPSBgQWRqIENsb3NlYCkpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjUpICsgICMgU2NhdHRlciBwbG90IHBvaW50cwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gImdyZWVuIiwgc2UgPSBGQUxTRSkgKyAgIyBBZGQgbGluZWFyIHRyZW5kIGxpbmUKICBsYWJzKHRpdGxlID0gcGFzdGUoIkNvcnJlbGF0aW9uIHZpc3VhbGl6YXRpb24gYmV0d2VlbiBTJlAgNTAwIGFuZCBCaXRjb2luIFByaWNlcyIpLAogICAgICAgeCA9ICJTJlAgNTAwIFByaWNlIiwKICAgICAgIHkgPSAiQml0Y29pbiBQcmljZSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpgYGB7cn0KIyBEaXNwbGF5aW5nIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudApzcF9idGNvaW5fY29ycmVsYXRpb25fY29lZmZpY2llbnQKYGBgCgojIyBUYXNrIDQKClRoaXMgdGFzayBldmFsdWF0ZXMgd2hldGhlciB0aGUgUyZQIDUwMCBhbmQgQml0Y29pbiBkYXRhc2V0cyBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiBIaXN0b2dyYW1zIGFuZCBRLVEgcGxvdHMgYXJlIHVzZWQgaW4gdGhlIHN0dWR5IHRvIHZpc3VhbGx5IGNoZWNrIHRoZSBkYXRhIGFuZCBldmFsdWF0ZSBpdHMgZGlzdHJpYnV0aW9uIGFuZCBmb3JtLiBUbyBvZmZpY2lhbGx5IHRlc3QgZm9yIG5vcm1hbGl0eSwgdGhlIFNoYXBpcm8tV2lsayB0ZXN0IGlzIGFsc28gcnVuIG9uIGJvdGggZGF0YXNldHMuIEZ1cnRoZXIgc3RhdGlzdGljYWwgYW5hbHlzaXMgaXMgZ3VpZGVkIGJ5IHRoZSByZXN1bHRzLCB3aGljaCBzaGVkIGxpZ2h0IG9uIHRoZSBkaXN0cmlidXRpb24gY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBTJlAgNTAwIGFuZCBCaXRjb2luIHZhbHVlcy4KCmBgYHtyfQojIE5vcm1hbCBEaXN0cmlidXRpb24gQW5hbHlzaXMKCiMgVmlzdWFsbHkgaW5zcGVjdGluZyBieSBnZW5lcmF0aW5nIGhpc3RvZ3JhbSBmb3IgUyZQIDUwMApnZ3Bsb3Qoc3BfNTAwX2RhdGFmcmFtZSwgYWVzKHggPSBQcmljZSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDE1MCwgZmlsbCA9ICJncmVlbiIsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFMmUCA1MDAgUHJpY2UiLCB4ID0gIlMmUCA1MDAgUHJpY2UiLCB5ID0gIkZyZXF1ZW5jeSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpgYGB7cn0KIyBRLVEgUGxvdCBmb3IgUyZQIDUwMApnZ3Bsb3Qoc3BfNTAwX2RhdGFmcmFtZSwgYWVzKHNhbXBsZSA9IFByaWNlKSkgKwogIHN0YXRfcXEoKSArCiAgc3RhdF9xcV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiUS1RIFBsb3QgZm9yIFMmUCA1MDAgUHJpY2UiLCB4ID0gIlRoZW9yZXRpY2FsIFF1YW50aWxlcyIsIHkgPSAiU2FtcGxlIFF1YW50aWxlcyIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpgYGB7cn0KIyBWaXN1YWxseSBpbnNwZWN0aW5nIGJ5IGdlbmVyYXRpbmcgaGlzdG9ncmFtIGZvciBCaXRjb2luCmdncGxvdChidGNvaW5fZGF0YWZyYW1lLCBhZXMoeCA9IGBBZGogQ2xvc2VgKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMjUwMCwgZmlsbCA9ICJyZWQiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBCaXRjb2luIFByaWNlIiwgeCA9ICJCaXRjb2luIFByaWNlIChBZGogQ2xvc2UpIiwgeSA9ICJGcmVxdWVuY3kiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3J9CiMgUS1RIFBsb3QgZm9yIEJpdGNvaW4KZ2dwbG90KGJ0Y29pbl9kYXRhZnJhbWUsIGFlcyhzYW1wbGUgPSBgQWRqIENsb3NlYCkpICsKICBzdGF0X3FxKCkgKwogIHN0YXRfcXFfbGluZSgpICsKICBsYWJzKHRpdGxlID0gIlEtUSBQbG90IGZvciBCaXRjb2luIFByaWNlIiwgeCA9ICJUaGVvcmV0aWNhbCBRdWFudGlsZXMiLCB5ID0gIlNhbXBsZSBRdWFudGlsZXMiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3J9CiMgU2hhcGlyby1XaWxrIFRlc3QgZm9yIE5vcm1hbGl0eQoKIyBTaGFwaXJvLVdpbGsgdGVzdCBmb3IgUyZQIDUwMApzcF81MDBfdGVzdGluZyA8LSBzaGFwaXJvLnRlc3Qoc3BfNTAwX2RhdGFmcmFtZSRQcmljZSkKCiMgU2hhcGlyby1XaWxrIHRlc3QgZm9yIEJpdGNvaW4KYnRjb2luX3Rlc3RpbmcgPC0gc2hhcGlyby50ZXN0KGJ0Y29pbl9kYXRhZnJhbWUkYEFkaiBDbG9zZWApCgojIERpc3BsYXlpbmcgdGhlIHJlc3VsdHMgb2YgdGhlIFNoYXBpcm8tV2lsayB0ZXN0CnNwXzUwMF90ZXN0aW5nCmJ0Y29pbl90ZXN0aW5nCmBgYAoKIyMgUmVmZXJlbmNlcwoKWzFdIFJNSVQgKDIwMjQpIE1vZHVsZSAxIG1hdGVyaWFscy4gQWNjZXNzZWQgb246ICgxNSBBdWcgLSAwNSBTZXApLzIwMjQuIExpbms6IDxodHRwczovL3JtaXQuaW5zdHJ1Y3R1cmUuY29tL2NvdXJzZXMvMTI0MjE5L3BhZ2VzL3dlZWstMS1sZWFybmluZy1tYXRlcmlhbHMtc2xhc2gtYWN0aXZpdGllcz9tb2R1bGVfaXRlbV9pZD02MzIyMDk1PgoKWzJdIFJNSVQgKDIwMjQpIE1vZHVsZSAyIG1hdGVyaWFscy4gQWNjZXNzZWQgb246ICgyMCBBdWcgLSAwNSBTZXApLzIwMjQuIExpbms6IDxodHRwczovL3JtaXQuaW5zdHJ1Y3R1cmUuY29tL2NvdXJzZXMvMTI0MjE5L3BhZ2VzL3dlZWstMi1sZWFybmluZy1tYXRlcmlhbHMtc2xhc2gtYWN0aXZpdGllcz9tb2R1bGVfaXRlbV9pZD02MzIyMTAwPgoKWzNdIFF1aWxsQm90IFdlYnNpdGUsIHVzZWQgZm9yIHBhcmFwaHJhc2luZyBteSBleHBsYW5hdGlvbnMuIEFjY2Vzc2VkIG9uOiAoMDEgU2VwIC0gMDUgU2VwKS8yMDI0LiBVUkw6IDxodHRwczovL3F1aWxsYm90LmNvbT4KCls0XSBTaGFwaXJvLCBTLiBTLiwgJiBXaWxrLCBNLiBCLiAoMTk2NSkuIEFuIEFuYWx5c2lzIG9mIFZhcmlhbmNlIFRlc3QgZm9yIE5vcm1hbGl0eSAoQ29tcGxldGUgU2FtcGxlcykuIEJpb21ldHJpa2EsIDUyKDMtNCksIDU5MeKAkzYxMS4gQWNjZXNzZWQgb246ICgwMSBTZXAgLSAwNSBTZXApLzIwMjQuIExpbms6IDxodHRwczovL2RvaS5vcmcvMTAuMTA5My9iaW9tZXQvNTIuMy00LjU5MT4uCg==