Abstract

In this workshop we will practice writing functions and a loop. We will work on the CAPM regression model.

Challenge I - Writing a function for the CAPM

In the previous workshop we learned how to write a function for the market regression model. Now you have to write a function that estimates the CAPM for a stock, and it has to return:

beta coefficients (beta0 and beta1), standard errors of beta coefficients, minimim value of the 95% confidence interval for beta0 and beta1 maximum value of the 95% confidence interval for beta0 and beta1 the # of valid (non-missing) observations used to run the regression. I will first do a review of the CAPM model. I also recommend you to read Basics of Portfolio theory - Part III, where I explain how the CAPM was developed.

A CAPM model can be estimated running a simple regression model using the market premium as the independent variable, and the individual asset premium as the dependent variable:

[ri(t)−rf]=α[rM(t)−rf]+εt According to the CAPM and the efficient market hypothesis, the expected value of the constant in this regression model should be zero. Why? because if we find an individual asset that has a significant positive alpha coefficient when running the CAPM regression, then this individual asset is expected to over perform the market. According to the efficient market hypothesis, the most efficient or more optimal portfolio in a financial market is the market portfolio. If there is an individual asset with a positive and significant alpha, it is expected that sooner or later (sooner more than later), its alpha will tend to zero. However, in reality, the efficient market hypothesis does not always hold.

Let’s write an R function to estimate a CAPM regression model given a stock return, a market return, and a risk-free rate vectors. The function has to return a vector with several regression results.

Here are the specifications of the function:

Your function has to receive 3 parameters: 1) the continuously compounded (cc) return of a stock, 2) the risk-free rate in continuously compounded, and 2) the cc returns of the market.

Using the lm function, run a simple regression model according to the market model. Remember that the dependent variable must the stock premium return, and the independent variable must be the market premium returns.

Your function must return a vector with 9 values. The structure of this vector is illustrated in the following example:

b0 se(b0) min(b0) max(b0) b1 se(b1) min(b1) max(b1) # Non-missing 0.01 0.02 -0.03 0.05 1.3 0.10 1.1 1.5 35 The non-missing observations can be calculated using the attriute df.residual of the regression model. You just have to add 2 to this value since the degrees of freedom of the regression residual is N-2, where N is the number of non-missing observations.

Test your function with at least 2 Mexican stocks (select any stocks you want), and use the correct market index. Display the vector results. For 1 stock respond to the following questions: * Is the stock offering returns systematically over the market? Explain * Is the stock significantly riskier than the market? Explain

You have to bring data from Yahoo Finace for the stock and the Mexican market, and bring the CETES data form the FRED database (ticker for CETES: INTGSTMXM193N)

Challenge II - Running the CAPM for several stocks with a loop using your function

Using the Excel file InputTickers.xlsx posted in the course site, you have to bring monthly stock prices, and a monthly series for the market index. Bring data from Jan 2018 to Dec 2021. In one Sheet you can find the stock tickers, and in the other Sheet you find the market ticker.

Write the corresponding code to estimate the CAPM models of all stocks. The specifications of the program are the following:

Write a loop to run the a market regression model for each stock.

You must use the function you defined in the previous part to run the CAPM models.

Make sure your program runs with any number of tickers specified in the Excel file and it is validated in case the ticker does not exist in Yahoo. I recommend you to start testing your program with few tickers (2 or 3), so create another excel file with only 2 or 3 stocks.

Your program must create a Matrix with the results of the models for all stocks. The structure of this matrix is the following:

MATRIX RESULTS:

STOCK b0 se(b0) min(b0) max(b0) b1 se(b1) min(b1) max(b1) # Non-missing ALFA 0.01 0.02 -0.03 0.05 1.3 0.10 1.1 1.5 35 … … … … … … …. … … .. Use the stock names as the rownames of the matrix.

Then, each row will be the CAPM results for each stock, and each column will have specific values of the betas, std errors, 95%C.I. and the # of non-missing values used in the regression. Note that it is possible that some stocks might not have prices/returns for some periods.

Challenge III - Selection of stocks based on market regressions

Write a code to select 5 stocks according to the following criteria: Select 10 stocks those with the highest minimum value of the 95% C.I. of b0

Out of these 10 stocks, select 5 stocks that have the least market risk

Challenge IV - Optimize your portfolio

With these 5 stocks, and using the xts-zoo objects of these stocks (data from 2018 to 2021), calculate the optimal portfolio considering an annual risk-free rate of 2% annual (convert this to monthly since your dataset is monthly).

Bring price data of these 5 tickers, but now from Jan 2022 to date. Using the optimal weights and these months, calculate the holding-period return of this portfolio. Report your results.

Bring data of the market index from Jan 2021 to date. Calculate the holding-period return of the market. Which HPR was better, the one from the market or the HPR of your optimal portfolio?

Solutions

LETS FIRST REMEMBER THE CAPM FORMULA E(Ri)=Rf+βiE(Rm)−Rf) WHERE, E(Ri) is the expected returnn of the asset. Rf is the risk-free asset, typically a US government bond. βi is the sensitivity of the expected excess asset returns to the expected market returns. E(Rm)−Rf is the considered the risk premium.

NEXT WE WILL READY OUR ENVIRONMENT LOAD DESIRED PACKAGES

library(quantmod)
library(PerformanceAnalytics)
library(IntroCompFinR)
library(readxl)
input.df<-read_excel("InputTickers.xlsx",sheet = "tickers")
tickers.list<-input.df$ticker
na.omit(tickers.list)
 [1] "AC.MX"        "ACCELSAB.MX"  "ACTINVRB.MX"  "AEROMEX.MX"  
 [5] "ALFAA.MX"     "ALPEKA.MX"    "ALSEA.MX"     "AMXL.MX"     
 [9] "ARA.MX"       "ARISTOSA.MX"  "ASURB.MX"     "AUTLANB.MX"  
[13] "AXTELCPO.MX"  "CMOCTEZ.MX"   "CREAL.MX"     "CULTIBAB.MX" 
[17] "EDOARDOB.MX"  "ELEKTRA.MX"   "FEMSAUBD.MX"  "FIBRAMQ12.MX"
[21] "FIBRAPL14.MX" "FINDEP.MX"    "FMTY14.MX"    "FRAGUAB.MX"  
[25] "FUNO11.MX"    "GAPB.MX"      "GCARSOA1.MX"  "GCC.MX"      
[29] "GENTERA.MX"   "HOGARB.MX"    "HOMEX.MX"     "HOTEL.MX"    
[33] "ICA.MX"       "ICHB.MX"      "LALAB.MX"     "LAMOSA.MX"   
[37] "MINSAB.MX"    "MONEXB.MX"    "OMAB.MX"      "PASAB.MX"    
[41] "PINFRA.MX"    "POCHTECB.MX"  "POSADASA.MX"  "VITROA.MX"   
[45] "VOLARA.MX"    "WALMEX.MX"   
getSymbols(tickers.list,
           from = "2021-01-01", to = "2022-01-01",
           periodicity = "monthly",
           src = "yahoo")
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
pausing 1 second between requests for more than 5 symbols
 [1] "AC.MX"        "ACCELSAB.MX"  "ACTINVRB.MX"  "AEROMEX.MX"  
 [5] "ALFAA.MX"     "ALPEKA.MX"    "ALSEA.MX"     "AMXL.MX"     
 [9] "ARA.MX"       "ARISTOSA.MX"  "ASURB.MX"     "AUTLANB.MX"  
[13] "AXTELCPO.MX"  "CMOCTEZ.MX"   "CREAL.MX"     "CULTIBAB.MX" 
[17] "EDOARDOB.MX"  "ELEKTRA.MX"   "FEMSAUBD.MX"  "FIBRAMQ12.MX"
[21] "FIBRAPL14.MX" "FINDEP.MX"    "FMTY14.MX"    "FRAGUAB.MX"  
[25] "FUNO11.MX"    "GAPB.MX"      "GCARSOA1.MX"  "GCC.MX"      
[29] "GENTERA.MX"   "HOGARB.MX"    "HOMEX.MX"     "HOTEL.MX"    
[33] "ICA.MX"       "ICHB.MX"      "LALAB.MX"     "LAMOSA.MX"   
[37] "MINSAB.MX"    "MONEXB.MX"    "OMAB.MX"      "PASAB.MX"    
[41] "PINFRA.MX"    "POCHTECB.MX"  "POSADASA.MX"  "VITROA.MX"   
[45] "VOLARA.MX"    "WALMEX.MX"   

DATA MANAGEMENT

objList <- lapply(tickers.list, get)
class(objList)
[1] "list"
prices.zoo <- do.call(merge, objList)
prices.df <- as.data.frame(na.omit(Ad(prices.zoo)))

OBTAINING RETURNS

returns.df <- diff(log(as.zoo(prices.df)))

NOTE: quantmod::as.zoo.data.frame() is deprecated
  Use as.zoo(x, order.by = as.Date(rownames(x))) instead.
  This note is printed once. To see it for every call, set
  options(quantmod.deprecate.as.zoo.data.frame = TRUE)
head(returns.df)
           AC.MX.Adjusted ACCELSAB.MX.Adjusted
2021-02-01     0.01810116            0.0000000
2021-03-01     0.06218124            0.0000000
2021-04-01     0.07274719            0.0000000
2021-05-01     0.06770828            0.0000000
2021-06-01     0.02256725            0.1300531
2021-07-01     0.04100867            0.0000000
           ACTINVRB.MX.Adjusted AEROMEX.MX.Adjusted
2021-02-01          0.000000000         -0.15020682
2021-03-01          0.051293124          0.04902167
2021-04-01          0.000000000         -0.07696104
2021-05-01          0.043059514         -0.10351038
2021-06-01         -0.048174565          0.10849792
2021-07-01         -0.005141458          0.03902934
           ALFAA.MX.Adjusted ALPEKA.MX.Adjusted
2021-02-01       -0.12449147        0.072083672
2021-03-01        0.03536369        0.004730598
2021-04-01        0.18302757        0.171062975
2021-05-01       -0.01180299        0.007067189
2021-06-01        0.06775229        0.075835613
2021-07-01        0.01328038        0.008126826
           ALSEA.MX.Adjusted AMXL.MX.Adjusted ARA.MX.Adjusted
2021-02-01        0.09605731      -0.02069548      0.15290776
2021-03-01        0.17416468       0.04168781      0.11057077
2021-04-01        0.08450383       0.01351861      0.13714409
2021-05-01        0.01386397       0.09627350     -0.01763024
2021-06-01        0.05983204      -0.03793791     -0.09313868
2021-07-01        0.12939961       0.10616021      0.02569736
           ARISTOSA.MX.Adjusted ASURB.MX.Adjusted
2021-02-01                    0        0.19361051
2021-03-01                    0       -0.07532123
2021-04-01                    0       -0.05789288
2021-05-01                    0        0.05858127
2021-06-01                    0        0.01261021
2021-07-01                    0       -0.01721779
           AUTLANB.MX.Adjusted AXTELCPO.MX.Adjusted
2021-02-01         0.070533377          -0.08621285
2021-03-01         0.136758906           0.05588046
2021-04-01        -0.022814692          -0.01643873
2021-05-01        -0.007722078          -0.00925076
2021-06-01        -0.010128602           0.11073637
2021-07-01        -0.032633269          -0.16222534
           CMOCTEZ.MX.Adjusted CREAL.MX.Adjusted
2021-02-01          0.00000000        0.06949779
2021-03-01          0.08269171       -0.15032996
2021-04-01         -0.00812819       -0.06248724
2021-05-01         -0.01013282       -0.34349135
2021-06-01          0.02525322        0.43032056
2021-07-01         -0.03159116        0.54083176
           CULTIBAB.MX.Adjusted EDOARDOB.MX.Adjusted
2021-02-01          -0.03217279                    0
2021-03-01          -0.16458945                    0
2021-04-01          -0.08734201                    0
2021-05-01          -0.04712488                    0
2021-06-01          -0.04335571                    0
2021-07-01          -0.03357206                    0
           ELEKTRA.MX.Adjusted FEMSAUBD.MX.Adjusted
2021-02-01       -0.0001227060           0.02432609
2021-03-01       -0.0083764917           0.07371366
2021-04-01        0.1054952749           0.01800805
2021-05-01        0.0659696165           0.06478151
2021-06-01       -0.0064676764           0.01896271
2021-07-01       -0.0008547864           0.03247704
           FIBRAMQ12.MX.Adjusted FIBRAPL14.MX.Adjusted
2021-02-01           0.008929439            0.04470687
2021-03-01           0.009856158            0.03660907
2021-04-01          -0.039838058           -0.01099167
2021-05-01          -0.070658200            0.08501381
2021-06-01           0.093685521           -0.05115821
2021-07-01           0.008097118           -0.01818643
           FINDEP.MX.Adjusted FMTY14.MX.Adjusted
2021-02-01        0.000000000        0.030458819
2021-03-01       -0.006825965       -0.010976083
2021-04-01        0.027028672        0.021264934
2021-05-01       -0.036663984        0.006875066
2021-06-01        0.075884698        0.060491292
2021-07-01        0.006389798       -0.016669022
           FRAGUAB.MX.Adjusted FUNO11.MX.Adjusted
2021-02-01        -0.018312677        0.033085678
2021-03-01        -0.004342897        0.022755560
2021-04-01         0.054895206        0.045815880
2021-05-01         0.185170835       -0.056758772
2021-06-01        -0.028862864       -0.079454086
2021-07-01         0.029165493        0.007864898
           GAPB.MX.Adjusted GCARSOA1.MX.Adjusted
2021-02-01      0.024102082          0.004834318
2021-03-01      0.009499229          0.075044433
2021-04-01     -0.025694637          0.032916780
2021-05-01      0.032318769          0.042876987
2021-06-01      0.004379912          0.032800610
2021-07-01      0.076253771          0.058852045
           GCC.MX.Adjusted GENTERA.MX.Adjusted
2021-02-01     0.006888008          0.28268207
2021-03-01     0.081094733         -0.15305480
2021-04-01     0.014555925          0.10885933
2021-05-01     0.024770659          0.09905374
2021-06-01     0.086926581          0.04607521
2021-07-01     0.005823379         -0.01196606
           HOGARB.MX.Adjusted HOMEX.MX.Adjusted
2021-02-01                  0       -0.02817088
2021-03-01                  0       -0.12136086
2021-04-01                  0       -0.17589067
2021-05-01                  0       -0.31365756
2021-06-01                  0        0.00000000
2021-07-01                  0        0.42285685
           HOTEL.MX.Adjusted ICA.MX.Adjusted ICHB.MX.Adjusted
2021-02-01       -0.01487806               0       0.03711184
2021-03-01        0.07822917               0       0.01629979
2021-04-01       -0.03015304               0       0.18025214
2021-05-01        0.05942342               0       0.04886156
2021-06-01        0.01526747               0       0.13614703
2021-07-01       -0.06453852               0       0.05514778
           LALAB.MX.Adjusted LAMOSA.MX.Adjusted
2021-02-01     -0.0409334560        0.190353764
2021-03-01     -0.0397704854       -0.022472854
2021-04-01      0.0896331043       -0.025621399
2021-05-01      0.0932986748        0.203912243
2021-06-01      0.0099652846        0.009661869
2021-07-01     -0.0006106024       -0.019418081
           MINSAB.MX.Adjusted MONEXB.MX.Adjusted
2021-02-01          0.0000000       -0.010775161
2021-03-01         -0.0106658        0.000000000
2021-04-01          0.0000000       -0.008368131
2021-05-01         -0.4411162        0.056907059
2021-06-01         -0.3101527       -0.013029517
2021-07-01          0.3156974       -0.023218272
           OMAB.MX.Adjusted PASAB.MX.Adjusted
2021-02-01      0.003053401       0.004338402
2021-03-01      0.057323287      -0.095310180
2021-04-01     -0.020120217       0.000000000
2021-05-01      0.016534441       0.141830195
2021-06-01      0.017494136      -0.050858417
2021-07-01     -0.067202238       0.000000000
           PINFRA.MX.Adjusted POCHTECB.MX.Adjusted
2021-02-01       -0.001168982          -0.00836825
2021-03-01        0.015988007          -0.03419136
2021-04-01        0.001150445           0.09134978
2021-05-01        0.019922947          -0.03226086
2021-06-01       -0.001378505           0.23293156
2021-07-01       -0.060287656           0.06291383
           POSADASA.MX.Adjusted VITROA.MX.Adjusted
2021-02-01        -0.0046620131      -0.0616379098
2021-03-01        -0.0429660359      -0.0772061846
2021-04-01         0.0719803201       0.0729843306
2021-05-01         0.0009073503      -0.0434241072
2021-06-01         0.0700505584      -0.0004023738
2021-07-01         0.0908798538       0.1013282521
           VOLARA.MX.Adjusted WALMEX.MX.Adjusted
2021-02-01         0.31015493        0.022537584
2021-03-01        -0.07821901        0.077203100
2021-04-01         0.12200803        0.028140715
2021-05-01         0.04805192       -0.013818569
2021-06-01         0.10048334       -0.005058614
2021-07-01         0.14187782        0.008416940
tail(returns.df)
           AC.MX.Adjusted ACCELSAB.MX.Adjusted
2021-07-01    0.041008668                    0
2021-08-01    0.071358725                    0
2021-09-01   -0.027347343                    0
2021-10-01    0.009389197                    0
2021-11-01    0.040895328                    0
2021-12-01   -0.001913541                    0
           ACTINVRB.MX.Adjusted AEROMEX.MX.Adjusted
2021-07-01         -0.005141458          0.03902934
2021-08-01          0.010256617         -0.09531018
2021-09-01          0.115512777         -0.03390155
2021-10-01          0.000000000         -0.04643360
2021-11-01         -0.018349057         -0.01147240
2021-12-01          0.080897095         -0.62620770
           ALFAA.MX.Adjusted ALPEKA.MX.Adjusted
2021-07-01        0.01328038        0.008126826
2021-08-01       -0.07248551       -0.042577186
2021-09-01        0.01478376       -0.008055945
2021-10-01        0.04107353       -0.041283295
2021-11-01        0.02777949       -0.015199276
2021-12-01       -0.02042893        0.004773025
           ALSEA.MX.Adjusted AMXL.MX.Adjusted ARA.MX.Adjusted
2021-07-01        0.12939961      0.106160207     0.025697360
2021-08-01       -0.02788077      0.182581613    -0.047628157
2021-09-01        0.05813441     -0.079452659    -0.014297909
2021-10-01        0.03796283      0.004916596     0.016148022
2021-11-01       -0.16379916      0.024759035    -0.020809902
2021-12-01        0.03376532      0.153356149     0.002333657
           ARISTOSA.MX.Adjusted ASURB.MX.Adjusted
2021-07-01         0.0000000000      -0.017217794
2021-08-01        -0.0007695268      -0.003268488
2021-09-01         0.0000000000       0.067943470
2021-10-01         0.0000000000       0.095351623
2021-11-01         0.0000000000      -0.055359369
2021-12-01         0.0000000000       0.073427797
           AUTLANB.MX.Adjusted AXTELCPO.MX.Adjusted
2021-07-01        -0.032633269          -0.16222534
2021-08-01        -0.001619356           0.11276940
2021-09-01         0.080915040          -0.13853891
2021-10-01        -0.003744013          -0.06213178
2021-11-01         0.004517935          -0.12502070
2021-12-01         0.025201832          -0.06502290
           CMOCTEZ.MX.Adjusted CREAL.MX.Adjusted
2021-07-01         -0.03159116        0.54083176
2021-08-01          0.04982188       -0.11683535
2021-09-01          0.11067016       -0.26927332
2021-10-01         -0.06412833       -0.11638916
2021-11-01          0.03699965       -0.30551942
2021-12-01         -0.03745753        0.07195532
           CULTIBAB.MX.Adjusted EDOARDOB.MX.Adjusted
2021-07-01          -0.03357206                    0
2021-08-01          -0.02917253                    0
2021-09-01          -0.02909637                    0
2021-10-01          -0.01923136                    0
2021-11-01          -0.02955880                    0
2021-12-01           0.27307592                    0
           ELEKTRA.MX.Adjusted FEMSAUBD.MX.Adjusted
2021-07-01       -0.0008547864          0.032477038
2021-08-01       -0.0083695055          0.006828284
2021-09-01       -0.0196634310          0.024627084
2021-10-01        0.0075044934         -0.057233957
2021-11-01       -0.1231326594         -0.104599237
2021-12-01        0.1037810805          0.044078152
           FIBRAMQ12.MX.Adjusted FIBRAPL14.MX.Adjusted
2021-07-01           0.008097118         -0.0181864284
2021-08-01           0.067620208          0.0779222656
2021-09-01          -0.053319589         -0.0380872249
2021-10-01           0.014924603          0.0557567125
2021-11-01           0.006493511         -0.0002978815
2021-12-01           0.059291166          0.0000000000
           FINDEP.MX.Adjusted FMTY14.MX.Adjusted
2021-07-01        0.006389798       -0.016669022
2021-08-01        0.012658397        0.016074120
2021-09-01       -0.012658397        0.006885685
2021-10-01        0.000000000       -0.008117522
2021-11-01        0.018928010        0.018597909
2021-12-01        0.000000000        0.020891810
           FRAGUAB.MX.Adjusted FUNO11.MX.Adjusted
2021-07-01         0.029165493        0.007864898
2021-08-01        -0.001513960        0.051638808
2021-09-01         0.000000000        0.039348486
2021-10-01         0.003025722       -0.134264313
2021-11-01        -0.010630368       -0.037852940
2021-12-01         0.035838650        0.111709398
           GAPB.MX.Adjusted GCARSOA1.MX.Adjusted
2021-07-01       0.07625377           0.05885204
2021-08-01       0.02126087           0.04831406
2021-09-01       0.02578909           0.03511666
2021-10-01       0.11165851          -0.02086386
2021-11-01      -0.04669431          -0.10463874
2021-12-01       0.13029635           0.05944498
           GCC.MX.Adjusted GENTERA.MX.Adjusted
2021-07-01     0.005823379         -0.01196606
2021-08-01     0.000864383         -0.05115750
2021-09-01    -0.040458200          0.08164249
2021-10-01    -0.009746742          0.02715095
2021-11-01    -0.024054549         -0.12337891
2021-12-01     0.058075883          0.19085556
           HOGARB.MX.Adjusted HOMEX.MX.Adjusted
2021-07-01                  0        0.42285685
2021-08-01                  0        0.03390155
2021-09-01                  0        0.83290912
2021-10-01                  0       -0.26381459
2021-11-01                  0        0.01869213
2021-12-01                  0        0.00000000
           HOTEL.MX.Adjusted ICA.MX.Adjusted ICHB.MX.Adjusted
2021-07-01       -0.06453852               0       0.05514778
2021-08-01       -0.02247286               0      -0.10075795
2021-09-01       -0.02722681               0       0.02042021
2021-10-01        0.01265840               0       0.08319894
2021-11-01       -0.03629000               0      -0.01183449
2021-12-01        0.02150621               0       0.07894323
           LALAB.MX.Adjusted LAMOSA.MX.Adjusted
2021-07-01     -0.0006106024        -0.01941808
2021-08-01      0.0506211357         0.27256844
2021-09-01      0.0177613119         0.07227201
2021-10-01     -0.0005759953         0.03278987
2021-11-01      0.0000000000         0.24998439
2021-12-01      0.0088886863         0.16794751
           MINSAB.MX.Adjusted MONEXB.MX.Adjusted
2021-07-01        0.315697420      -0.0232182719
2021-08-01       -0.009997814       0.0108471183
2021-09-01       -0.052701714       0.0358635668
2021-10-01       -0.059378599      -0.0342052606
2021-11-01        0.082628888      -0.0008289039
2021-12-01       -0.077648963      -0.0049875240
           OMAB.MX.Adjusted PASAB.MX.Adjusted
2021-07-01     -0.067202238        0.00000000
2021-08-01     -0.005101063        0.02575250
2021-09-01     -0.001403316        0.09684983
2021-10-01      0.025848364       -0.02334736
2021-11-01     -0.020247109        0.08306660
2021-12-01      0.121809020       -0.03165520
           PINFRA.MX.Adjusted POCHTECB.MX.Adjusted
2021-07-01      -0.0602876558          0.062913825
2021-08-01      -0.0009328604          0.025287320
2021-09-01      -0.0472315197         -0.028952565
2021-10-01       0.0724184435         -0.002450982
2021-11-01      -0.0264360829         -0.087122928
2021-12-01       0.0816847482          0.002673798
           POSADASA.MX.Adjusted VITROA.MX.Adjusted
2021-07-01           0.09087985         0.10132825
2021-08-01          -0.01949379        -0.09531018
2021-09-01           0.00000000         0.02019471
2021-10-01           0.05737711        -0.06519207
2021-11-01          -0.01498155        -0.05195412
2021-12-01           0.11568440         0.06236004
           VOLARA.MX.Adjusted WALMEX.MX.Adjusted
2021-07-01         0.14187782         0.00841694
2021-08-01        -0.09381128         0.08525730
2021-09-01         0.12182431        -0.01878718
2021-10-01        -0.18919593         0.02367305
2021-11-01        -0.15539756        -0.06367548
2021-12-01         0.13625696         0.12654925
options(scipen=100)
options(digits=2)
returns.df <- returns.df[,-1]
boxplot(returns.df,main="Monthly Compounde Returns", xlab="Stock Picks", ylab="Returns")

NEXT WE WILL COMPUTE MEAN AND STANRARD DEVIATION OF COMPOUNDED RETURNS

na.omit(mean(returns.df))
[1] 0.013
Mean=sapply(returns.df,mean)
Rf = mean(input.df$ticker)
Warning: argument is not numeric or logical: returning NA
paste("Market Free Retrun = ",Rf*100)
[1] "Market Free Retrun =  NA"
SD=sapply(returns.df,sd)
cbind(Mean,SD)
                          Mean      SD
ACTINVRB.MX.Adjusted   0.02085 0.04731
AEROMEX.MX.Adjusted   -0.08613 0.19441
ALFAA.MX.Adjusted      0.01399 0.07833
ALPEKA.MX.Adjusted     0.02151 0.06253
ALSEA.MX.Adjusted      0.04509 0.08856
AMXL.MX.Adjusted       0.04411 0.08169
ARA.MX.Adjusted        0.02285 0.07842
ARISTOSA.MX.Adjusted  -0.00007 0.00023
ASURB.MX.Adjusted      0.02659 0.08050
AUTLANB.MX.Adjusted    0.02175 0.05238
AXTELCPO.MX.Adjusted  -0.03504 0.09571
CMOCTEZ.MX.Adjusted    0.01400 0.05301
CREAL.MX.Adjusted     -0.02288 0.28626
CULTIBAB.MX.Adjusted  -0.02201 0.10638
EDOARDOB.MX.Adjusted   0.00000 0.00000
ELEKTRA.MX.Adjusted    0.01052 0.06389
FEMSAUBD.MX.Adjusted   0.01327 0.05180
FIBRAMQ12.MX.Adjusted  0.00955 0.05078
FIBRAPL14.MX.Adjusted  0.01648 0.04613
FINDEP.MX.Adjusted     0.00770 0.02819
FMTY14.MX.Adjusted     0.01325 0.02170
FRAGUAB.MX.Adjusted    0.02222 0.05943
FUNO11.MX.Adjusted     0.00035 0.07033
GAPB.MX.Adjusted       0.03302 0.05382
GCARSOA1.MX.Adjusted   0.02406 0.05023
GCC.MX.Adjusted        0.01861 0.04113
GENTERA.MX.Adjusted    0.04516 0.12903
HOGARB.MX.Adjusted     0.00000 0.00000
HOMEX.MX.Adjusted      0.03686 0.32765
HOTEL.MX.Adjusted     -0.00077 0.04285
ICA.MX.Adjusted        0.00000 0.00000
ICHB.MX.Adjusted       0.04944 0.07422
LALAB.MX.Adjusted      0.01712 0.04453
LAMOSA.MX.Adjusted     0.10291 0.11587
MINSAB.MX.Adjusted    -0.05121 0.19518
MONEXB.MX.Adjusted     0.00075 0.02594
OMAB.MX.Adjusted       0.01164 0.04822
PASAB.MX.Adjusted      0.01370 0.06945
PINFRA.MX.Adjusted     0.00488 0.04345
POCHTECB.MX.Adjusted   0.02016 0.08570
POSADASA.MX.Adjusted   0.02953 0.05283
VITROA.MX.Adjusted    -0.01257 0.06770
VOLARA.MX.Adjusted     0.04218 0.15242
WALMEX.MX.Adjusted     0.02459 0.05399

Getting That Beta

attach(input.df)
The following object is masked from input.df (pos = 3):

    ticker

The following object is masked from input.df (pos = 4):

    ticker
lm.MMM<- lm(ACTINVRB.MX ~ WALMEX.MX)
summary(WALMEX.MX)
     Index            WALMEX.MX.Open WALMEX.MX.High
 Min.   :2021-01-01   Min.   :56     Min.   :64    
 1st Qu.:2021-03-24   1st Qu.:63     1st Qu.:67    
 Median :2021-06-16   Median :66     Median :69    
 Mean   :2021-06-16   Mean   :65     Mean   :71    
 3rd Qu.:2021-09-08   3rd Qu.:69     3rd Qu.:74    
 Max.   :2021-12-01   Max.   :72     Max.   :80    
 WALMEX.MX.Low WALMEX.MX.Close WALMEX.MX.Volume   
 Min.   :56    Min.   :58      Min.   :154369128  
 1st Qu.:61    1st Qu.:65      1st Qu.:245115059  
 Median :63    Median :66      Median :309865272  
 Mean   :63    Mean   :67      Mean   :291140956  
 3rd Qu.:67    3rd Qu.:70      3rd Qu.:344714862  
 Max.   :69    Max.   :76      Max.   :370541737  
 WALMEX.MX.Adjusted
 Min.   :58        
 1st Qu.:64        
 Median :65        
 Mean   :66        
 3rd Qu.:70        
 Max.   :76        
plot(ACTINVRB.MX,WALMEX.MX, xlim=c(-20,20),ylim=c(-20,20),main="Beta")
BetaMMM <- summary(lm.MMM)$coefficients[2, 1]
abline(lm.MMM, col="blue")
Warning: only using the first two of 42 regression coefficients
text(-20, 20, BetaMMM, pos = 4)

Rstde <- summary(lm.MMM)$sigma
paste("MMM Beta = ",BetaMMM)
[1] "MMM Beta =  "
paste("MMM Standard Deviation = ",Rstde)
[1] "MMM Standard Deviation =  "
coefs <- coef(lm.MMM)
paste("alpha = ",coefs[1])
[1] "alpha =  5.68903548099235"
paste("beta = ",coefs[2])
[1] "beta =  0.102683026488156"
lm.WALMEX.MX<- lm(ACTINVRB.MX ~ WALMEX.MX)
summary(lm.WALMEX.MX)
Response ACTINVRB.MX.Open :

Call:
lm(formula = ACTINVRB.MX.Open ~ WALMEX.MX)

Residuals:
           ACTINVRB.MX.Open
2021-01-01      0.181308015
2021-02-01      0.033552240
2021-03-01     -0.287062782
2021-04-01      0.103948254
2021-05-01     -0.235096338
2021-06-01      0.325929901
2021-07-01     -0.205052358
2021-08-01     -0.183042836
2021-09-01     -0.489389627
2021-10-01      0.720222911
2021-11-01      0.034682470
2021-12-01      0.000000151

Coefficients:
                                  Estimate     Std. Error
(Intercept)                  5.68903548099  2.79150609434
WALMEX.MXWALMEX.MX.Open      0.10268302649  0.11391321203
WALMEX.MXWALMEX.MX.High      0.08696533920  0.06802037172
WALMEX.MXWALMEX.MX.Low      -0.09770004171  0.21244257764
WALMEX.MXWALMEX.MX.Close    -1.77424372027  2.27074465895
WALMEX.MXWALMEX.MX.Volume   -0.00000000139  0.00000000315
WALMEX.MXWALMEX.MX.Adjusted  1.76278200588  2.22278196563
                            t value Pr(>|t|)  
(Intercept)                    2.04    0.097 .
WALMEX.MXWALMEX.MX.Open        0.90    0.409  
WALMEX.MXWALMEX.MX.High        1.28    0.257  
WALMEX.MXWALMEX.MX.Low        -0.46    0.665  
WALMEX.MXWALMEX.MX.Close      -0.78    0.470  
WALMEX.MXWALMEX.MX.Volume     -0.44    0.677  
WALMEX.MXWALMEX.MX.Adjusted    0.79    0.464  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.47 on 5 degrees of freedom
Multiple R-squared:  0.687, Adjusted R-squared:  0.312 
F-statistic: 1.83 on 6 and 5 DF,  p-value: 0.262


Response ACTINVRB.MX.High :

Call:
lm(formula = ACTINVRB.MX.High ~ WALMEX.MX)

Residuals:
           ACTINVRB.MX.High
2021-01-01       0.25491251
2021-02-01      -0.01045488
2021-03-01      -0.04417813
2021-04-01      -0.00986915
2021-05-01       0.29931018
2021-06-01      -0.24029466
2021-07-01      -0.26954584
2021-08-01      -0.47047786
2021-09-01       0.11216352
2021-10-01       0.73509493
2021-11-01      -0.35666319
2021-12-01       0.00000257

Coefficients:
                                  Estimate     Std. Error
(Intercept)                  1.62989939367  2.87103478524
WALMEX.MXWALMEX.MX.Open      0.15960564136  0.11715854566
WALMEX.MXWALMEX.MX.High      0.03360569962  0.06995824000
WALMEX.MXWALMEX.MX.Low      -0.08400796439  0.21849496640
WALMEX.MXWALMEX.MX.Close    -1.48123932760  2.33543710238
WALMEX.MXWALMEX.MX.Volume    0.00000000226  0.00000000324
WALMEX.MXWALMEX.MX.Adjusted  1.50705283679  2.28610797457
                            t value Pr(>|t|)
(Intercept)                    0.57     0.59
WALMEX.MXWALMEX.MX.Open        1.36     0.23
WALMEX.MXWALMEX.MX.High        0.48     0.65
WALMEX.MXWALMEX.MX.Low        -0.38     0.72
WALMEX.MXWALMEX.MX.Close      -0.63     0.55
WALMEX.MXWALMEX.MX.Volume      0.70     0.52
WALMEX.MXWALMEX.MX.Adjusted    0.66     0.54

Residual standard error: 0.49 on 5 degrees of freedom
Multiple R-squared:  0.807, Adjusted R-squared:  0.576 
F-statistic: 3.49 on 6 and 5 DF,  p-value: 0.0958


Response ACTINVRB.MX.Low :

Call:
lm(formula = ACTINVRB.MX.Low ~ WALMEX.MX)

Residuals:
           ACTINVRB.MX.Low
2021-01-01      0.01926322
2021-02-01      0.16721851
2021-03-01      0.04748211
2021-04-01     -0.25054568
2021-05-01      0.15803050
2021-06-01     -0.07218164
2021-07-01     -0.13821050
2021-08-01     -0.27963062
2021-09-01     -0.13273305
2021-10-01      0.61859458
2021-11-01     -0.13729468
2021-12-01      0.00000726

Coefficients:
                                  Estimate     Std. Error
(Intercept)                  4.44080546924  2.10666197129
WALMEX.MXWALMEX.MX.Open      0.07600975990  0.08596672323
WALMEX.MXWALMEX.MX.High      0.06303603013  0.05133283809
WALMEX.MXWALMEX.MX.Low      -0.09085198316  0.16032374076
WALMEX.MXWALMEX.MX.Close    -0.98848253355  1.71365967254
WALMEX.MXWALMEX.MX.Volume   -0.00000000112  0.00000000238
WALMEX.MXWALMEX.MX.Adjusted  1.02717040765  1.67746373435
                            t value Pr(>|t|)  
(Intercept)                    2.11    0.089 .
WALMEX.MXWALMEX.MX.Open        0.88    0.417  
WALMEX.MXWALMEX.MX.High        1.23    0.274  
WALMEX.MXWALMEX.MX.Low        -0.57    0.595  
WALMEX.MXWALMEX.MX.Close      -0.58    0.589  
WALMEX.MXWALMEX.MX.Volume     -0.47    0.657  
WALMEX.MXWALMEX.MX.Adjusted    0.61    0.567  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.36 on 5 degrees of freedom
Multiple R-squared:  0.786, Adjusted R-squared:  0.528 
F-statistic: 3.05 on 6 and 5 DF,  p-value: 0.121


Response ACTINVRB.MX.Close :

Call:
lm(formula = ACTINVRB.MX.Close ~ WALMEX.MX)

Residuals:
           ACTINVRB.MX.Close
2021-01-01        0.00091778
2021-02-01        0.06875238
2021-03-01        0.22412290
2021-04-01        0.05040780
2021-05-01        0.25966223
2021-06-01       -0.30569639
2021-07-01       -0.23725455
2021-08-01       -0.42253799
2021-09-01        0.23357233
2021-10-01        0.38732775
2021-11-01       -0.25927298
2021-12-01       -0.00000127

Coefficients:
                                   Estimate      Std. Error
(Intercept)                  2.942543175395  2.242261027682
WALMEX.MXWALMEX.MX.Open      0.099076084646  0.091500124747
WALMEX.MXWALMEX.MX.High      0.049559749744  0.054636967801
WALMEX.MXWALMEX.MX.Low      -0.021160684803  0.170643264378
WALMEX.MXWALMEX.MX.Close    -2.820908135476  1.823962434799
WALMEX.MXWALMEX.MX.Volume    0.000000000311  0.000000002532
WALMEX.MXWALMEX.MX.Adjusted  2.826053316118  1.785436680462
                            t value Pr(>|t|)
(Intercept)                    1.31     0.25
WALMEX.MXWALMEX.MX.Open        1.08     0.33
WALMEX.MXWALMEX.MX.High        0.91     0.41
WALMEX.MXWALMEX.MX.Low        -0.12     0.91
WALMEX.MXWALMEX.MX.Close      -1.55     0.18
WALMEX.MXWALMEX.MX.Volume      0.12     0.91
WALMEX.MXWALMEX.MX.Adjusted    1.58     0.17

Residual standard error: 0.38 on 5 degrees of freedom
Multiple R-squared:  0.87,  Adjusted R-squared:  0.715 
F-statistic:  5.6 on 6 and 5 DF,  p-value: 0.0392


Response ACTINVRB.MX.Volume :

Call:
lm(formula = ACTINVRB.MX.Volume ~ WALMEX.MX)

Residuals:
           ACTINVRB.MX.Volume
2021-01-01          -426859.1
2021-02-01          1308279.2
2021-03-01          -132030.4
2021-04-01          -851278.8
2021-05-01          1126668.5
2021-06-01         -1539861.5
2021-07-01          -272307.6
2021-08-01           442882.2
2021-09-01           514504.1
2021-10-01           -23354.6
2021-11-01          -146666.4
2021-12-01               24.2

Coefficients:
                                   Estimate      Std. Error
(Intercept)                   1124835.33636   6883964.90804
WALMEX.MXWALMEX.MX.Open        602627.76574    280914.50552
WALMEX.MXWALMEX.MX.High        -37874.73733    167740.93844
WALMEX.MXWALMEX.MX.Low        -593140.74455    523891.83475
WALMEX.MXWALMEX.MX.Close    -12472373.00466   5599746.52359
WALMEX.MXWALMEX.MX.Volume           0.00757         0.00777
WALMEX.MXWALMEX.MX.Adjusted  12573557.59809   5481468.61676
                            t value Pr(>|t|)  
(Intercept)                    0.16    0.877  
WALMEX.MXWALMEX.MX.Open        2.15    0.085 .
WALMEX.MXWALMEX.MX.High       -0.23    0.830  
WALMEX.MXWALMEX.MX.Low        -1.13    0.309  
WALMEX.MXWALMEX.MX.Close      -2.23    0.076 .
WALMEX.MXWALMEX.MX.Volume      0.97    0.375  
WALMEX.MXWALMEX.MX.Adjusted    2.29    0.070 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1170000 on 5 degrees of freedom
Multiple R-squared:  0.741, Adjusted R-squared:  0.431 
F-statistic: 2.39 on 6 and 5 DF,  p-value: 0.179


Response ACTINVRB.MX.Adjusted :

Call:
lm(formula = ACTINVRB.MX.Adjusted ~ WALMEX.MX)

Residuals:
           ACTINVRB.MX.Adjusted
2021-01-01          0.022101571
2021-02-01          0.028448339
2021-03-01          0.177927210
2021-04-01         -0.029108062
2021-05-01          0.209675747
2021-06-01         -0.201534316
2021-07-01         -0.154054052
2021-08-01         -0.346228574
2021-09-01          0.154595720
2021-10-01          0.354672363
2021-11-01         -0.216496674
2021-12-01          0.000000728

Coefficients:
                                   Estimate      Std. Error
(Intercept)                  1.733121576777  1.783244317955
WALMEX.MXWALMEX.MX.Open      0.077629309505  0.072768993231
WALMEX.MXWALMEX.MX.High      0.041096944699  0.043452149941
WALMEX.MXWALMEX.MX.Low       0.035177968384  0.135710618809
WALMEX.MXWALMEX.MX.Close    -2.861056652322  1.450576274511
WALMEX.MXWALMEX.MX.Volume    0.000000000214  0.000000002013
WALMEX.MXWALMEX.MX.Adjusted  2.851660885105  1.419937186703
                            t value Pr(>|t|)
(Intercept)                    0.97     0.38
WALMEX.MXWALMEX.MX.Open        1.07     0.33
WALMEX.MXWALMEX.MX.High        0.95     0.39
WALMEX.MXWALMEX.MX.Low         0.26     0.81
WALMEX.MXWALMEX.MX.Close      -1.97     0.11
WALMEX.MXWALMEX.MX.Volume      0.11     0.92
WALMEX.MXWALMEX.MX.Adjusted    2.01     0.10

Residual standard error: 0.3 on 5 degrees of freedom
Multiple R-squared:  0.92,  Adjusted R-squared:  0.824 
F-statistic: 9.59 on 6 and 5 DF,  p-value: 0.0127
plot(ACTINVRB.MX,WALMEX.MX, xlim=c(-20,20),ylim=c(-20,20),main="Beta")
abline(lm.WALMEX.MX, col="blue")
Warning: only using the first two of 42 regression coefficients
BetaACTINVRB <- summary(lm.WALMEX.MX)$coefficients[2, 1]
text(-20,20, BetaACTINVRB, pos = 4)

Programming code for the functional algorithm

# I create an empty vector 
W<-c()
# I do a loop from 1 to 3 to create 1,000 columns of 3 random weights following
#   the uniform probability distribution:
for(i in 1:3)  {
  W<-rbind(W,runif(1000))
}
# Now I just add a row at the end with values equal to 1 minus the sum of the 3
#   random weights. I do this to force that the sum of each column must be equal to 1

W<-rbind(W,1-colSums(W))

# The each column of this matrix represents a random portfolio. The last weight
#   is the only one that can have negative weight

# I can check that the sum of the columns is equal to 1. Since the matrix has
#  many columns, I just do the sum for 5 columns:
colSums(W[,1:5])
[1] 1 1 1 1 1
# All sums are equal to 1, as expected
# I create an empty vector 
W2<-c()
# I do a loop from 1 to 4 to create 1,000 columns of 4 random weights following
#   the uniform probability distribution:
for(i in 1:4)  {
  W2<-rbind(W2,runif(1000))
}
# The problem I have now is that some of the 1,000 portfolios
#  might end up having a sum of weights higher than one. # I can do a simple "trick" by 
#   dividing each of the 4 weights by the sum of these 4
#   weights. And I can do this # for all 1000 portfolios: 

# I first create a vector with the sum of weights for all portfolios:
sumw <- colSums(W2)
# I do another loop to divide each weight by the sum of weights: 
for(i in 1:4)  {
  W2[i,]<-W2[i,]/sumw
  # In each iteration I divide one raw of W2 by the vector sumw, 
  #  which is the sum of the weights of all 1000 portfolios
}

# I check that the sum of weights is 1 (I do this for 5 portfolios)
colSums(W2[,1:5])
[1] 1 1 1 1 1
# All sums are equal to 1, as expected

# Then each column of this matrix represents a random portfolio without allowing for short sales. 
# I create a matrix for the historical returns of the assets:
ret.mat <- as.matrix(returns.df)
# I generate the expected returns of the assets as their geometric means:
exp.rets<-exp(colMeans(ret.mat)) - 1
# I generate the variance-covariance matrix:
COV<-var(ret.mat)
# I estimate the expected returns of all 1,000 portfolios using matrix algebra:
ERP <- t(W2)%*%exp.rets
# I estimate the expected variance and risk of the portfolios using matrix algebra:
VARP<-t(W2)%*%COV%*%W2
# I get the diagonal of this matrix and take square root to get the expected risk
#   of the 1,000 portfolios:
RISKP<-sqrt(diag(VARP))
# I remove the VARP object since it has 1,000 times 1,000 cels! 1 million cells!
rm(VARP)
plot(RISKP,ERP[,1], main="Random portfolios of 4 assets",xlab="Volatility",ylab="Exp Return")
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKYXV0aG9yOiBTdGVmYW4gU2Nod2VpdHplciwgQTAxMjA5NzU1Cm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KIyBBYnN0cmFjdApJbiB0aGlzIHdvcmtzaG9wIHdlIHdpbGwgcHJhY3RpY2Ugd3JpdGluZyBmdW5jdGlvbnMgYW5kIGEgbG9vcC4gV2Ugd2lsbCB3b3JrIG9uIHRoZSBDQVBNIHJlZ3Jlc3Npb24gbW9kZWwuCgojIENoYWxsZW5nZSBJIC0gV3JpdGluZyBhIGZ1bmN0aW9uIGZvciB0aGUgQ0FQTQoKSW4gdGhlIHByZXZpb3VzIHdvcmtzaG9wIHdlIGxlYXJuZWQgaG93IHRvIHdyaXRlIGEgZnVuY3Rpb24gZm9yIHRoZSBtYXJrZXQgcmVncmVzc2lvbiBtb2RlbC4gTm93IHlvdSBoYXZlIHRvIHdyaXRlIGEgZnVuY3Rpb24gdGhhdCBlc3RpbWF0ZXMgdGhlIENBUE0gZm9yIGEgc3RvY2ssIGFuZCBpdCBoYXMgdG8gcmV0dXJuOgoKYmV0YSBjb2VmZmljaWVudHMgKGJldGEwIGFuZCBiZXRhMSksCnN0YW5kYXJkIGVycm9ycyBvZiBiZXRhIGNvZWZmaWNpZW50cywKbWluaW1pbSB2YWx1ZSBvZiB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIGJldGEwIGFuZCBiZXRhMQptYXhpbXVtIHZhbHVlIG9mIHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgYmV0YTAgYW5kIGJldGExCnRoZSAjIG9mIHZhbGlkIChub24tbWlzc2luZykgb2JzZXJ2YXRpb25zIHVzZWQgdG8gcnVuIHRoZSByZWdyZXNzaW9uLgpJIHdpbGwgZmlyc3QgZG8gYSByZXZpZXcgb2YgdGhlIENBUE0gbW9kZWwuIEkgYWxzbyByZWNvbW1lbmQgeW91IHRvIHJlYWQgQmFzaWNzIG9mIFBvcnRmb2xpbyB0aGVvcnkgLSBQYXJ0IElJSSwgd2hlcmUgSSBleHBsYWluIGhvdyB0aGUgQ0FQTSB3YXMgZGV2ZWxvcGVkLgoKQSBDQVBNIG1vZGVsIGNhbiBiZSBlc3RpbWF0ZWQgcnVubmluZyBhIHNpbXBsZSByZWdyZXNzaW9uIG1vZGVsIHVzaW5nIHRoZSBtYXJrZXQgcHJlbWl1bSBhcyB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUsIGFuZCB0aGUgaW5kaXZpZHVhbCBhc3NldCBwcmVtaXVtIGFzIHRoZSBkZXBlbmRlbnQgdmFyaWFibGU6CgpbcmkodCniiJJyZl09zrFeK86yXltyTSh0KeKIknJmXSvOtXQKQWNjb3JkaW5nIHRvIHRoZSBDQVBNIGFuZCB0aGUgZWZmaWNpZW50IG1hcmtldCBoeXBvdGhlc2lzLCB0aGUgZXhwZWN0ZWQgdmFsdWUgb2YgdGhlIGNvbnN0YW50IGluIHRoaXMgcmVncmVzc2lvbiBtb2RlbCBzaG91bGQgYmUgemVyby4gV2h5PyBiZWNhdXNlIGlmIHdlIGZpbmQgYW4gaW5kaXZpZHVhbCBhc3NldCB0aGF0IGhhcyBhIHNpZ25pZmljYW50IHBvc2l0aXZlIGFscGhhIGNvZWZmaWNpZW50IHdoZW4gcnVubmluZyB0aGUgQ0FQTSByZWdyZXNzaW9uLCB0aGVuIHRoaXMgaW5kaXZpZHVhbCBhc3NldCBpcyBleHBlY3RlZCB0byBvdmVyIHBlcmZvcm0gdGhlIG1hcmtldC4gQWNjb3JkaW5nIHRvIHRoZSBlZmZpY2llbnQgbWFya2V0IGh5cG90aGVzaXMsIHRoZSBtb3N0IGVmZmljaWVudCBvciBtb3JlIG9wdGltYWwgcG9ydGZvbGlvIGluIGEgZmluYW5jaWFsIG1hcmtldCBpcyB0aGUgbWFya2V0IHBvcnRmb2xpby4gSWYgdGhlcmUgaXMgYW4gaW5kaXZpZHVhbCBhc3NldCB3aXRoIGEgcG9zaXRpdmUgYW5kIHNpZ25pZmljYW50IGFscGhhLCBpdCBpcyBleHBlY3RlZCB0aGF0IHNvb25lciBvciBsYXRlciAoc29vbmVyIG1vcmUgdGhhbiBsYXRlciksIGl0cyBhbHBoYSB3aWxsIHRlbmQgdG8gemVyby4gSG93ZXZlciwgaW4gcmVhbGl0eSwgdGhlIGVmZmljaWVudCBtYXJrZXQgaHlwb3RoZXNpcyBkb2VzIG5vdCBhbHdheXMgaG9sZC4KCkxldOKAmXMgd3JpdGUgYW4gUiBmdW5jdGlvbiB0byBlc3RpbWF0ZSBhIENBUE0gcmVncmVzc2lvbiBtb2RlbCBnaXZlbiBhIHN0b2NrIHJldHVybiwgYSBtYXJrZXQgcmV0dXJuLCBhbmQgYSByaXNrLWZyZWUgcmF0ZSB2ZWN0b3JzLiBUaGUgZnVuY3Rpb24gaGFzIHRvIHJldHVybiBhIHZlY3RvciB3aXRoIHNldmVyYWwgcmVncmVzc2lvbiByZXN1bHRzLgoKSGVyZSBhcmUgdGhlIHNwZWNpZmljYXRpb25zIG9mIHRoZSBmdW5jdGlvbjoKCllvdXIgZnVuY3Rpb24gaGFzIHRvIHJlY2VpdmUgMyBwYXJhbWV0ZXJzOiAxKSB0aGUgY29udGludW91c2x5IGNvbXBvdW5kZWQgKGNjKSByZXR1cm4gb2YgYSBzdG9jaywgMikgdGhlIHJpc2stZnJlZSByYXRlIGluIGNvbnRpbnVvdXNseSBjb21wb3VuZGVkLCBhbmQgMikgdGhlIGNjIHJldHVybnMgb2YgdGhlIG1hcmtldC4KClVzaW5nIHRoZSBsbSBmdW5jdGlvbiwgcnVuIGEgc2ltcGxlIHJlZ3Jlc3Npb24gbW9kZWwgYWNjb3JkaW5nIHRvIHRoZSBtYXJrZXQgbW9kZWwuIFJlbWVtYmVyIHRoYXQgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBtdXN0IHRoZSBzdG9jayBwcmVtaXVtIHJldHVybiwgYW5kIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSBtdXN0IGJlIHRoZSBtYXJrZXQgcHJlbWl1bSByZXR1cm5zLgoKWW91ciBmdW5jdGlvbiBtdXN0IHJldHVybiBhIHZlY3RvciB3aXRoIDkgdmFsdWVzLiBUaGUgc3RydWN0dXJlIG9mIHRoaXMgdmVjdG9yIGlzIGlsbHVzdHJhdGVkIGluIHRoZSBmb2xsb3dpbmcgZXhhbXBsZToKCmIwCXNlKGIwKQltaW4oYjApCW1heChiMCkJYjEJc2UoYjEpCW1pbihiMSkJbWF4KGIxKQkjIE5vbi1taXNzaW5nCjAuMDEJMC4wMgktMC4wMwkwLjA1CTEuMwkwLjEwCTEuMQkxLjUJMzUKVGhlIG5vbi1taXNzaW5nIG9ic2VydmF0aW9ucyBjYW4gYmUgY2FsY3VsYXRlZCB1c2luZyB0aGUgYXR0cml1dGUgZGYucmVzaWR1YWwgb2YgdGhlIHJlZ3Jlc3Npb24gbW9kZWwuIFlvdSBqdXN0IGhhdmUgdG8gYWRkIDIgdG8gdGhpcyB2YWx1ZSBzaW5jZSB0aGUgZGVncmVlcyBvZiBmcmVlZG9tIG9mIHRoZSByZWdyZXNzaW9uIHJlc2lkdWFsIGlzIE4tMiwgd2hlcmUgTiBpcyB0aGUgbnVtYmVyIG9mIG5vbi1taXNzaW5nIG9ic2VydmF0aW9ucy4KClRlc3QgeW91ciBmdW5jdGlvbiB3aXRoIGF0IGxlYXN0IDIgTWV4aWNhbiBzdG9ja3MgKHNlbGVjdCBhbnkgc3RvY2tzIHlvdSB3YW50KSwgYW5kIHVzZSB0aGUgY29ycmVjdCBtYXJrZXQgaW5kZXguIERpc3BsYXkgdGhlIHZlY3RvciByZXN1bHRzLiBGb3IgMSBzdG9jayByZXNwb25kIHRvIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zOiAqIElzIHRoZSBzdG9jayBvZmZlcmluZyByZXR1cm5zIHN5c3RlbWF0aWNhbGx5IG92ZXIgdGhlIG1hcmtldD8gRXhwbGFpbiAqIElzIHRoZSBzdG9jayBzaWduaWZpY2FudGx5IHJpc2tpZXIgdGhhbiB0aGUgbWFya2V0PyBFeHBsYWluCgpZb3UgaGF2ZSB0byBicmluZyBkYXRhIGZyb20gWWFob28gRmluYWNlIGZvciB0aGUgc3RvY2sgYW5kIHRoZSBNZXhpY2FuIG1hcmtldCwgYW5kIGJyaW5nIHRoZSBDRVRFUyBkYXRhIGZvcm0gdGhlIEZSRUQgZGF0YWJhc2UgKHRpY2tlciBmb3IgQ0VURVM6IElOVEdTVE1YTTE5M04pCgojIENoYWxsZW5nZSBJSSAtIFJ1bm5pbmcgdGhlIENBUE0gZm9yIHNldmVyYWwgc3RvY2tzIHdpdGggYSBsb29wIHVzaW5nIHlvdXIgZnVuY3Rpb24KVXNpbmcgdGhlIEV4Y2VsIGZpbGUgSW5wdXRUaWNrZXJzLnhsc3ggcG9zdGVkIGluIHRoZSBjb3Vyc2Ugc2l0ZSwgeW91IGhhdmUgdG8gYnJpbmcgbW9udGhseSBzdG9jayBwcmljZXMsIGFuZCBhIG1vbnRobHkgc2VyaWVzIGZvciB0aGUgbWFya2V0IGluZGV4LiBCcmluZyBkYXRhIGZyb20gSmFuIDIwMTggdG8gRGVjIDIwMjEuIEluIG9uZSBTaGVldCB5b3UgY2FuIGZpbmQgdGhlIHN0b2NrIHRpY2tlcnMsIGFuZCBpbiB0aGUgb3RoZXIgU2hlZXQgeW91IGZpbmQgdGhlIG1hcmtldCB0aWNrZXIuCgpXcml0ZSB0aGUgY29ycmVzcG9uZGluZyBjb2RlIHRvIGVzdGltYXRlIHRoZSBDQVBNIG1vZGVscyBvZiBhbGwgc3RvY2tzLiBUaGUgc3BlY2lmaWNhdGlvbnMgb2YgdGhlIHByb2dyYW0gYXJlIHRoZSBmb2xsb3dpbmc6CgpXcml0ZSBhIGxvb3AgdG8gcnVuIHRoZSBhIG1hcmtldCByZWdyZXNzaW9uIG1vZGVsIGZvciBlYWNoIHN0b2NrLgoKWW91IG11c3QgdXNlIHRoZSBmdW5jdGlvbiB5b3UgZGVmaW5lZCBpbiB0aGUgcHJldmlvdXMgcGFydCB0byBydW4gdGhlIENBUE0gbW9kZWxzLgoKTWFrZSBzdXJlIHlvdXIgcHJvZ3JhbSBydW5zIHdpdGggYW55IG51bWJlciBvZiB0aWNrZXJzIHNwZWNpZmllZCBpbiB0aGUgRXhjZWwgZmlsZSBhbmQgaXQgaXMgdmFsaWRhdGVkIGluIGNhc2UgdGhlIHRpY2tlciBkb2VzIG5vdCBleGlzdCBpbiBZYWhvby4gSSByZWNvbW1lbmQgeW91IHRvIHN0YXJ0IHRlc3RpbmcgeW91ciBwcm9ncmFtIHdpdGggZmV3IHRpY2tlcnMgKDIgb3IgMyksIHNvIGNyZWF0ZSBhbm90aGVyIGV4Y2VsIGZpbGUgd2l0aCBvbmx5IDIgb3IgMyBzdG9ja3MuCgpZb3VyIHByb2dyYW0gbXVzdCBjcmVhdGUgYSBNYXRyaXggd2l0aCB0aGUgcmVzdWx0cyBvZiB0aGUgbW9kZWxzIGZvciBhbGwgc3RvY2tzLiBUaGUgc3RydWN0dXJlIG9mIHRoaXMgbWF0cml4IGlzIHRoZSBmb2xsb3dpbmc6CgpNQVRSSVggUkVTVUxUUzoKClNUT0NLCWIwCXNlKGIwKQltaW4oYjApCW1heChiMCkJYjEJc2UoYjEpCW1pbihiMSkJbWF4KGIxKQkjIE5vbi1taXNzaW5nCkFMRkEJMC4wMQkwLjAyCS0wLjAzCTAuMDUJMS4zCTAuMTAJMS4xCTEuNQkzNQrigKYJ4oCmCeKApgnigKYJ4oCmCeKApgnigKYuCeKApgnigKYJLi4KVXNlIHRoZSBzdG9jayBuYW1lcyBhcyB0aGUgcm93bmFtZXMgb2YgdGhlIG1hdHJpeC4KClRoZW4sIGVhY2ggcm93IHdpbGwgYmUgdGhlIENBUE0gcmVzdWx0cyBmb3IgZWFjaCBzdG9jaywgYW5kIGVhY2ggY29sdW1uIHdpbGwgaGF2ZSBzcGVjaWZpYyB2YWx1ZXMgb2YgdGhlIGJldGFzLCBzdGQgZXJyb3JzLCA5NSVDLkkuIGFuZCB0aGUgIyBvZiBub24tbWlzc2luZyB2YWx1ZXMgdXNlZCBpbiB0aGUgcmVncmVzc2lvbi4gTm90ZSB0aGF0IGl0IGlzIHBvc3NpYmxlIHRoYXQgc29tZSBzdG9ja3MgbWlnaHQgbm90IGhhdmUgcHJpY2VzL3JldHVybnMgZm9yIHNvbWUgcGVyaW9kcy4KCiMgQ2hhbGxlbmdlIElJSSAtIFNlbGVjdGlvbiBvZiBzdG9ja3MgYmFzZWQgb24gbWFya2V0IHJlZ3Jlc3Npb25zCldyaXRlIGEgY29kZSB0byBzZWxlY3QgNSBzdG9ja3MgYWNjb3JkaW5nIHRvIHRoZSBmb2xsb3dpbmcgY3JpdGVyaWE6ClNlbGVjdCAxMCBzdG9ja3MgdGhvc2Ugd2l0aCB0aGUgaGlnaGVzdCBtaW5pbXVtIHZhbHVlIG9mIHRoZSA5NSUgQy5JLiBvZiBiMAoKT3V0IG9mIHRoZXNlIDEwIHN0b2Nrcywgc2VsZWN0IDUgc3RvY2tzIHRoYXQgaGF2ZSB0aGUgbGVhc3QgbWFya2V0IHJpc2sKCiMgQ2hhbGxlbmdlIElWIC0gT3B0aW1pemUgeW91ciBwb3J0Zm9saW8KV2l0aCB0aGVzZSA1IHN0b2NrcywgYW5kIHVzaW5nIHRoZSB4dHMtem9vIG9iamVjdHMgb2YgdGhlc2Ugc3RvY2tzIChkYXRhIGZyb20gMjAxOCB0byAyMDIxKSwgY2FsY3VsYXRlIHRoZSBvcHRpbWFsIHBvcnRmb2xpbyBjb25zaWRlcmluZyBhbiBhbm51YWwgcmlzay1mcmVlIHJhdGUgb2YgMiUgYW5udWFsIChjb252ZXJ0IHRoaXMgdG8gbW9udGhseSBzaW5jZSB5b3VyIGRhdGFzZXQgaXMgbW9udGhseSkuCgpCcmluZyBwcmljZSBkYXRhIG9mIHRoZXNlIDUgdGlja2VycywgYnV0IG5vdyBmcm9tIEphbiAyMDIyIHRvIGRhdGUuIFVzaW5nIHRoZSBvcHRpbWFsIHdlaWdodHMgYW5kIHRoZXNlIG1vbnRocywgY2FsY3VsYXRlIHRoZSBob2xkaW5nLXBlcmlvZCByZXR1cm4gb2YgdGhpcyBwb3J0Zm9saW8uIFJlcG9ydCB5b3VyIHJlc3VsdHMuCgpCcmluZyBkYXRhIG9mIHRoZSBtYXJrZXQgaW5kZXggZnJvbSBKYW4gMjAyMSB0byBkYXRlLiBDYWxjdWxhdGUgdGhlIGhvbGRpbmctcGVyaW9kIHJldHVybiBvZiB0aGUgbWFya2V0LiBXaGljaCBIUFIgd2FzIGJldHRlciwgdGhlIG9uZSBmcm9tIHRoZSBtYXJrZXQgb3IgdGhlIEhQUiBvZiB5b3VyIG9wdGltYWwgcG9ydGZvbGlvPwoKCiMjIFNvbHV0aW9ucwoKTEVUUyBGSVJTVCBSRU1FTUJFUiBUSEUgQ0FQTSBGT1JNVUxBCkUoUmkpPVJmK86yaVtFKFJtKeKIklJmKV0oMSkKV0hFUkUsCkUoUmkpIGlzIHRoZSBleHBlY3RlZCByZXR1cm5uIG9mIHRoZSBhc3NldC4KUmYgaXMgdGhlIHJpc2stZnJlZSBhc3NldCwgdHlwaWNhbGx5IGEgVVMgZ292ZXJubWVudCBib25kLgrOsmkgaXMgdGhlIHNlbnNpdGl2aXR5IG9mIHRoZSBleHBlY3RlZCBleGNlc3MgYXNzZXQgcmV0dXJucyB0byB0aGUgZXhwZWN0ZWQgbWFya2V0IHJldHVybnMuCkUoUm0p4oiSUmYgaXMgdGhlIGNvbnNpZGVyZWQgdGhlIHJpc2sgcHJlbWl1bS4KCk5FWFQgV0UgV0lMTCBSRUFEWSBPVVIgRU5WSVJPTk1FTlQKTE9BRCBERVNJUkVEIFBBQ0tBR0VTCgoKYGBge3J9CmxpYnJhcnkocXVhbnRtb2QpCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpCmxpYnJhcnkoSW50cm9Db21wRmluUikKbGlicmFyeShyZWFkeGwpCmBgYAoKYGBge3J9CmlucHV0LmRmPC1yZWFkX2V4Y2VsKCJJbnB1dFRpY2tlcnMueGxzeCIsc2hlZXQgPSAidGlja2VycyIpCnRpY2tlcnMubGlzdDwtaW5wdXQuZGYkdGlja2VyCmBgYApgYGB7cn0KbmEub21pdCh0aWNrZXJzLmxpc3QpCmBgYAoKYGBge3J9CmdldFN5bWJvbHModGlja2Vycy5saXN0LAogICAgICAgICAgIGZyb20gPSAiMjAyMS0wMS0wMSIsIHRvID0gIjIwMjItMDEtMDEiLAogICAgICAgICAgIHBlcmlvZGljaXR5ID0gIm1vbnRobHkiLAogICAgICAgICAgIHNyYyA9ICJ5YWhvbyIpCmBgYAoKIyBEQVRBIE1BTkFHRU1FTlQKCgoKYGBge3J9Cm9iakxpc3QgPC0gbGFwcGx5KHRpY2tlcnMubGlzdCwgZ2V0KQpjbGFzcyhvYmpMaXN0KQpgYGAKYGBge3J9CnByaWNlcy56b28gPC0gZG8uY2FsbChtZXJnZSwgb2JqTGlzdCkKYGBgCmBgYHtyfQpwcmljZXMuZGYgPC0gYXMuZGF0YS5mcmFtZShuYS5vbWl0KEFkKHByaWNlcy56b28pKSkKYGBgCgojIE9CVEFJTklORyBSRVRVUk5TCmBgYHtyfQpyZXR1cm5zLmRmIDwtIGRpZmYobG9nKGFzLnpvbyhwcmljZXMuZGYpKSkKYGBgCmBgYHtyfQpoZWFkKHJldHVybnMuZGYpCmBgYAoKYGBge3J9CnRhaWwocmV0dXJucy5kZikKYGBgCgpgYGB7cn0Kb3B0aW9ucyhzY2lwZW49MTAwKQpvcHRpb25zKGRpZ2l0cz0yKQpgYGAKCmBgYHtyfQpyZXR1cm5zLmRmIDwtIHJldHVybnMuZGZbLC0xXQpib3hwbG90KHJldHVybnMuZGYsbWFpbj0iTW9udGhseSBDb21wb3VuZGUgUmV0dXJucyIsIHhsYWI9IlN0b2NrIFBpY2tzIiwgeWxhYj0iUmV0dXJucyIpCmBgYAojIE5FWFQgV0UgV0lMTCBDT01QVVRFIE1FQU4gQU5EIFNUQU5SQVJEIERFVklBVElPTiBPRiBDT01QT1VOREVEIFJFVFVSTlMKCmBgYHtyfQpuYS5vbWl0KG1lYW4ocmV0dXJucy5kZikpCk1lYW49c2FwcGx5KHJldHVybnMuZGYsbWVhbikKUmYgPSBtZWFuKGlucHV0LmRmJHRpY2tlcikKcGFzdGUoIk1hcmtldCBGcmVlIFJldHJ1biA9ICIsUmYqMTAwKQpgYGAKCmBgYHtyfQpTRD1zYXBwbHkocmV0dXJucy5kZixzZCkKY2JpbmQoTWVhbixTRCkKYGBgCgojIEdldHRpbmcgVGhhdCBCZXRhCmBgYHtyfQphdHRhY2goaW5wdXQuZGYpCmxtLk1NTTwtIGxtKEFDVElOVlJCLk1YIH4gV0FMTUVYLk1YKQpzdW1tYXJ5KFdBTE1FWC5NWCkKYGBgCgpgYGB7cn0KcGxvdChBQ1RJTlZSQi5NWCxXQUxNRVguTVgsIHhsaW09YygtMjAsMjApLHlsaW09YygtMjAsMjApLG1haW49IkJldGEiKQpCZXRhTU1NIDwtIHN1bW1hcnkobG0uTU1NKSRjb2VmZmljaWVudHNbMiwgMV0KYWJsaW5lKGxtLk1NTSwgY29sPSJibHVlIikKdGV4dCgtMjAsIDIwLCBCZXRhTU1NLCBwb3MgPSA0KQpgYGAKCmBgYHtyfQpSc3RkZSA8LSBzdW1tYXJ5KGxtLk1NTSkkc2lnbWEKcGFzdGUoIk1NTSBCZXRhID0gIixCZXRhTU1NKQpgYGAKYGBge3J9CnBhc3RlKCJNTU0gU3RhbmRhcmQgRGV2aWF0aW9uID0gIixSc3RkZSkKYGBgCmBgYHtyfQpjb2VmcyA8LSBjb2VmKGxtLk1NTSkKcGFzdGUoImFscGhhID0gIixjb2Vmc1sxXSkKYGBgCmBgYHtyfQpwYXN0ZSgiYmV0YSA9ICIsY29lZnNbMl0pCmBgYApgYGB7cn0KbG0uV0FMTUVYLk1YPC0gbG0oQUNUSU5WUkIuTVggfiBXQUxNRVguTVgpCnN1bW1hcnkobG0uV0FMTUVYLk1YKQpgYGAKYGBge3J9CnBsb3QoQUNUSU5WUkIuTVgsV0FMTUVYLk1YLCB4bGltPWMoLTIwLDIwKSx5bGltPWMoLTIwLDIwKSxtYWluPSJCZXRhIikKYWJsaW5lKGxtLldBTE1FWC5NWCwgY29sPSJibHVlIikKQmV0YUFDVElOVlJCIDwtIHN1bW1hcnkobG0uV0FMTUVYLk1YKSRjb2VmZmljaWVudHNbMiwgMV0KdGV4dCgtMjAsMjAsIEJldGFBQ1RJTlZSQiwgcG9zID0gNCkKYGBgCgojIFByb2dyYW1taW5nIGNvZGUgZm9yIHRoZSBmdW5jdGlvbmFsIGFsZ29yaXRobQoKYGBge3J9CiMgSSBjcmVhdGUgYW4gZW1wdHkgdmVjdG9yIApXPC1jKCkKIyBJIGRvIGEgbG9vcCBmcm9tIDEgdG8gMyB0byBjcmVhdGUgMSwwMDAgY29sdW1ucyBvZiAzIHJhbmRvbSB3ZWlnaHRzIGZvbGxvd2luZwojICAgdGhlIHVuaWZvcm0gcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uOgpmb3IoaSBpbiAxOjMpICB7CiAgVzwtcmJpbmQoVyxydW5pZigxMDAwKSkKfQojIE5vdyBJIGp1c3QgYWRkIGEgcm93IGF0IHRoZSBlbmQgd2l0aCB2YWx1ZXMgZXF1YWwgdG8gMSBtaW51cyB0aGUgc3VtIG9mIHRoZSAzCiMgICByYW5kb20gd2VpZ2h0cy4gSSBkbyB0aGlzIHRvIGZvcmNlIHRoYXQgdGhlIHN1bSBvZiBlYWNoIGNvbHVtbiBtdXN0IGJlIGVxdWFsIHRvIDEKClc8LXJiaW5kKFcsMS1jb2xTdW1zKFcpKQoKIyBUaGUgZWFjaCBjb2x1bW4gb2YgdGhpcyBtYXRyaXggcmVwcmVzZW50cyBhIHJhbmRvbSBwb3J0Zm9saW8uIFRoZSBsYXN0IHdlaWdodAojICAgaXMgdGhlIG9ubHkgb25lIHRoYXQgY2FuIGhhdmUgbmVnYXRpdmUgd2VpZ2h0CgojIEkgY2FuIGNoZWNrIHRoYXQgdGhlIHN1bSBvZiB0aGUgY29sdW1ucyBpcyBlcXVhbCB0byAxLiBTaW5jZSB0aGUgbWF0cml4IGhhcwojICBtYW55IGNvbHVtbnMsIEkganVzdCBkbyB0aGUgc3VtIGZvciA1IGNvbHVtbnM6CmNvbFN1bXMoV1ssMTo1XSkKYGBgCmBgYHtyfQojIEFsbCBzdW1zIGFyZSBlcXVhbCB0byAxLCBhcyBleHBlY3RlZApgYGAKCmBgYHtyfQojIEkgY3JlYXRlIGFuIGVtcHR5IHZlY3RvciAKVzI8LWMoKQojIEkgZG8gYSBsb29wIGZyb20gMSB0byA0IHRvIGNyZWF0ZSAxLDAwMCBjb2x1bW5zIG9mIDQgcmFuZG9tIHdlaWdodHMgZm9sbG93aW5nCiMgICB0aGUgdW5pZm9ybSBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb246CmZvcihpIGluIDE6NCkgIHsKICBXMjwtcmJpbmQoVzIscnVuaWYoMTAwMCkpCn0KIyBUaGUgcHJvYmxlbSBJIGhhdmUgbm93IGlzIHRoYXQgc29tZSBvZiB0aGUgMSwwMDAgcG9ydGZvbGlvcwojICBtaWdodCBlbmQgdXAgaGF2aW5nIGEgc3VtIG9mIHdlaWdodHMgaGlnaGVyIHRoYW4gb25lLiAjIEkgY2FuIGRvIGEgc2ltcGxlICJ0cmljayIgYnkgCiMgICBkaXZpZGluZyBlYWNoIG9mIHRoZSA0IHdlaWdodHMgYnkgdGhlIHN1bSBvZiB0aGVzZSA0CiMgICB3ZWlnaHRzLiBBbmQgSSBjYW4gZG8gdGhpcyAjIGZvciBhbGwgMTAwMCBwb3J0Zm9saW9zOiAKCiMgSSBmaXJzdCBjcmVhdGUgYSB2ZWN0b3Igd2l0aCB0aGUgc3VtIG9mIHdlaWdodHMgZm9yIGFsbCBwb3J0Zm9saW9zOgpzdW13IDwtIGNvbFN1bXMoVzIpCiMgSSBkbyBhbm90aGVyIGxvb3AgdG8gZGl2aWRlIGVhY2ggd2VpZ2h0IGJ5IHRoZSBzdW0gb2Ygd2VpZ2h0czogCmZvcihpIGluIDE6NCkgIHsKICBXMltpLF08LVcyW2ksXS9zdW13CiAgIyBJbiBlYWNoIGl0ZXJhdGlvbiBJIGRpdmlkZSBvbmUgcmF3IG9mIFcyIGJ5IHRoZSB2ZWN0b3Igc3VtdywgCiAgIyAgd2hpY2ggaXMgdGhlIHN1bSBvZiB0aGUgd2VpZ2h0cyBvZiBhbGwgMTAwMCBwb3J0Zm9saW9zCn0KCiMgSSBjaGVjayB0aGF0IHRoZSBzdW0gb2Ygd2VpZ2h0cyBpcyAxIChJIGRvIHRoaXMgZm9yIDUgcG9ydGZvbGlvcykKY29sU3VtcyhXMlssMTo1XSkKYGBgCmBgYHtyfQojIEFsbCBzdW1zIGFyZSBlcXVhbCB0byAxLCBhcyBleHBlY3RlZAoKIyBUaGVuIGVhY2ggY29sdW1uIG9mIHRoaXMgbWF0cml4IHJlcHJlc2VudHMgYSByYW5kb20gcG9ydGZvbGlvIHdpdGhvdXQgYWxsb3dpbmcgZm9yIHNob3J0IHNhbGVzLiB8CmBgYAoKYGBge3J9CiMgSSBjcmVhdGUgYSBtYXRyaXggZm9yIHRoZSBoaXN0b3JpY2FsIHJldHVybnMgb2YgdGhlIGFzc2V0czoKcmV0Lm1hdCA8LSBhcy5tYXRyaXgocmV0dXJucy5kZikKIyBJIGdlbmVyYXRlIHRoZSBleHBlY3RlZCByZXR1cm5zIG9mIHRoZSBhc3NldHMgYXMgdGhlaXIgZ2VvbWV0cmljIG1lYW5zOgpleHAucmV0czwtZXhwKGNvbE1lYW5zKHJldC5tYXQpKSAtIDEKIyBJIGdlbmVyYXRlIHRoZSB2YXJpYW5jZS1jb3ZhcmlhbmNlIG1hdHJpeDoKQ09WPC12YXIocmV0Lm1hdCkKIyBJIGVzdGltYXRlIHRoZSBleHBlY3RlZCByZXR1cm5zIG9mIGFsbCAxLDAwMCBwb3J0Zm9saW9zIHVzaW5nIG1hdHJpeCBhbGdlYnJhOgpFUlAgPC0gdChXMiklKiVleHAucmV0cwojIEkgZXN0aW1hdGUgdGhlIGV4cGVjdGVkIHZhcmlhbmNlIGFuZCByaXNrIG9mIHRoZSBwb3J0Zm9saW9zIHVzaW5nIG1hdHJpeCBhbGdlYnJhOgpWQVJQPC10KFcyKSUqJUNPViUqJVcyCiMgSSBnZXQgdGhlIGRpYWdvbmFsIG9mIHRoaXMgbWF0cml4IGFuZCB0YWtlIHNxdWFyZSByb290IHRvIGdldCB0aGUgZXhwZWN0ZWQgcmlzawojICAgb2YgdGhlIDEsMDAwIHBvcnRmb2xpb3M6ClJJU0tQPC1zcXJ0KGRpYWcoVkFSUCkpCiMgSSByZW1vdmUgdGhlIFZBUlAgb2JqZWN0IHNpbmNlIGl0IGhhcyAxLDAwMCB0aW1lcyAxLDAwMCBjZWxzISAxIG1pbGxpb24gY2VsbHMhCnJtKFZBUlApCmBgYApgYGB7cn0KcGxvdChSSVNLUCxFUlBbLDFdLCBtYWluPSJSYW5kb20gcG9ydGZvbGlvcyBvZiA0IGFzc2V0cyIseGxhYj0iVm9sYXRpbGl0eSIseWxhYj0iRXhwIFJldHVybiIpCmBgYAoK