Ejercicio en Clase

Concepto

Una Serie de tiempo es una colección de observaciones sobre un determinado fenómeno, efectuadas en momentos sucesivos, usualmente equiespaciados.
1.Precios de acciones.
2.Niveles de inventario.
3.Rotación de personal.
4.Ventas.
5.PIB (GDP)
Más Información Libro R for Data Science (2e)

Instalar paquetes y llamar librerías

#install.packages("forecast")
library(forecast)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo

Crear la serie de tiempo

Ejemplo:
Los siguientes datos de producción trimestral inician en el primer trimestre del 2020. Se busca pronosticar la producción de los siguientes 5 trimestres.
produccion <- c(50,53,55,57,55,60)

ts <- ts(data=produccion, start = c(2020,1), frequency = 4)
ts
##      Qtr1 Qtr2 Qtr3 Qtr4
## 2020   50   53   55   57
## 2021   55   60

Crear modelo ARIMA

ARIMA significa AutoRegressive Integrated Moving Average o Modelo Autorregresivo Integrado de Promedio Móvil.
arima <- auto.arima(ts)
arima
## Series: ts 
## ARIMA(0,1,0) 
## 
## sigma^2 = 9.2:  log likelihood = -12.64
## AIC=27.29   AICc=28.62   BIC=26.89
summary(arima)
## Series: ts 
## ARIMA(0,1,0) 
## 
## sigma^2 = 9.2:  log likelihood = -12.64
## AIC=27.29   AICc=28.62   BIC=26.89
## 
## Training set error measures:
##                 ME    RMSE      MAE      MPE     MAPE      MASE       ACF1
## Training set 1.675 2.76895 2.341667 2.933747 4.145868 0.3902778 -0.5152989

Generar el pronóstico

pronostico <- forecast(arima, level=c(95), h=5)
pronostico
##         Point Forecast    Lo 95    Hi 95
## 2021 Q3             60 54.05497 65.94503
## 2021 Q4             60 51.59246 68.40754
## 2022 Q1             60 49.70291 70.29709
## 2022 Q2             60 48.10995 71.89005
## 2022 Q3             60 46.70652 73.29348
plot(pronostico)

Actividad 2 - Hershey’s

library(readxl)
lechita <- read_excel("Ventas_Históricas_Lechitas.xlsx")

Crear la serie de tiempo

ts1 <- ts(data=lechita$Ventas, start = c(2017,1), frequency = 12)
ts1
##           Jan      Feb      Mar      Apr      May      Jun      Jul      Aug
## 2017 25520.51 23740.11 26253.58 25868.43 27072.87 27150.50 27067.10 28145.25
## 2018 28463.69 26996.11 29768.20 29292.51 29950.68 30099.17 30851.26 32271.76
## 2019 32496.44 31287.28 33376.02 32949.77 34004.11 33757.89 32927.30 34324.12
##           Sep      Oct      Nov      Dec
## 2017 27546.29 28400.37 27441.98 27852.47
## 2018 31940.74 32995.93 32197.12 31984.82
## 2019 35151.28 36133.07 34799.91 34846.17

Crear modelo ARIMA

arima1 <- auto.arima(ts1)
arima1
## Series: ts1 
## ARIMA(1,0,0)(1,1,0)[12] with drift 
## 
## Coefficients:
##          ar1     sar1     drift
##       0.6383  -0.5517  288.8979
## s.e.  0.1551   0.2047   14.5026
## 
## sigma^2 = 202701:  log likelihood = -181.5
## AIC=371   AICc=373.11   BIC=375.72
summary(arima1)
## Series: ts1 
## ARIMA(1,0,0)(1,1,0)[12] with drift 
## 
## Coefficients:
##          ar1     sar1     drift
##       0.6383  -0.5517  288.8979
## s.e.  0.1551   0.2047   14.5026
## 
## sigma^2 = 202701:  log likelihood = -181.5
## AIC=371   AICc=373.11   BIC=375.72
## 
## Training set error measures:
##                    ME    RMSE    MAE        MPE      MAPE       MASE      ACF1
## Training set 25.22158 343.864 227.17 0.08059932 0.7069542 0.06491044 0.2081026

Generar el pronóstico

pronostico1 <- forecast(arima1, level=c(95), h=12)
pronostico1
##          Point Forecast    Lo 95    Hi 95
## Jan 2020       35498.90 34616.48 36381.32
## Feb 2020       34202.17 33155.28 35249.05
## Mar 2020       36703.01 35596.10 37809.92
## Apr 2020       36271.90 35141.44 37402.36
## May 2020       37121.98 35982.07 38261.90
## Jun 2020       37102.65 35958.90 38246.40
## Jul 2020       37151.04 36005.73 38296.34
## Aug 2020       38564.64 37418.70 39710.58
## Sep 2020       38755.22 37609.03 39901.42
## Oct 2020       39779.02 38632.72 40925.32
## Nov 2020       38741.63 37595.28 39887.97
## Dec 2020       38645.86 37499.50 39792.22
plot(pronostico1)

Finanzas Corporativas

Instalar paquetes y llamar librerías

#install.packages("finreportr")
library(finreportr)

Información disponible

Con la función finreportr podemos obtener la siguiente información:
* CompanyInfo() = Brinda información general como Nombre, Ubicación, ZIP, etc.
* AnnualReports() = Brinda el nombre, fecha y número de acceso.
* GetIncome() = Brinda el Estado de Resultados.
* GetBalanceSheet() = Brinda el Balance General.
* getCashFlow() = Brinda el Flujo de Efectivo.
options(HTTPUserAgent = "a a@gmail.com")
CompanyInfo("JPM")
##               company        CIK  SIC state state.inc FY.end     street.address
## 1 JPMORGAN CHASE & CO 0000019617 6021    NY        DE   1231 383 MADISON AVENUE
##          city.state
## 1 NEW YORK NY 10017
AnnualReports("BABA", foreign = TRUE)
##    filing.name filing.date         accession.no
## 1       20-F/A  2024-02-23 0001193125-24-044480
## 2         20-F  2023-07-21 0000950170-23-033752
## 3         20-F  2022-07-26 0001104659-22-082622
## 4         20-F  2021-07-27 0001104659-21-096092
## 5         20-F  2020-07-09 0001104659-20-082409
## 6         20-F  2019-06-05 0001047469-19-003492
## 7         20-F  2018-07-27 0001047469-18-005257
## 8         20-F  2017-06-15 0001047469-17-004019
## 9         20-F  2016-05-24 0001047469-16-013400
## 10        20-F  2015-06-25 0001047469-15-005768
google_income <- GetIncome("GOOG", 2016)
amazon_balance <- GetBalanceSheet("AMZN",2015)
apple_cash <- GetCashFlow("AAPL",2014)

Tarea 4: Análisis Financiero: Empresa Apple

Integrantes: Regina Enríquez, Maximiliano Carvajal, Guillermo Cazares

library(forecast)
library(finreportr)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
options(HTTPUserAgent = "a a@gmail.com")
AnnualReports("AAPL")
##    filing.name filing.date         accession.no
## 1         10-K  2023-11-03 0000320193-23-000106
## 2         10-K  2022-10-28 0000320193-22-000108
## 3         10-K  2021-10-29 0000320193-21-000105
## 4         10-K  2020-10-30 0000320193-20-000096
## 5         10-K  2019-10-31 0000320193-19-000119
## 6         10-K  2018-11-05 0000320193-18-000145
## 7         10-K  2017-11-03 0000320193-17-000070
## 8         10-K  2016-10-26 0001628280-16-020309
## 9         10-K  2015-10-28 0001193125-15-356351
## 10        10-K  2014-10-27 0001193125-14-383437
## 11        10-K  2013-10-30 0001193125-13-416534
## 12        10-K  2012-10-31 0001193125-12-444068
## 13        10-K  2011-10-26 0001193125-11-282113
## 14        10-K  2010-10-27 0001193125-10-238044
## 15      10-K/A  2010-01-25 0001193125-10-012091
## 16        10-K  2009-10-27 0001193125-09-214859
## 17        10-K  2008-11-05 0001193125-08-224958
## 18        10-K  2007-11-15 0001047469-07-009340
## 19        10-K  2006-12-29 0001104659-06-084288
## 20        10-K  2005-12-01 0001104659-05-058421
## 21        10-K  2004-12-03 0001047469-04-035975
## 22        10-K  2003-12-19 0001047469-03-041604
## 23        10-K  2002-12-19 0001047469-02-007674
## 24     10-K405  2001-12-21 0000912057-01-544436
## 25        10-K  2000-12-14 0000912057-00-053623
## 26        10-K  1999-12-22 0000912057-99-010244
## 27     10-K405  1998-12-23 0001047469-98-044981
## 28      10-K/A  1998-01-23 0001047469-98-001822
## 29        10-K  1997-12-05 0001047469-97-006960
## 30        10-K  1996-12-19 0000320193-96-000023
## 31        10-K  1995-12-19 0000320193-95-000016
## 32        10-K  1994-12-13 0000320193-94-000016

Pronóstico 1: Operating expenses (Income)

apple_income_2011 <- GetIncome("AAPL", 2011)
apple_income_2014 <- GetIncome("AAPL", 2014)
apple_income_2017 <- GetIncome("AAPL", 2017)
Apple_OpExp_11 <- select(apple_income_2011,Metric,Amount,endDate)
Apple_OpExp_11 <- subset(Apple_OpExp_11, Metric == "Total operating expenses")

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

Apple_OpExp_17 <- select(apple_income_2017,Metric,Amount,endDate)
Apple_OpExp_17 <- subset(Apple_OpExp_17, Metric == "Operating Expenses")
Apple_OpExp_complete <- rbind(Apple_OpExp_11,Apple_OpExp_14,Apple_OpExp_17)
Apple_OpExp_complete <- Apple_OpExp_complete[order(Apple_OpExp_complete$endDate),]
Apple_OpExp_complete$Amount <- as.numeric(Apple_OpExp_complete$Amount)

Crear la serie de tiempo

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
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
pronostico_1 <- forecast(arima_OpExp, level=c(95), h=6)
pronostico_1
##      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_1)

Pronóstico 2: Reasearch and Development (Income)

Apple_Net_11 <- select(apple_income_2011,Metric,Amount,endDate)
Apple_Net_11 <- subset(Apple_Net_11, Metric == "Research and Development Expense")

Apple_Net_14 <- select(apple_income_2014,Metric,Amount,endDate)
Apple_Net_14 <- subset(Apple_Net_14, Metric == "Research and Development Expense")

Apple_Net_17 <- select(apple_income_2017,Metric,Amount,endDate)
Apple_Net_17 <- subset(Apple_Net_17, Metric == "Research and Development Expense")
Apple_Net_complete <- rbind(Apple_Net_11,Apple_Net_14,Apple_Net_17)
Apple_Net_complete <- Apple_Net_complete[order(Apple_Net_complete$endDate),]
Apple_Net_complete$Amount <- as.numeric(Apple_Net_complete$Amount)
Apple_Net_complete
##                               Metric     Amount    endDate
## 23  Research and Development Expense 1.3330e+09 2009-09-26
## 24  Research and Development Expense 1.7820e+09 2010-09-25
## 25  Research and Development Expense 2.4290e+09 2011-09-24
## 251 Research and Development Expense 3.3810e+09 2012-09-29
## 231 Research and Development Expense 4.4750e+09 2013-09-28
## 241 Research and Development Expense 6.0410e+09 2014-09-27
## 26  Research and Development Expense 8.0670e+09 2015-09-26
## 27  Research and Development Expense 1.0045e+10 2016-09-24
## 28  Research and Development Expense 1.1581e+10 2017-09-30

Crear la serie de tiempo

ts_Net <- ts(data=Apple_Net_complete$Amount, start = c(2012,1), frequency = 1)
ts_Net
## Time Series:
## Start = 2012 
## End = 2020 
## Frequency = 1 
## [1] 1.3330e+09 1.7820e+09 2.4290e+09 3.3810e+09 4.4750e+09 6.0410e+09 8.0670e+09
## [8] 1.0045e+10 1.1581e+10
arima_Net <- auto.arima(ts_Net)
arima_Net
## Series: ts_Net 
## ARIMA(0,2,0) 
## 
## sigma^2 = 1.121e+17:  log likelihood = -147.34
## AIC=296.67   AICc=297.47   BIC=296.62
summary(arima_Net)
## Series: ts_Net 
## ARIMA(0,2,0) 
## 
## sigma^2 = 1.121e+17:  log likelihood = -147.34
## AIC=296.67   AICc=297.47   BIC=296.62
## 
## Training set error measures:
##                     ME      RMSE       MAE      MPE     MAPE      MASE
## Training set 120756858 295229848 229820061 3.285274 4.249377 0.1794068
##                   ACF1
## Training set 0.2873511
pronostico_2 <- forecast(arima_Net, level=c(95), h=6)
pronostico_2
##      Point Forecast       Lo 95       Hi 95
## 2021     1.3117e+10 12460884059 13773115941
## 2022     1.4653e+10 13185880155 16120119845
## 2023     1.6189e+10 13734038944 18643961056
## 2024     1.7725e+10 14131304989 21318695011
## 2025     1.9261e+10 14395113953 24126886047
## 2026     2.0797e+10 14538052835 27055947165
plot(pronostico_2)

Pronóstico 3: Assets (Balance Sheet)

apple_balance_2011 <- GetBalanceSheet("AAPL",2011)
apple_balance_2014 <- GetBalanceSheet("AAPL",2014)
apple_balance_2017 <- GetBalanceSheet("AAPL",2017)
Bingus_bal <- apple_balance_2011[,-2]
Bingus_bal <- subset(Bingus_bal, Metric == "Total assets")
Bingus_bal <- Bingus_bal[order(Bingus_bal$endDate),]
Bingus_bal2 <- apple_balance_2014[,-2]
Bingus_bal2 <- subset(Bingus_bal2, Metric == "Assets")
Bingus_bal2 <- Bingus_bal2[order(Bingus_bal2$endDate),]
Bingus_bal3 <- apple_balance_2017[,-2]
Bingus_bal3 <- subset(Bingus_bal3, Metric == "Assets")
Bingus_bal3 <- Bingus_bal3[order(Bingus_bal3$endDate),]
apple_balance_2015 <- GetBalanceSheet("AAPL",2015)
Bingus_bal4 <- apple_balance_2015[,-2]
Bingus_bal4 <- subset(Bingus_bal4, Metric == "Assets")
Bingus_bal4 <- Bingus_bal4[order(Bingus_bal4$endDate),]
Bingus_bal4 <- Bingus_bal4[-1,]
apple_balance_2012 <- GetBalanceSheet("AAPL",2012)
Bingus_bal5 <- apple_balance_2012[,-2]
Bingus_bal5 <- subset(Bingus_bal5, Metric == "Assets")
Bingus_bal5 <- Bingus_bal5[order(Bingus_bal5$endDate),]
Bingus_bal5 <- Bingus_bal5[-1,]
bingus_balance <- rbind(Bingus_bal,Bingus_bal2,Bingus_bal3, Bingus_bal4, Bingus_bal5)
str(bingus_balance)
## 'data.frame':    9 obs. of  4 variables:
##  $ Metric   : chr  "Total assets" "Total assets" "Total assets" "Assets" ...
##  $ Amount   : chr  "47501000000" "75183000000" "116371000000" "207000000000" ...
##  $ startDate: chr  NA NA NA NA ...
##  $ endDate  : chr  "2009-09-26" "2010-09-25" "2011-09-24" "2013-09-28" ...
bingus_balance$year <- year(as.Date(bingus_balance$endDate))
bingus_balance$Amount <- as.numeric(bingus_balance$Amount)
bingus_balance
##           Metric      Amount startDate    endDate year
## 11  Total assets 4.75010e+10      <NA> 2009-09-26 2009
## 12  Total assets 7.51830e+10      <NA> 2010-09-25 2010
## 13  Total assets 1.16371e+11      <NA> 2011-09-24 2011
## 111       Assets 2.07000e+11      <NA> 2013-09-28 2013
## 121       Assets 2.31839e+11      <NA> 2014-09-27 2014
## 27        Assets 3.21686e+11      <NA> 2016-09-24 2016
## 28        Assets 3.75319e+11      <NA> 2017-09-30 2017
## 122       Assets 2.90479e+11      <NA> 2015-09-26 2015
## 123       Assets 1.76064e+11      <NA> 2012-09-29 2012
bingus_balance$Amount <- log(as.numeric(bingus_balance$Amount))
bingus_balance <- bingus_balance%>% arrange(year)
bingus_balance
##           Metric   Amount startDate    endDate year
## 11  Total assets 24.58402      <NA> 2009-09-26 2009
## 12  Total assets 25.04319      <NA> 2010-09-25 2010
## 13  Total assets 25.48005      <NA> 2011-09-24 2011
## 123       Assets 25.89411      <NA> 2012-09-29 2012
## 111       Assets 26.05598      <NA> 2013-09-28 2013
## 121       Assets 26.16931      <NA> 2014-09-27 2014
## 122       Assets 26.39480      <NA> 2015-09-26 2015
## 27        Assets 26.49684      <NA> 2016-09-24 2016
## 28        Assets 26.65104      <NA> 2017-09-30 2017
bingus_balance <- bingus_balance[,c(2,5)]
bingus_balance
##       Amount year
## 11  24.58402 2009
## 12  25.04319 2010
## 13  25.48005 2011
## 123 25.89411 2012
## 111 26.05598 2013
## 121 26.16931 2014
## 122 26.39480 2015
## 27  26.49684 2016
## 28  26.65104 2017

Crear la serie de tiempo

ts_Assets <- ts(data=bingus_balance$Amount, frequency = 1, start = c(2009), end = c(2017))
plot(ts_Assets)

ts_Assets
## Time Series:
## Start = 2009 
## End = 2017 
## Frequency = 1 
## [1] 24.58402 25.04319 25.48005 25.89411 26.05598 26.16931 26.39480 26.49684
## [9] 26.65104
arima_Assets <- auto.arima(ts_Assets)
summary(arima_Assets)
## Series: ts_Assets 
## ARIMA(0,2,0) 
## 
## sigma^2 = 0.01409:  log likelihood = 5.03
## AIC=-8.05   AICc=-7.25   BIC=-8.1
## 
## Training set error measures:
##                       ME     RMSE        MAE        MPE      MAPE      MASE
## Training set -0.03621508 0.104699 0.07517371 -0.1396808 0.2875401 0.2909445
##                    ACF1
## Training set -0.2564044
arima_Assets
## Series: ts_Assets 
## ARIMA(0,2,0) 
## 
## sigma^2 = 0.01409:  log likelihood = 5.03
## AIC=-8.05   AICc=-7.25   BIC=-8.1
pronostico_3 <- forecast(arima_Assets, h=5)
pronostico_3
##      Point Forecast    Lo 80    Hi 80    Lo 95    Hi 95
## 2018       26.80524 26.65310 26.95739 26.57256 27.03792
## 2019       26.95944 26.61924 27.29964 26.43915 27.47974
## 2020       27.11364 26.54438 27.68291 26.24303 27.98426
## 2021       27.26784 26.43452 28.10116 25.99339 28.54230
## 2022       27.42204 26.29372 28.55036 25.69643 29.14766
plot(pronostico_3)

Conclusión

Dentro de los 3 pronósticos se puede observar que la empresa de Apple mantiene una tendencia positiva con un crecimiento general durante los años, lo cual hace sentido ya que la empresa está creciendo e innovando constantemente. En este caso creemos que es mejor manejar los datos de manera trimestral, debido a que si se maneja por año el pronóstico comienza a ser un poco más pesado y los pronósticos terminan siendo obsoletos ya que el paquete de forecast simplemente no cambia. De igual forma identificamos que en ocasiones puede haber repeticiones de los años, por lo que es importante hacer nota de estos y seleccionar los necesarios a través de manipulación de bases de datos para crear un buen pronóstico.

LS0tCnRpdGxlOiAiQWN0aXZpZGFkIDIgLSBTZXJpZXMgZGUgVGllbXBvIgphdXRob3I6ICJSZWdpbmEgRW5yw61xdWV6IC0gQTAxNzIxNDM1IgpkYXRlOiAiMjAyNC0wMi0xNiIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiBUUlVFCiAgICB0b2NfZmxvYXQ6IFRSVUUKICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMgRWplcmNpY2lvIGVuIENsYXNlCgohW10oc2VyaWVzLmdpZikKCiMjIENvbmNlcHRvIAojIyMjIyBVbmEgKlNlcmllIGRlIHRpZW1wbyogZXMgdW5hIGNvbGVjY2nDs24gZGUgb2JzZXJ2YWNpb25lcyBzb2JyZSB1biBkZXRlcm1pbmFkbyBmZW7Ds21lbm8sIGVmZWN0dWFkYXMgZW4gbW9tZW50b3Mgc3VjZXNpdm9zLCB1c3VhbG1lbnRlIGVxdWllc3BhY2lhZG9zLgojIyMjIyAxLlByZWNpb3MgZGUgYWNjaW9uZXMuCiMjIyMjIDIuTml2ZWxlcyBkZSBpbnZlbnRhcmlvLgojIyMjIyAzLlJvdGFjacOzbiBkZSBwZXJzb25hbC4KIyMjIyMgNC5WZW50YXMuCiMjIyMjIDUuUElCICgqR0RQKikKCiMjIyMjIE3DoXMgSW5mb3JtYWNpw7NuIFtMaWJybyAqUiBmb3IgRGF0YSBTY2llbmNlICgyZSkqXShodHRwczovL3I0ZHMuaGFkbGV5Lm56LykKCiMjIEluc3RhbGFyIHBhcXVldGVzIHkgbGxhbWFyIGxpYnJlcsOtYXMgCmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygiZm9yZWNhc3QiKQpsaWJyYXJ5KGZvcmVjYXN0KQpgYGAKCiMjIENyZWFyIGxhIHNlcmllIGRlIHRpZW1wbwojIyMjIyAqKkVqZW1wbG86KioKIyMjIyMgTG9zIHNpZ3VpZW50ZXMgZGF0b3MgZGUgcHJvZHVjY2nDs24gdHJpbWVzdHJhbCBpbmljaWFuIGVuIGVsIHByaW1lciB0cmltZXN0cmUgZGVsIDIwMjAuIFNlIGJ1c2NhIHByb25vc3RpY2FyIGxhIHByb2R1Y2Npw7NuIGRlIGxvcyBzaWd1aWVudGVzIDUgdHJpbWVzdHJlcy4KCmBgYHtyfQpwcm9kdWNjaW9uIDwtIGMoNTAsNTMsNTUsNTcsNTUsNjApCgp0cyA8LSB0cyhkYXRhPXByb2R1Y2Npb24sIHN0YXJ0ID0gYygyMDIwLDEpLCBmcmVxdWVuY3kgPSA0KQp0cwpgYGAKCiMjIENyZWFyIG1vZGVsbyBBUklNQQojIyMjIyAqKkFSSU1BKiogc2lnbmlmaWNhICpBdXRvUmVncmVzc2l2ZSBJbnRlZ3JhdGVkIE1vdmluZyBBdmVyYWdlKiBvIE1vZGVsbyBBdXRvcnJlZ3Jlc2l2byBJbnRlZ3JhZG8gZGUgUHJvbWVkaW8gTcOzdmlsLgoKYGBge3J9CmFyaW1hIDwtIGF1dG8uYXJpbWEodHMpCmFyaW1hCnN1bW1hcnkoYXJpbWEpCmBgYAoKIyMgR2VuZXJhciBlbCBwcm9uw7NzdGljbwpgYGB7cn0KcHJvbm9zdGljbyA8LSBmb3JlY2FzdChhcmltYSwgbGV2ZWw9Yyg5NSksIGg9NSkKcHJvbm9zdGljbwpwbG90KHByb25vc3RpY28pCmBgYAoKCiMgQWN0aXZpZGFkIDIgLSBIZXJzaGV5J3MKCiFbXSh3b25rYS5naWYpCgpgYGB7cn0KbGlicmFyeShyZWFkeGwpCmxlY2hpdGEgPC0gcmVhZF9leGNlbCgiVmVudGFzX0hpc3RvzIFyaWNhc19MZWNoaXRhcy54bHN4IikKYGBgCgojIyBDcmVhciBsYSBzZXJpZSBkZSB0aWVtcG8KCmBgYHtyfQp0czEgPC0gdHMoZGF0YT1sZWNoaXRhJFZlbnRhcywgc3RhcnQgPSBjKDIwMTcsMSksIGZyZXF1ZW5jeSA9IDEyKQp0czEKYGBgCgojIyBDcmVhciBtb2RlbG8gQVJJTUEKCmBgYHtyfQphcmltYTEgPC0gYXV0by5hcmltYSh0czEpCmFyaW1hMQpzdW1tYXJ5KGFyaW1hMSkKYGBgCgojIyBHZW5lcmFyIGVsIHByb27Ds3N0aWNvCgpgYGB7cn0KcHJvbm9zdGljbzEgPC0gZm9yZWNhc3QoYXJpbWExLCBsZXZlbD1jKDk1KSwgaD0xMikKcHJvbm9zdGljbzEKcGxvdChwcm9ub3N0aWNvMSkKYGBgCgojIEZpbmFuemFzIENvcnBvcmF0aXZhcwoKIVtdKGZpbmFuemFzLmdpZikKCiMjIEluc3RhbGFyIHBhcXVldGVzIHkgbGxhbWFyIGxpYnJlcsOtYXMKCmBgYHtyfQojaW5zdGFsbC5wYWNrYWdlcygiZmlucmVwb3J0ciIpCmxpYnJhcnkoZmlucmVwb3J0cikKYGBgCgojIyBJbmZvcm1hY2nDs24gIGRpc3BvbmlibGUKIyMjIyMgQ29uIGxhIGZ1bmNpw7NuICpmaW5yZXBvcnRyKiBwb2RlbW9zIG9idGVuZXIgbGEgc2lndWllbnRlIGluZm9ybWFjacOzbjoKIyMjIyMgKiBDb21wYW55SW5mbygpID0gQnJpbmRhIGluZm9ybWFjacOzbiBnZW5lcmFsIGNvbW8gTm9tYnJlLCBVYmljYWNpw7NuLCBaSVAsIGV0Yy4KIyMjIyMgKiBBbm51YWxSZXBvcnRzKCkgPSBCcmluZGEgZWwgbm9tYnJlLCBmZWNoYSB5IG7Dum1lcm8gZGUgYWNjZXNvLgojIyMjIyAqIEdldEluY29tZSgpID0gQnJpbmRhIGVsIEVzdGFkbyBkZSBSZXN1bHRhZG9zLgojIyMjIyAqIEdldEJhbGFuY2VTaGVldCgpID0gQnJpbmRhIGVsIEJhbGFuY2UgR2VuZXJhbC4KIyMjIyMgKiBnZXRDYXNoRmxvdygpID0gQnJpbmRhIGVsIEZsdWpvIGRlIEVmZWN0aXZvLgoKYGBge3J9Cm9wdGlvbnMoSFRUUFVzZXJBZ2VudCA9ICJhIGFAZ21haWwuY29tIikKQ29tcGFueUluZm8oIkpQTSIpCkFubnVhbFJlcG9ydHMoIkJBQkEiLCBmb3JlaWduID0gVFJVRSkKZ29vZ2xlX2luY29tZSA8LSBHZXRJbmNvbWUoIkdPT0ciLCAyMDE2KQphbWF6b25fYmFsYW5jZSA8LSBHZXRCYWxhbmNlU2hlZXQoIkFNWk4iLDIwMTUpCmFwcGxlX2Nhc2ggPC0gR2V0Q2FzaEZsb3coIkFBUEwiLDIwMTQpCmBgYAoKCiMgVGFyZWEgNDogQW7DoWxpc2lzIEZpbmFuY2llcm86IEVtcHJlc2EgQXBwbGUKIyMjIyMgSW50ZWdyYW50ZXM6IFJlZ2luYSBFbnLDrXF1ZXosIE1heGltaWxpYW5vIENhcnZhamFsLCBHdWlsbGVybW8gQ2F6YXJlcwoKIVtdKGFwcGxlLmdpZikKCmBgYHtyfQpsaWJyYXJ5KGZvcmVjYXN0KQpsaWJyYXJ5KGZpbnJlcG9ydHIpCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCmBgYHtyfQpvcHRpb25zKEhUVFBVc2VyQWdlbnQgPSAiYSBhQGdtYWlsLmNvbSIpCkFubnVhbFJlcG9ydHMoIkFBUEwiKQpgYGAKCiMjIFByb27Ds3N0aWNvIDE6ICpPcGVyYXRpbmcgZXhwZW5zZXMgKEluY29tZSkqCgpgYGB7cn0KYXBwbGVfaW5jb21lXzIwMTEgPC0gR2V0SW5jb21lKCJBQVBMIiwgMjAxMSkKYXBwbGVfaW5jb21lXzIwMTQgPC0gR2V0SW5jb21lKCJBQVBMIiwgMjAxNCkKYXBwbGVfaW5jb21lXzIwMTcgPC0gR2V0SW5jb21lKCJBQVBMIiwgMjAxNykKYGBgCgpgYGB7cn0KQXBwbGVfT3BFeHBfMTEgPC0gc2VsZWN0KGFwcGxlX2luY29tZV8yMDExLE1ldHJpYyxBbW91bnQsZW5kRGF0ZSkKQXBwbGVfT3BFeHBfMTEgPC0gc3Vic2V0KEFwcGxlX09wRXhwXzExLCBNZXRyaWMgPT0gIlRvdGFsIG9wZXJhdGluZyBleHBlbnNlcyIpCgpBcHBsZV9PcEV4cF8xNCA8LSBzZWxlY3QoYXBwbGVfaW5jb21lXzIwMTQsTWV0cmljLEFtb3VudCxlbmREYXRlKQpBcHBsZV9PcEV4cF8xNCA8LSBzdWJzZXQoQXBwbGVfT3BFeHBfMTQsIE1ldHJpYyA9PSAiT3BlcmF0aW5nIEV4cGVuc2VzIikKCkFwcGxlX09wRXhwXzE3IDwtIHNlbGVjdChhcHBsZV9pbmNvbWVfMjAxNyxNZXRyaWMsQW1vdW50LGVuZERhdGUpCkFwcGxlX09wRXhwXzE3IDwtIHN1YnNldChBcHBsZV9PcEV4cF8xNywgTWV0cmljID09ICJPcGVyYXRpbmcgRXhwZW5zZXMiKQpgYGAKCmBgYHtyfQpBcHBsZV9PcEV4cF9jb21wbGV0ZSA8LSByYmluZChBcHBsZV9PcEV4cF8xMSxBcHBsZV9PcEV4cF8xNCxBcHBsZV9PcEV4cF8xNykKQXBwbGVfT3BFeHBfY29tcGxldGUgPC0gQXBwbGVfT3BFeHBfY29tcGxldGVbb3JkZXIoQXBwbGVfT3BFeHBfY29tcGxldGUkZW5kRGF0ZSksXQpgYGAKCmBgYHtyfQpBcHBsZV9PcEV4cF9jb21wbGV0ZSRBbW91bnQgPC0gYXMubnVtZXJpYyhBcHBsZV9PcEV4cF9jb21wbGV0ZSRBbW91bnQpCmBgYAoKIyMgQ3JlYXIgbGEgc2VyaWUgZGUgdGllbXBvCgpgYGB7cn0KdHNfT3BFeHAgPC0gdHMoZGF0YT1BcHBsZV9PcEV4cF9jb21wbGV0ZSRBbW91bnQsIHN0YXJ0ID0gYygyMDA5LDEpLCBmcmVxdWVuY3kgPSAxKQp0c19PcEV4cApgYGAKCmBgYHtyfQphcmltYV9PcEV4cCA8LSBhdXRvLmFyaW1hKHRzX09wRXhwKQphcmltYV9PcEV4cApzdW1tYXJ5KGFyaW1hX09wRXhwKQpgYGAKCmBgYHtyfQpwcm9ub3N0aWNvXzEgPC0gZm9yZWNhc3QoYXJpbWFfT3BFeHAsIGxldmVsPWMoOTUpLCBoPTYpCnByb25vc3RpY29fMQpwbG90KHByb25vc3RpY29fMSkKYGBgCgojIyBQcm9uw7NzdGljbyAyOiAqUmVhc2VhcmNoIGFuZCBEZXZlbG9wbWVudCAoSW5jb21lKSoKCmBgYHtyfQpBcHBsZV9OZXRfMTEgPC0gc2VsZWN0KGFwcGxlX2luY29tZV8yMDExLE1ldHJpYyxBbW91bnQsZW5kRGF0ZSkKQXBwbGVfTmV0XzExIDwtIHN1YnNldChBcHBsZV9OZXRfMTEsIE1ldHJpYyA9PSAiUmVzZWFyY2ggYW5kIERldmVsb3BtZW50IEV4cGVuc2UiKQoKQXBwbGVfTmV0XzE0IDwtIHNlbGVjdChhcHBsZV9pbmNvbWVfMjAxNCxNZXRyaWMsQW1vdW50LGVuZERhdGUpCkFwcGxlX05ldF8xNCA8LSBzdWJzZXQoQXBwbGVfTmV0XzE0LCBNZXRyaWMgPT0gIlJlc2VhcmNoIGFuZCBEZXZlbG9wbWVudCBFeHBlbnNlIikKCkFwcGxlX05ldF8xNyA8LSBzZWxlY3QoYXBwbGVfaW5jb21lXzIwMTcsTWV0cmljLEFtb3VudCxlbmREYXRlKQpBcHBsZV9OZXRfMTcgPC0gc3Vic2V0KEFwcGxlX05ldF8xNywgTWV0cmljID09ICJSZXNlYXJjaCBhbmQgRGV2ZWxvcG1lbnQgRXhwZW5zZSIpCmBgYAoKYGBge3J9CkFwcGxlX05ldF9jb21wbGV0ZSA8LSByYmluZChBcHBsZV9OZXRfMTEsQXBwbGVfTmV0XzE0LEFwcGxlX05ldF8xNykKQXBwbGVfTmV0X2NvbXBsZXRlIDwtIEFwcGxlX05ldF9jb21wbGV0ZVtvcmRlcihBcHBsZV9OZXRfY29tcGxldGUkZW5kRGF0ZSksXQpgYGAKCmBgYHtyfQpBcHBsZV9OZXRfY29tcGxldGUkQW1vdW50IDwtIGFzLm51bWVyaWMoQXBwbGVfTmV0X2NvbXBsZXRlJEFtb3VudCkKQXBwbGVfTmV0X2NvbXBsZXRlCmBgYAoKIyMgQ3JlYXIgbGEgc2VyaWUgZGUgdGllbXBvCgpgYGB7cn0KdHNfTmV0IDwtIHRzKGRhdGE9QXBwbGVfTmV0X2NvbXBsZXRlJEFtb3VudCwgc3RhcnQgPSBjKDIwMTIsMSksIGZyZXF1ZW5jeSA9IDEpCnRzX05ldApgYGAKCmBgYHtyfQphcmltYV9OZXQgPC0gYXV0by5hcmltYSh0c19OZXQpCmFyaW1hX05ldApzdW1tYXJ5KGFyaW1hX05ldCkKYGBgCgpgYGB7cn0KcHJvbm9zdGljb18yIDwtIGZvcmVjYXN0KGFyaW1hX05ldCwgbGV2ZWw9Yyg5NSksIGg9NikKcHJvbm9zdGljb18yCnBsb3QocHJvbm9zdGljb18yKQpgYGAKCiMjIFByb27Ds3N0aWNvIDM6ICpBc3NldHMgKEJhbGFuY2UgU2hlZXQpKgoKYGBge3J9CmFwcGxlX2JhbGFuY2VfMjAxMSA8LSBHZXRCYWxhbmNlU2hlZXQoIkFBUEwiLDIwMTEpCmFwcGxlX2JhbGFuY2VfMjAxNCA8LSBHZXRCYWxhbmNlU2hlZXQoIkFBUEwiLDIwMTQpCmFwcGxlX2JhbGFuY2VfMjAxNyA8LSBHZXRCYWxhbmNlU2hlZXQoIkFBUEwiLDIwMTcpCmBgYAoKYGBge3J9CkJpbmd1c19iYWwgPC0gYXBwbGVfYmFsYW5jZV8yMDExWywtMl0KQmluZ3VzX2JhbCA8LSBzdWJzZXQoQmluZ3VzX2JhbCwgTWV0cmljID09ICJUb3RhbCBhc3NldHMiKQpCaW5ndXNfYmFsIDwtIEJpbmd1c19iYWxbb3JkZXIoQmluZ3VzX2JhbCRlbmREYXRlKSxdCmBgYAoKYGBge3J9CkJpbmd1c19iYWwyIDwtIGFwcGxlX2JhbGFuY2VfMjAxNFssLTJdCkJpbmd1c19iYWwyIDwtIHN1YnNldChCaW5ndXNfYmFsMiwgTWV0cmljID09ICJBc3NldHMiKQpCaW5ndXNfYmFsMiA8LSBCaW5ndXNfYmFsMltvcmRlcihCaW5ndXNfYmFsMiRlbmREYXRlKSxdCmBgYAoKYGBge3J9CkJpbmd1c19iYWwzIDwtIGFwcGxlX2JhbGFuY2VfMjAxN1ssLTJdCkJpbmd1c19iYWwzIDwtIHN1YnNldChCaW5ndXNfYmFsMywgTWV0cmljID09ICJBc3NldHMiKQpCaW5ndXNfYmFsMyA8LSBCaW5ndXNfYmFsM1tvcmRlcihCaW5ndXNfYmFsMyRlbmREYXRlKSxdCmBgYAoKYGBge3J9CmFwcGxlX2JhbGFuY2VfMjAxNSA8LSBHZXRCYWxhbmNlU2hlZXQoIkFBUEwiLDIwMTUpCkJpbmd1c19iYWw0IDwtIGFwcGxlX2JhbGFuY2VfMjAxNVssLTJdCkJpbmd1c19iYWw0IDwtIHN1YnNldChCaW5ndXNfYmFsNCwgTWV0cmljID09ICJBc3NldHMiKQpCaW5ndXNfYmFsNCA8LSBCaW5ndXNfYmFsNFtvcmRlcihCaW5ndXNfYmFsNCRlbmREYXRlKSxdCkJpbmd1c19iYWw0IDwtIEJpbmd1c19iYWw0Wy0xLF0KYGBgCgpgYGB7cn0KYXBwbGVfYmFsYW5jZV8yMDEyIDwtIEdldEJhbGFuY2VTaGVldCgiQUFQTCIsMjAxMikKQmluZ3VzX2JhbDUgPC0gYXBwbGVfYmFsYW5jZV8yMDEyWywtMl0KQmluZ3VzX2JhbDUgPC0gc3Vic2V0KEJpbmd1c19iYWw1LCBNZXRyaWMgPT0gIkFzc2V0cyIpCkJpbmd1c19iYWw1IDwtIEJpbmd1c19iYWw1W29yZGVyKEJpbmd1c19iYWw1JGVuZERhdGUpLF0KQmluZ3VzX2JhbDUgPC0gQmluZ3VzX2JhbDVbLTEsXQpgYGAKCmBgYHtyfQpiaW5ndXNfYmFsYW5jZSA8LSByYmluZChCaW5ndXNfYmFsLEJpbmd1c19iYWwyLEJpbmd1c19iYWwzLCBCaW5ndXNfYmFsNCwgQmluZ3VzX2JhbDUpCmBgYAoKYGBge3J9CnN0cihiaW5ndXNfYmFsYW5jZSkKYmluZ3VzX2JhbGFuY2UkeWVhciA8LSB5ZWFyKGFzLkRhdGUoYmluZ3VzX2JhbGFuY2UkZW5kRGF0ZSkpCmJpbmd1c19iYWxhbmNlJEFtb3VudCA8LSBhcy5udW1lcmljKGJpbmd1c19iYWxhbmNlJEFtb3VudCkKYmluZ3VzX2JhbGFuY2UKYGBgCgpgYGB7cn0KYmluZ3VzX2JhbGFuY2UkQW1vdW50IDwtIGxvZyhhcy5udW1lcmljKGJpbmd1c19iYWxhbmNlJEFtb3VudCkpCmJpbmd1c19iYWxhbmNlIDwtIGJpbmd1c19iYWxhbmNlJT4lIGFycmFuZ2UoeWVhcikKYmluZ3VzX2JhbGFuY2UKYGBgCgpgYGB7cn0KYmluZ3VzX2JhbGFuY2UgPC0gYmluZ3VzX2JhbGFuY2VbLGMoMiw1KV0KYmluZ3VzX2JhbGFuY2UKYGBgCgojIyBDcmVhciBsYSBzZXJpZSBkZSB0aWVtcG8KCmBgYHtyfQp0c19Bc3NldHMgPC0gdHMoZGF0YT1iaW5ndXNfYmFsYW5jZSRBbW91bnQsIGZyZXF1ZW5jeSA9IDEsIHN0YXJ0ID0gYygyMDA5KSwgZW5kID0gYygyMDE3KSkKcGxvdCh0c19Bc3NldHMpCnRzX0Fzc2V0cwpgYGAKCmBgYHtyfQphcmltYV9Bc3NldHMgPC0gYXV0by5hcmltYSh0c19Bc3NldHMpCnN1bW1hcnkoYXJpbWFfQXNzZXRzKQphcmltYV9Bc3NldHMKYGBgCgpgYGB7cn0KcHJvbm9zdGljb18zIDwtIGZvcmVjYXN0KGFyaW1hX0Fzc2V0cywgaD01KQpwcm9ub3N0aWNvXzMKcGxvdChwcm9ub3N0aWNvXzMpCmBgYAoKIyMgQ29uY2x1c2nDs24KCkRlbnRybyBkZSBsb3MgMyBwcm9uw7NzdGljb3Mgc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGxhIGVtcHJlc2EgZGUgQXBwbGUgbWFudGllbmUgdW5hIHRlbmRlbmNpYSBwb3NpdGl2YSBjb24gdW4gY3JlY2ltaWVudG8gZ2VuZXJhbCBkdXJhbnRlIGxvcyBhw7FvcywgbG8gY3VhbCBoYWNlIHNlbnRpZG8geWEgcXVlIGxhIGVtcHJlc2EgZXN0w6EgY3JlY2llbmRvIGUgaW5ub3ZhbmRvIGNvbnN0YW50ZW1lbnRlLiBFbiBlc3RlIGNhc28gY3JlZW1vcyBxdWUgZXMgbWVqb3IgbWFuZWphciBsb3MgZGF0b3MgZGUgbWFuZXJhIHRyaW1lc3RyYWwsIGRlYmlkbyBhIHF1ZSBzaSBzZSBtYW5lamEgcG9yIGHDsW8gZWwgcHJvbsOzc3RpY28gY29taWVuemEgYSBzZXIgdW4gcG9jbyBtw6FzIHBlc2FkbyB5IGxvcyBwcm9uw7NzdGljb3MgdGVybWluYW4gc2llbmRvIG9ic29sZXRvcyB5YSBxdWUgZWwgcGFxdWV0ZSBkZSAqZm9yZWNhc3QqIHNpbXBsZW1lbnRlIG5vIGNhbWJpYS4gRGUgaWd1YWwgZm9ybWEgaWRlbnRpZmljYW1vcyBxdWUgZW4gb2Nhc2lvbmVzIHB1ZWRlIGhhYmVyIHJlcGV0aWNpb25lcyBkZSBsb3MgYcOxb3MsIHBvciBsbyBxdWUgZXMgaW1wb3J0YW50ZSBoYWNlciBub3RhIGRlIGVzdG9zIHkgc2VsZWNjaW9uYXIgbG9zIG5lY2VzYXJpb3MgYSB0cmF2w6lzIGRlIG1hbmlwdWxhY2nDs24gZGUgYmFzZXMgZGUgZGF0b3MgcGFyYSBjcmVhciB1biBidWVuIHByb27Ds3N0aWNvLgoK