Ejercicio en clase

Concepto

Una Serie de tiempo es una colección de observaciones sobre un determinado fenómeno, efectuadas en momentos sucesivos, usualmente esquiespaciados.
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

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

Crear la serie de tiempo

Ejemplo Los siguentes datos de producción trimestral inician en el primer trimestre de 2020. Se busca pronosticar la producción de los siguentes 5 trimestres.

produccion <- c(50,54,55,57,55,60)
ts <- ts(data=produccion, start = c(2020,1), frequency = 4)
ts
##      Qtr1 Qtr2 Qtr3 Qtr4
## 2020   50   54   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, D=1)
summary(arima)
## Series: ts 
## ARIMA(0,0,0)(0,1,0)[4] with drift 
## 
## Coefficients:
##        drift
##       1.3750
## s.e.  0.0884
## 
## sigma^2 = 0.5102:  log likelihood = -1.45
## AIC=6.9   AICc=-5.1   BIC=4.29
## 
## Training set error measures:
##                      ME      RMSE      MAE        MPE      MAPE       MASE
## Training set 0.03370832 0.2916137 0.200375 0.04987509 0.3529054 0.03643182
##                    ACF1
## Training set -0.5114898

Generar el pronóstico

pronostico <- forecast(arima, level =c(50), h=5)
pronostico
##         Point Forecast    Lo 50    Hi 50
## 2021 Q3           60.5 60.01821 60.98179
## 2021 Q4           62.5 62.01821 62.98179
## 2022 Q1           60.5 60.01821 60.98179
## 2022 Q2           65.5 65.01821 65.98179
## 2022 Q3           66.0 65.31864 66.68136
plot(pronostico)

Actividad 2 - Hershey’s

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

ARIMA significa AutoRegressive Integrated Moving Average o Modelo Autorregresivo Integrado de Promedio Móvil.

arima1 <- auto.arima(ts1)
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=5)
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
plot(pronostico1)

Finanzas Corporativas

Instalar paquetes y llamar librerias

library(finreportr)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

Infromación disponible

Con la función “fillreport” 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.
- BalanceSheet() = 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_cashflow <- GetCashFlow("AAPL",2014)

Ejercicio en equipos

Equipo7: Ares Melendéz, Humberto Mena, Tania Ortega.

options(HTTPUserAgent = "a a@gmail.com")
CompanyInfo("WFC")
##                    company        CIK  SIC state state.inc FY.end
## 1 WELLS FARGO & COMPANY/MN 0000072971 6021    CA        DE   1231
##          street.address             city.state
## 1 420 MONTGOMERY STREET SAN FRANCISCO CA 94104
AnnualReports("WFC")
##    filing.name filing.date         accession.no
## 1         10-K  2024-02-20 0000072971-24-000064
## 2         10-K  2023-02-21 0000072971-23-000071
## 3         10-K  2022-02-22 0000072971-22-000096
## 4         10-K  2021-02-23 0000072971-21-000197
## 5         10-K  2020-02-27 0000072971-20-000217
## 6         10-K  2019-02-27 0000072971-19-000227
## 7         10-K  2018-03-01 0000072971-18-000272
## 8         10-K  2017-03-01 0000072971-17-000278
## 9         10-K  2016-02-24 0000072971-16-001045
## 10        10-K  2015-02-25 0000072971-15-000449
## 11        10-K  2014-02-26 0000072971-14-000337
## 12        10-K  2013-02-27 0001193125-13-078820
## 13        10-K  2012-02-28 0001193125-12-084528
## 14        10-K  2011-02-25 0000950123-11-018541
## 15        10-K  2010-02-26 0000950123-10-017877
## 16        10-K  2009-02-27 0000950134-09-003967
## 17        10-K  2008-02-29 0000950134-08-003822
## 18        10-K  2007-03-01 0000950134-07-004518
## 19        10-K  2006-03-09 0000950149-06-000083
## 20      10-K/A  2005-03-17 0000950134-05-005350
## 21        10-K  2005-03-10 0000950134-05-004623
## 22        10-K  2004-03-12 0000950134-04-003387
## 23      10-K/A  2004-01-16 0000950149-04-000152
## 24        10-K  2003-03-14 0001047469-03-008749
## 25        10-K  2002-03-15 0000912057-02-010174
## 26        10-K  2001-03-16 0000912057-01-504042
## 27        10-K  2000-03-17 0000912057-00-012168
## 28      10-K/A  1999-03-23 0001047469-99-010910
## 29     10-K405  1999-03-17 0001047469-99-010171
## 30        10-K  1998-02-27 0001045969-98-000259
## 31        10-K  1997-03-04 0000950109-97-001905
## 32        10-K  1996-03-07 0000950131-96-000962
## 33        10-K  1995-03-16 0000950131-95-000611
## 34      10-K/A  1994-05-13 0000072971-94-000005
## 35        10-K  1994-03-08 0000072971-94-000003

Obtención de los datos

ER5<- GetIncome('WFC',2013)
ER4 <- GetIncome('WFC',2014)
ER1 <- GetIncome('WFC',2015)
ER <- GetIncome('WFC',2016)
ER2 <- GetIncome('WFC',2017)
ER3 <- GetIncome('WFC',2018)
BS5<- GetBalanceSheet('WFC',2013)
BS4 <- GetBalanceSheet('WFC',2014)
BS1 <- GetBalanceSheet('WFC',2015)
BS <- GetBalanceSheet('WFC',2016)
BS2 <- GetBalanceSheet('WFC',2017)
BS3 <- GetBalanceSheet('WFC',2018)

Selección de Variables

Income Statement
e1 <- ER5[c(16,17,18),]
e2 <- ER4[c(16,17,18),]
e3 <- ER1[c(63,64,65),]
e4 <- ER[c(63,64,65),]
e5 <- ER2[c(63,64,65),]
e6<- ER3[c(63,64,65),]
ER_<- rbind(e1,e2,e3,e4,e5,e6)
ER_$startDate<- as.Date(ER_$startDate)
ER_<- arrange(ER_, startDate)
ER_ <- ER_[c(1,2,4,7,10,13,16,18),]
ER_$Amount<- as.numeric(ER_$Amount)
Balance Sheet
B1 <- BS5[c(37,38,39),]
B2 <- BS4[c(39,40,41),]
B3 <- BS1[c(35,36,37),]
B4 <- BS[c(35,36,37),]
B5 <- BS2[c(35,36,37),]
B6<- BS3[c(35,36,37),]
BS_<- rbind(B1,B2,B3,B4,B5,B6)
BS_$startDate<- as.Date(BS_$startDate)
BS_<- arrange(BS_, startDate)
BS_ <- BS_[c(1,2,4,7,10,13,16,18),]
BS_$Amount<- as.numeric(BS_$Amount)

Serie de Tiempo

ts <- ts(data=ER_$Amount , start = 2010)

Arima with INSURANCE SERVICES REVENUE (Income Statement)*

arima2 <- auto.arima(ER_$Amount, D=1)
arima2
## Series: ER_$Amount 
## ARIMA(0,1,0) with drift 
## 
## Coefficients:
##            drift
##       -153857143
## s.e.    51448140
## 
## sigma^2 = 2.192e+16:  log likelihood = -141.08
## AIC=286.17   AICc=289.17   BIC=286.06
summary(arima2)
## Series: ER_$Amount 
## ARIMA(0,1,0) with drift 
## 
## Coefficients:
##            drift
##       -153857143
## s.e.    51448140
## 
## sigma^2 = 2.192e+16:  log likelihood = -141.08
## AIC=286.17   AICc=289.17   BIC=286.06
## 
## Training set error measures:
##                  ME      RMSE      MAE       MPE     MAPE      MASE       ACF1
## Training set 284982 128204941 88927839 -1.030368 6.120293 0.5389566 -0.2415709
pronostico2 <- forecast(arima2, level = c(95), h=5)
pronostico2
##    Point Forecast      Lo 95      Hi 95
##  9      895142857  604993093 1185292621
## 10      741285714  330951983 1151619446
## 11      587428571   84874438 1089982705
## 12      433571429 -146728100 1013870957
## 13      279714286 -369080311  928508882
plot(pronostico2)

Al observar esta gráfica podemos entender que la cantidad de dinero que enseñaba el estado de resultados a través de los años ha ido disminuyendo notoriamente por el paso de los años. El estado de resultados en una evaluación financiera la cual nos indica si la empresa ha tenido ganancias o pérdidas durante un periodo determinado. En este caso podemos comprender que durante los últimos años el banco americano, Wells Fargo, ha perdido dinero de acuerdo a su estado de resultados y de acuerdo a nuestro pronóstico podemos inferir que estas pérdidas seguirán ocurriendo durante los próximos años.

Arima with Goodwill (Balance Sheet)

arima3 <- auto.arima(BS_$Amount, D=1)
arima3
## Series: BS_$Amount 
## ARIMA(0,1,0) 
## 
## sigma^2 = 2.21e+17:  log likelihood = -149.71
## AIC=301.42   AICc=302.22   BIC=301.37
summary(arima3)
## Series: BS_$Amount 
## ARIMA(0,1,0) 
## 
## sigma^2 = 2.21e+17:  log likelihood = -149.71
## AIC=301.42   AICc=302.22   BIC=301.37
## 
## Training set error measures:
##                     ME      RMSE       MAE       MPE     MAPE      MASE
## Training set 230221248 439756545 274221248 0.8830396 1.055393 0.8849925
##                    ACF1
## Training set -0.3716326
pronostico3 <- forecast(arima, level = c(95), h=5)
pronostico3
##         Point Forecast    Lo 95    Hi 95
## 2021 Q3           60.5 59.09999 61.90001
## 2021 Q4           62.5 61.09999 63.90001
## 2022 Q1           60.5 59.09999 61.90001
## 2022 Q2           65.5 64.09999 66.90001
## 2022 Q3           66.0 64.02008 67.97992
plot(pronostico3)

Al observar la gráfica podemos entender que el pronóstico en cuanto a los ingresos basados en el balance general de la empresa han ido aumentando conforme el paso de los años y se pronostica que dentro de un futuro se mantengan incrementando.
LS0tCnRpdGxlOiAiU2VyaWVzIGRlIFRpZW1wbyIKYXV0aG9yOiAiVGFuaWEgT3J0ZWdhIC0gQTAxNzIxNDQ5IgpkYXRlOiAiMjAyNC0wMi0xNSIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiBUUlVFCiAgICB0b2NfZmxvYXQ6IFRSVUUKICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUKLS0tCiMgRWplcmNpY2lvIGVuIGNsYXNlCiFbXSgyMDAud2VicCkKCiMjIENvbmNlcHRvClVuYSAqKlNlcmllIGRlIHRpZW1wbyoqIGVzIHVuYSBjb2xlY2Npw7NuIGRlIG9ic2VydmFjaW9uZXMgc29icmUgdW4gZGV0ZXJtaW5hZG8gZmVuw7NtZW5vLCBlZmVjdHVhZGFzIGVuIG1vbWVudG9zIHN1Y2VzaXZvcywgdXN1YWxtZW50ZSBlc3F1aWVzcGFjaWFkb3MuICAgICAgICAgCjEuIFByZWNpb3MgZGUgYWNjaW9uZXMuICAgICAgICAgCjIuIE5pdmVsZXMgZGUgaW52ZW50YXJpby4gICAgICAgICAKMy4gUm90YWNpw7NuIGRlIHBlcnNvbmFsICAgICAgICAgCjQuIFZlbnRhcy4gICAgICAgIAo1LiBQSUIgKCpHRFAqKS4gICAgICAgICAKCk3DoXMgaW5mb3JtYWNpw7NuOgpbTGlicm8gKlIgZm9yIERhdGEgU2NpZW5jZSgyZSkqXShodHRwczovL3I0ZHMuaGFkbGV5Lm56LykKCiMjIEluc3RhbGFyIHBhcXVldGVzIHkgbGxhbWFyIGxpYnJlcsOtYXMKYGBge3J9CmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkocmVhZHhsKQpgYGAKCiMjIENyZWFyIGxhIHNlcmllIGRlIHRpZW1wbwoqKkVqZW1wbG8qKgpMb3Mgc2lndWVudGVzIGRhdG9zIGRlIHByb2R1Y2Npw7NuIHRyaW1lc3RyYWwgaW5pY2lhbiBlbiBlbCBwcmltZXIgdHJpbWVzdHJlIGRlIDIwMjAuIApTZSBidXNjYSBwcm9ub3N0aWNhciBsYSBwcm9kdWNjacOzbiBkZSBsb3Mgc2lndWVudGVzIDUgdHJpbWVzdHJlcy4gIAoKYGBge3J9CnByb2R1Y2Npb24gPC0gYyg1MCw1NCw1NSw1Nyw1NSw2MCkKdHMgPC0gdHMoZGF0YT1wcm9kdWNjaW9uLCBzdGFydCA9IGMoMjAyMCwxKSwgZnJlcXVlbmN5ID0gNCkKdHMKYGBgCgojIyBDcmVhciBtb2RlbG8gQVJJTUEKKipBUklNQSoqIHNpZ25pZmljYSAqQXV0b1JlZ3Jlc3NpdmUgSW50ZWdyYXRlZCBNb3ZpbmcgQXZlcmFnZSogbyBNb2RlbG8gQXV0b3JyZWdyZXNpdm8gSW50ZWdyYWRvIGRlIFByb21lZGlvIE3Ds3ZpbC4gIApgYGB7cn0KYXJpbWEgPC0gYXV0by5hcmltYSh0cywgRD0xKQpzdW1tYXJ5KGFyaW1hKQpgYGAKCiMjIEdlbmVyYXIgZWwgcHJvbsOzc3RpY28gCmBgYHtyfQpwcm9ub3N0aWNvIDwtIGZvcmVjYXN0KGFyaW1hLCBsZXZlbCA9Yyg1MCksIGg9NSkKcHJvbm9zdGljbwpwbG90KHByb25vc3RpY28pCmBgYAoKIyBBY3RpdmlkYWQgMiAtIEhlcnNoZXkncyAKIVtdKGhlcnNoZXkuZ2lmKQoKYGBge3J9CmxlY2hpdGE8LSByZWFkX2V4Y2VsKCdWZW50YXNfSGlzdG/MgXJpY2FzX0xlY2hpdGFzLnhsc3gnKQpgYGAKCiMjIENyZWFyIGxhIHNlcmllIGRlIHRpZW1wbwpgYGB7cn0KdHMxIDwtIHRzKGRhdGE9bGVjaGl0YSRWZW50YXMsIHN0YXJ0ID0gYygyMDE3LDEpLCBmcmVxdWVuY3kgPSAxMikKdHMxCmBgYAoKIyMgQ3JlYXIgbW9kZWxvIEFSSU1BCioqQVJJTUEqKiBzaWduaWZpY2EgKkF1dG9SZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UqIG8gTW9kZWxvIEF1dG9ycmVncmVzaXZvIEludGVncmFkbyBkZSBQcm9tZWRpbyBNw7N2aWwuICAKYGBge3J9CmFyaW1hMSA8LSBhdXRvLmFyaW1hKHRzMSkKc3VtbWFyeShhcmltYTEpCmBgYAoKIyMgR2VuZXJhciBlbCBwcm9uw7NzdGljbyAKYGBge3J9CnByb25vc3RpY28xIDwtIGZvcmVjYXN0KGFyaW1hMSwgbGV2ZWwgPWMoOTUpLCBoPTUpCnByb25vc3RpY28xCnBsb3QocHJvbm9zdGljbzEpCmBgYAoKCiMgRmluYW56YXMgQ29ycG9yYXRpdmFzCgojIyBJbnN0YWxhciBwYXF1ZXRlcyB5IGxsYW1hciBsaWJyZXJpYXMKYGBge3J9CmxpYnJhcnkoZmlucmVwb3J0cikKbGlicmFyeShkcGx5cikKYGBgCgojIyBJbmZyb21hY2nDs24gZGlzcG9uaWJsZQpDb24gbGEgZnVuY2nDs24gImZpbGxyZXBvcnQiIHBvZGVtb3Mgb2J0ZW5lciBsYSBzaWd1aWVudGUgaW5mb3JtYWNpw7NuOiAgICAgICAKLSBDb21wYW55SW5mbygpID0gQnJpbmRhIGluZm9ybWFjacOzbiBnZW5lcmFsIGNvbW8gTm9tYnJlLCBVYmljYWNpw7NuLCBaSVAsIGV0Yy4gICAgICAgICAgICAgICAgCi0gQW5udWFsUmVwb3J0cygpID0gQnJpbmRhIGVsIG5vbWJyZSwgZmVjaGEgeSBuw7ptZXJvIGRlIGFjY2Vzby4gICAgICAgICAgICAgICAgCi0gR2V0SW5jb21lKCgpKT0gQnJpbmRhIGVsIEVzdGFkbyBkZSBSZXN1bHRhZG9zLiAgICAgICAgICAgICAgICAgIAotIEJhbGFuY2VTaGVldCgpID0gQnJpbmRhIGVsIEJhbGFuY2UgR2VuZXJhbC4gICAgICAgICAgICAgICAgCi0gR2V0Q2FzaEZsb3coKSA9IEJyaW5kYSBlbCBmbHVqbyBkZSBFZmVjdGl2by4gICAgICAgICAgCiAgICAgIAoKCiFbXShzdG9jay5naWYpCgpgYGB7cn0Kb3B0aW9ucyhIVFRQVXNlckFnZW50ID0gImEgYUBnbWFpbC5jb20iKQpDb21wYW55SW5mbygiSlBNIikKQW5udWFsUmVwb3J0cygiQkFCQSIsIGZvcmVpZ24gPSBUUlVFKQpnb29nbGVfaW5jb21lIDwtIEdldEluY29tZSgiR09PRyIsMjAxNikKYW1hem9uX2JhbGFuY2UgPC0gR2V0QmFsYW5jZVNoZWV0KCJBTVpOIiwyMDE1KQphcHBsZV9jYXNoZmxvdyA8LSBHZXRDYXNoRmxvdygiQUFQTCIsMjAxNCkKYGBgCgojIyBFamVyY2ljaW8gZW4gZXF1aXBvcyAKIyMjIEVxdWlwbzc6IEFyZXMgTWVsZW5kw6l6LCBIdW1iZXJ0byBNZW5hLCBUYW5pYSBPcnRlZ2EuCmBgYHtyfSAKb3B0aW9ucyhIVFRQVXNlckFnZW50ID0gImEgYUBnbWFpbC5jb20iKQpDb21wYW55SW5mbygiV0ZDIikKQW5udWFsUmVwb3J0cygiV0ZDIikKYGBgCiAKIyMjIE9idGVuY2nDs24gZGUgbG9zIGRhdG9zIApgYGB7cn0KRVI1PC0gR2V0SW5jb21lKCdXRkMnLDIwMTMpCkVSNCA8LSBHZXRJbmNvbWUoJ1dGQycsMjAxNCkKRVIxIDwtIEdldEluY29tZSgnV0ZDJywyMDE1KQpFUiA8LSBHZXRJbmNvbWUoJ1dGQycsMjAxNikKRVIyIDwtIEdldEluY29tZSgnV0ZDJywyMDE3KQpFUjMgPC0gR2V0SW5jb21lKCdXRkMnLDIwMTgpCmBgYAoKYGBge3J9CkJTNTwtIEdldEJhbGFuY2VTaGVldCgnV0ZDJywyMDEzKQpCUzQgPC0gR2V0QmFsYW5jZVNoZWV0KCdXRkMnLDIwMTQpCkJTMSA8LSBHZXRCYWxhbmNlU2hlZXQoJ1dGQycsMjAxNSkKQlMgPC0gR2V0QmFsYW5jZVNoZWV0KCdXRkMnLDIwMTYpCkJTMiA8LSBHZXRCYWxhbmNlU2hlZXQoJ1dGQycsMjAxNykKQlMzIDwtIEdldEJhbGFuY2VTaGVldCgnV0ZDJywyMDE4KQpgYGAKCiMjIyBTZWxlY2Npw7NuIGRlIFZhcmlhYmxlcyAKCiMjIyMjIEluY29tZSBTdGF0ZW1lbnQKYGBge3J9CmUxIDwtIEVSNVtjKDE2LDE3LDE4KSxdCmUyIDwtIEVSNFtjKDE2LDE3LDE4KSxdCmUzIDwtIEVSMVtjKDYzLDY0LDY1KSxdCmU0IDwtIEVSW2MoNjMsNjQsNjUpLF0KZTUgPC0gRVIyW2MoNjMsNjQsNjUpLF0KZTY8LSBFUjNbYyg2Myw2NCw2NSksXQpgYGAKCmBgYHtyfQpFUl88LSByYmluZChlMSxlMixlMyxlNCxlNSxlNikKRVJfJHN0YXJ0RGF0ZTwtIGFzLkRhdGUoRVJfJHN0YXJ0RGF0ZSkKRVJfPC0gYXJyYW5nZShFUl8sIHN0YXJ0RGF0ZSkKRVJfIDwtIEVSX1tjKDEsMiw0LDcsMTAsMTMsMTYsMTgpLF0KYGBgCgpgYGB7cn0KRVJfJEFtb3VudDwtIGFzLm51bWVyaWMoRVJfJEFtb3VudCkKYGBgCgojIyMjIyBCYWxhbmNlIFNoZWV0CmBgYHtyfQpCMSA8LSBCUzVbYygzNywzOCwzOSksXQpCMiA8LSBCUzRbYygzOSw0MCw0MSksXQpCMyA8LSBCUzFbYygzNSwzNiwzNyksXQpCNCA8LSBCU1tjKDM1LDM2LDM3KSxdCkI1IDwtIEJTMltjKDM1LDM2LDM3KSxdCkI2PC0gQlMzW2MoMzUsMzYsMzcpLF0KYGBgCgpgYGB7cn0KQlNfPC0gcmJpbmQoQjEsQjIsQjMsQjQsQjUsQjYpCkJTXyRzdGFydERhdGU8LSBhcy5EYXRlKEJTXyRzdGFydERhdGUpCkJTXzwtIGFycmFuZ2UoQlNfLCBzdGFydERhdGUpCkJTXyA8LSBCU19bYygxLDIsNCw3LDEwLDEzLDE2LDE4KSxdCmBgYAoKYGBge3J9CkJTXyRBbW91bnQ8LSBhcy5udW1lcmljKEJTXyRBbW91bnQpCmBgYAoKIyMjIFNlcmllIGRlIFRpZW1wbwpgYGB7cn0KdHMgPC0gdHMoZGF0YT1FUl8kQW1vdW50ICwgc3RhcnQgPSAyMDEwKQpgYGAKCgojIyMgKkFyaW1hIHdpdGggSU5TVVJBTkNFIFNFUlZJQ0VTIFJFVkVOVUUgKihJbmNvbWUgU3RhdGVtZW50KSogCmBgYHtyfQphcmltYTIgPC0gYXV0by5hcmltYShFUl8kQW1vdW50LCBEPTEpCmFyaW1hMgpzdW1tYXJ5KGFyaW1hMikKYGBgCgpgYGB7cn0KcHJvbm9zdGljbzIgPC0gZm9yZWNhc3QoYXJpbWEyLCBsZXZlbCA9IGMoOTUpLCBoPTUpCnByb25vc3RpY28yCmBgYAoKYGBge3J9CnBsb3QocHJvbm9zdGljbzIpCmBgYAoKIyMjIyMgQWwgb2JzZXJ2YXIgZXN0YSBncsOhZmljYSBwb2RlbW9zIGVudGVuZGVyIHF1ZSBsYSBjYW50aWRhZCBkZSBkaW5lcm8gcXVlIGVuc2XDsWFiYSBlbCBlc3RhZG8gZGUgcmVzdWx0YWRvcyBhIHRyYXbDqXMgZGUgbG9zIGHDsW9zIGhhIGlkbyBkaXNtaW51eWVuZG8gbm90b3JpYW1lbnRlIHBvciBlbCBwYXNvIGRlIGxvcyBhw7Fvcy4gRWwgZXN0YWRvIGRlIHJlc3VsdGFkb3MgZW4gdW5hIGV2YWx1YWNpw7NuIGZpbmFuY2llcmEgbGEgY3VhbCBub3MgaW5kaWNhIHNpIGxhIGVtcHJlc2EgaGEgdGVuaWRvIGdhbmFuY2lhcyBvIHDDqXJkaWRhcyBkdXJhbnRlIHVuIHBlcmlvZG8gZGV0ZXJtaW5hZG8uIEVuIGVzdGUgY2FzbyBwb2RlbW9zIGNvbXByZW5kZXIgcXVlIGR1cmFudGUgbG9zIMO6bHRpbW9zIGHDsW9zIGVsIGJhbmNvIGFtZXJpY2FubywgV2VsbHMgRmFyZ28sIGhhIHBlcmRpZG8gZGluZXJvIGRlIGFjdWVyZG8gYSBzdSBlc3RhZG8gZGUgcmVzdWx0YWRvcyB5IGRlIGFjdWVyZG8gYSBudWVzdHJvIHByb27Ds3N0aWNvIHBvZGVtb3MgaW5mZXJpciBxdWUgZXN0YXMgcMOpcmRpZGFzIHNlZ3VpcsOhbiBvY3VycmllbmRvIGR1cmFudGUgbG9zIHByw7N4aW1vcyBhw7Fvcy4gCgoKIyMjICpBcmltYSB3aXRoIEdvb2R3aWxsIChCYWxhbmNlIFNoZWV0KSoKYGBge3J9CmFyaW1hMyA8LSBhdXRvLmFyaW1hKEJTXyRBbW91bnQsIEQ9MSkKYXJpbWEzCnN1bW1hcnkoYXJpbWEzKQpgYGAKCmBgYHtyfQpwcm9ub3N0aWNvMyA8LSBmb3JlY2FzdChhcmltYSwgbGV2ZWwgPSBjKDk1KSwgaD01KQpwcm9ub3N0aWNvMwpgYGAKCmBgYHtyfQpwbG90KHByb25vc3RpY28zKQpgYGAKCiMjIyMjIEFsIG9ic2VydmFyIGxhIGdyw6FmaWNhIHBvZGVtb3MgZW50ZW5kZXIgcXVlIGVsIHByb27Ds3N0aWNvIGVuIGN1YW50byBhIGxvcyBpbmdyZXNvcyBiYXNhZG9zIGVuIGVsIGJhbGFuY2UgZ2VuZXJhbCBkZSBsYSBlbXByZXNhIGhhbiBpZG8gYXVtZW50YW5kbyBjb25mb3JtZSBlbCBwYXNvIGRlIGxvcyBhw7FvcyB5IHNlIHByb25vc3RpY2EgcXVlIGRlbnRybyBkZSB1biBmdXR1cm8gc2UgbWFudGVuZ2FuIGluY3JlbWVudGFuZG8uIAo=