Introduction
The Capital Asset Pricing Model (CAPM) is one of the
cornerstones of modern financial theory, establishing a linear
relationship between an asset’s systematic risk and its expected return.
Developed in the 1960s, the model postulates that an investment’s return
should be proportional to its exposure to market risk, measured by the
Beta (\(\beta\)) coefficient, in
addition to a risk-free rate.
The central premise is that investors should be compensated only for
risk that cannot be diversified (systematic risk), while
company-specific risk can be eliminated through a well-structured
portfolio. Despite criticisms regarding its simplifications—such as
market efficiency and the focus on a single risk factor—CAPM remains
widely used to estimate the cost of equity and evaluate the performance
of portfolio managers.
Behavior of \(\beta\)
In the context of the Capital Asset Pricing Model (CAPM), the Beta
(\(\beta\)) coefficient is a measure of
an asset’s systematic risk—the risk that cannot be diversified away. It
quantifies how sensitive a specific stock’s returns are to the movements
of the broader market.+1Mathematically, it is defined as: \[
\beta = \frac{Cov(R, R_m)}{Var(R_m)}
\] Where \(R\) and \(R_m\) are the asset and market returns,
respectively.
\(\beta > 1\) (High
Sensitivity) - The asset is more volatile than the market. If the
market rises by 10%, a stock with a \(\beta\) of 1.5 is expected to rise by 15%.
Conversely, it will likely fall further than the market during a
downturn. Stocks in sectors like technology or biotechnology often have
high betas.
\(\beta = 1\) (Market
Neutrality) - The asset moves in lockstep with the market. Its
systematic risk is identical to that of the market proxy (like the
S&P 500).
\(0<\beta<1\) (Low
Sensitivity) - The asset is less volatile than the market. It is
considered a “defensive” stock. For example, a utility company might
have a \(\beta\) of 0.5, meaning it
only captures about half of the market’s swings.
\(\beta=0\) (No
Correlation) - The asset’s returns have no linear relationship with
the market’s returns. A risk-free asset, like a Treasury bond (in
theory), has a \(\beta\) of 0. Gold is
also sometimes cited as having a beta near zero, as its price is often
driven by factors unrelated to equity markets.
\(\beta<0\) (Inverse
Correlation) - The asset moves in the opposite direction of the
market. While rare for individual stocks, some “inverse ETFs” or “put
options” are designed to have negative betas. Historically, during
extreme market crashes, very few traditional assets maintain a negative
beta consistently, though some “safe havens” may exhibit this behavior
temporarily.
Petrobras vs
S&P500
In this document, we estimate the CAPM parameters for
Petrobras (PBR), traded on the NYSE, using the
S&P 500 (SPY) as the market proxy. We adopt a
Bayesian framework, which allows us to incorporate prior beliefs and
obtain a full posterior distribution for the risk parameters.
The CAPM equation is defined as:
\[
R_t = \alpha + \beta R_{mt}+ \epsilon_t
\]
Where:
\(t\) is the time frequency,
usually daily.
\(R_t\): Return of the risky
asset (PBR).
\(R_{mt}\): Return of the market
index (S&P 500).
\(\alpha\): The “Alpha”,
representing abnormal returns.
\(\beta\): The “Beta”, measuring
the asset’s sensitivity to market movements.
\(\epsilon_t \sim N(0,
\sigma^2)\): The idiosyncratic error term with variance \(\sigma^2\).
Uploading and
processing the data
We uploaded data from February 10th 2016 to February 9th 2026, ie
about 10 years of daily data or \(n=2514\) observations.
if (!require("pacman")) install.packages("pacman")
## Loading required package: pacman
pacman::p_load(quantmod, brms, tidyverse, PerformanceAnalytics)
symbols <- c("PBR", "SPY")
getSymbols(symbols, src = "yahoo", from = "2016-02-09", to = Sys.Date())
## [1] "PBR" "SPY"
# Computing returns
returns_pbr <- Return.calculate(Cl(PBR), method = "log")
returns_spy <- Return.calculate(Cl(SPY), method = "log")
# Combining the time series and removing missing values
data_capm <- merge(returns_pbr, returns_spy) %>%
as.data.frame() %>%
drop_na()
colnames(data_capm) <- c("PBR", "Market")
y = data_capm[,1]
x = data_capm[,2]
par(mfrow=c(1,1))
ts.plot(y,ylab="Returns")
lines(x,col=2)
legend("topright",legend=c("PBR","SPY"),col=1:2,lty=1,bty="n",lwd=2)

Ordinary least
squares
##
## Call:
## lm(formula = y ~ x)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.272099 -0.013966 0.000262 0.014354 0.157838
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.0000107 0.0005673 0.019 0.985
## x 1.2151846 0.0499735 24.317 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.02841 on 2512 degrees of freedom
## Multiple R-squared: 0.1905, Adjusted R-squared: 0.1902
## F-statistic: 591.3 on 1 and 2512 DF, p-value: < 2.2e-16
par(mfrow=c(1,1))
plot(x,y,xlab="SPY",ylab="PBR")
title("Jan 3rd 2020 - February 6th 2026")
abline(lm(y~x),col=2,lwd=2)

Maximum likelihood
estimation
When \(x=(x_1,\ldots,x_n)'\) and
\(X\) is an \((n \times 2)\) matrix where the first
column contains only ones (for the intercept) and the second column is
\(x\), the Gaussian linear model can be
represented as \[
y = X \theta + \epsilon \qquad \qquad \epsilon \sim N(0,\sigma^2 I_n)
\] with parameters \(\theta=(\alpha,\beta)\) and \(\sigma^2\). The ML estimator of \(\theta\) and \(\sigma^2\) are \[
{\widehat \theta} = (X'X)^{-1}X'y \qquad \mbox{and} \qquad
{\widehat \sigma}^2 = \frac{(y-X{\widehat \theta})'(y-X{\widehat
\theta})}{n},
\] respectively.
X = cbind(1,x)
n = nrow(X)
p = ncol(X)
theta.mle = solve(t(X)%*%X)%*%t(X)%*%y
y.hat = X%*%theta.mle
e.hat = y-y.hat
sig.mle = sqrt(mean(e.hat^2))
table = round(rbind(cbind(theta.mle,lm(y~X-1)$coef),
c(sig.mle,(n-p)/n*summary(lm(y~X-1))$sigma)),4)
colnames(table) = c("Our function","lm function")
rownames(table)[1] = "constant"
rownames(table)[p+1] = "sigma"
table
## Our function lm function
## constant 0.0000 0.0000
## x 1.2152 1.2152
## sigma 0.0284 0.0284
MCMC-based Bayesian
inference (conditionally conjugacy)
When the conjugate prior, presented above, is replaced by the
following conditionally conjugate one, we loose closed form derivation
for posterior inference: \[\begin{eqnarray*}
\theta|\sigma^2 &\sim& N(b_0,V_0)\\
\sigma^2 &\sim& IG(c_0,d_0).
\end{eqnarray*}\] In this case, a standard solution since the
early 1990s is to implement an Markov chain Monte Carlo (MCMC)
algorithm. For the Gaussian linear model with conditionally conjugate
prior, it is well established that the Gibbs sampler is the simplest and
cleanest MCMC scheme.
The Gibbs sampler, in our particular set up, cycles through the two
full conditionals \[
p(\theta|\sigma^2,\mbox{data}) \ \ \ \mbox{and} \ \ \
p(\sigma^2|\theta,\mbox{data}),
\] both of which are easily derived: \[
N(b_1,V_1) \ \ \ \mbox{and} \ \ \ IG(c_1,d_1)
\] where \[\begin{eqnarray*}
V_1^{-1} &=& X'X/\sigma^2 + V_0^{-1}\\
V_1^{-1}b_1 &=& X'y/\sigma^2 + V_0^{-1} b_0\\
c_1 &=& c_0 + n/2\\
d_1 &=& d_0 + (y-X'\theta)(y-X'\theta)/2
\end{eqnarray*}\]
# Prior knowledge
b0 = rep(0,p)
V0 = diag(c(1,0.25))
c0 = 0.001
d0 = 0.001
iV0 = solve(V0)
iV0b0 = iV0%*%b0
# Gibbs sampler
sigma2 = 1
M0 = 1000
M = 10000
thin = 1
niter = M0+M*thin
thetas = matrix(0,niter,p)
sigs = rep(0,niter)
for (iter in 1:niter){
V1 = solve(t(X)%*%X/sigma2+iV0)
b1 = V1%*%(t(X)%*%y/sigma2+iV0b0)
theta = b1 + t(chol(V1))%*%rnorm(p)
c1 = c0 + n/2
d1 = d0 + sum((y-X%*%theta)^2)/2
sigma2 = 1/rgamma(1,c1,d1)
thetas[iter,] = theta
sigs[iter] = sqrt(sigma2)
}
ind = seq(M0+1,niter,by=thin)
thetas = thetas[ind,]
sigs = sigs[ind]
mean.theta = apply(thetas,2,mean)
table = round(cbind(theta.mle,mean.theta),5)
colnames(table) = c("ML","Bayes")
rownames(table) = c("Intercept","Market")
table
## ML Bayes
## Intercept 0.00001 0.00002
## Market 1.21518 1.20305
par(mfrow=c(3,3))
ts.plot(thetas[,1],xlab="Iterations",ylab="",main=expression(alpha))
ts.plot(thetas[,2],xlab="Iterations",ylab="",main=expression(beta))
ts.plot(sigs,xlab="Iterations",ylab="",main=expression(sigma))
acf(thetas[,1],main="")
acf(thetas[,2],main="")
acf(sigs,main="")
hist(thetas[,1],prob=TRUE,xlab="",main="")
hist(thetas[,2],prob=TRUE,xlab="",main="")
hist(sigs,prob=TRUE,xlab="",main="")

Comparison
We compare the ML estimate with the posterior densities, based on
both conjugate and conditionally conjugate priors, for the parameters
\(\alpha\), \(\beta\) and \(\sigma^2\).
par(mfrow=c(1,3))
plot(density(thetas[,1]),xlab="Intercept",main="")
bb = seq(min(thetas[,1]),max(thetas[,1]),length=1000)
den = dt((bb-b1[1,1])/sqrt(sig21*B1[1,1]),df=nu1)/sqrt(sig21*B1[1,1])
lines(bb,den,col=2,lwd=2)
abline(v=theta.mle[1,1],col=3,lwd=2)
legend("topleft",legend=c("MLE","C Prior","CC prior"),col=c(3,2,1),bty="n",lwd=2)
plot(density(thetas[,2]),xlab="Slope",main="")
bb = seq(min(thetas[,2]),max(thetas[,2]),length=1000)
den = dt((bb-b1[2,1])/sqrt(sig21*B1[2,2]),df=nu1)/sqrt(sig21*B1[2,2])
lines(bb,den,col=2,lwd=2)
abline(v=theta.mle[2,1],col=3,lwd=2)
legend("topleft",legend=c("MLE","C Prior","CC prior"),col=c(3,2,1),bty="n",lwd=2)
sigs2 = sigs^2
s2 = seq(min(sigs2),max(sigs2),length=1000)
den = dgamma(1/s2,nu1/2,nu1*sig21/2)/(s2^2)
den.d = density(sigs2)
plot(den.d$x,den.d$y,xlab="Error variance",main="",ylim=range(den.d$y,den),type="l",ylab="Density")
lines(s2,den,col=2,lwd=2)
abline(v=sig.mle^2,col=3,lwd=2)
legend("topleft",legend=c("MLE","C Prior","CC prior"),col=c(3,2,1),bty="n",lwd=2)

Things you had to know
to understand this class
Covariance
Variance
Fitting a line via ordinary least squares
Gaussian linear model
Basic matrix algebra
Likelihood function
maximum likelihood estimator
Prior and posterior distributions
Inverse-gamma distribution
Conjugacy
Conditional conjugacy
Monte Carlo posterior simulation
LS0tCnRpdGxlOiAiQ0FQTTogQmF5ZXNpYW4gbGluZWFyIG1vZGVsaW5nIgpzdWJ0aXRsZTogIlBldHJvYnJhcyB2cyBTJlAgNTAwIgphdXRob3I6ICJIZWRpYmVydCBGcmVpdGFzIExvcGVzIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGZsYXRseQogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIHRvY19jb2xsYXBzZWQ6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQotLS0KCiMgSW50cm9kdWN0aW9uCgpUaGUgKipDYXBpdGFsIEFzc2V0IFByaWNpbmcgTW9kZWwgKENBUE0pKiogaXMgb25lIG9mIHRoZSBjb3JuZXJzdG9uZXMgb2YgbW9kZXJuIGZpbmFuY2lhbCB0aGVvcnksIGVzdGFibGlzaGluZyBhIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiBhbiBhc3NldCdzIHN5c3RlbWF0aWMgcmlzayBhbmQgaXRzIGV4cGVjdGVkIHJldHVybi4gRGV2ZWxvcGVkIGluIHRoZSAxOTYwcywgdGhlIG1vZGVsIHBvc3R1bGF0ZXMgdGhhdCBhbiBpbnZlc3RtZW50J3MgcmV0dXJuIHNob3VsZCBiZSBwcm9wb3J0aW9uYWwgdG8gaXRzIGV4cG9zdXJlIHRvIG1hcmtldCByaXNrLCBtZWFzdXJlZCBieSB0aGUgQmV0YSAoJFxiZXRhJCkgY29lZmZpY2llbnQsIGluIGFkZGl0aW9uIHRvIGEgcmlzay1mcmVlIHJhdGUuICAKClRoZSBjZW50cmFsIHByZW1pc2UgaXMgdGhhdCBpbnZlc3RvcnMgc2hvdWxkIGJlIGNvbXBlbnNhdGVkIG9ubHkgZm9yIHJpc2sgdGhhdCBjYW5ub3QgYmUgZGl2ZXJzaWZpZWQgKHN5c3RlbWF0aWMgcmlzayksIHdoaWxlIGNvbXBhbnktc3BlY2lmaWMgcmlzayBjYW4gYmUgZWxpbWluYXRlZCB0aHJvdWdoIGEgd2VsbC1zdHJ1Y3R1cmVkIHBvcnRmb2xpby4gRGVzcGl0ZSBjcml0aWNpc21zIHJlZ2FyZGluZyBpdHMgc2ltcGxpZmljYXRpb25z4oCUc3VjaCBhcyBtYXJrZXQgZWZmaWNpZW5jeSBhbmQgdGhlIGZvY3VzIG9uIGEgc2luZ2xlIHJpc2sgZmFjdG9y4oCUQ0FQTSByZW1haW5zIHdpZGVseSB1c2VkIHRvIGVzdGltYXRlIHRoZSBjb3N0IG9mIGVxdWl0eSBhbmQgZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIHBvcnRmb2xpbyBtYW5hZ2Vycy4KCiMjIEJlaGF2aW9yIG9mICRcYmV0YSQKCkluIHRoZSBjb250ZXh0IG9mIHRoZSBDYXBpdGFsIEFzc2V0IFByaWNpbmcgTW9kZWwgKENBUE0pLCB0aGUgQmV0YSAoJFxiZXRhJCkgY29lZmZpY2llbnQgaXMgYSBtZWFzdXJlIG9mIGFuIGFzc2V0J3Mgc3lzdGVtYXRpYyByaXNr4oCUdGhlIHJpc2sgdGhhdCBjYW5ub3QgYmUgZGl2ZXJzaWZpZWQgYXdheS4gSXQgcXVhbnRpZmllcyBob3cgc2Vuc2l0aXZlIGEgc3BlY2lmaWMgc3RvY2sncyByZXR1cm5zIGFyZSB0byB0aGUgbW92ZW1lbnRzIG9mIHRoZSBicm9hZGVyIG1hcmtldC4rMU1hdGhlbWF0aWNhbGx5LCBpdCBpcyBkZWZpbmVkIGFzOgokJApcYmV0YSA9IFxmcmFje0NvdihSLCBSX20pfXtWYXIoUl9tKX0KJCQKV2hlcmUgJFIkIGFuZCAkUl9tJCBhcmUgdGhlIGFzc2V0IGFuZCBtYXJrZXQgcmV0dXJucywgcmVzcGVjdGl2ZWx5LgoKKiAkXGJldGEgPiAxJCAqKEhpZ2ggU2Vuc2l0aXZpdHkpKiAtIFRoZSBhc3NldCBpcyBtb3JlIHZvbGF0aWxlIHRoYW4gdGhlIG1hcmtldC4gSWYgdGhlIG1hcmtldCByaXNlcyBieSAxMCUsIGEgc3RvY2sgd2l0aCBhICRcYmV0YSQgb2YgMS41IGlzIGV4cGVjdGVkIHRvIHJpc2UgYnkgMTUlLiBDb252ZXJzZWx5LCBpdCB3aWxsIGxpa2VseSBmYWxsIGZ1cnRoZXIgdGhhbiB0aGUgbWFya2V0IGR1cmluZyBhIGRvd250dXJuLiBTdG9ja3MgaW4gc2VjdG9ycyBsaWtlIHRlY2hub2xvZ3kgb3IgYmlvdGVjaG5vbG9neSBvZnRlbiBoYXZlIGhpZ2ggYmV0YXMuCgoqICRcYmV0YSA9IDEkICooTWFya2V0IE5ldXRyYWxpdHkpKiAtIFRoZSBhc3NldCBtb3ZlcyBpbiBsb2Nrc3RlcCB3aXRoIHRoZSBtYXJrZXQuIEl0cyBzeXN0ZW1hdGljIHJpc2sgaXMgaWRlbnRpY2FsIHRvIHRoYXQgb2YgdGhlIG1hcmtldCBwcm94eSAobGlrZSB0aGUgUyZQIDUwMCkuCgoqICQwPFxiZXRhPDEkICooTG93IFNlbnNpdGl2aXR5KSogLSBUaGUgYXNzZXQgaXMgbGVzcyB2b2xhdGlsZSB0aGFuIHRoZSBtYXJrZXQuIEl0IGlzIGNvbnNpZGVyZWQgYSAiZGVmZW5zaXZlIiBzdG9jay4gRm9yIGV4YW1wbGUsIGEgdXRpbGl0eSBjb21wYW55IG1pZ2h0IGhhdmUgYSAkXGJldGEkIG9mIDAuNSwgbWVhbmluZyBpdCBvbmx5IGNhcHR1cmVzIGFib3V0IGhhbGYgb2YgdGhlIG1hcmtldCdzIHN3aW5ncy4KCiogJFxiZXRhPTAkICooTm8gQ29ycmVsYXRpb24pKiAtIFRoZSBhc3NldCdzIHJldHVybnMgaGF2ZSBubyBsaW5lYXIgcmVsYXRpb25zaGlwIHdpdGggdGhlIG1hcmtldCdzIHJldHVybnMuIEEgcmlzay1mcmVlIGFzc2V0LCBsaWtlIGEgVHJlYXN1cnkgYm9uZCAoaW4gdGhlb3J5KSwgaGFzIGEgJFxiZXRhJCBvZiAwLiBHb2xkIGlzIGFsc28gc29tZXRpbWVzIGNpdGVkIGFzIGhhdmluZyBhIGJldGEgbmVhciB6ZXJvLCBhcyBpdHMgcHJpY2UgaXMgb2Z0ZW4gZHJpdmVuIGJ5IGZhY3RvcnMgdW5yZWxhdGVkIHRvIGVxdWl0eSBtYXJrZXRzLgoKKiAkXGJldGE8MCQgKihJbnZlcnNlIENvcnJlbGF0aW9uKSogLSBUaGUgYXNzZXQgbW92ZXMgaW4gdGhlIG9wcG9zaXRlIGRpcmVjdGlvbiBvZiB0aGUgbWFya2V0LiBXaGlsZSByYXJlIGZvciBpbmRpdmlkdWFsIHN0b2Nrcywgc29tZSAiaW52ZXJzZSBFVEZzIiBvciAicHV0IG9wdGlvbnMiIGFyZSBkZXNpZ25lZCB0byBoYXZlIG5lZ2F0aXZlIGJldGFzLiBIaXN0b3JpY2FsbHksIGR1cmluZyBleHRyZW1lIG1hcmtldCBjcmFzaGVzLCB2ZXJ5IGZldyB0cmFkaXRpb25hbCBhc3NldHMgbWFpbnRhaW4gYSBuZWdhdGl2ZSBiZXRhIGNvbnNpc3RlbnRseSwgdGhvdWdoIHNvbWUgInNhZmUgaGF2ZW5zIiBtYXkgZXhoaWJpdCB0aGlzIGJlaGF2aW9yIHRlbXBvcmFyaWx5LgoKIyMgUGV0cm9icmFzIHZzIFMmUDUwMAoKSW4gdGhpcyBkb2N1bWVudCwgd2UgZXN0aW1hdGUgdGhlIENBUE0gcGFyYW1ldGVycyBmb3IgKipQZXRyb2JyYXMgKFBCUikqKiwgdHJhZGVkIG9uIHRoZSBOWVNFLCB1c2luZyB0aGUgKipTJlAgNTAwIChTUFkpKiogYXMgdGhlIG1hcmtldCBwcm94eS4gV2UgYWRvcHQgYSBCYXllc2lhbiBmcmFtZXdvcmssIHdoaWNoIGFsbG93cyB1cyB0byBpbmNvcnBvcmF0ZSBwcmlvciBiZWxpZWZzIGFuZCBvYnRhaW4gYSBmdWxsIHBvc3RlcmlvciBkaXN0cmlidXRpb24gZm9yIHRoZSByaXNrIHBhcmFtZXRlcnMuCgpUaGUgQ0FQTSBlcXVhdGlvbiBpcyBkZWZpbmVkIGFzOgoKJCQKUl90ID0gXGFscGhhICsgXGJldGEgUl97bXR9KyBcZXBzaWxvbl90CiQkCgpXaGVyZToKCiogJHQkIGlzIHRoZSB0aW1lIGZyZXF1ZW5jeSwgdXN1YWxseSBkYWlseS4KCiogJFJfdCQ6IFJldHVybiBvZiB0aGUgcmlza3kgYXNzZXQgKFBCUikuCgoqICRSX3ttdH0kOiBSZXR1cm4gb2YgdGhlIG1hcmtldCBpbmRleCAoUyZQIDUwMCkuCgoqICRcYWxwaGEkOiBUaGUgIkFscGhhIiwgcmVwcmVzZW50aW5nIGFibm9ybWFsIHJldHVybnMuCgoqICRcYmV0YSQ6IFRoZSAiQmV0YSIsIG1lYXN1cmluZyB0aGUgYXNzZXQncyBzZW5zaXRpdml0eSB0byBtYXJrZXQgbW92ZW1lbnRzLgoKKiAkXGVwc2lsb25fdCBcc2ltIE4oMCwgXHNpZ21hXjIpJDogVGhlIGlkaW9zeW5jcmF0aWMgZXJyb3IgdGVybSB3aXRoIHZhcmlhbmNlICRcc2lnbWFeMiQuCgojIFVwbG9hZGluZyBhbmQgcHJvY2Vzc2luZyB0aGUgZGF0YQoKV2UgdXBsb2FkZWQgZGF0YSBmcm9tIEZlYnJ1YXJ5IDEwdGggMjAxNiB0byBGZWJydWFyeSA5dGggMjAyNiwgaWUgYWJvdXQgMTAgeWVhcnMgb2YgZGFpbHkgZGF0YSBvciAkbj0yNTE0JCBvYnNlcnZhdGlvbnMuCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQpwYWNtYW46OnBfbG9hZChxdWFudG1vZCwgYnJtcywgdGlkeXZlcnNlLCBQZXJmb3JtYW5jZUFuYWx5dGljcykKCnN5bWJvbHMgPC0gYygiUEJSIiwgIlNQWSIpCmdldFN5bWJvbHMoc3ltYm9scywgc3JjID0gInlhaG9vIiwgZnJvbSA9ICIyMDE2LTAyLTA5IiwgdG8gPSBTeXMuRGF0ZSgpKQoKIyBDb21wdXRpbmcgcmV0dXJucwpyZXR1cm5zX3BiciA8LSBSZXR1cm4uY2FsY3VsYXRlKENsKFBCUiksIG1ldGhvZCA9ICJsb2ciKQpyZXR1cm5zX3NweSA8LSBSZXR1cm4uY2FsY3VsYXRlKENsKFNQWSksIG1ldGhvZCA9ICJsb2ciKQoKIyBDb21iaW5pbmcgdGhlIHRpbWUgc2VyaWVzIGFuZCByZW1vdmluZyBtaXNzaW5nIHZhbHVlcwpkYXRhX2NhcG0gPC0gbWVyZ2UocmV0dXJuc19wYnIsIHJldHVybnNfc3B5KSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICBkcm9wX25hKCkKY29sbmFtZXMoZGF0YV9jYXBtKSA8LSBjKCJQQlIiLCAiTWFya2V0IikKCnkgPSBkYXRhX2NhcG1bLDFdCgp4ID0gZGF0YV9jYXBtWywyXQoKcGFyKG1mcm93PWMoMSwxKSkKdHMucGxvdCh5LHlsYWI9IlJldHVybnMiKQpsaW5lcyh4LGNvbD0yKQpsZWdlbmQoInRvcHJpZ2h0IixsZWdlbmQ9YygiUEJSIiwiU1BZIiksY29sPTE6MixsdHk9MSxidHk9Im4iLGx3ZD0yKQpgYGAKCiMgT3JkaW5hcnkgbGVhc3Qgc3F1YXJlcwpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQpzdW1tYXJ5KGxtKHl+eCkpCgpwYXIobWZyb3c9YygxLDEpKQpwbG90KHgseSx4bGFiPSJTUFkiLHlsYWI9IlBCUiIpCnRpdGxlKCJKYW4gM3JkIDIwMjAgLSBGZWJydWFyeSA2dGggMjAyNiIpCmFibGluZShsbSh5fngpLGNvbD0yLGx3ZD0yKQpgYGAKCiMgTWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRpb24KV2hlbiAkeD0oeF8xLFxsZG90cyx4X24pJyQgYW5kICRYJCBpcyBhbiAkKG4gXHRpbWVzIDIpJCBtYXRyaXggd2hlcmUgdGhlIGZpcnN0IGNvbHVtbiBjb250YWlucyBvbmx5IG9uZXMgKGZvciB0aGUgaW50ZXJjZXB0KSBhbmQgdGhlIHNlY29uZCBjb2x1bW4gaXMgJHgkLCB0aGUgR2F1c3NpYW4gbGluZWFyIG1vZGVsIGNhbiBiZSByZXByZXNlbnRlZCBhcwokJAp5ID0gWCBcdGhldGEgKyBcZXBzaWxvbiBccXF1YWQgXHFxdWFkIFxlcHNpbG9uIFxzaW0gTigwLFxzaWdtYV4yIElfbikKJCQKd2l0aCBwYXJhbWV0ZXJzICRcdGhldGE9KFxhbHBoYSxcYmV0YSkkIGFuZCAkXHNpZ21hXjIkLiAgVGhlIE1MIGVzdGltYXRvciBvZiAkXHRoZXRhJCBhbmQgJFxzaWdtYV4yJCBhcmUKJCQKe1x3aWRlaGF0IFx0aGV0YX0gPSAoWCdYKV57LTF9WCd5IFxxcXVhZCBcbWJveHthbmR9IFxxcXVhZAp7XHdpZGVoYXQgXHNpZ21hfV4yID0gXGZyYWN7KHktWHtcd2lkZWhhdCBcdGhldGF9KScoeS1Ye1x3aWRlaGF0IFx0aGV0YX0pfXtufSwKJCQKcmVzcGVjdGl2ZWx5LgoKYGBge3J9ClggICAgICAgICA9IGNiaW5kKDEseCkKbiAgICAgICAgID0gbnJvdyhYKQpwICAgICAgICAgPSBuY29sKFgpCnRoZXRhLm1sZSA9IHNvbHZlKHQoWCklKiVYKSUqJXQoWCklKiV5CnkuaGF0ICAgICA9IFglKiV0aGV0YS5tbGUKZS5oYXQgICAgID0geS15LmhhdApzaWcubWxlICAgPSBzcXJ0KG1lYW4oZS5oYXReMikpCgp0YWJsZSA9IHJvdW5kKHJiaW5kKGNiaW5kKHRoZXRhLm1sZSxsbSh5flgtMSkkY29lZiksCiAgICAgICAgICAgICAgYyhzaWcubWxlLChuLXApL24qc3VtbWFyeShsbSh5flgtMSkpJHNpZ21hKSksNCkKY29sbmFtZXModGFibGUpICAgICAgPSBjKCJPdXIgZnVuY3Rpb24iLCJsbSBmdW5jdGlvbiIpCnJvd25hbWVzKHRhYmxlKVsxXSAgID0gImNvbnN0YW50Igpyb3duYW1lcyh0YWJsZSlbcCsxXSA9ICJzaWdtYSIKdGFibGUKYGBgCgoKIyBDbG9zZWQtZm9ybSBCYXllc2lhbiBpbmZlcmVuY2UgKGNvbmp1Z2FjeSkKTGV0IHVzIGNvbWJpbmUgdGhlIGFib3ZlIEdhdXNzaWFuIGxpbmVhciBtb2RlbCB3aXRoIGEgY29uanVnYXRlIHByaW9yCmZvciAkXHRoZXRhLFxzaWdtYV4yJDoKXGJlZ2lue2VxbmFycmF5Kn0KXHRoZXRhfFxzaWdtYV4yICZcc2ltJiBOKGJfMCxcc2lnbWFeMiBCXzApXFwKXHNpZ21hXjIgJlxzaW0mIElHKFxudV8wLzIsXG51XzBcc2lnbWFfMF4yLzIpLApcZW5ke2VxbmFycmF5Kn0KZm9yIGh5cGVycGFyYW1ldGVycyAkYl8wLEJfMCxcbnVfMCQgYW5kICRcc2lnbWFfMF4yJC4gIFRoaXMgcHJpb3IgaXMgY29uanVnYXRlIHNpbmNlIHRoZSBwb3N0ZXJpb3IgZm9sbG93cyB0aGUgc2FtZSBmYW1pbHkgb2YgZGlzdHJpYnV0aW9ucyBhcyB0aGUgcHJpb3Igd2l0aCBoeXBlcnBhcmFtZXRlcnMgYWRqdXN0ZWQgYnkgdGhlIG9ic2VydmVkIGRhdGEuICBNb3JlIHByZWNpc2VseSwKXGJlZ2lue2VxbmFycmF5Kn0KXHRoZXRhfFxzaWdtYV4yLFxtYm94e2RhdGF9ICZcc2ltJiBOKGJfMSxcc2lnbWFeMiBCXzEpXFwKXHNpZ21hXjJ8XG1ib3h7ZGF0YX0gJlxzaW0mIElHKFxudV8xLzIsXG51XzFcc2lnbWFfMV4yLzIpXFwKXHRoZXRhfFxtYm94e2RhdGF9ICZcc2ltJiB0X3tcbnVfMX0oYl8xLFxzaWdtYV8xXjIgQl8xKSwKXGVuZHtlcW5hcnJheSp9CndoZXJlIApcYmVnaW57ZXFuYXJyYXkqfQpCXzEgJj0mIChCXzBeey0xfStYJ1gpXnstMX1cXApCXzFeey0xfSBiXzEgJj0mIEJfMF57LTF9IGJfMCArIFgneVxcClxudV8xICY9JiBcbnVfMCArIG5cXApcbnVfMVxzaWdtYV8xXjIgJj0mIFxudV8wXHNpZ21hXzBeMiArICh5LVggYl8xKSd5ICsgKGJfMC1iXzEpJ0JfMF57LTF9Yl8wLgpcZW5ke2VxbmFycmF5Kn0KCgpOb3RpY2UgdGhhdCB0aGUgYWJvdmUgZGVyaXZhdGlvbnMsIGJvdGggTUxFIGFuZCBCYXllc2lhbiB3aXRoIGNvbmp1Z2F0ZSBwcmlvciwgZm9yIHRoZSBHYXVzc2lhbiBsaW5lYXIgcmVncmVzc2lvbiBpcyBzdGlsbCB2YWxpZCBmb3IgJHA+MiQgYW5kIGlzIHRoZSBiYXNlIG9mIHRoZSBzdGFuZGFyZCBHYXVzc2lhbiBsaW5lYXIgcmVncmVzc2lvbiBmcmFtZXdvcmsgdGF1Z2h0IGluIHZpcnR1YWxseSBhbGwgaW50cm9kdWN0b3J5IGVjb25vbWV0cmljcyBjbGFzc2VzLgoKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTE4fQojIFByaW9yIGh5cGVycGFyYW1ldGVycwpiMCAgICAgICA9IGMoMCwxKQpCMCAgICAgICA9IGRpYWcoYygxMDAwLDI1MCksMikKbnUwICAgICAgPSAwLjAwMgpzaWcyMCAgICA9IDEuMAoKIyBQb3N0ZXJpb3IgaHlwZXJwYXJhbWV0ZXJzCm51MHNpZzIwID0gbnUwKnNpZzIwCmlCMCAgICAgID0gc29sdmUoQjApCmlCMGIwICAgID0gaUIwJSolYjAKQjEgICAgICAgPSBzb2x2ZShpQjArdChYKSUqJVgpCnRjQjEgICAgID0gdChjaG9sKEIxKSkKYjEgICAgICAgPSBCMSUqJShpQjBiMCt0KFgpJSoleSkKbnUxICAgICAgPSBudTAgKyBuCnNpZzIxICAgID0gKChudTBzaWcyMCtzdW0oKHktWCUqJWIxKSp5KSt0KGIwLWIxKSUqJWlCMGIwKS9udTEpWzFdCnNlICAgICAgID0gc3FydChudTEvKG51MS0yKSpzaWcyMSpkaWFnKEIxKSkKCnRhYiA9IHJvdW5kKGNiaW5kKGIxLHNlLGIxL3NlLDIqKDEtcHQoYWJzKGIxL3NlKSxkZj1udTEpKSksNSkKY29sbmFtZXModGFiKT1jKCJNZWFuIiwiU3REZXYiLCJ0IiwidGFpbCIpCnJvd25hbWVzKHRhYik9YygiSW50ZXJjZXB0IiwiTWFya2V0IikKdGFiCmBgYAoKIyBNQ01DLWJhc2VkIEJheWVzaWFuIGluZmVyZW5jZSAoY29uZGl0aW9uYWxseSBjb25qdWdhY3kpCldoZW4gdGhlIGNvbmp1Z2F0ZSBwcmlvciwgcHJlc2VudGVkIGFib3ZlLCBpcyByZXBsYWNlZCBieSB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbmFsbHkgY29uanVnYXRlIG9uZSwgd2UgbG9vc2UgY2xvc2VkIGZvcm0gZGVyaXZhdGlvbiBmb3IgCnBvc3RlcmlvciBpbmZlcmVuY2U6ClxiZWdpbntlcW5hcnJheSp9Clx0aGV0YXxcc2lnbWFeMiAmXHNpbSYgTihiXzAsVl8wKVxcClxzaWdtYV4yICZcc2ltJiBJRyhjXzAsZF8wKS4KXGVuZHtlcW5hcnJheSp9CkluIHRoaXMgY2FzZSwgYSBzdGFuZGFyZCBzb2x1dGlvbiBzaW5jZSB0aGUgZWFybHkgMTk5MHMgaXMgdG8gaW1wbGVtZW50IGFuIE1hcmtvdiBjaGFpbiBNb250ZSBDYXJsbyAoTUNNQykgYWxnb3JpdGhtLiAgRm9yIHRoZSBHYXVzc2lhbiBsaW5lYXIgbW9kZWwgd2l0aCBjb25kaXRpb25hbGx5IGNvbmp1Z2F0ZSBwcmlvciwgaXQgaXMgd2VsbCBlc3RhYmxpc2hlZCB0aGF0IHRoZSBHaWJicyBzYW1wbGVyIGlzIHRoZSBzaW1wbGVzdCBhbmQgY2xlYW5lc3QgTUNNQyBzY2hlbWUuCgpUaGUgR2liYnMgc2FtcGxlciwgaW4gb3VyIHBhcnRpY3VsYXIgc2V0IHVwLCBjeWNsZXMgdGhyb3VnaCB0aGUgdHdvIGZ1bGwgY29uZGl0aW9uYWxzIAokJApwKFx0aGV0YXxcc2lnbWFeMixcbWJveHtkYXRhfSkgXCBcIFwgXG1ib3h7YW5kfSBcIFwgXCAKcChcc2lnbWFeMnxcdGhldGEsXG1ib3h7ZGF0YX0pLAokJApib3RoIG9mIHdoaWNoIGFyZSBlYXNpbHkgZGVyaXZlZDoKJCQKTihiXzEsVl8xKSBcIFwgXCBcbWJveHthbmR9IFwgXCBcIElHKGNfMSxkXzEpCiQkCndoZXJlClxiZWdpbntlcW5hcnJheSp9ClZfMV57LTF9ICY9JiBYJ1gvXHNpZ21hXjIgKyBWXzBeey0xfVxcClZfMV57LTF9Yl8xICY9JiAgWCd5L1xzaWdtYV4yICsgVl8wXnstMX0gYl8wXFwKY18xICY9JiBjXzAgICsgbi8yXFwKZF8xICY9JiBkXzAgKyAoeS1YJ1x0aGV0YSkoeS1YJ1x0aGV0YSkvMgpcZW5ke2VxbmFycmF5Kn0KCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTl9CiMgUHJpb3Iga25vd2xlZGdlIApiMCA9IHJlcCgwLHApClYwID0gZGlhZyhjKDEsMC4yNSkpCmMwID0gMC4wMDEKZDAgPSAwLjAwMQppVjAgPSBzb2x2ZShWMCkKaVYwYjAgPSBpVjAlKiViMAoKIyBHaWJicyBzYW1wbGVyCnNpZ21hMiAgPSAxIApNMCAgICAgID0gMTAwMApNICAgICAgID0gMTAwMDAKdGhpbiAgICA9IDEKbml0ZXIgICA9IE0wK00qdGhpbgp0aGV0YXMgID0gbWF0cml4KDAsbml0ZXIscCkKc2lncyAgICA9IHJlcCgwLG5pdGVyKQpmb3IgKGl0ZXIgaW4gMTpuaXRlcil7CiAgVjEgPSBzb2x2ZSh0KFgpJSolWC9zaWdtYTIraVYwKQogIGIxID0gVjElKiUodChYKSUqJXkvc2lnbWEyK2lWMGIwKQogIHRoZXRhID0gYjEgKyB0KGNob2woVjEpKSUqJXJub3JtKHApCiAgYzEgPSBjMCArIG4vMgogIGQxID0gZDAgKyBzdW0oKHktWCUqJXRoZXRhKV4yKS8yCiAgc2lnbWEyID0gMS9yZ2FtbWEoMSxjMSxkMSkKICB0aGV0YXNbaXRlcixdID0gdGhldGEKICBzaWdzW2l0ZXJdID0gc3FydChzaWdtYTIpCn0KaW5kICAgID0gc2VxKE0wKzEsbml0ZXIsYnk9dGhpbikKdGhldGFzID0gdGhldGFzW2luZCxdCnNpZ3MgICA9IHNpZ3NbaW5kXQoKbWVhbi50aGV0YSA9IGFwcGx5KHRoZXRhcywyLG1lYW4pCnRhYmxlID0gcm91bmQoY2JpbmQodGhldGEubWxlLG1lYW4udGhldGEpLDUpCmNvbG5hbWVzKHRhYmxlKSA9IGMoIk1MIiwiQmF5ZXMiKQpyb3duYW1lcyh0YWJsZSkgPSBjKCJJbnRlcmNlcHQiLCJNYXJrZXQiKQp0YWJsZQoKcGFyKG1mcm93PWMoMywzKSkKdHMucGxvdCh0aGV0YXNbLDFdLHhsYWI9Ikl0ZXJhdGlvbnMiLHlsYWI9IiIsbWFpbj1leHByZXNzaW9uKGFscGhhKSkKdHMucGxvdCh0aGV0YXNbLDJdLHhsYWI9Ikl0ZXJhdGlvbnMiLHlsYWI9IiIsbWFpbj1leHByZXNzaW9uKGJldGEpKQp0cy5wbG90KHNpZ3MseGxhYj0iSXRlcmF0aW9ucyIseWxhYj0iIixtYWluPWV4cHJlc3Npb24oc2lnbWEpKQphY2YodGhldGFzWywxXSxtYWluPSIiKQphY2YodGhldGFzWywyXSxtYWluPSIiKQphY2Yoc2lncyxtYWluPSIiKQpoaXN0KHRoZXRhc1ssMV0scHJvYj1UUlVFLHhsYWI9IiIsbWFpbj0iIikKaGlzdCh0aGV0YXNbLDJdLHByb2I9VFJVRSx4bGFiPSIiLG1haW49IiIpCmhpc3Qoc2lncyxwcm9iPVRSVUUseGxhYj0iIixtYWluPSIiKQpgYGAKCiMgQ29tcGFyaXNvbgoKV2UgY29tcGFyZSB0aGUgTUwgZXN0aW1hdGUgd2l0aCB0aGUgcG9zdGVyaW9yIGRlbnNpdGllcywgYmFzZWQgb24gYm90aCBjb25qdWdhdGUgYW5kIGNvbmRpdGlvbmFsbHkgY29uanVnYXRlIHByaW9ycywgZm9yIHRoZSBwYXJhbWV0ZXJzICRcYWxwaGEkLCAkXGJldGEkIGFuZCAkXHNpZ21hXjIkLgoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NH0KcGFyKG1mcm93PWMoMSwzKSkKcGxvdChkZW5zaXR5KHRoZXRhc1ssMV0pLHhsYWI9IkludGVyY2VwdCIsbWFpbj0iIikKYmIgPSBzZXEobWluKHRoZXRhc1ssMV0pLG1heCh0aGV0YXNbLDFdKSxsZW5ndGg9MTAwMCkKZGVuID0gZHQoKGJiLWIxWzEsMV0pL3NxcnQoc2lnMjEqQjFbMSwxXSksZGY9bnUxKS9zcXJ0KHNpZzIxKkIxWzEsMV0pCmxpbmVzKGJiLGRlbixjb2w9Mixsd2Q9MikKYWJsaW5lKHY9dGhldGEubWxlWzEsMV0sY29sPTMsbHdkPTIpCmxlZ2VuZCgidG9wbGVmdCIsbGVnZW5kPWMoIk1MRSIsIkMgUHJpb3IiLCJDQyBwcmlvciIpLGNvbD1jKDMsMiwxKSxidHk9Im4iLGx3ZD0yKQoKcGxvdChkZW5zaXR5KHRoZXRhc1ssMl0pLHhsYWI9IlNsb3BlIixtYWluPSIiKQpiYiA9IHNlcShtaW4odGhldGFzWywyXSksbWF4KHRoZXRhc1ssMl0pLGxlbmd0aD0xMDAwKQpkZW4gPSBkdCgoYmItYjFbMiwxXSkvc3FydChzaWcyMSpCMVsyLDJdKSxkZj1udTEpL3NxcnQoc2lnMjEqQjFbMiwyXSkKbGluZXMoYmIsZGVuLGNvbD0yLGx3ZD0yKQphYmxpbmUodj10aGV0YS5tbGVbMiwxXSxjb2w9Myxsd2Q9MikKbGVnZW5kKCJ0b3BsZWZ0IixsZWdlbmQ9YygiTUxFIiwiQyBQcmlvciIsIkNDIHByaW9yIiksY29sPWMoMywyLDEpLGJ0eT0ibiIsbHdkPTIpCgoKc2lnczIgPSBzaWdzXjIKczIgICAgPSBzZXEobWluKHNpZ3MyKSxtYXgoc2lnczIpLGxlbmd0aD0xMDAwKQpkZW4gICA9IGRnYW1tYSgxL3MyLG51MS8yLG51MSpzaWcyMS8yKS8oczJeMikKZGVuLmQgPSBkZW5zaXR5KHNpZ3MyKQpwbG90KGRlbi5kJHgsZGVuLmQkeSx4bGFiPSJFcnJvciB2YXJpYW5jZSIsbWFpbj0iIix5bGltPXJhbmdlKGRlbi5kJHksZGVuKSx0eXBlPSJsIix5bGFiPSJEZW5zaXR5IikKbGluZXMoczIsZGVuLGNvbD0yLGx3ZD0yKQphYmxpbmUodj1zaWcubWxlXjIsY29sPTMsbHdkPTIpCmxlZ2VuZCgidG9wbGVmdCIsbGVnZW5kPWMoIk1MRSIsIkMgUHJpb3IiLCJDQyBwcmlvciIpLGNvbD1jKDMsMiwxKSxidHk9Im4iLGx3ZD0yKQpgYGAKCiMgVGhpbmdzIHlvdSBoYWQgdG8ga25vdyB0byB1bmRlcnN0YW5kIHRoaXMgY2xhc3MKCjEuIENvdmFyaWFuY2UKCjIuIFZhcmlhbmNlCgozLiBGaXR0aW5nIGEgbGluZSB2aWEgb3JkaW5hcnkgbGVhc3Qgc3F1YXJlcwoKNC4gR2F1c3NpYW4gbGluZWFyIG1vZGVsCgo1LiBCYXNpYyBtYXRyaXggYWxnZWJyYQoKNi4gTGlrZWxpaG9vZCBmdW5jdGlvbgoKNy4gbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRvcgoKOC4gUHJpb3IgYW5kIHBvc3RlcmlvciBkaXN0cmlidXRpb25zCgo5LiBJbnZlcnNlLWdhbW1hIGRpc3RyaWJ1dGlvbgoKMTAuIENvbmp1Z2FjeQoKMTEuIENvbmRpdGlvbmFsIGNvbmp1Z2FjeQoKMTIuIE1vbnRlIENhcmxvIHBvc3RlcmlvciBzaW11bGF0aW9uCg==