Integrantes:

Regina Enríquez Chapa A01721435

Maximiliano Carvajal A01552179

Guillermo Cazares Cruz A01283709

Análisis Financiero de Empresa: Crear base de datos y serie de tiempo, modelo ARIMA y pronóstico (30 puntos, 10 c/u)

Cargar librerías y verificar que se cuenta con la información de Apple

#install.packages("finreportr")
#install.packages("tidyverse")
#install.packages("forecast")

library(finreportr)
library(tidyverse)
options(HTTPUserAgent = "a a@gmail.com")
CompanyInfo("AAPL")
##      company        CIK  SIC state state.inc FY.end     street.address
## 1 Apple Inc. 0000320193 3571    CA        CA   0928 ONE APPLE PARK WAY
##           city.state
## 1 CUPERTINO CA 95014

Cargar información en varias bases de datos

Se planea analizar los operating costs y net revenue de la empresa, ambas provienen de GetIncome.

options(HTTPUserAgent = "a a@gmail.com")
Apple11_income <- GetIncome("AAPL",2011)
A13_income <- GetIncome("AAPL",2013)
Apple14_income <- GetIncome("AAPL",2014)
A15_income <- GetIncome("AAPL",2015)
A16_income <- GetIncome("AAPL",2016)
Apple17_income <- GetIncome("AAPL",2017)
#options(HTTPUserAgent = "a a@gmail.com")
#Apple11_balance <- GetBalanceSheet("AAPL",2011)
#Apple11_cash <- GetCashFlow("AAPL",2011) 
#Apple14_balance <- GetBalanceSheet("AAPL",2014)
#Apple14_cash <- GetCashFlow("AAPL",2014) 
#Apple17_balance <- GetBalanceSheet("AAPL",2017)
#Apple17_cash<- GetCashFlow("AAPL",2017) 

El proceso consiste en: seleccionar una variable, cortarla de cada tabla, juntarlas para obtener todas las fechas, armar la time series, y hacer la predicción.

Operating expenses

Aislar operating expenses en cada tabla requerida

Apple_OpExp_11 <- select(Apple11_income,Metric,Amount,endDate)
Apple_OpExp_11 <- subset(Apple_OpExp_11, Metric == "Total operating expenses")

Apple_OpExp_14 <- select(Apple14_income,Metric,Amount,endDate)
Apple_OpExp_14 <- subset(Apple_OpExp_14, Metric == "Operating Expenses")

Apple_OpExp_17 <- select(Apple17_income,Metric,Amount,endDate)
Apple_OpExp_17 <- subset(Apple_OpExp_17, Metric == "Operating Expenses")

Juntar todas las tablas, y ordenarlas por la fecha fin

Apple_OpExp_complete <- rbind(Apple_OpExp_11,Apple_OpExp_14,Apple_OpExp_17)
Apple_OpExp_complete <- Apple_OpExp_complete[order(Apple_OpExp_complete$endDate),]

Cambiar amount de character a numeric

Apple_OpExp_complete$Amount <- as.numeric(Apple_OpExp_complete$Amount)

Armar la serie de tiempo

library(forecast)
ts_OpExp <- ts(data=Apple_OpExp_complete$Amount, start = c(2009,1), frequency = 1)
ts_OpExp
## Time Series:
## Start = 2009 
## End = 2017 
## Frequency = 1 
## [1] 5.4820e+09 7.2990e+09 1.0028e+10 1.3421e+10 1.5305e+10 1.8034e+10 2.2396e+10
## [8] 2.4239e+10 2.6842e+10

Armar el modelo ARIMA

arima_OpExp <- auto.arima(ts_OpExp)
arima_OpExp
## Series: ts_OpExp 
## ARIMA(0,1,0) with drift 
## 
## Coefficients:
##            drift
##       2670000000
## s.e.   296005922
## 
## sigma^2 = 7.752e+17:  log likelihood = -175.58
## AIC=355.17   AICc=357.57   BIC=355.33
summary(arima_OpExp)
## Series: ts_OpExp 
## ARIMA(0,1,0) with drift 
## 
## Coefficients:
##            drift
##       2670000000
## s.e.   296005922
## 
## sigma^2 = 7.752e+17:  log likelihood = -175.58
## AIC=355.17   AICc=357.57   BIC=355.33
## 
## Training set error measures:
##                    ME      RMSE       MAE        MPE     MAPE      MASE
## Training set 312444.3 776486811 563201333 -0.7305296 3.821376 0.2109368
##                    ACF1
## Training set -0.3443892

Generar pronósticos, 6 años en el futuro

pronostico_2 <- forecast(arima_OpExp, level=c(95), h=6)
pronostico_2
##      Point Forecast       Lo 95       Hi 95
## 2018     2.9512e+10 27786343272 31237656728
## 2019     3.2182e+10 29741552851 34622447149
## 2020     3.4852e+10 31863074870 37840925130
## 2021     3.7522e+10 34070686543 40973313457
## 2022     4.0192e+10 36333314250 44050685750
## 2023     4.2862e+10 38635021544 47088978456
plot(pronostico_2)

Los pronósticos muestran un crecimiento constante durante los siguiente 6 años. En la gráfica se aprecia que las predicciones siguen de manera perfecta la dirección en la que ya se dirigían los datos históricos.

Estas fueron las predicciones:

2018 - 2.9512e+10, 2019 - 3.2182e+10, 2020 - 3.4852e+10

2021 - 3.7522e+10, 2022 - 4.0192e+10, 2023 - 4.2862e+10

Pruebas, para las variables que vienen por trimestre

Cada base solo trae completo los datos de un año anterior al que seleccionaste en la función GetIncome, las otras dos vienen incompletas.

Bingus <- Apple11_income[,-2]
Bingus <- subset(Bingus, Metric == "Revenue, Net")
Bingus <- Bingus[order(Bingus$endDate),]
Bingus_2 <- Apple14_income[,-2]
Bingus_2 <- subset(Bingus_2, Metric == "Revenue, Net")
Bingus_2 <- Bingus_2[order(Bingus_2$endDate),]
Bingus_3 <- Apple17_income[,-2]
Bingus_3 <- subset(Bingus_3, Metric == "Revenue, Net")
Bingus_3 <- Bingus_3[order(Bingus_3$endDate),]

Después de probar, vi que por trimestre solo viene la info completa del año anterior al seleccionado en getincome(), mientras que los otros dos vienen incompletos

Por lo tanto, ocupo 2017 (2017-2015), 2016 (2015-2014), 2015(2014-2013), 2014(2013-2012), 2013(2012) Si quiero calcular desde 2012 a 2017 por trimestre

Revenue, Net

Aislar “Revenue, Net” en cada base, además de cortar todas las filas que no nos servirán o que estén repetidas entre bases.

RevNet_17 <- subset(Apple17_income, Metric == "Revenue, Net")
RevNet_17 <- RevNet_17[order(RevNet_17$endDate,RevNet_17$startDate),]
RevNet_17 <- RevNet_17[-c(1,5,10),]
RevNet_16 <- subset(A16_income, Metric == "Revenue, Net")
RevNet_16 <- RevNet_16[order(RevNet_16$endDate,RevNet_16$startDate),]
RevNet_16 <- RevNet_16[c(2:4,6),]
RevNet_15 <- subset(A15_income, Metric == "Revenue, Net")
RevNet_15 <- RevNet_15[order(RevNet_15$endDate,RevNet_15$startDate),]
RevNet_15 <- RevNet_15[c(2:4,6),]
RevNet_14 <- subset(Apple14_income, Metric == "Revenue, Net")
RevNet_14 <- RevNet_14[order(RevNet_14$endDate,RevNet_14$startDate),]
RevNet_14 <- RevNet_14[c(2:4,6),]
RevNet_13 <- subset(A13_income, Metric == "Sales Revenue Net")
RevNet_13 <- RevNet_13[order(RevNet_13$endDate,RevNet_13$startDate),]
RevNet_13 <- RevNet_13[c(3,4,6),]

Juntar todas las bases y ordernar por fecha fin.

RevNet_complete <- rbind(RevNet_13,RevNet_14,RevNet_15,RevNet_16,RevNet_17)
RevNet_complete <- RevNet_complete[order(RevNet_complete$endDate),]

Cambiar amount de character a numeric

str(RevNet_complete)
## 'data.frame':    23 obs. of  5 variables:
##  $ Metric   : chr  "Sales Revenue Net" "Sales Revenue Net" "Sales Revenue Net" "Revenue, Net" ...
##  $ Units    : chr  "iso4217_USD" "iso4217_USD" "iso4217_USD" "iso4217_USD" ...
##  $ Amount   : chr  "39186000000" "35023000000" "35966000000" "54512000000" ...
##  $ startDate: chr  "2012-01-01" "2012-04-01" "2012-07-01" "2012-09-30" ...
##  $ endDate  : chr  "2012-03-31" "2012-06-30" "2012-09-29" "2012-12-29" ...
RevNet_complete$Amount <- as.numeric(RevNet_complete$Amount)
str(RevNet_complete)
## 'data.frame':    23 obs. of  5 variables:
##  $ Metric   : chr  "Sales Revenue Net" "Sales Revenue Net" "Sales Revenue Net" "Revenue, Net" ...
##  $ Units    : chr  "iso4217_USD" "iso4217_USD" "iso4217_USD" "iso4217_USD" ...
##  $ Amount   : num  3.92e+10 3.50e+10 3.60e+10 5.45e+10 4.36e+10 ...
##  $ startDate: chr  "2012-01-01" "2012-04-01" "2012-07-01" "2012-09-30" ...
##  $ endDate  : chr  "2012-03-31" "2012-06-30" "2012-09-29" "2012-12-29" ...

Armar Serie de tiempo

library(forecast)
ts_RevNet <- ts(data=RevNet_complete$Amount, start = c(2012,1), frequency = 4)
ts_RevNet
##            Qtr1       Qtr2       Qtr3       Qtr4
## 2012 3.9186e+10 3.5023e+10 3.5966e+10 5.4512e+10
## 2013 4.3603e+10 3.5323e+10 3.7472e+10 5.7594e+10
## 2014 4.5646e+10 3.7432e+10 4.2123e+10 7.4599e+10
## 2015 5.8010e+10 4.9605e+10 5.1501e+10 7.5872e+10
## 2016 5.0557e+10 4.2358e+10 4.6852e+10 7.8351e+10
## 2017 5.2896e+10 4.5408e+10 5.2579e+10

Armar modelo Arima

arima_RevNet <- auto.arima(ts_RevNet)
arima_RevNet
## Series: ts_RevNet 
## ARIMA(0,0,0)(0,1,0)[4] with drift 
## 
## Coefficients:
##           drift
##       849302632
## s.e.  461280066
## 
## sigma^2 = 3.92e+19:  log likelihood = -455.04
## AIC=914.08   AICc=914.83   BIC=915.97
summary(arima_RevNet)
## Series: ts_RevNet 
## ARIMA(0,0,0)(0,1,0)[4] with drift 
## 
## Coefficients:
##           drift
##       849302632
## s.e.  461280066
## 
## sigma^2 = 3.92e+19:  log likelihood = -455.04
## AIC=914.08   AICc=914.83   BIC=915.97
## 
## Training set error measures:
##                   ME       RMSE        MAE        MPE     MAPE      MASE
## Training set 6791039 5538526781 3653271588 -0.7888238 7.147855 0.6723053
##                   ACF1
## Training set 0.6995847

Generar pronósticos, 8 trimestres en el futuro

pronostico_1 <- forecast(arima_RevNet, level=c(95), h=8)
pronostico_1
##         Point Forecast       Lo 95        Hi 95
## 2017 Q4    81748210526 69477491366  94018929687
## 2018 Q1    56293210526 44022491366  68563929687
## 2018 Q2    48805210526 36534491366  61075929687
## 2018 Q3    55976210526 43705491366  68246929687
## 2018 Q4    85145421053 67792003596 102498838509
## 2019 Q1    59690421053 42337003596  77043838509
## 2019 Q2    52202421053 34849003596  69555838509
## 2019 Q3    59373421053 42020003596  76726838509
plot(pronostico_1)

Los pronósticos muestran un patrón similar a los datos históricos, en donde los trimestres más altos fueron Q1 y el Q4 (en especial el 4). Otro aspecto importante es que aunque el patrón se repita, la cantidad en cada trimestre va aumentando gradualmente conforme pasan los años.

Las predicciones fueron:

2017 Q4 - 81748210526

2018 Q1 - 56293210526, Q2 - 48805210526, Q3 - 55976210526, Q4 - 85145421053

2019 Q1 - 59690421053, Q2 - 52202421053, Q3 - 59373421053

LS0tDQp0aXRsZTogIkFjdGl2aWRhZCBlbiBjbGFzZSBkaWEgNiINCmF1dGhvcjogIkd1aWxsZXJtbyBDw6F6YXJlcyBDcnV6Ig0KZGF0ZTogIjIwMjQtMDItMTkiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUNCi0tLQ0KDQohW10oaHR0cHM6Ly9tZWRpYS5naXBoeS5jb20vbWVkaWEvVTNHOVFsSnJTbjJaRy9naXBoeS5naWY/Y2lkPTc5MGI3NjExdm1jbzhqb2wzeDF4Nnh6ejg4ZHd4aGlvM2pnNm4weXBqZ3R6NHU2dCZlcD12MV9naWZzX3NlYXJjaCZyaWQ9Z2lwaHkuZ2lmJmN0PWcpDQoNCkludGVncmFudGVzOiANCg0KUmVnaW5hIEVucsOtcXVleiBDaGFwYSAJQTAxNzIxNDM1DQoNCk1heGltaWxpYW5vIENhcnZhamFsIAlBMDE1NTIxNzkNCg0KR3VpbGxlcm1vIENhemFyZXMgQ3J1eiAJQTAxMjgzNzA5DQoNCiMgQW7DoWxpc2lzIEZpbmFuY2llcm8gZGUgRW1wcmVzYTogQ3JlYXIgYmFzZSBkZSBkYXRvcyB5IHNlcmllIGRlIHRpZW1wbywgbW9kZWxvIEFSSU1BIHkgcHJvbsOzc3RpY28gKDMwIHB1bnRvcywgMTAgYy91KQ0KDQojIyBDYXJnYXIgbGlicmVyw61hcyB5IHZlcmlmaWNhciBxdWUgc2UgY3VlbnRhIGNvbiBsYSBpbmZvcm1hY2nDs24gZGUgQXBwbGUNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiNpbnN0YWxsLnBhY2thZ2VzKCJmaW5yZXBvcnRyIikNCiNpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KI2luc3RhbGwucGFja2FnZXMoImZvcmVjYXN0IikNCg0KbGlicmFyeShmaW5yZXBvcnRyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpgYGANCg0KYGBge3J9DQpvcHRpb25zKEhUVFBVc2VyQWdlbnQgPSAiYSBhQGdtYWlsLmNvbSIpDQpDb21wYW55SW5mbygiQUFQTCIpDQpgYGANCg0KIyMgQ2FyZ2FyIGluZm9ybWFjacOzbiBlbiB2YXJpYXMgYmFzZXMgZGUgZGF0b3MNCg0KU2UgcGxhbmVhIGFuYWxpemFyIGxvcyBvcGVyYXRpbmcgY29zdHMgeSBuZXQgcmV2ZW51ZSBkZSBsYSBlbXByZXNhLCBhbWJhcyBwcm92aWVuZW4gZGUgYEdldEluY29tZWAuDQoNCmBgYHtyfQ0Kb3B0aW9ucyhIVFRQVXNlckFnZW50ID0gImEgYUBnbWFpbC5jb20iKQ0KQXBwbGUxMV9pbmNvbWUgPC0gR2V0SW5jb21lKCJBQVBMIiwyMDExKQ0KQTEzX2luY29tZSA8LSBHZXRJbmNvbWUoIkFBUEwiLDIwMTMpDQpBcHBsZTE0X2luY29tZSA8LSBHZXRJbmNvbWUoIkFBUEwiLDIwMTQpDQpBMTVfaW5jb21lIDwtIEdldEluY29tZSgiQUFQTCIsMjAxNSkNCkExNl9pbmNvbWUgPC0gR2V0SW5jb21lKCJBQVBMIiwyMDE2KQ0KQXBwbGUxN19pbmNvbWUgPC0gR2V0SW5jb21lKCJBQVBMIiwyMDE3KQ0KDQpgYGANCg0KYGBge3J9DQojb3B0aW9ucyhIVFRQVXNlckFnZW50ID0gImEgYUBnbWFpbC5jb20iKQ0KI0FwcGxlMTFfYmFsYW5jZSA8LSBHZXRCYWxhbmNlU2hlZXQoIkFBUEwiLDIwMTEpDQojQXBwbGUxMV9jYXNoIDwtIEdldENhc2hGbG93KCJBQVBMIiwyMDExKSANCiNBcHBsZTE0X2JhbGFuY2UgPC0gR2V0QmFsYW5jZVNoZWV0KCJBQVBMIiwyMDE0KQ0KI0FwcGxlMTRfY2FzaCA8LSBHZXRDYXNoRmxvdygiQUFQTCIsMjAxNCkgDQojQXBwbGUxN19iYWxhbmNlIDwtIEdldEJhbGFuY2VTaGVldCgiQUFQTCIsMjAxNykNCiNBcHBsZTE3X2Nhc2g8LSBHZXRDYXNoRmxvdygiQUFQTCIsMjAxNykgDQpgYGANCg0KRWwgcHJvY2VzbyBjb25zaXN0ZSBlbjogc2VsZWNjaW9uYXIgdW5hIHZhcmlhYmxlLCBjb3J0YXJsYSBkZSBjYWRhIHRhYmxhLCBqdW50YXJsYXMgcGFyYSBvYnRlbmVyIHRvZGFzIGxhcyBmZWNoYXMsIGFybWFyIGxhIHRpbWUgc2VyaWVzLCB5IGhhY2VyIGxhIHByZWRpY2Npw7NuLg0KDQoNCg0KIyMgT3BlcmF0aW5nIGV4cGVuc2VzDQoNCiMjIyBBaXNsYXIgb3BlcmF0aW5nIGV4cGVuc2VzIGVuIGNhZGEgdGFibGEgcmVxdWVyaWRhDQoNCmBgYHtyfQ0KQXBwbGVfT3BFeHBfMTEgPC0gc2VsZWN0KEFwcGxlMTFfaW5jb21lLE1ldHJpYyxBbW91bnQsZW5kRGF0ZSkNCkFwcGxlX09wRXhwXzExIDwtIHN1YnNldChBcHBsZV9PcEV4cF8xMSwgTWV0cmljID09ICJUb3RhbCBvcGVyYXRpbmcgZXhwZW5zZXMiKQ0KDQpBcHBsZV9PcEV4cF8xNCA8LSBzZWxlY3QoQXBwbGUxNF9pbmNvbWUsTWV0cmljLEFtb3VudCxlbmREYXRlKQ0KQXBwbGVfT3BFeHBfMTQgPC0gc3Vic2V0KEFwcGxlX09wRXhwXzE0LCBNZXRyaWMgPT0gIk9wZXJhdGluZyBFeHBlbnNlcyIpDQoNCkFwcGxlX09wRXhwXzE3IDwtIHNlbGVjdChBcHBsZTE3X2luY29tZSxNZXRyaWMsQW1vdW50LGVuZERhdGUpDQpBcHBsZV9PcEV4cF8xNyA8LSBzdWJzZXQoQXBwbGVfT3BFeHBfMTcsIE1ldHJpYyA9PSAiT3BlcmF0aW5nIEV4cGVuc2VzIikNCmBgYA0KDQojIyMgSnVudGFyIHRvZGFzIGxhcyB0YWJsYXMsIHkgb3JkZW5hcmxhcyBwb3IgbGEgZmVjaGEgZmluDQoNCmBgYHtyfQ0KQXBwbGVfT3BFeHBfY29tcGxldGUgPC0gcmJpbmQoQXBwbGVfT3BFeHBfMTEsQXBwbGVfT3BFeHBfMTQsQXBwbGVfT3BFeHBfMTcpDQpBcHBsZV9PcEV4cF9jb21wbGV0ZSA8LSBBcHBsZV9PcEV4cF9jb21wbGV0ZVtvcmRlcihBcHBsZV9PcEV4cF9jb21wbGV0ZSRlbmREYXRlKSxdDQpgYGANCg0KIyMjIENhbWJpYXIgKiphbW91bnQqKiBkZSAqY2hhcmFjdGVyKiBhICpudW1lcmljKg0KDQpgYGB7cn0NCkFwcGxlX09wRXhwX2NvbXBsZXRlJEFtb3VudCA8LSBhcy5udW1lcmljKEFwcGxlX09wRXhwX2NvbXBsZXRlJEFtb3VudCkNCmBgYA0KDQojIyMgQXJtYXIgbGEgc2VyaWUgZGUgdGllbXBvDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGZvcmVjYXN0KQ0KYGBgDQoNCmBgYHtyfQ0KdHNfT3BFeHAgPC0gdHMoZGF0YT1BcHBsZV9PcEV4cF9jb21wbGV0ZSRBbW91bnQsIHN0YXJ0ID0gYygyMDA5LDEpLCBmcmVxdWVuY3kgPSAxKQ0KdHNfT3BFeHANCmBgYA0KDQojIyMgQXJtYXIgZWwgbW9kZWxvIEFSSU1BDQoNCmBgYHtyfQ0KYXJpbWFfT3BFeHAgPC0gYXV0by5hcmltYSh0c19PcEV4cCkNCmFyaW1hX09wRXhwDQpzdW1tYXJ5KGFyaW1hX09wRXhwKQ0KYGBgDQoNCiMjIyBHZW5lcmFyIHByb27Ds3N0aWNvcywgNiBhw7FvcyBlbiBlbCBmdXR1cm8NCg0KYGBge3J9DQpwcm9ub3N0aWNvXzIgPC0gZm9yZWNhc3QoYXJpbWFfT3BFeHAsIGxldmVsPWMoOTUpLCBoPTYpDQpwcm9ub3N0aWNvXzINCnBsb3QocHJvbm9zdGljb18yKQ0KYGBgDQoNCkxvcyBwcm9uw7NzdGljb3MgbXVlc3RyYW4gdW4gY3JlY2ltaWVudG8gY29uc3RhbnRlIGR1cmFudGUgbG9zIHNpZ3VpZW50ZSA2IGHDsW9zLiBFbiBsYSBncsOhZmljYSBzZSBhcHJlY2lhIHF1ZSBsYXMgcHJlZGljY2lvbmVzIHNpZ3VlbiBkZSBtYW5lcmEgcGVyZmVjdGEgbGEgZGlyZWNjacOzbiBlbiBsYSBxdWUgeWEgc2UgZGlyaWfDrWFuIGxvcyBkYXRvcyBoaXN0w7NyaWNvcy4NCg0KRXN0YXMgZnVlcm9uIGxhcyBwcmVkaWNjaW9uZXM6DQoNCjIwMTggLSAyLjk1MTJlKzEwLCAyMDE5IC0gMy4yMTgyZSsxMCwgMjAyMCAtIDMuNDg1MmUrMTAJDQoNCjIwMjEgLSAzLjc1MjJlKzEwLCAyMDIyIC0gNC4wMTkyZSsxMCwgMjAyMyAtIDQuMjg2MmUrMTAJDQoNCg0KDQojIyBQcnVlYmFzLCBwYXJhIGxhcyB2YXJpYWJsZXMgcXVlIHZpZW5lbiBwb3IgdHJpbWVzdHJlIA0KDQpDYWRhIGJhc2Ugc29sbyB0cmFlIGNvbXBsZXRvIGxvcyBkYXRvcyBkZSB1biBhw7FvIGFudGVyaW9yIGFsIHF1ZSBzZWxlY2Npb25hc3RlIGVuIGxhIGZ1bmNpw7NuICpHZXRJbmNvbWUqLCBsYXMgb3RyYXMgZG9zIHZpZW5lbiBpbmNvbXBsZXRhcy4NCg0KYGBge3J9DQpCaW5ndXMgPC0gQXBwbGUxMV9pbmNvbWVbLC0yXQ0KQmluZ3VzIDwtIHN1YnNldChCaW5ndXMsIE1ldHJpYyA9PSAiUmV2ZW51ZSwgTmV0IikNCkJpbmd1cyA8LSBCaW5ndXNbb3JkZXIoQmluZ3VzJGVuZERhdGUpLF0NCmBgYA0KDQpgYGB7cn0NCkJpbmd1c18yIDwtIEFwcGxlMTRfaW5jb21lWywtMl0NCkJpbmd1c18yIDwtIHN1YnNldChCaW5ndXNfMiwgTWV0cmljID09ICJSZXZlbnVlLCBOZXQiKQ0KQmluZ3VzXzIgPC0gQmluZ3VzXzJbb3JkZXIoQmluZ3VzXzIkZW5kRGF0ZSksXQ0KYGBgDQoNCmBgYHtyfQ0KQmluZ3VzXzMgPC0gQXBwbGUxN19pbmNvbWVbLC0yXQ0KQmluZ3VzXzMgPC0gc3Vic2V0KEJpbmd1c18zLCBNZXRyaWMgPT0gIlJldmVudWUsIE5ldCIpDQpCaW5ndXNfMyA8LSBCaW5ndXNfM1tvcmRlcihCaW5ndXNfMyRlbmREYXRlKSxdDQpgYGANCg0KRGVzcHXDqXMgZGUgcHJvYmFyLCB2aSBxdWUgcG9yIHRyaW1lc3RyZSBzb2xvIHZpZW5lIGxhIGluZm8gY29tcGxldGEgZGVsIGHDsW8gYW50ZXJpb3IgYWwgc2VsZWNjaW9uYWRvIGVuIGdldGluY29tZSgpLCBtaWVudHJhcyBxdWUgbG9zIG90cm9zIGRvcyB2aWVuZW4gaW5jb21wbGV0b3MNCg0KUG9yIGxvIHRhbnRvLCBvY3VwbyAyMDE3ICgyMDE3LTIwMTUpLCAyMDE2ICgyMDE1LTIwMTQpLCAyMDE1KDIwMTQtMjAxMyksIDIwMTQoMjAxMy0yMDEyKSwgMjAxMygyMDEyKSBTaSBxdWllcm8gY2FsY3VsYXIgZGVzZGUgMjAxMiBhIDIwMTcgcG9yIHRyaW1lc3RyZQ0KDQoNCg0KIyMgUmV2ZW51ZSwgTmV0DQoNCiMjIyBBaXNsYXIgIlJldmVudWUsIE5ldCIgZW4gY2FkYSBiYXNlLCBhZGVtw6FzIGRlIGNvcnRhciB0b2RhcyBsYXMgZmlsYXMgcXVlIG5vIG5vcyBzZXJ2aXLDoW4gbyBxdWUgZXN0w6luIHJlcGV0aWRhcyBlbnRyZSBiYXNlcy4NCg0KYGBge3J9DQpSZXZOZXRfMTcgPC0gc3Vic2V0KEFwcGxlMTdfaW5jb21lLCBNZXRyaWMgPT0gIlJldmVudWUsIE5ldCIpDQpSZXZOZXRfMTcgPC0gUmV2TmV0XzE3W29yZGVyKFJldk5ldF8xNyRlbmREYXRlLFJldk5ldF8xNyRzdGFydERhdGUpLF0NClJldk5ldF8xNyA8LSBSZXZOZXRfMTdbLWMoMSw1LDEwKSxdDQpgYGANCg0KDQpgYGB7cn0NClJldk5ldF8xNiA8LSBzdWJzZXQoQTE2X2luY29tZSwgTWV0cmljID09ICJSZXZlbnVlLCBOZXQiKQ0KUmV2TmV0XzE2IDwtIFJldk5ldF8xNltvcmRlcihSZXZOZXRfMTYkZW5kRGF0ZSxSZXZOZXRfMTYkc3RhcnREYXRlKSxdDQpgYGANCg0KYGBge3J9DQpSZXZOZXRfMTYgPC0gUmV2TmV0XzE2W2MoMjo0LDYpLF0NCmBgYA0KDQpgYGB7cn0NClJldk5ldF8xNSA8LSBzdWJzZXQoQTE1X2luY29tZSwgTWV0cmljID09ICJSZXZlbnVlLCBOZXQiKQ0KUmV2TmV0XzE1IDwtIFJldk5ldF8xNVtvcmRlcihSZXZOZXRfMTUkZW5kRGF0ZSxSZXZOZXRfMTUkc3RhcnREYXRlKSxdDQpSZXZOZXRfMTUgPC0gUmV2TmV0XzE1W2MoMjo0LDYpLF0NCmBgYA0KDQpgYGB7cn0NClJldk5ldF8xNCA8LSBzdWJzZXQoQXBwbGUxNF9pbmNvbWUsIE1ldHJpYyA9PSAiUmV2ZW51ZSwgTmV0IikNClJldk5ldF8xNCA8LSBSZXZOZXRfMTRbb3JkZXIoUmV2TmV0XzE0JGVuZERhdGUsUmV2TmV0XzE0JHN0YXJ0RGF0ZSksXQ0KUmV2TmV0XzE0IDwtIFJldk5ldF8xNFtjKDI6NCw2KSxdDQpgYGANCg0KYGBge3J9DQpSZXZOZXRfMTMgPC0gc3Vic2V0KEExM19pbmNvbWUsIE1ldHJpYyA9PSAiU2FsZXMgUmV2ZW51ZSBOZXQiKQ0KUmV2TmV0XzEzIDwtIFJldk5ldF8xM1tvcmRlcihSZXZOZXRfMTMkZW5kRGF0ZSxSZXZOZXRfMTMkc3RhcnREYXRlKSxdDQpSZXZOZXRfMTMgPC0gUmV2TmV0XzEzW2MoMyw0LDYpLF0NCmBgYA0KDQojIyMgSnVudGFyIHRvZGFzIGxhcyBiYXNlcyB5IG9yZGVybmFyIHBvciBmZWNoYSBmaW4uDQoNCmBgYHtyfQ0KUmV2TmV0X2NvbXBsZXRlIDwtIHJiaW5kKFJldk5ldF8xMyxSZXZOZXRfMTQsUmV2TmV0XzE1LFJldk5ldF8xNixSZXZOZXRfMTcpDQpSZXZOZXRfY29tcGxldGUgPC0gUmV2TmV0X2NvbXBsZXRlW29yZGVyKFJldk5ldF9jb21wbGV0ZSRlbmREYXRlKSxdDQpgYGANCg0KIyMjIENhbWJpYXIgYW1vdW50IGRlICpjaGFyYWN0ZXIqIGEgKm51bWVyaWMqDQoNCmBgYHtyfQ0Kc3RyKFJldk5ldF9jb21wbGV0ZSkNCmBgYA0KDQpgYGB7cn0NClJldk5ldF9jb21wbGV0ZSRBbW91bnQgPC0gYXMubnVtZXJpYyhSZXZOZXRfY29tcGxldGUkQW1vdW50KQ0KYGBgDQoNCmBgYHtyfQ0Kc3RyKFJldk5ldF9jb21wbGV0ZSkNCmBgYA0KDQojIyMgQXJtYXIgU2VyaWUgZGUgdGllbXBvDQoNCmBgYHtyfQ0KbGlicmFyeShmb3JlY2FzdCkNCmBgYA0KDQpgYGB7cn0NCnRzX1Jldk5ldCA8LSB0cyhkYXRhPVJldk5ldF9jb21wbGV0ZSRBbW91bnQsIHN0YXJ0ID0gYygyMDEyLDEpLCBmcmVxdWVuY3kgPSA0KQ0KdHNfUmV2TmV0DQpgYGANCg0KIyMjIEFybWFyIG1vZGVsbyBBcmltYQ0KDQpgYGB7cn0NCmFyaW1hX1Jldk5ldCA8LSBhdXRvLmFyaW1hKHRzX1Jldk5ldCkNCmFyaW1hX1Jldk5ldA0Kc3VtbWFyeShhcmltYV9SZXZOZXQpDQpgYGANCg0KIyMjIEdlbmVyYXIgcHJvbsOzc3RpY29zLCA4IHRyaW1lc3RyZXMgZW4gZWwgZnV0dXJvDQoNCmBgYHtyfQ0KcHJvbm9zdGljb18xIDwtIGZvcmVjYXN0KGFyaW1hX1Jldk5ldCwgbGV2ZWw9Yyg5NSksIGg9OCkNCnByb25vc3RpY29fMQ0KcGxvdChwcm9ub3N0aWNvXzEpDQpgYGANCg0KTG9zIHByb27Ds3N0aWNvcyBtdWVzdHJhbiB1biBwYXRyw7NuIHNpbWlsYXIgYSBsb3MgZGF0b3MgaGlzdMOzcmljb3MsIGVuIGRvbmRlIGxvcyB0cmltZXN0cmVzIG3DoXMgYWx0b3MgZnVlcm9uICpRMSogeSBlbCAqUTQqIChlbiBlc3BlY2lhbCBlbCA0KS4gT3RybyBhc3BlY3RvIGltcG9ydGFudGUgZXMgcXVlIGF1bnF1ZSBlbCBwYXRyw7NuIHNlIHJlcGl0YSwgbGEgY2FudGlkYWQgZW4gY2FkYSB0cmltZXN0cmUgdmEgYXVtZW50YW5kbyBncmFkdWFsbWVudGUgY29uZm9ybWUgcGFzYW4gbG9zIGHDsW9zLg0KDQpMYXMgcHJlZGljY2lvbmVzIGZ1ZXJvbjoNCg0KMjAxNyAqUTQqIC0gODE3NDgyMTA1MjYNCg0KMjAxOCAqUTEqIC0gNTYyOTMyMTA1MjYsICpRMiogLSA0ODgwNTIxMDUyNiwgKlEzKiAtIDU1OTc2MjEwNTI2LCAqUTQqIC0gODUxNDU0MjEwNTMNCg0KMjAxOSAqUTEqIC0gNTk2OTA0MjEwNTMsICpRMiogLSA1MjIwMjQyMTA1MywgKlEzKiAtIDU5MzczNDIxMDUzDQoNCg0K