Primero descargamos y analizamos los datos utilizados en este proyecto, los cuales son empresas peruanas que accionan en la bolsa de Estados unidos. LA acción de análisis fundamental el cual se tomara se Credicorp representada con el ticker BAP.
En la siguiente tabla se encuentran los datos que vammos a utlizar a lo largo de este trabajo, el cual se puede descargar los datos para el uso del lector.
Ahora después de haber descargado los datos procedemos a realizar un resumen de estos, en la cual se mostrara los siguienres aspectos:
| Mean | SD | Median | Min | Max | Boxplot | Histogram | Line | |
|---|---|---|---|---|---|---|---|---|
| SCCO | 35.38 | 13.07 | 32.73 | 18.89 | 81.41 | |||
| BAP | 169.57 | 44.00 | 155.69 | 81.57 | 250.70 | |||
| BVN | 11.90 | 3.13 | 12.31 | 3.31 | 17.71 | |||
| CPAC | 6.86 | 1.43 | 6.83 | 3.64 | 10.05 | |||
| FSM | 4.76 | 1.64 | 4.53 | 1.80 | 9.54 |
Este gráfico se puede ver en la acción BAP que su valor mÃnimo es de 81.57 y su máximo es de 250.70 por lo cual se decidió tomar 8 estados para hacer el pronstico de para l aacción de credicorp
library(PerformanceAnalytics)
chart.TimeSeries(precios %>% scale(),legend.loc = "left",main = "Cotizaciones de las acciones peruanas")Ahora tomamos la serie de BAP y hallamos matiz de estado de esta serie tomando solo 7 estados como se dijo en la primera parte.
Lo primero es definir los estados de la serie los cuales se obtiene el comando seq() lo que permite dividir el rango entre el minimo y el máximo de la serie en una secuencia de 8 valores, de esos 8 valores se toman los limites para cada estado. Después de realizar eso queda el paso de armar la matriz de frecuencia para ver el cambio de estado a estado. lo cual se puede hacer con la función table() y resagando la serie un periodo. Como ultimo paso se divide cada fila entre su total y se obtiene la matriz de transición.
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|
| 95 | 3 | 0 | 0 | 0 | 0 | 2 |
| 3 | 188 | 11 | 0 | 0 | 0 | 14 |
| 0 | 9 | 412 | 11 | 0 | 0 | 14 |
| 0 | 0 | 13 | 141 | 2 | 0 | 4 |
| 0 | 0 | 0 | 2 | 77 | 12 | 5 |
| 0 | 0 | 0 | 0 | 13 | 335 | 20 |
| 2 | 15 | 11 | 6 | 4 | 21 | 187 |
Después de ver hallado la matriz de transción seperamos los datos en test y entrenamiento. En el caso del test se tiene los siguientes resultados plasmado en el sigueinte gráfico y cuadro.
Precio original | Esatdo original | Estado pronosticado | Precio pronosticado |
120,34 | 2 | 2 | 117,8121 |
117,95 | 2 | 2 | 117,8121 |
119,99 | 2 | 2 | 117,8121 |
116,33 | 2 | 2 | 117,8121 |
116,58 | 2 | 2 | 117,8121 |
116,76 | 2 | 2 | 117,8121 |
116,53 | 2 | 2 | 117,8121 |
118,04 | 2 | 2 | 117,8121 |
119,53 | 2 | 2 | 117,8121 |
123,71 | 2 | 2 | 117,8121 |
Fuente: Propia | |||
Interpretación: Podemos observar que los estados predichos y la serie original concuerdan en un 100%. En este caso la predicción o el valor pronosticado es la media entre los intervalos de los estados en este caso es en el estado número 2.
Interpretación: En este gráfico podemos observar que el valor predicho es constante en todo la serie esto se debe a que la predicción solo da un intervalo esto se sera explicado en el pronostico en donde se verá los intervaloes de la serie.
Vamos a realizar una predicción hacia el futuro en 10 periodos y se graficara el intervalo de confianza.
Interpretación: Como se menciono alteriormente que se tomaba la media de cada de intervalo de los 7 estados y se puede observar que el precio fluctua en el intervalo marcado de color azul.
Ahora después de haber analizado la serie con el metodo de cadenas de markov, se procede a realiazar diversos metodos de series de tiempo y de redes neuronales para comparar cual de estos modelos me da una mejor predicción.
Primero se analiza la serie para ver si hay precencia de datos atipicos.
Primero vamos a graficar el famoso diagrama de cajas el cual nos permite ver si hay datos atipicos:
Interpretación: Podemos ver el inicio y el final de la data tomada para este trabajo. Se puede observar que en los años 2016 y 2020 presentan una gran cantidad de datos atipicos, esto se observa más en el año 2020 el cual se ve reflejado el impacto del covid 19.
La segunda opción es usando un paquete de R el cual es anomalize y nos permite hallar los valores atipicos mediante un grafico en el cual me da un intervalo de confianza, los valores de rojo son aquellos atipicos.
Interpretación: Como se anlizo antes se puede observar que en donde hay más datos atipicos es en el año 2020.
Cuando se analizan las estas series con los modelos ARIMA una condición es que esta serie sea estacionaria para esto se va analizar con el test de dicker-fuller, en el cual consiste en no rechazar la hipotesis alternativa osea que el p-value sea menor a 0.05.
El resulatdo obtenido al aplicar este test es de 0.9573389 por la cual no se rechaza la hipotesis nula por lo cual se tiene que diferrenciar la serie.
Para esto se calcula los retornos de la serie y se compara con la serie antigua,
Interpretación: Se puede observar las diferencias entre las series. La serie diferenciada se mueve entorno a una media de 0.
Después de diferenciar la serie se compara sus acf y pcaf para tomar el mejor modelo ARIMA. Antes de este paso vamos a limpiar la serie es decir que vamos a quitar el ruido, ruido seria cuando se generan anomaliaz en esta serie. Uno de los metodos es usar el filtro kalman pero este se aplicara en el codigo de python en este caso se usara el fltro de hampel.
library(pracma )
data<- data.frame("fecha"=index(d),"retornos"=as.numeric(d))
omad <- hampel(data$retornos, k=20)
data$"filtro"<- NA
data$"filtro"[omad$ind]<- data$retornos[omad$ind]
ggplot(data)+geom_line(mapping = aes(x=fecha,y=retornos),color="red",alpha=0.5)+
geom_point(mapping = aes(y=filtro,x=fecha),color="blue")+labs(title="Filtro de hampel")+theme_elegante()table_t(data[omad$ind,c(1,2)] %>% as.data.frame(),"blue","Fuente: Propia","Resulatdo del algoritmo")fecha | retornos |
2015-04-01 | 5,592941 |
2015-08-14 | -6,517510 |
2015-08-27 | 5,974396 |
2015-10-05 | 4,607193 |
2015-12-18 | -5,852646 |
2016-04-11 | 11,967499 |
2016-06-10 | -7,014633 |
2016-06-24 | -6,272248 |
2016-07-08 | 5,834427 |
2016-09-09 | -6,367416 |
2016-11-04 | 8,432770 |
2017-08-10 | -6,978989 |
2017-09-19 | -7,729523 |
2017-12-14 | -11,368134 |
2017-12-18 | 10,230331 |
2018-02-02 | -7,395782 |
2018-02-08 | -10,809219 |
2018-09-04 | -6,230011 |
2018-11-20 | -8,639999 |
2019-02-07 | -9,339996 |
2019-04-15 | -7,860001 |
2019-05-08 | -7,789994 |
2019-05-13 | -8,070007 |
2019-08-14 | -6,739991 |
2019-11-08 | -10,580002 |
2019-11-15 | 6,669999 |
2020-01-07 | -7,110001 |
2020-02-06 | -12,620010 |
2020-03-13 | 20,480011 |
2020-03-16 | -24,440002 |
2020-05-01 | -9,449997 |
2020-06-05 | 11,180008 |
2020-10-06 | 4,519996 |
2020-11-09 | 18,750000 |
2020-11-10 | -24,580002 |
2021-01-06 | 5,860000 |
2021-02-09 | 6,830001 |
2021-04-06 | 6,540008 |
2021-04-08 | 7,820008 |
2021-05-10 | 12,379997 |
2021-05-12 | 6,640000 |
Fuente: Propia | |
En este cuadro se puede ver los precios y las fechas en los cuales el algoritmos los a clasificado como anomalos.
despues de esto se reemplaza los valores atipicos respecto a su mediana.
d<- diff(precios$BAP)[-1]
omad <- hampel(d, k=20)
d_new<- omad$yCon la limpieza ya hecha ahora procedemos analizar el mejor modelo ARIMA. Para esto usaremos un ciclo for y se mostrara los resultados.
Ahora mostrareos el ACF:
Interpretación: Se puede tomar el rezago 2 y el 4 para el orden de autorregresivos.
Interpretación: Se puede tomar el rezago 2 y el 4 para el orden de medias moviles.
Para esta parte se tomara 5 rezagos para crear el modelo es decir se ira probando mediante un ciclo for cual de todos es el mejor modelo tomando como referencia el criterio de akaike.
| z1 | sigma | logLik | AIC | BIC | |
|---|---|---|---|---|---|
| 2 | ARMA(0,0) | 2.985154 | -4100.547 | 8205.093 | 8215.888 |
| 3 | ARMA(0,1) | 2.976497 | -4095.810 | 8197.619 | 8213.812 |
| 4 | ARMA(0,2) | 2.965851 | -4089.969 | 8187.938 | 8209.528 |
| 5 | ARMA(0,3) | 2.965256 | -4089.642 | 8189.283 | 8216.271 |
| 6 | ARMA(0,4) | 2.964135 | -4089.026 | 8190.053 | 8222.438 |
| 7 | ARMA(0,5) | 2.963759 | -4088.821 | 8191.641 | 8229.424 |
| 8 | ARMA(1,0) | 2.975036 | -4095.009 | 8196.018 | 8212.211 |
| 9 | ARMA(1,1) | 2.967814 | -4091.047 | 8190.094 | 8211.684 |
| 10 | ARMA(1,2) | 2.964741 | -4089.359 | 8188.717 | 8215.705 |
| 11 | ARMA(1,3) | 2.964739 | -4089.357 | 8190.715 | 8223.100 |
| 12 | ARMA(1,4) | 2.964018 | -4088.962 | 8191.925 | 8229.708 |
| 13 | ARMA(1,5) | 2.963703 | -4088.790 | 8193.580 | 8236.761 |
| 14 | ARMA(2,0) | 2.964904 | -4089.449 | 8186.897 | 8208.487 |
| 15 | ARMA(2,1) | 2.964700 | -4089.336 | 8188.672 | 8215.660 |
| 16 | ARMA(2,2) | 2.964695 | -4089.334 | 8190.668 | 8223.053 |
| 17 | ARMA(2,3) | 2.964643 | -4089.305 | 8192.610 | 8230.393 |
| 18 | ARMA(2,4) | 2.952400 | -4082.583 | 8181.166 | 8224.347 |
| 19 | ARMA(2,5) | 2.949320 | -4080.889 | 8179.779 | 8228.357 |
| 20 | ARMA(3,0) | 2.964733 | -4089.355 | 8188.709 | 8215.697 |
| 21 | ARMA(3,1) | 2.964746 | -4089.362 | 8190.723 | 8223.109 |
| 22 | ARMA(3,2) | 2.964672 | -4089.321 | 8192.642 | 8230.425 |
| 23 | ARMA(3,3) | 2.951471 | -4082.076 | 8180.152 | 8223.333 |
| 24 | ARMA(3,4) | 2.950608 | -4081.600 | 8181.201 | 8229.779 |
| 25 | ARMA(3,5) | 2.951049 | -4081.844 | 8183.689 | 8237.664 |
| 26 | ARMA(4,0) | 2.964569 | -4089.264 | 8190.529 | 8222.914 |
| 27 | ARMA(4,1) | 2.964560 | -4089.259 | 8192.519 | 8230.302 |
| 28 | ARMA(4,2) | 2.951038 | -4081.838 | 8179.676 | 8222.856 |
| 29 | ARMA(4,3) | 2.950548 | -4081.567 | 8181.135 | 8229.713 |
| 30 | ARMA(4,4) | 2.951099 | -4081.871 | 8183.743 | 8237.719 |
| 31 | ARMA(4,5) | 2.950441 | -4081.508 | 8185.016 | 8244.389 |
| 32 | ARMA(5,0) | 2.964446 | -4089.197 | 8192.393 | 8230.176 |
| 33 | ARMA(5,1) | 2.959271 | -4086.356 | 8188.712 | 8231.893 |
| 34 | ARMA(5,2) | 2.949909 | -4083.396 | 8184.793 | 8233.371 |
| 35 | ARMA(5,3) | 2.951037 | -4081.838 | 8183.676 | 8237.651 |
| 36 | ARMA(5,4) | 2.950452 | -4081.514 | 8185.029 | 8244.402 |
| 37 | ARMA(5,5) | 2.943817 | -4078.218 | 8180.436 | 8245.207 |
Al obtener toda la lista de los modelos se procede a evaluar el mejor modelos de todos ellos y como se dijo antes se procede a eligir el que tiene el mejor critetio de akike (AIC). Esto se realiza con la función autoarimaprorpocionada del paquete forecast.
| sigma | logLik | AIC | BIC |
|---|---|---|---|
| 2.967704 | -4089.987 | 8185.975 | 8202.167 |
El mejor modelo para esta serie es un arma(0,0,2).
pre<- forecast(modelo,10)
data<- data.frame("fechas1"=index(test),"test"=as.numeric(test$BAP),
"prediccion"=as.numeric(pre$mean))
data[,2]<- as.numeric(data[,2])
data[,3]<- as.numeric(data[,3])
ggplot(data)+geom_line(mapping = aes(x=fechas1,y=test,col="test"))+
geom_line(mapping = aes(x=fechas1,y=prediccion,color="prediccion"))+theme_elegante()+
labs(title="Modelo ARIMA",x="",y="Precios" )Interpretación: A diferencia del metodo de cadenas de markov podemos ver que esta ves la predicción esta por encima de los valores predichos.
fecha<- seq(as.Date("2021-06-29"),length=10,by="1 day")
matriz3<- as.data.frame(pre$mean)
matriz<- as.data.frame(pre$lower)
matriz1<- as.data.frame(pre$upper)
serie<- precios$BAP
ata=ggplot()+ geom_line(mapping = aes(x=index(serie[1300:length(serie)]),y=as.numeric(serie[1300:length(serie)])),color="#0000FF")+
geom_line(mapping = aes(x=fecha,y=matriz$`80%`,color="1"),lty=2,size=1)+
geom_line(mapping = aes(x=fecha,y=matriz$`95%`,color="2"),lty=2,size=1)+
geom_line(mapping = aes(x=fecha,y=matriz1$`80%`,color="1"),lty=2,size=1)+
geom_line(mapping = aes(x=fecha,y=matriz1$`95%`,color="2"),lty=2,size=1)+
geom_line(mapping = aes(x=fecha,y=matriz3$x,color="3"),size=1)+
scale_color_manual(" ",values = c("#58FAF4","#FF00FF","#FF0040"),labels=c("80%","95%","poryeccion"))+
theme_elegante()+xlab("Fechas")+ylab("Precios de las acciones")+labs(title = "Proyección de los precios de credicorp")
ata+geom_ribbon(aes(ymin=matriz$`80%`,ymax=matriz1$`80%`,x=fecha),alpha=.3,fill="blue")+
geom_ribbon(aes(ymin=matriz$`95%`,ymax=matriz1$`95%`,x=fecha),alpha=.5,fill="blue")En esta siguiente parte veremo como las noticias negativas tienen um impacto significativo sobre el pronostico de la acción de AMZN.
library(readr)
library(tidyverse)
library(forecast)Sentimientos <- read_csv("C:/Users/atita/Downloads/Sentimientos.csv")Sentimientos %>% select(count) %>% group_by(count) %>%
summarise(n=n()) %>% ggplot()+geom_col(aes(x=count,y=n,fill=n))+
labs(title = "Cantidad de twets negativos por dÃa ",
x=" ",y="Cantidad",caption = "Elaborado por Sebastián Sosa Pérez")+
theme_minimal()Sentimientos %>% select(Date,Close) %>% ggplot(aes(x=Date,y=Close))+
geom_line(color="blue",size=1)+geom_area(fill="gray",alpha=0.4)+
labs(title = "Cotización de la AMZN",
x=" ",y="Precios",caption = "Elaborado por Sebastián Sosa Pérez")+
theme_minimal()time<- Sentimientos %>% select(Close,count) %>% ts()amzn_tr<- time[,1][1:110]
amzn_te<- time[,1][111:115]
negative_tr<- time[,2][1:110]
negative_te<- time[,2][111:115]modelo1<- auto.arima(amzn_tr)
prediction<- forecast(modelo1,5)
plot(prediction)plot(as.numeric(prediction$mean),type = "l",ylim = c (1730,1870))
lines(amzn_te,col="red")modelo2<- auto.arima(amzn_tr,xreg = negative_tr)
prediction2<- forecast(modelo2,h=5,xreg = negative_tr[106:110])
plot(prediction2)plot(as.numeric(prediction2$mean),type = "l",ylim = c (1730,1870))
lines(amzn_te,col="red")
lines(as.numeric(prediction$mean),col="blue")modelo3<- nnetar(amzn_tr,xreg = negative_tr)
prediction3<- forecast(modelo3,h=5,xreg = negative_tr[106:110])
plot(prediction3)plot(as.numeric(prediction2$mean),type = "l",ylim = c (1730,1870))
lines(amzn_te,col="red")
lines(as.numeric(prediction$mean),col="blue")
lines(as.numeric(prediction3$mean),col="pink")