Regression in R

Aktualisiert:

5 Minuten zum Lesen

Regression am Beispiel des Capital Asset Pricing Models.

Regression

Statistische Auswertungen drehen sich oft darum, aus den Werten der Vergangenheit ein Model zu erstellen, mit dem man den Verlauf von bestimmten Variablen in der Zukunft voraus sagen kann. Eine Möglichkeit der Modellbildung ist die Lineare Regression.

Ganz vereinfacht gesagt: Für eine gegebene Anzahl von Werten \(Y=f(X)\) möchte man dabei die Funktion \(f(X)\) herausfinden. Damit können dann zukünftige Werte auf Basis des Vergangenen berechnet werden. \(Y\) ist die – von den unabhängigen Variablen in der Funktion \(f(X)\) – abhängige Variable. Die Funktion \(f(X)\) besteht aus einer liniearen Gleichung unabhängiger Variablen. Bei der Linearen Regression wird eine Gerade durch die Punkte \([X,Y]\) gelegt. Für die Gerade gilt \(Y=\beta X + \alpha\). Dabei ist \(\alpha\) der Offset, bei dem die Gerade die Y-Achse schneidet (\(X=0\)). \(\beta\) ist die Steigung der Gerade. Da wir nur die \([X,Y]\)-Koordinaten der Punkte haben, muß man eine Möglichkeit der Bewertung der Güte der Geraden haben. Dazu gibt es mehrere Verfahren, eines davon ist, die Abstände der Punkte zur Geraden über alle Punkte zu minimieren, z.B. mit Hilfe der Methode der kleinsten Quadrate. Das alles noch theoretischer nachlesen kann man hier bei Wikipedia.

Das Capital Asset Pricing Model

In dem Kurs wurde das alles am Beispiel des Capital Asset Pricing Models berechnet. Dabei soll die zukünftige Auschüttung einer Versicherung anhand der Wertentwicklung in der Vergangenheit vorhergesagt werden. Die Formel zur Bewertung einer Versicherung ist wie folgt:

\[ R_i = R_{riskfree} + \beta_i (R_{market} - R_{riskfree}) \]

Die Ausschüttung ergibt sich aus dem risikofreien Anteil \(R_{riskfree}\) und dem risikobehafteten Anteil, der Ausschüttung des Marktes \(R_{market}\) oberhalb dem risikofreien Anteil \(R_{riskfree}\) multipliziert mit \(\beta_i\), dem Risiko der Versicherung im Vergleich zum Markt. \(\beta_i\) ist gesucht. Umgestellt nach \(\beta_i\) zeigt die Gleichung:

\[ \beta_i = \frac{(R_i - R_{riskfree})}{(R_{market} - R_{riskfree})} \]

Um Werte zu erhalten, mit denen man eine Berechnung durchspielen kann, kann man diese bei Yahoo Finance herunterladen. Als Aufgabe sollte das \(\beta\) von Google berechnet werden. Dazu werden als erstes die historischen Werte des Google Index (GOOG) für die letzten 5 Jahre in Monatsschritten heruntergeladen. Man erhält eine CSV-Datei, die man in R einlesen kann. Als Market-Werte wird der NASDAQ Composite INdex (^IXIC) verwendet. Für denselben Zeitraum werden hier die historischen Werte herunterladen. Und dann noch als risikofreie Vergleichswerte die Werte von Schatzbriefen nehmen – hier Treasury Yield 5 Years (^FVX). Diese Dateien werden eingelesen und in der Funktion preProcess vorverarbeitet. Dabei werden aus den Werten der Aktien die Ausschüttungen berechnet. Die Ausschüttung ergibt sich aus

\[ R = \frac{Neuer Preis - Alter Preis}{Alter Preis} = \frac{Neuer Preis}{Alter Preis} - 1 \]

Am Schluß werden dann die Kennwerte der Regression ausgegeben. Wenn man ein Diagramm mit den Grunddaten anlegt, kann man mit plot(Kennwerte der Regression) die Regressiongerade in das zuletzt erstellte Diagramm zeichnen lassen.

# Bewertete Versicherung: Google
googFile <- '/home/holgre/Data/Kurse/Learn By Example - Statistics and Data Science in R/12 Linear Regression in Excel/goog-100101-170101-table.csv'
# Market-Werte: Nasdaq
nasdaqFile <-'/home/holgre/Data/Kurse/Learn By Example - Statistics and Data Science in R/12 Linear Regression in Excel/ixic-100101-170101-table.csv'
## Risikofreie Schatzbriefe: TBonds
tbondsFile <-'/home/holgre/Data/Kurse/Learn By Example - Statistics and Data Science in R/12 Linear Regression in Excel/fvx-100101-170101-table.csv'
preProcess <-function(googFile,nasdaqFile,tbondsFile){
  # Es werden nur die Spalten Datum (Date) und Schlußwert (Adj.Close) verwendet
  goog <- read.table(googFile,header =TRUE, sep =",")[,c("Date","Adj.Close")]
  # Die Spalte Adj.Close mit einem eindeutigen Namen versehen
  names(goog)[2]<-"goog.price"
  # Date-Werte sind Strings -> umwandeln in Datumsformat 
  goog[,c("Date")] <-as.Date(goog[,c("Date")])
  nasdaq <- read.table(nasdaqFile,header =TRUE, sep =",")[,c("Date","Adj.Close")]
  names(nasdaq)[2]<-"nasdaq.price"
  nasdaq[,c("Date")] <-as.Date(nasdaq[,c("Date")])
  # Tabellen mergen mit dem Datum als Index
  goog <-merge(goog, nasdaq, by ="Date")
  goog[,c("Date")] <-as.Date(goog[,c("Date")])
  # Tabelle ordnen
  goog <-goog[order(goog$Date, decreasing =TRUE),]
  # Aus den Schlußwerten Returns berechnen indem zeilenweise der alte Wert vom neuen abgezogen wird 
  goog[-nrow(goog),-1] <-goog[-nrow(goog),-1]/goog[-1,-1]-1
  # Spalten neu benennen
  names(goog)[2:3]<-c("goog.returns","nasdaq.returns")
  # letzte Zeile verwerfen, da dafür der Subtrahent fehlt 
  goog <-goog[-nrow(goog),]
  # Mit den risikofreien Werten dasselbe durchführen
  tbonds <- read.table(tbondsFile,header =TRUE, sep =",")[,c("Date","Adj.Close")]
  names(tbonds)[2]<-"tbonds.returns"
  tbonds[,c("Date")] <-as.Date(tbonds[,c("Date")])
  goog <-merge(goog, tbonds, by="Date")
  # Werte in Prozent umrechnen
  goog$tbonds.returns <-goog$tbonds.returns/100
  # von beiden Spalten google und nasdaq die tbonds-Werte abziehen.
  goog[,c("goog.returns","nasdaq.returns")] <-goog[,c("goog.returns","nasdaq.returns")]-goog[,"tbonds.returns"]
  # NA-Werte: Wenn Werte fehlen, werden sie durch den Mittelwert erwetzt
  goog[,"goog.returns"][is.na(goog[,"goog.returns"])] <-mean(goog[,"goog.returns"])
  return(goog)
}
# Dateien vorbereiten
goog <-preProcess(googFile,nasdaqFile,tbondsFile)
# lm - lineares Modell für Regression berechnen 
# NA-Werte: na.omit (default), na.exclude, na.fail
googM <-lm(goog$goog.returns~goog$nasdaq.returns, na.action = na.omit)
# Ergebnisse des linearen Modells ausgeben
summary(googM)

Call:
lm(formula = goog$goog.returns ~ goog$nasdaq.returns, na.action = na.omit)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.184898 -0.039235 -0.003841  0.028819  0.194899 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)         0.003339   0.006397   0.522    0.603    
goog$nasdaq.returns 0.994451   0.148751   6.685 2.71e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.05823 on 81 degrees of freedom
Multiple R-squared:  0.3556,    Adjusted R-squared:  0.3476 
F-statistic: 44.69 on 1 and 81 DF,  p-value: 2.712e-09
plot(goog$goog.returns~goog$nasdaq.returns,xlab="Nasdaq Returns",ylab="Google Returns")
abline(googM)
# Robuste Regression, um den Einfluß der Ausreißer zu verringern
googRLM <-rlm(goog$goog.returns~goog$nasdaq.returns)
abline(googRLM, lty ='dashed',col='deepskyblue')

Regressionsanalysen, die die Methode der kleinsten Quadrate verwenden, sind nicht robust gegenüber Ausreißern. D.h. Ausreißer können das Ergebnis der Regression stark beeinflußen. Hier kann die Robuste Regression angewendet werden, bei der die Ausreißer das Ergebnis nicht so stark ins Gewicht fallen und so diese Schwäche der klassischen Verfahren umgange wird. Dies kann z.B. über die Berechnung eines M-Schätzers unter Verwendung des IWLS-Algorithmus (iterated re-weighted least squares) wie in der Funktion rlm() geschehen.

Bewertung der Daten

Wie ich finde, ist das eines der wichtigsten Themen: die Bewertung der Daten, die man zur Berechnung der Regression verwendet. Man kann ziemlich viel mit Statistik und der Darstellung von Ergebnissen und Auswertungen anstellen. Man kann Sachverhalte genauso verdeutlichen wie verschleiern oder die Interpretation und Wahrnehmung der Ergebnisse in bestimmte Richtungen lenken. Daher hier ein kurzer Blick auf eine der Möglichkeiten, mit der man die Eignung der Daten für eine Regression bewerten kann. Mit plot() kann man 4 Diagnose-Plots der Residuen der Regressionsdaten ausgeben.

plot(googM)

Damit die Daten sich für eine Regression eignen, müssen sie folgenden Annahmen genügen.

Annahme 1: Die Residuen sind normalverteilt

Um diese Annahme zu überprüfen, kann man sich den Plot Normal Q-Q anschauen, einen Quantil-Quantil-Plot. Quantilen sind Punkte, die den sortierten Datensatz in gleichfroße Gruppen einteilen. Eine Quartile teilt den Datensatz z.B. in vier gleichgroße Gruppen. Die Idee ist, das, wenn die Quantilen zweier Datensätze gleich sind, sie die gleiche Verteilung haben. Wenn sie die gleiche Verteilung haben, dann müßten die Punkte auf der Linie \(Y=X\) liegen. Der Q-Q-Plot trägt die Quantilen der Residuen unserer Daten über den Quantilen der Normalverteilung auf. Wie man sieht, liegen die Werte bis auf ein paar Ausreißer ganz gut auf der Linie \(Y=X\). Genaueres über einen Q-Q-Plot kann man hier bei Wikipedia nachlesen.

Annahme 2: Die Varianz der Residuen ändert sich nicht entlang der Regressionslinie

Zum Einschätzen dienen hier die Plots Residuals vs Fitted und Scale-Location. Im letzteren Plot sind die Residuen standartisiert. Das bedeutet, daß ihre Verteilung der Standardnormalverteilung entspricht (Mittelwert = 0, Standardabweichung = 1). Um die Annahme zu überprüfen, schaut man sich die beiden Plots an und schätzt ein, ob der Bereich, in dem die Werte liegen, konstant bleibt und in seiner Größe nicht variiert. Die beiden Plots zeigen, daß die Bereiche ungefähr konstant bleiben und sich daher die verwendeten Werte gut für die Regression eignen.

Mit Hilfe des letzten Plots Residuals vs Leverage kann man abschätzen, ob einige Punkte – wie z.B. Ausreißer – größeren Einfluß auf das Regressionsergebnis haben als andere. Näheres zu Cook’s Distance wieder hier bei Wikipedia. Liegen Datenpunkte jenseits der mit 0.5 gekennzeichneten gestrichelten Linie, dann müssen diese näher untersucht werden.

LS0tCnRpdGxlOiAiUmVncmVzc2lvbiBpbiBSIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogbm9uZQogICAgZGZfcHJpbnQ6IGthYmxlCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICB0aGVtZTogZmxhdGx5CiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICBrZWVwX21kOiB5ZXMKLS0tCgojIyBSZWdyZXNzaW9uCgpTdGF0aXN0aXNjaGUgQXVzd2VydHVuZ2VuIGRyZWhlbiBzaWNoIG9mdCBkYXJ1bSwgYXVzIGRlbiBXZXJ0ZW4gZGVyIFZlcmdhbmdlbmhlaXQgZWluIE1vZGVsIHp1IGVyc3RlbGxlbiwgbWl0IGRlbSBtYW4gZGVuIFZlcmxhdWYgdm9uIGJlc3RpbW10ZW4gVmFyaWFibGVuIGluIGRlciBadWt1bmZ0IHZvcmF1cyBzYWdlbiBrYW5uLiBFaW5lIE3DtmdsaWNoa2VpdCBkZXIgTW9kZWxsYmlsZHVuZyBpc3QgZGllIExpbmVhcmUgUmVncmVzc2lvbi4gCgpHYW56IHZlcmVpbmZhY2h0IGdlc2FndDogRsO8ciBlaW5lIGdlZ2ViZW5lIEFuemFobCB2b24gV2VydGVuICRZPWYoWCkkIG3DtmNodGUgbWFuIGRhYmVpIGRpZSBGdW5rdGlvbiAkZihYKSQgaGVyYXVzZmluZGVuLiBEYW1pdCBrw7ZubmVuIGRhbm4genVrw7xuZnRpZ2UgV2VydGUgYXVmIEJhc2lzIGRlcyBWZXJnYW5nZW5lbiBiZXJlY2huZXQgd2VyZGVuLiAkWSQgaXN0IGRpZSAtLSB2b24gZGVuIHVuYWJow6RuZ2lnZW4gVmFyaWFibGVuIGluIGRlciBGdW5rdGlvbiAkZihYKSQgLS0gYWJow6RuZ2lnZSBWYXJpYWJsZS4gRGllIEZ1bmt0aW9uICRmKFgpJCBiZXN0ZWh0IGF1cyBlaW5lciBsaW5pZWFyZW4gR2xlaWNodW5nIHVuYWJow6RuZ2lnZXIgVmFyaWFibGVuLiBCZWkgZGVyIExpbmVhcmVuIFJlZ3Jlc3Npb24gd2lyZCBlaW5lIEdlcmFkZSBkdXJjaCBkaWUgUHVua3RlICRbWCxZXSQgZ2VsZWd0LiBGw7xyIGRpZSBHZXJhZGUgZ2lsdCAkWT1cYmV0YSBYICsgXGFscGhhJC4gRGFiZWkgaXN0ICRcYWxwaGEkIGRlciBPZmZzZXQsIGJlaSBkZW0gZGllIEdlcmFkZSBkaWUgWS1BY2hzZSBzY2huZWlkZXQgKCRYPTAkKS4gJFxiZXRhJCBpc3QgZGllIFN0ZWlndW5nIGRlciBHZXJhZGUuIERhIHdpciBudXIgZGllICRbWCxZXSQtS29vcmRpbmF0ZW4gZGVyIFB1bmt0ZSBoYWJlbiwgbXXDnyBtYW4gZWluZSBNw7ZnbGljaGtlaXQgZGVyIEJld2VydHVuZyBkZXIgR8O8dGUgZGVyIEdlcmFkZW4gaGFiZW4uIERhenUgZ2lidCBlcyBtZWhyZXJlIFZlcmZhaHJlbiwgZWluZXMgZGF2b24gaXN0LCBkaWUgQWJzdMOkbmRlIGRlciBQdW5rdGUgenVyIEdlcmFkZW4gw7xiZXIgYWxsZSBQdW5rdGUgenUgbWluaW1pZXJlbiwgei5CLiBtaXQgSGlsZmUgZGVyIE1ldGhvZGUgZGVyIGtsZWluc3RlbiBRdWFkcmF0ZS4gRGFzIGFsbGVzIG5vY2ggdGhlb3JldGlzY2hlciBuYWNobGVzZW4ga2FubiBtYW4gW2hpZXIgYmVpIFdpa2lwZWRpYV0oaHR0cHM6Ly9kZS53aWtpcGVkaWEub3JnL3dpa2kvTGluZWFyZV9SZWdyZXNzaW9uI0VpbmZhY2hlX2xpbmVhcmVfUmVncmVzc2lvbil7OnRhcmdldD0iX2JsYW5rIn0uICAKCiMjIERhcyBDYXBpdGFsIEFzc2V0IFByaWNpbmcgTW9kZWwKCkluIGRlbSBLdXJzIHd1cmRlIGRhcyBhbGxlcyBhbSBCZWlzcGllbCBkZXMgQ2FwaXRhbCBBc3NldCBQcmljaW5nIE1vZGVscyBiZXJlY2huZXQuIERhYmVpIHNvbGwgZGllIHp1a8O8bmZ0aWdlIEF1c2Now7x0dHVuZyBlaW5lciBWZXJzaWNoZXJ1bmcgYW5oYW5kIGRlciBXZXJ0ZW50d2lja2x1bmcgaW4gZGVyIFZlcmdhbmdlbmhlaXQgdm9yaGVyZ2VzYWd0IHdlcmRlbi4gRGllIEZvcm1lbCB6dXIgQmV3ZXJ0dW5nIGVpbmVyIFZlcnNpY2hlcnVuZyBpc3Qgd2llIGZvbGd0OgoKJCQKUl9pID0gUl97cmlza2ZyZWV9ICsgXGJldGFfaSAoUl97bWFya2V0fSAtIFJfe3Jpc2tmcmVlfSkKJCQKCkRpZSBBdXNzY2jDvHR0dW5nIGVyZ2lidCBzaWNoIGF1cyBkZW0gcmlzaWtvZnJlaWVuIEFudGVpbCAkUl97cmlza2ZyZWV9JCB1bmQgZGVtIHJpc2lrb2JlaGFmdGV0ZW4gQW50ZWlsLCBkZXIgQXVzc2Now7x0dHVuZyBkZXMgTWFya3RlcyAkUl97bWFya2V0fSQgb2JlcmhhbGIgZGVtIHJpc2lrb2ZyZWllbiBBbnRlaWwgJFJfe3Jpc2tmcmVlfSQgbXVsdGlwbGl6aWVydCBtaXQgJFxiZXRhX2kkLCBkZW0gUmlzaWtvIGRlciBWZXJzaWNoZXJ1bmcgaW0gVmVyZ2xlaWNoIHp1bSBNYXJrdC4gJFxiZXRhX2kkIGlzdCBnZXN1Y2h0LiBVbWdlc3RlbGx0IG5hY2ggJFxiZXRhX2kkIHplaWd0IGRpZSBHbGVpY2h1bmc6CgokJApcYmV0YV9pID0gXGZyYWN7KFJfaSAtIFJfe3Jpc2tmcmVlfSl9eyhSX3ttYXJrZXR9IC0gUl97cmlza2ZyZWV9KX0KJCQKClVtIFdlcnRlIHp1IGVyaGFsdGVuLCBtaXQgZGVuZW4gbWFuIGVpbmUgQmVyZWNobnVuZyBkdXJjaHNwaWVsZW4ga2Fubiwga2FubiBtYW4gZGllc2UgYmVpIFlhaG9vIEZpbmFuY2UgaGVydW50ZXJsYWRlbi4gQWxzIEF1ZmdhYmUgc29sbHRlIGRhcyAkXGJldGEkIHZvbiBHb29nbGUgYmVyZWNobmV0IHdlcmRlbi4gRGF6dSB3ZXJkZW4gYWxzIGVyc3RlcyBkaWUgaGlzdG9yaXNjaGVuIFdlcnRlIGRlcyBHb29nbGUgSW5kZXggKEdPT0cpIGbDvHIgZGllIGxldHp0ZW4gNSBKYWhyZSBpbiBNb25hdHNzY2hyaXR0ZW4gaGVydW50ZXJnZWxhZGVuLiBNYW4gZXJow6RsdCBlaW5lIENTVi1EYXRlaSwgZGllIG1hbiBpbiBSIGVpbmxlc2VuIGthbm4uIEFscyBNYXJrZXQtV2VydGUgd2lyZCBkZXIgTkFTREFRIENvbXBvc2l0ZSBJTmRleCAoXklYSUMpIHZlcndlbmRldC4gRsO8ciBkZW5zZWxiZW4gWmVpdHJhdW0gd2VyZGVuIGhpZXIgZGllIGhpc3RvcmlzY2hlbiBXZXJ0ZSBoZXJ1bnRlcmxhZGVuLiBVbmQgZGFubiBub2NoIGFscyByaXNpa29mcmVpZSBWZXJnbGVpY2hzd2VydGUgZGllIFdlcnRlIHZvbiBTY2hhdHpicmllZmVuIG5laG1lbiAtLSBoaWVyIFRyZWFzdXJ5IFlpZWxkIDUgWWVhcnMgKF5GVlgpLiBEaWVzZSBEYXRlaWVuIHdlcmRlbiBlaW5nZWxlc2VuIHVuZCBpbiBkZXIgRnVua3Rpb24gKnByZVByb2Nlc3MqIHZvcnZlcmFyYmVpdGV0LiBEYWJlaSB3ZXJkZW4gYXVzIGRlbiBXZXJ0ZW4gZGVyIEFrdGllbiBkaWUgQXVzc2Now7x0dHVuZ2VuIGJlcmVjaG5ldC4gRGllIEF1c3NjaMO8dHR1bmcgZXJnaWJ0IHNpY2ggYXVzIAoKJCQKUiA9IFxmcmFje05ldWVyIFByZWlzIC0gQWx0ZXIgUHJlaXN9e0FsdGVyIFByZWlzfSA9IFxmcmFje05ldWVyIFByZWlzfXtBbHRlciBQcmVpc30gLSAxCiQkCgpBbSBTY2hsdcOfIHdlcmRlbiBkYW5uIGRpZSBLZW5ud2VydGUgZGVyIFJlZ3Jlc3Npb24gYXVzZ2VnZWJlbi4gV2VubiBtYW4gZWluIERpYWdyYW1tIG1pdCBkZW4gR3J1bmRkYXRlbiBhbmxlZ3QsIGthbm4gbWFuIG1pdCAqcGxvdChLZW5ud2VydGUgZGVyIFJlZ3Jlc3Npb24pKiBkaWUgUmVncmVzc2lvbmdlcmFkZSBpbiBkYXMgenVsZXR6dCBlcnN0ZWxsdGUgRGlhZ3JhbW0gemVpY2huZW4gbGFzc2VuLiAKCmBgYHtyfQojIEJld2VydGV0ZSBWZXJzaWNoZXJ1bmc6IEdvb2dsZQpnb29nRmlsZSA8LSAnL2hvbWUvaG9sZ3JlL0RhdGEvS3Vyc2UvTGVhcm4gQnkgRXhhbXBsZSAtIFN0YXRpc3RpY3MgYW5kIERhdGEgU2NpZW5jZSBpbiBSLzEyIExpbmVhciBSZWdyZXNzaW9uIGluIEV4Y2VsL2dvb2ctMTAwMTAxLTE3MDEwMS10YWJsZS5jc3YnCiMgTWFya2V0LVdlcnRlOiBOYXNkYXEKbmFzZGFxRmlsZSA8LScvaG9tZS9ob2xncmUvRGF0YS9LdXJzZS9MZWFybiBCeSBFeGFtcGxlIC0gU3RhdGlzdGljcyBhbmQgRGF0YSBTY2llbmNlIGluIFIvMTIgTGluZWFyIFJlZ3Jlc3Npb24gaW4gRXhjZWwvaXhpYy0xMDAxMDEtMTcwMTAxLXRhYmxlLmNzdicKIyMgUmlzaWtvZnJlaWUgU2NoYXR6YnJpZWZlOiBUQm9uZHMKdGJvbmRzRmlsZSA8LScvaG9tZS9ob2xncmUvRGF0YS9LdXJzZS9MZWFybiBCeSBFeGFtcGxlIC0gU3RhdGlzdGljcyBhbmQgRGF0YSBTY2llbmNlIGluIFIvMTIgTGluZWFyIFJlZ3Jlc3Npb24gaW4gRXhjZWwvZnZ4LTEwMDEwMS0xNzAxMDEtdGFibGUuY3N2JwoKcHJlUHJvY2VzcyA8LWZ1bmN0aW9uKGdvb2dGaWxlLG5hc2RhcUZpbGUsdGJvbmRzRmlsZSl7CiAgIyBFcyB3ZXJkZW4gbnVyIGRpZSBTcGFsdGVuIERhdHVtIChEYXRlKSB1bmQgU2NobHXDn3dlcnQgKEFkai5DbG9zZSkgdmVyd2VuZGV0CiAgZ29vZyA8LSByZWFkLnRhYmxlKGdvb2dGaWxlLGhlYWRlciA9VFJVRSwgc2VwID0iLCIpWyxjKCJEYXRlIiwiQWRqLkNsb3NlIildCiAgIyBEaWUgU3BhbHRlIEFkai5DbG9zZSBtaXQgZWluZW0gZWluZGV1dGlnZW4gTmFtZW4gdmVyc2VoZW4KICBuYW1lcyhnb29nKVsyXTwtImdvb2cucHJpY2UiCiAgIyBEYXRlLVdlcnRlIHNpbmQgU3RyaW5ncyAtPiB1bXdhbmRlbG4gaW4gRGF0dW1zZm9ybWF0IAogIGdvb2dbLGMoIkRhdGUiKV0gPC1hcy5EYXRlKGdvb2dbLGMoIkRhdGUiKV0pCiAgbmFzZGFxIDwtIHJlYWQudGFibGUobmFzZGFxRmlsZSxoZWFkZXIgPVRSVUUsIHNlcCA9IiwiKVssYygiRGF0ZSIsIkFkai5DbG9zZSIpXQogIG5hbWVzKG5hc2RhcSlbMl08LSJuYXNkYXEucHJpY2UiCiAgbmFzZGFxWyxjKCJEYXRlIildIDwtYXMuRGF0ZShuYXNkYXFbLGMoIkRhdGUiKV0pCiAgIyBUYWJlbGxlbiBtZXJnZW4gbWl0IGRlbSBEYXR1bSBhbHMgSW5kZXgKICBnb29nIDwtbWVyZ2UoZ29vZywgbmFzZGFxLCBieSA9IkRhdGUiKQogIGdvb2dbLGMoIkRhdGUiKV0gPC1hcy5EYXRlKGdvb2dbLGMoIkRhdGUiKV0pCiAgIyBUYWJlbGxlIG9yZG5lbgogIGdvb2cgPC1nb29nW29yZGVyKGdvb2ckRGF0ZSwgZGVjcmVhc2luZyA9VFJVRSksXQogICMgQXVzIGRlbiBTY2hsdcOfd2VydGVuIFJldHVybnMgYmVyZWNobmVuIGluZGVtIHplaWxlbndlaXNlIGRlciBhbHRlIFdlcnQgdm9tIG5ldWVuIGFiZ2V6b2dlbiB3aXJkIAogIGdvb2dbLW5yb3coZ29vZyksLTFdIDwtZ29vZ1stbnJvdyhnb29nKSwtMV0vZ29vZ1stMSwtMV0tMQogICMgU3BhbHRlbiBuZXUgYmVuZW5uZW4KICBuYW1lcyhnb29nKVsyOjNdPC1jKCJnb29nLnJldHVybnMiLCJuYXNkYXEucmV0dXJucyIpCiAgIyBsZXR6dGUgWmVpbGUgdmVyd2VyZmVuLCBkYSBkYWbDvHIgZGVyIFN1YnRyYWhlbnQgZmVobHQgCiAgZ29vZyA8LWdvb2dbLW5yb3coZ29vZyksXQogICMgTWl0IGRlbiByaXNpa29mcmVpZW4gV2VydGVuIGRhc3NlbGJlIGR1cmNoZsO8aHJlbgogIHRib25kcyA8LSByZWFkLnRhYmxlKHRib25kc0ZpbGUsaGVhZGVyID1UUlVFLCBzZXAgPSIsIilbLGMoIkRhdGUiLCJBZGouQ2xvc2UiKV0KICBuYW1lcyh0Ym9uZHMpWzJdPC0idGJvbmRzLnJldHVybnMiCiAgdGJvbmRzWyxjKCJEYXRlIildIDwtYXMuRGF0ZSh0Ym9uZHNbLGMoIkRhdGUiKV0pCiAgZ29vZyA8LW1lcmdlKGdvb2csIHRib25kcywgYnk9IkRhdGUiKQogICMgV2VydGUgaW4gUHJvemVudCB1bXJlY2huZW4KICBnb29nJHRib25kcy5yZXR1cm5zIDwtZ29vZyR0Ym9uZHMucmV0dXJucy8xMDAKICAjIHZvbiBiZWlkZW4gU3BhbHRlbiBnb29nbGUgdW5kIG5hc2RhcSBkaWUgdGJvbmRzLVdlcnRlIGFiemllaGVuLgogIGdvb2dbLGMoImdvb2cucmV0dXJucyIsIm5hc2RhcS5yZXR1cm5zIildIDwtZ29vZ1ssYygiZ29vZy5yZXR1cm5zIiwibmFzZGFxLnJldHVybnMiKV0tZ29vZ1ssInRib25kcy5yZXR1cm5zIl0KICAjIE5BLVdlcnRlOiBXZW5uIFdlcnRlIGZlaGxlbiwgd2VyZGVuIHNpZSBkdXJjaCBkZW4gTWl0dGVsd2VydCBlcndldHp0CiAgZ29vZ1ssImdvb2cucmV0dXJucyJdW2lzLm5hKGdvb2dbLCJnb29nLnJldHVybnMiXSldIDwtbWVhbihnb29nWywiZ29vZy5yZXR1cm5zIl0pCiAgcmV0dXJuKGdvb2cpCn0KIyBEYXRlaWVuIHZvcmJlcmVpdGVuCmdvb2cgPC1wcmVQcm9jZXNzKGdvb2dGaWxlLG5hc2RhcUZpbGUsdGJvbmRzRmlsZSkKIyBsbSAtIGxpbmVhcmVzIE1vZGVsbCBmw7xyIFJlZ3Jlc3Npb24gYmVyZWNobmVuIAojIE5BLVdlcnRlOiBuYS5vbWl0IChkZWZhdWx0KSwgbmEuZXhjbHVkZSwgbmEuZmFpbApnb29nTSA8LWxtKGdvb2ckZ29vZy5yZXR1cm5zfmdvb2ckbmFzZGFxLnJldHVybnMsIG5hLmFjdGlvbiA9IG5hLm9taXQpCiMgRXJnZWJuaXNzZSBkZXMgbGluZWFyZW4gTW9kZWxscyBhdXNnZWJlbgpzdW1tYXJ5KGdvb2dNKQpwbG90KGdvb2ckZ29vZy5yZXR1cm5zfmdvb2ckbmFzZGFxLnJldHVybnMseGxhYj0iTmFzZGFxIFJldHVybnMiLHlsYWI9Ikdvb2dsZSBSZXR1cm5zIikKYWJsaW5lKGdvb2dNKQojIFJvYnVzdGUgUmVncmVzc2lvbiwgdW0gZGVuIEVpbmZsdcOfIGRlciBBdXNyZWnDn2VyIHp1IHZlcnJpbmdlcm4KZ29vZ1JMTSA8LXJsbShnb29nJGdvb2cucmV0dXJuc35nb29nJG5hc2RhcS5yZXR1cm5zKQphYmxpbmUoZ29vZ1JMTSwgbHR5ID0nZGFzaGVkJyxjb2w9J2RlZXBza3libHVlJykKYGBgCgpSZWdyZXNzaW9uc2FuYWx5c2VuLCBkaWUgZGllIE1ldGhvZGUgZGVyIGtsZWluc3RlbiBRdWFkcmF0ZSB2ZXJ3ZW5kZW4sIHNpbmQgbmljaHQgcm9idXN0IGdlZ2Vuw7xiZXIgQXVzcmVpw59lcm4uIEQuaC4gQXVzcmVpw59lciBrw7ZubmVuIGRhcyBFcmdlYm5pcyBkZXIgUmVncmVzc2lvbiBzdGFyayBiZWVpbmZsdcOfZW4uIEhpZXIga2FubiBkaWUgUm9idXN0ZSBSZWdyZXNzaW9uIGFuZ2V3ZW5kZXQgd2VyZGVuLCBiZWkgZGVyIGRpZSBBdXNyZWnDn2VyIGRhcyBFcmdlYm5pcyBuaWNodCBzbyBzdGFyayBpbnMgR2V3aWNodCBmYWxsZW4gdW5kIHNvIGRpZXNlIFNjaHfDpGNoZSBkZXIga2xhc3Npc2NoZW4gVmVyZmFocmVuIHVtZ2FuZ2Ugd2lyZC4gRGllcyBrYW5uIHouQi4gw7xiZXIgZGllIEJlcmVjaG51bmcgZWluZXMgTS1TY2jDpHR6ZXJzIHVudGVyIFZlcndlbmR1bmcgZGVzIElXTFMtQWxnb3JpdGhtdXMgKGl0ZXJhdGVkIHJlLXdlaWdodGVkIGxlYXN0IHNxdWFyZXMpIHdpZSBpbiBkZXIgRnVua3Rpb24gcmxtKCkgZ2VzY2hlaGVuLgoKIyMgQmV3ZXJ0dW5nIGRlciBEYXRlbgoKV2llIGljaCBmaW5kZSwgaXN0IGRhcyBlaW5lcyBkZXIgd2ljaHRpZ3N0ZW4gVGhlbWVuOiBkaWUgQmV3ZXJ0dW5nIGRlciBEYXRlbiwgZGllIG1hbiB6dXIgQmVyZWNobnVuZyBkZXIgUmVncmVzc2lvbiB2ZXJ3ZW5kZXQuIE1hbiBrYW5uIHppZW1saWNoIHZpZWwgbWl0IFN0YXRpc3RpayB1bmQgZGVyIERhcnN0ZWxsdW5nIHZvbiBFcmdlYm5pc3NlbiB1bmQgQXVzd2VydHVuZ2VuIGFuc3RlbGxlbi4gTWFuIGthbm4gU2FjaHZlcmhhbHRlIGdlbmF1c28gdmVyZGV1dGxpY2hlbiB3aWUgdmVyc2NobGVpZXJuIG9kZXIgZGllIEludGVycHJldGF0aW9uIHVuZCBXYWhybmVobXVuZyBkZXIgRXJnZWJuaXNzZSBpbiBiZXN0aW1tdGUgUmljaHR1bmdlbiBsZW5rZW4uIERhaGVyIGhpZXIgZWluIGt1cnplciBCbGljayBhdWYgZWluZSBkZXIgTcO2Z2xpY2hrZWl0ZW4sIG1pdCBkZXIgbWFuIGRpZSBFaWdudW5nIGRlciBEYXRlbiBmw7xyIGVpbmUgUmVncmVzc2lvbiBiZXdlcnRlbiBrYW5uLgpNaXQgYHBsb3QoKWAga2FubiBtYW4gNCBEaWFnbm9zZS1QbG90cyBkZXIgUmVzaWR1ZW4gZGVyIFJlZ3Jlc3Npb25zZGF0ZW4gYXVzZ2ViZW4uCgpgYGB7cn0KcGxvdChnb29nTSkKYGBgCgpEYW1pdCBkaWUgRGF0ZW4gc2ljaCBmw7xyIGVpbmUgUmVncmVzc2lvbiBlaWduZW4sIG3DvHNzZW4gc2llIGZvbGdlbmRlbiBBbm5haG1lbiBnZW7DvGdlbi4KCiMjIyBBbm5haG1lIDE6IERpZSBSZXNpZHVlbiBzaW5kIG5vcm1hbHZlcnRlaWx0CgpVbSBkaWVzZSBBbm5haG1lIHp1IMO8YmVycHLDvGZlbiwga2FubiBtYW4gc2ljaCBkZW4gUGxvdCBfTm9ybWFsIFEtUV8gYW5zY2hhdWVuLCBlaW5lbiBRdWFudGlsLVF1YW50aWwtUGxvdC4gUXVhbnRpbGVuIHNpbmQgUHVua3RlLCBkaWUgZGVuIHNvcnRpZXJ0ZW4gRGF0ZW5zYXR6IGluIGdsZWljaGZyb8OfZSBHcnVwcGVuIGVpbnRlaWxlbi4gRWluZSBRdWFydGlsZSB0ZWlsdCBkZW4gRGF0ZW5zYXR6IHouQi4gaW4gdmllciBnbGVpY2hncm/Dn2UgR3J1cHBlbi4gRGllIElkZWUgaXN0LCBkYXMsIHdlbm4gZGllIFF1YW50aWxlbiB6d2VpZXIgRGF0ZW5zw6R0emUgZ2xlaWNoIHNpbmQsIHNpZSBkaWUgZ2xlaWNoZSBWZXJ0ZWlsdW5nIGhhYmVuLiBXZW5uIHNpZSBkaWUgZ2xlaWNoZSBWZXJ0ZWlsdW5nIGhhYmVuLCBkYW5uIG3DvMOfdGVuIGRpZSBQdW5rdGUgYXVmIGRlciBMaW5pZSAkWT1YJCBsaWVnZW4uIERlciBRLVEtUGxvdCB0csOkZ3QgZGllIFF1YW50aWxlbiBkZXIgUmVzaWR1ZW4gdW5zZXJlciBEYXRlbiDDvGJlciBkZW4gUXVhbnRpbGVuIGRlciBOb3JtYWx2ZXJ0ZWlsdW5nIGF1Zi4gV2llIG1hbiBzaWVodCwgbGllZ2VuIGRpZSBXZXJ0ZSBiaXMgYXVmIGVpbiBwYWFyIEF1c3JlacOfZXIgZ2FueiBndXQgYXVmIGRlciBMaW5pZSAkWT1YJC4gR2VuYXVlcmVzIMO8YmVyIGVpbmVuIFEtUS1QbG90IGthbm4gbWFuIFtoaWVyIGJlaSBXaWtpcGVkaWFdKGh0dHBzOi8vZGUud2lraXBlZGlhLm9yZy93aWtpL1F1YW50aWwtUXVhbnRpbC1EaWFncmFtbSl7OnRhcmdldD0iX2JsYW5rIn0gbmFjaGxlc2VuLiAKCiMjIyBBbm5haG1lIDI6IERpZSBWYXJpYW56IGRlciBSZXNpZHVlbiDDpG5kZXJ0IHNpY2ggbmljaHQgZW50bGFuZyBkZXIgUmVncmVzc2lvbnNsaW5pZQoKWnVtIEVpbnNjaMOkdHplbiBkaWVuZW4gaGllciBkaWUgUGxvdHMgX1Jlc2lkdWFscyB2cyBGaXR0ZWRfIHVuZCBfU2NhbGUtTG9jYXRpb25fLiBJbSBsZXR6dGVyZW4gUGxvdCBzaW5kIGRpZSBSZXNpZHVlbiBzdGFuZGFydGlzaWVydC4gRGFzIGJlZGV1dGV0LCBkYcOfIGlocmUgVmVydGVpbHVuZyBkZXIgU3RhbmRhcmRub3JtYWx2ZXJ0ZWlsdW5nIGVudHNwcmljaHQgKE1pdHRlbHdlcnQgPSAwLCBTdGFuZGFyZGFid2VpY2h1bmcgPSAxKS4gVW0gZGllIEFubmFobWUgenUgw7xiZXJwcsO8ZmVuLCBzY2hhdXQgbWFuIHNpY2ggZGllIGJlaWRlbiBQbG90cyBhbiB1bmQgc2Now6R0enQgZWluLCBvYiBkZXIgQmVyZWljaCwgaW4gZGVtIGRpZSBXZXJ0ZSBsaWVnZW4sIGtvbnN0YW50IGJsZWlidCB1bmQgaW4gc2VpbmVyIEdyw7bDn2UgbmljaHQgdmFyaWllcnQuIERpZSBiZWlkZW4gUGxvdHMgemVpZ2VuLCBkYcOfIGRpZSBCZXJlaWNoZSB1bmdlZsOkaHIga29uc3RhbnQgYmxlaWJlbiB1bmQgc2ljaCBkYWhlciBkaWUgdmVyd2VuZGV0ZW4gV2VydGUgZ3V0IGbDvHIgZGllIFJlZ3Jlc3Npb24gZWlnbmVuLgoKTWl0IEhpbGZlIGRlcyBsZXR6dGVuIFBsb3RzIF9SZXNpZHVhbHMgdnMgTGV2ZXJhZ2VfIGthbm4gbWFuIGFic2Now6R0emVuLCBvYiBlaW5pZ2UgUHVua3RlIC0tIHdpZSB6LkIuIEF1c3JlacOfZXIgLS0gZ3LDtsOfZXJlbiBFaW5mbHXDnyBhdWYgZGFzIFJlZ3Jlc3Npb25zZXJnZWJuaXMgaGFiZW4gYWxzIGFuZGVyZS4gTsOkaGVyZXMgenUgQ29vaydzIERpc3RhbmNlIHdpZWRlciBbaGllciBiZWkgV2lraXBlZGlhXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db29rJTI3c19kaXN0YW5jZSl7OnRhcmdldD0iX2JsYW5rIn0uIExpZWdlbiBEYXRlbnB1bmt0ZSBqZW5zZWl0cyBkZXIgbWl0IDAuNSBnZWtlbm56ZWljaG5ldGVuIGdlc3RyaWNoZWx0ZW4gTGluaWUsIGRhbm4gbcO8c3NlbiBkaWVzZSBuw6RoZXIgdW50ZXJzdWNodCB3ZXJkZW4uICAKCgoK