Hoy en dia se vive incertidumbre en el mercado, gracias a los distintos factores macroeconomicos y geopolitcos actuales. Principalmente las tasas de interes que durante 2022 ha tenido un incremento nunca antes visto, alcanzando asi el maximo historico, teniendo en referencia la tasa de interes de USA, a continuación se observa una grafica desde el 2018 con la evolución de la tasa de interés.
De igual forma, va de la mano con la fuerte inflación que se presenta hoy en dia, por consecuencia los bancos centrales de cada pais buscan proteger su moenda y no tener un crecimiento exponencial de la inflación.
Gracias a estos factores, la mayoria de los portafolios relacionados a las acciones de Estados Unidos tienen rendimientos por deba del indice del mercado del S&P500.
El reto con este analisis es a traves de realiazar una nueva reingenieria de algoritmos para la seleccion de acciones, poder crear un portafolio de 10 acciones, las cuales tengas rendimientos superiores al mercado.
Para este analisis se utilizara una base de datos con información financeira hisotirca trimestral de todas las empresas que cotizan en NYSE y el NASDAQ, en donde encontramos dos data sets, el cual el primero (USPANEL), encontramos información financiera de cada empresa, como ventas, COGS, utilidad neta, entre otras, y el segundo data set (US FIRM), encontramos información general de cada empresa, por ejemplo, la industria la cual pertenece, el nombre del ticker de la bolsa, nombre completo de la acción, entre otras.
Teniendo ya las bases de datos,se va realizar una busqueda de ratios financieros, la cual nos ayude a visualizar y entender el comportamiento de la accion desde el primer trimestre del año 2000 hasta el segundo trimestre del 2022, y observar su comportamiento historico.
A continuación, ya con los ratios financeiros, realizaremos un modelo de regresión logistica en donde esten los ratios seleccionados, y con el resultado de esta primera regresión, observar cual de estas variables estan relacionadas con los rendimientos anuales del mercado, y para visualizar si estan relacionadas, tenemos que fijarnos en el P-Value, el cual debe ser significativo (P-Value menor a 5%, para tener un nivel de confianza mayor al 95%). Entonces si tenemos una beta positiva (Ratio financiero, seleccionado) y significativa (P-Value < 0.05), podemos decir que el Ratio financiero esta relacionado de una manera positiva y significativa con la probabilidad de que el retorno de la accion sea superior a la rentabilidad del mercado.
Despues se realizara un Machine Learning model para ver la asertividad de nuestro modelo y observar la presición de predecir si realmente el retorno de la accion va superar el retorno del mercado, a traves de hacer un pronostico a futuro, y con la información historica de cada empresa.
Y por ultimo construiremos nuestro portafolio de las mejores 10 acciones las cuales pronostiquemos que su retorno sea superior a la rentabilidad del mercado, a partir de los ratios financieros seleccionados.
Primero limpiamos nuestro enviorment para que otra variable ya corrida nos afecte en el analisis, y despues bajamos las distintas librerias para poder correr los codigos sin ningun problema.
rm(list=ls())
# To avoid scientific notation for numbers:
options(scipen=999)
library(readxl)
## Warning: package 'readxl' was built under R version 4.1.3
library(plm)
## Warning: package 'plm' was built under R version 4.1.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.1.3
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:plm':
##
## between, lag, lead
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(quantmod)
## Warning: package 'quantmod' was built under R version 4.1.3
## Loading required package: xts
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 4.1.3
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
## Attaching package: 'xts'
## The following objects are masked from 'package:dplyr':
##
## first, last
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(statar)
## Warning: package 'statar' was built under R version 4.1.3
library(caret)
## Warning: package 'caret' was built under R version 4.1.3
## Loading required package: ggplot2
## Warning: package 'ggplot2' was built under R version 4.1.3
## Loading required package: lattice
library(ggplot2)
library(lattice)
library(PerformanceAnalytics)
##
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
##
## legend
library(pROC)
## Warning: package 'pROC' was built under R version 4.1.3
## Type 'citation("pROC")' for a citation.
##
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
##
## cov, smooth, var
A continuación bajamos nuestros data sets de la base de datos, lo descargamos como un archivo excel y despues creamos un codigo para poder importarlo a RStudio.
# Download the panel dataset from an online excel file:
#download.file("http://www.apradie.com/datos/us2022q2a.xlsx",
# "us2022q.xlsx", mode="wb")
uspanel <- read_excel("us2022q.xlsx",sheet = "data")
usfirms <- read_excel("us2022q.xlsx",sheet = "firms")
dicdata <- read_excel("us2022q.xlsx",sheet = "DicDatos")
Despues realizamos con la librerira DPLYR, un selección de las columnas que me interesan para el analisis de la base de datos USFIRMS, aqui seleccionamos las columnas Ticker, El nombre de la accion, y la columna NAICS3 (a que indutria pertenece la empresa). Y por ultimo juntamos la base de datos seleccionada a USPANEL, para asi tener todos nuestros datos en una misma Base de Datos.
usfirms_summary <- usfirms %>%
select(Ticker, Name, NAICS3) %>%
rename(firm = Ticker)
uspanel <- merge(uspanel,usfirms_summary)
A continuación declaramos nuestra base de datos como un pdata.frame y utilizamos la función as.Date para que R entienda que la base de datos se clasifica por fecha (q).
uspanel <- pdata.frame(uspanel, index= c("firm","q"))
uspanel$q<-as.Date(uspanel$q)
Teniendo ya nuestro USPANEL completo de las acciones, el siguiente paso es bajar la base de datos del mercado (GSPC) desde el 01-01-1999 al 07-10-2022, con una periocidad mensual.
A continuación creamos una nueva base de datos del mercado, la cual se va convertir en trimestral, esto lo hacemos usando la función to.quartely, y asi tener en la misma clasificacion de fechas nuestra base de datos de las acciones (USPANEL) y la del mercado (GSPC.Q), y por ultimo convertimos esta base de datos en pdata.frame para que se pueda unir a la otra base de datos.
getSymbols("^GSPC", from="1999-01-01", to= "2022-10-7",
periodicity="monthly", src="yahoo")
## [1] "^GSPC"
GSPC.q <- to.quarterly(GSPC,indexAt='startof')
# I keep only the adjusted column, which has the market index:
GSPC.q = Ad(GSPC)
GSPC.Returns = diff(log(GSPC.q), lag=4)
# Renaming the column:
names(GSPC.Returns) = c("mktret")
GSPC.df<-data.frame(q=index(GSPC.Returns),coredata(GSPC.Returns))
Comprobamos la clase de cada base de datos y que esten filtrados por “Date”.
class(uspanel$q)
## [1] "pseries" "Date"
class(GSPC.df$q)
## [1] "Date"
Y por ultimo realizamos el merge de ambas base de datos, con el fin de tener toda la información en una misma, utilizamos la función left_join, con el fin de seguir teniendo el atributo de USPANEL.
#uspanel<-merge(uspanel,GSPC.df,by="q")
# Instead of merge, use left_join to keep the pdata.frame attribute of the uspanel
uspanel<-left_join(uspanel,GSPC.df,by="q")
Teniendo nuestra base de datos llena de informacion relevante de cada accion, realizamos una busqueda de diversos ratios financieros los cuales nos ayude a predecir que acción puede estar por encima del mercado. #### OEPSP Operational epsebit deflated by stock price, este ratio, lo podriamos traducir como las ganancias que tiene la accion, siendo un ratio atractivo para inversionistas.
Valor total de las acciones en ciruclación de la empresa, este ratio nos va servir para visualizar el tamaño de la empresa y como multiplo para el calculo de otros ratios financieros. Solo hay que tener presente que se utiliza el precio de la accion original (antes de dividendos y de splits) y el numero de acciones en ciruclacion historico. Ocupamos log de market cap para achicar nuestros valores.
Return on assets, este ratio de rendimiento nos sirve para conocer la rentabilidad de nuestros activos totales, este ratio se puede interpetar en si la empresa tiene una toma de decisión correcta entorno a sus inversiones. A manera de entenderlo facilmente es por cada dolar invertido, cuanto es lo que la empresa genera.
Return on Investment, este ratio nos va ayudar a visualizar la rentabilidad que se tiene, en este portafolio vamos a calcular el ROI de las ventas entre el costo de ventas, para observar lo rentable del negocio. Ocupando (Total de ventas - Costo de ventas) / Costo de ventas
Renturn on equity, este ratio nos va ayudar a ver la rentabilidad que ofrece la empresa con relacion a su capital contable, igualmente podemos interpretar este indicador como que tan rentable como inversionista sin tomar en cuenta pasivos ni deuda.
Relación libro-mercado, este ratio nos sirve para evaluar la empresa. considerando el valor de libros y el valor del mercado
Relación deuda-capital, la cual nos dice la proporcion de capital y deuda de la empresa, que esta utilizando para financiar sus activos, y ver hasta donde la empresa puede cubrir o cumplir sus obligaciones.
Indice de cobertura de intereses, nos sirve para determinar con que facilidad una empresa puede pagar los gastos de interes sobre su deuda, este ratio nos puede servir para visualizar si la empresa posee un riesgo en relación con la deuda que presenta. Aqui deberiamos de buscar por lo minimo un resultado mayor a 1.5, el cual se puee considerar como el minimo aceptable.
Por ultimo, el quick ratio nos ayuda a visualizar la liquidez a corto plazo de una empresa, aqui debemos de buscar un ratio minimo el cual sea mayor a 1.
A continuacion con la libreria dplyr, vamos a realizar los disntintos calculos paras las razones financieras, ocupamos la funcion mutate para crear nuevas columnas.
uspanel <- uspanel %>%
mutate(
grossprofit = revenue - cogs,
ebit = grossprofit -sgae,
oeps = ifelse(sharesoutstanding==0, NA, ebit /sharesoutstanding),
oepsp = ifelse(originalprice==0, NA, oeps / originalprice),
netincome = ebit - finexp - incometax,
marketcap = originalprice * sharesoutstanding,
log_mk = log(marketcap),
ROA = ebit / totalassets,
ROI = (revenue - cogs)/cogs,
ROE = netincome / stockholderequity,
bookvalue = totalassets - totalliabilities,
booktomarket = ifelse(marketcap==0,NA, bookvalue / marketcap),
debt.to.equity = (shortdebt + longdebt) / stockholderequity,
ICR = ebit / finexp,
Quick.ratio = (currentassets - inventory) / currentliabilities
)
En esta parte del analisis, en mis ratios financieros, les aplique la función “winsorise”, la cual nos sirve para remplazar valores atipicos, asignando el valor atipico un peso mas bajo, para que entre dentro de la distribución normal. Ademas del histograma, obervamos en la consola, en porcentaje de observaciones que se remplazaron en la parte de hasta arriba y de hasta abajo.
uspanel$win.oepsp<- winsorise(uspanel$oepsp)
## 1.28 % observations replaced at the bottom
## 0.56 % observations replaced at the top
hist(uspanel$win.oepsp)
uspanel$win.ROA<- winsorise(uspanel$ROA)
## 2.72 % observations replaced at the bottom
## 0.39 % observations replaced at the top
hist(uspanel$win.ROA)
uspanel$win.ROI<- winsorise(uspanel$ROI)
## 0.04 % observations replaced at the bottom
## 9.81 % observations replaced at the top
hist(uspanel$win.ROI)
uspanel$win.ROE <- winsorise(uspanel$ROE)
## 2.07 % observations replaced at the bottom
## 1.23 % observations replaced at the top
hist(uspanel$win.ROE)
uspanel$win.bookvalue <- winsorise(uspanel$bookvalue)
## 0.03 % observations replaced at the bottom
## 3.45 % observations replaced at the top
hist(uspanel$win.bookvalue)
uspanel$win.booktomarket <- winsorise(uspanel$booktomarket)
## 0.10 % observations replaced at the bottom
## 0.40 % observations replaced at the top
hist(uspanel$win.booktomarket)
uspanel$win.debt.to.equity <- winsorise(uspanel$debt.to.equity)
## 0.74 % observations replaced at the bottom
## 1.17 % observations replaced at the top
hist(uspanel$win.debt.to.equity)
uspanel$winICR <- winsorise(uspanel$ICR)
## 2.66 % observations replaced at the bottom
## 9.73 % observations replaced at the top
hist(uspanel$winICR)
uspanel$win.Quick.ratio <- winsorise(uspanel$Quick.ratio)
## 0.00 % observations replaced at the bottom
## 2.04 % observations replaced at the top
hist(uspanel$win.Quick.ratio)
En esta parte , primero realizamos la diferencia de logartimos de los adjusted price de la accion, y ocupamos lag=4 para hacer los valores anuales. A partir de esta función, podemos realizar las variables del stock return y del market return a futuro, por eso utilizamos en la funcion al final -1 para que nos de el retorno futuro.
uspanel$stock_return= diff(log(uspanel$adjprice), lag=4)
uspanel$F1r_stock <- plm::lag(uspanel$stock_return,-1)
uspanel$F1_market <- plm::lag(uspanel$mktret,-1)
#Aqui realizamos la función future stock above mediante ifelse, la cual nos muestra cuando la accion supera el mercado nos da 1 y si no lo supera nos da un 0
uspanel$F1stock_above = ifelse(uspanel$F1r_stock>uspanel$F1_market,1,0)
Aqui creamos otra base de datos con todas las variables.
uspanel_clean <- uspanel
Ya con los ratios financieros calculados y winsorizados, con el fin que nuestra regresión no tenga datos extremos y quede dentro de la distribución normal, vamos a realizar un modelo de regresion logistica con la función glm, para observar la relación de las variables independientes (ratios finaniceros) con la dependiente que es el retorno futuro de la accion esta por encima del mercado.
lm1_prueba <- glm(F1stock_above ~ win.oepsp + win.booktomarket + win.debt.to.equity + win.ROA + win.ROE + win.ROI + log_mk + winICR + win.Quick.ratio, data= uspanel, family="binomial",na.action=na.omit)
summary(lm1_prueba)
##
## Call:
## glm(formula = F1stock_above ~ win.oepsp + win.booktomarket +
## win.debt.to.equity + win.ROA + win.ROE + win.ROI + log_mk +
## winICR + win.Quick.ratio, family = "binomial", data = uspanel,
## na.action = na.omit)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.284 -1.214 0.823 1.009 2.454
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.04582695 0.05265168 -19.863 < 0.0000000000000002 ***
## win.oepsp 3.14967560 0.22176235 14.203 < 0.0000000000000002 ***
## win.booktomarket -0.56682611 0.01458938 -38.852 < 0.0000000000000002 ***
## win.debt.to.equity 0.00026951 0.00473191 0.057 0.954581
## win.ROA 5.59535000 0.22921316 24.411 < 0.0000000000000002 ***
## win.ROE -0.16350306 0.07600567 -2.151 0.031461 *
## win.ROI -0.00106354 0.00040329 -2.637 0.008361 **
## log_mk 0.10088592 0.00347590 29.024 < 0.0000000000000002 ***
## winICR 0.00015081 0.00004482 3.365 0.000766 ***
## win.Quick.ratio 0.01247035 0.00309564 4.028 0.0000562 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 154143 on 112344 degrees of freedom
## Residual deviance: 144996 on 112335 degrees of freedom
## (215071 observations deleted due to missingness)
## AIC: 145016
##
## Number of Fisher Scoring iterations: 4
A continuación despues de realizar el modelo logistico, depuramos nuestros ratios financieros, los cuales no fueron significativos, osea un P-Value mayor a 0.05 o no consideramos para la elaboración de nuestro modelo.
lm2_definitivo <- glm(F1stock_above ~ win.oepsp + win.booktomarket + win.ROA + log_mk + winICR + win.Quick.ratio, data= uspanel, family="binomial",na.action=na.omit)
summary(lm2_definitivo)
##
## Call:
## glm(formula = F1stock_above ~ win.oepsp + win.booktomarket +
## win.ROA + log_mk + winICR + win.Quick.ratio, family = "binomial",
## data = uspanel, na.action = na.omit)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.2912 -1.1977 0.8119 1.0107 2.5531
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.08296172 0.05153219 -21.015 < 0.0000000000000002 ***
## win.oepsp 3.70578079 0.21032265 17.620 < 0.0000000000000002 ***
## win.booktomarket -0.57786294 0.01406739 -41.078 < 0.0000000000000002 ***
## win.ROA 5.02054472 0.19920474 25.203 < 0.0000000000000002 ***
## log_mk 0.10292163 0.00340283 30.246 < 0.0000000000000002 ***
## winICR 0.00010254 0.00004233 2.422 0.0154 *
## win.Quick.ratio 0.01367506 0.00275457 4.964 0.000000689 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 161119 on 117066 degrees of freedom
## Residual deviance: 150458 on 117060 degrees of freedom
## (210349 observations deleted due to missingness)
## AIC: 150472
##
## Number of Fisher Scoring iterations: 4
Dandonos una regresion logistica definitiva. La cual podemos concluir que:
OEPSP, esta relacionado de una manera positiva (beta=3.7) y significativa (P-value < 0.05) con la probabilidad de que el retorno de la accion sea mayor al mercado. Y dandonos un z-value de 17.015 (4to mas grande), el cual nos dice el peso que tiene la variable independiete sobre la dependiente.
Booktomarket, esta relacionado de una manera negativa (se movera al contrario del mercado) (beta=-0.577) y significativa (P-value < 0.05) con la probabilidad de que el retorno de la accion sea mayor al mercado. Y dandonos un z-value de -41.078 (El mas grande), el cual nos dice el peso que tiene la variable independiete sobre la dependiente.
ROA, esta relacionado de una manera positiva (beta=5.02) y significativa (P-value < 0.05) con la probabilidad de que el retorno de la accion sea mayor al mercado. Y dandonos un z-value de 25.203 (3ero mas grande), el cual nos dice el peso que tiene la variable independiete sobre la dependiente.
logaritmo de market cap, esta relacionado de una manera positiva (beta=0.1) y significativa (P-value < 0.05) con la probabilidad de que el retorno de la accion sea mayor al mercado. Y dandonos un z-value de 30.246 (2do mas grande), el cual nos dice el peso que tiene la variable independiete sobre la dependiente.
QUICK RATIO, esta relacionado de una manera positiva (beta=0.013) y significativa (P-value < 0.05) con la probabilidad de que el retorno de la accion sea mayor al mercado. Y dandonos un z-value de 4.9 (5to mas grande), el cual nos dice el peso que tiene la variable independiete sobre la dependiente.
ICR, esta relacionado de una manera positiva (beta=0.0001) y significativa (P-value < 0.05) con la probabilidad de que el retorno de la accion sea mayor al mercado. Y dandonos un z-value de 2.422 (5to mas grande), el cual nos dice el peso que tiene la variable independiete sobre la dependiente.
Machine Learning es una inteligencia artificial que forma parte en la integración de los números de forma historica para poder entender, como se esta comportando en este caso el mercado y con esto nos ayuda a sacar conclusiones optimas para nuestros portafolios, al igual que este Machine learning esta aprendiendo y mejorando con cada dato que le agregas.
A continuación realizaremos las primeras lineas de codigo para ejecuctar nuestro moedelo de machine learning y resumirlo con el resultado de confusion matrix.
Primero seleccionamos nuestra base de datos (USPANEL) y con la funcion sample y nrow, nos revuelve de forma aleatoria todas las filas de nuestra base de datos.
# Shuffle row indices:
rows_shuffled<-sample(nrow(uspanel)) #Revuelve la data set de forma alet
A continuacion realizamos una matriz de nuestro resultado de arriba, osea de nuestra base de datos.
# Randomly order data
shuffled_uspanel <- uspanel[rows_shuffled, ]
Con la base de datos ya revuelta, solo seleccionamos las variables que necesitamos para crear nuestro modelo.
shuffled_uspanel <- shuffled_uspanel %>%
select(firm, q, stock_return, mktret, win.oepsp, win.booktomarket, win.ROA, log_mk, winICR, win.Quick.ratio, F1r_stock, log_mk, F1_market, F1stock_above)
A continuación partimos nuestra base de datos al 90% para tomar los mayores datos posibles para que nuestro train y test tenga un acertividad mayor, y despues con este split, creamos un training set con los valores del 0% al 90%.
# Determine row to split on: split
split <- round(nrow(shuffled_uspanel)*.90)
# Create train
train <- shuffled_uspanel[1:split, ] #Selecciona del 0% hasta el 90%
Despues creamos nuestro test, seleccionando el otro 10% resntate.
# Create test
test <- shuffled_uspanel[(split+1):nrow(shuffled_uspanel), ] #Selecciona del 91% al 100%
Por ultimo realizamos esta división para confirmar que nuestro train sea del 90%.
# Confirmar que nuestro test sea el 90% de todo el conjunto de datos
nrow(train) / nrow(uspanel)
## [1] 0.8999988
Para esta segunda regresion logiitica, seleccionamos los ratios significativos, pero ahora corremos este modelo con el 90% de los valores (data=train) de forma aletaoria. Esto con el fin de calibrar nuestro modelo.
# Fit glm model: model
lm3 <- glm(F1stock_above ~ win.oepsp + win.booktomarket + win.ROA + log_mk + winICR + win.Quick.ratio, data = train, family = "binomial", na.action = na.omit)
summary(lm3)
##
## Call:
## glm(formula = F1stock_above ~ win.oepsp + win.booktomarket +
## win.ROA + log_mk + winICR + win.Quick.ratio, family = "binomial",
## data = train, na.action = na.omit)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.286 -1.199 0.814 1.012 2.547
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.07290659 0.05430328 -19.758 < 0.0000000000000002 ***
## win.oepsp 3.69893040 0.22150630 16.699 < 0.0000000000000002 ***
## win.booktomarket -0.57523567 0.01481224 -38.835 < 0.0000000000000002 ***
## win.ROA 4.97777795 0.20977570 23.729 < 0.0000000000000002 ***
## log_mk 0.10189466 0.00358534 28.420 < 0.0000000000000002 ***
## winICR 0.00011231 0.00004457 2.520 0.0117 *
## win.Quick.ratio 0.01400873 0.00290119 4.829 0.00000137 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 145116 on 105424 degrees of freedom
## Residual deviance: 135629 on 105418 degrees of freedom
## (189249 observations deleted due to missingness)
## AIC: 135643
##
## Number of Fisher Scoring iterations: 4
A continuacion se realiza una prediccion de la probabilidad de que el retorno de la accion le gana al retorno del mercado, usando la data “test”.
# Predict on test: p
test$p1 <- predict(lm3, newdata=test, type = "response")
summary(test$p1)
## total sum of squares: 261.6931
## id time
## 0.76907597 0.07433339
##
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 0.036 0.470 0.580 0.547 0.650 0.928 20522
Dandonos como resultado de la predicción, que de los valores que se tomo como “1”, el minimo es de 0,035 y el maximo de 0.920, dandonos una mediana de 0.583 y un promedio de 0.548,
A continuación creamos una nueva columna en nuestra base de datos test, la cual debe de decir 1 si la accion supera el mercado a partir de mi threshold seleccionado (0.5) y 0 si esta por debajo de mi threshold.
# If p exceeds threshold of 0.5, M else R: m_or_r
test$F1returns_pred <- ifelse(test$p1 >0.5, "1", "0")
table(test$F1returns_pred)
##
## 0 1
## 3653 8567
# convert to factor: p_factor
test$F1returns_pred = factor (test$F1returns_pred, levels = c("1", "0"))
test$F1stock_above = factor (test$F1stock_above , levels = c("1", "0"))
A partir de realizar nuestras predicciones, nuestro split, test y training, podeos crear nuestra Confusion matrix, para analizar la acertividad de nuestro modelo.
confusionMatrix(test$F1returns_pred, test$F1stock_above)
## Confusion Matrix and Statistics
##
## Reference
## Prediction 1 0
## 1 5272 2934
## 0 1180 2256
##
## Accuracy : 0.6466
## 95% CI : (0.6379, 0.6553)
## No Information Rate : 0.5542
## P-Value [Acc > NIR] : < 0.00000000000000022
##
## Kappa : 0.2604
##
## Mcnemar's Test P-Value : < 0.00000000000000022
##
## Sensitivity : 0.8171
## Specificity : 0.4347
## Pos Pred Value : 0.6425
## Neg Pred Value : 0.6566
## Prevalence : 0.5542
## Detection Rate : 0.4528
## Detection Prevalence : 0.7049
## Balanced Accuracy : 0.6259
##
## 'Positive' Class : 1
##
Despues de correr nuestro confusion matrix nos da como resultado:
PRIMERA COLUMNA: Esta columna nos dice realmente que de nuestro test (10%) 6555 casos, la acción supero al mercado. TRUE POSITIVE: Dentro de la primera columna, nuestro modelo predijo de manera correcta que 5346 casos superan el mercado, con una sensibilidad del 0.8156 la cual nos dice la sensibilidad del modelo para predecir TRUE POSITIVE FALSE NEGATIVE: Dentro de la primera columna, nuestro modelo predijo de manera incorrecta que 1209 casos no superarian el mercado, pero si lo superaron.
La segunda columna nos dice que de nuestro test (10%) 5231 casos, la acción no supero al mercado. FALSE POSITIVE: Dentro de la segunda columna, nuestro modelo predijo que 3067 casos superarian el mercado, pero realmente no lo supero. Teniendo una specificity de 0.4137 TRUE NEGATIVE: Por ultimo dentro de la segunda columna tenemos que nuestro modelo predijo correctamente que 2164 casos no superarian el mercado.
Dandonos un resultado de Accuracy o precisión del 63%, esto quiere decir que de cada 100 casos que se predicen voy a tener 63 casos que se predicieron correctamente, ya sea que la acción supere al mercado o que el mercado supere a la acción.
Con los resultados de sensitivity y specificity, podemos concluir que nuestro modelo predice de una manera mas efectiva cuando la accion supera al mercado, ya que nuestro sensitivity se encuentra mayor (0.8156), y que nuestro modelo predice de manera incorrecta cuando la accion no supera al mercado (0.4137), lo recomendable es que ambos esten por arriba del 0.5.
Entonces uno como analista no puede decidir cual de los dos coeficientes debemos de tener mayor, pero en mi opinion, tener una sensibilidad mayor es de mayor importancia, porque realmente es confiable nuestro modelo a la hora de seleccionar nuestros casos TRUE POSITIVES. Aun asi debemos de buscar que nuestro specificity este igual en una mayor proporcion, para que de igual forma nuestro modelo acierte en los casos que realmente no cumplen (TRUE NEGATIVE)
A continuación, despues de realizar la matriz de confusión con un traeshold de 0.5, y obtener distintos valores de accuracy, sensitivity y specificity, vamos a buscar a partir de las graficas del ROC, poder calibrar aún mas nuestro modelo, modificiando nuestro Traeshold.
roc1<- roc(response=test$F1stock_above, predictor=test$p1,plot=T,col="blue", levels=c("0","1"))
## Setting direction: controls < cases
En esta primera grafica observamos la relacion entre specificity y
sensitivity, poniendo como variables del data set “TEST”, future stock
above y nuestra predicción.
plot(1-roc1$specificities, roc1$sensitivities, col="red", pch=16,
xlab="False Positive",
ylab="Sensitivity")
En esta segunda grafica observamos la relacion entre false positive y
sensitivity
Para tener una mejor visón de cual puede ser nuestro Trashold mas acertado, realizamos esta grafica la cual nos muestra la relación entre sensitivity, specificity, true positives y true negatives.
library(ggplot2)
# I create a data frame with 3 columns: 1) the threshold probabilities, 2) Sensitivities, and
# 3) Specificities
thresholdvector <- cbind(roc1$thresholds,roc1$sensitivities,roc1$specificities)
thresholdvector <- as.data.frame(thresholdvector)
names(thresholdvector)<-c("threshold","sensitivities","specificities")
# The roc function does not calculate the positive-predicted ratio nor the negative-predicted
# ratio.To calculate these ratios, I need the # of tp, tn, fp and fn
# I add columns for #true positive cases (tp), #tn, #fp, and #fn:
thresholdvector$tp = thresholdvector$sensitivities*length(roc1$cases)
thresholdvector$tn = thresholdvector$specificities*length(roc1$controls)
thresholdvector$fp =length(roc1$cases) - thresholdvector$tp
thresholdvector$fn = length(roc1$controls) - thresholdvector$tn
# Check that the length(roc1$cases) is the total of cases when the event actually happened
# I create the positive-prediction ratio and the negative-prediction ratio:
thresholdvector$pospredratio = thresholdvector$tp / (thresholdvector$tp+thresholdvector$fn)
thresholdvector$negpredratio = thresholdvector$tn / (thresholdvector$tn+thresholdvector$fp)
# I plot the 4 ratios against the threshold probability to visualize which might be the
# best threshold probability:
ggplot(thresholdvector,aes(x=threshold)) +
geom_line(aes(y=specificities,color="Specificity ratio")) +
geom_line(aes(y=sensitivities,color="Sensitivity ratio")) +
geom_line(aes(y=pospredratio,color="True-Positive Predicted ratio")) +
geom_line(aes(y=negpredratio,color="True-Negative Predicted ratio"))
## Warning: Removed 1 row(s) containing missing values (geom_path).
## Removed 1 row(s) containing missing values (geom_path).
A partir de esta grafica podemos observar los distintos thresholds que se puedan usar comparandolo con el specificities rate. Y con esto poder maximisar nuestro modelo.
roc1$auc
## Area under the curve: 0.6708
Aqui realizamos el calculo del area bajo la curva, la cual nos dice lo maximo que puede llegar nuestra relación entre specificity y sensitivity, en este tipo de modelos debemos de buscar que el area bajo la curva este por arriba de 0.5, lo cual significa que nuestro modelo es mejor que uno navie o uno random.
A continuación realizaremos un nuevo calculo de nuestra matriz de confusiones, pero ahora con un Threshold calibrado y con el 100% de la base de datos de nuestras acciones, para asi poder llegar a conclusiones mucho mas asertivas de si realmente la acción va superar el retorno del mercado.
A continuacion se realiza una prediccion de la probabilidad de que el retorno de la accion le gana al retorno del mercado, usando ahora la data “USPANEL_CLEAN”, la cual presenta el 100% de la dataset.
# Predict on test: p
uspanel_clean$p_final <- predict(lm3, newdata=uspanel_clean, type = "response")
summary(uspanel_clean$p_final)
## total sum of squares: 2630.812
## id time
## 0.71604820 0.06893604
##
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 0.03 0.47 0.58 0.55 0.65 0.93 204188
Dandonos como resultado de la predicción, que de los valores que se tomo como “1”, el minimo es de 0,03 y el maximo de 0.93, dandonos una mediana de 0.58 y un promedio de 0.55, ocupando el 100% de nuestra muestra.
Para este nuevo modelo se ocupo un Threshold de 0.5375, el cual busca ya con toda nuestra muestra, subir nuestro coeficiente de specificity, para que nuestro modelo este mucho mas equilibrado a compración de nuestro test inicial. Sin restarle de manera significante a nuestro coeficiente de sensitivity, y mantener nuestro accurancy (AUC)
# Turn probabilities into classes and look at their frequencies
# If p exceeds threshold of 0.5, M else R: m_or_r
uspanel_clean$F1returns_predf <- ifelse(uspanel_clean$p_final >0.5375, "1", "0")
table(uspanel_clean$F1returns_predf)
##
## 0 1
## 45780 77448
A continuación convertimos nuestras variables en facto, con la función p_factor, para que se pueda correr correctamente nuestra matriz de confusión.
# convert to factor: p_factor
uspanel_clean$F1returns_predf = factor (uspanel_clean$F1returns_predf, levels = c("1", "0"))
uspanel_clean$F1stock_above = factor (uspanel_clean$F1stock_above , levels = c("1", "0"))
A partir de realizar nuestras predicciones, podemos crear nuestra Confusion matrix, para analizar la acertividad de nuestro modelo, pero ahora utilizando todo nuestro dataset.
# Use caret's helper function to calculate additional statistics
# Create confusion matrix
confusionMatrix(uspanel_clean$F1returns_predf, uspanel_clean$F1stock_above)
## Confusion Matrix and Statistics
##
## Reference
## Prediction 1 0
## 1 48001 26270
## 0 16381 26415
##
## Accuracy : 0.6357
## 95% CI : (0.6329, 0.6384)
## No Information Rate : 0.55
## P-Value [Acc > NIR] : < 0.00000000000000022
##
## Kappa : 0.2512
##
## Mcnemar's Test P-Value : < 0.00000000000000022
##
## Sensitivity : 0.7456
## Specificity : 0.5014
## Pos Pred Value : 0.6463
## Neg Pred Value : 0.6172
## Prevalence : 0.5500
## Detection Rate : 0.4100
## Detection Prevalence : 0.6344
## Balanced Accuracy : 0.6235
##
## 'Positive' Class : 1
##
Despues de correr nuestro confusion matrix ya con nuestra data set completa nos da como resultado:
PRIMERA COLUMNA: La acción supero al mercado 64,382 casos TRUE POSITIVE: Dentro de la primera columna, nuestro modelo predijo de manera correcta que 48,247 casos superan el mercado, con una sensibilidad del 0.7494 la cual nos dice la sensibilidad del modelo para predecir TRUE POSITIVE, este porcentaje disminuyo un 8% a relacion del test que hicimos previamente, es normal que la sensibilidad baje al tener muchos mas datos a considerar, pero aun asi un 75% de sensibilidad en un coeficiente aceptable. FALSE NEGATIVE: Dentro de la primera columna, nuestro modelo predijo de manera incorrecta que 16135 casos no superarian el mercado, pero si lo superaron.
La segunda columna nos dice que la acción no supero al mercado 52,685
de los casos FALSE POSITIVE: Dentro de la segunda columna, nuestro
modelo predijo que 26459 casos superarian el mercado, pero realmente no
lo supero. Teniendo una specificity de 0.4978
TRUE NEGATIVE: Por ultimo dentro de la segunda columna tenemos que
nuestro modelo predijo correctamente que 26226 casos no superarian el
mercado.
Dandonos un resultado de Accuracy o precisión del 63%, igual que el modelo pasado, esto quiere decir que de cada 100 casos que se predicen voy a tener 63 casos que se predicieron correctamente, ya sea que la acción supere al mercado o que el mercado supere a la acción.
Con los resultados de sensitivity y specificity, podemos concluir que nuestro modelo predice de una manera mas efectiva cuando la accion supera al mercado, ya que nuestro sensitivity se encuentra mayor (75%), y que nuestro modelo predice de manera incorrecta cuando la accion no supera al mercado (50%), lo recomendable es que ambos esten por arriba del 0.5. A comparación del modelo anterior nuestro sensitivity bajo un 5% y nuestro specificity aumento un 9%, asi equilibrando nuestros dos coeficientes dando un modelo realistico, de igual forma nuestro accurrency subio 0.4%.
Entonces uno como analista no puede decidir cual de los dos coeficientes debemos de tener mayor, pero en mi opinion, tener una sensibilidad mayor es de mayor importancia, porque realmente es confiable nuestro modelo a la hora de seleccionar nuestros casos TRUE POSITIVES. Aun asi debemos de buscar que nuestro specificity este igual en una mayor proporcion, para que de igual forma nuestro modelo acierte en los casos que realmente no cumplen (TRUE NEGATIVE)
Ya teniendo nuestra matriz de confusión y nuestros ratios winsorizados y depurados, vamos a crear un portafolio de las 10 empresas que superen el mercado.
uspanel_clean <- uspanel_clean %>%
filter(q=="2022-04-01") %>%
select(q, firm, F1returns_predf, p_final,booktomarket,oepsp,log_mk,win.ROA, Name, NAICS3) %>%
filter(F1returns_predf==1) %>%
filter(p_final >= 0.65) %>%
filter(log_mk >= 16.5) %>%
filter(booktomarket <= 0) %>%
arrange(desc(win.ROA),
desc(oepsp))
head(uspanel_clean,10)
## q firm F1returns_predf p_final booktomarket oepsp log_mk
## 1 2022-04-01 YUM 1 0.8456113 -0.264698163 0.028978394 17.29271
## 2 2022-04-01 SBUX 1 0.8503007 -0.098832700 0.045702805 18.28843
## 3 2022-04-01 HLT 1 0.8379335 -0.025437431 0.067607468 17.25006
## 4 2022-04-01 VRSN 1 0.8031886 -0.079377503 0.012874976 16.72406
## 5 2022-04-01 MO 1 0.7977939 -0.031774376 0.041056778 18.14132
## 6 2022-04-01 HD 1 0.7993375 -0.006062813 0.021033598 19.45700
## 7 2022-04-01 PM 1 0.7908515 -0.047433033 0.019966301 18.84633
## 8 2022-04-01 LOW 1 0.7851012 -0.061601643 0.029578105 18.53076
## 9 2022-04-01 ORLY 1 0.7566783 -0.026670472 0.019231649 17.54175
## 10 2022-04-01 MSCI 1 0.7450033 -0.030699872 0.008984066 17.32511
## win.ROA Name
## 1 0.14754324 Yum! Brands, Inc
## 2 0.14221024 Starbucks Corp
## 3 0.13632818 Hilton Worldwide Hldg Inc
## 4 0.13390071 Verisign Inc
## 5 0.08449899 Altria Group, Inc
## 6 0.07743545 Home Depot, Inc
## 7 0.07460938 Philip Morris Intl Inc
## 8 0.06640523 Lowes Companies Inc
## 9 0.06617257 O Reilly Automotive Inc
## 10 0.06214755 MSCI Inc
## NAICS3
## 1 Restaurants and Other Eating Places
## 2 Restaurants and Other Eating Places
## 3 Traveler Accommodation
## 4 Computer Systems Design and Related Services
## 5 Tobacco Manufacturing
## 6 Building Material and Supplies Dealers
## 7 Tobacco Manufacturing
## 8 Building Material and Supplies Dealers
## 9 Automotive Parts, Accessories, and Tire Stores
## 10 Business Support Services
Para la creación de mi portafolio, primero ocupamos un filtro que nos presente nada mas la información Q2, con el fin de comparar el crecimiento del Q2 al Q3 y ver realmente si nuestro portafolio es eficiente, a continuacion se selecciona de la base de datos solo las columnas que ibamos a comparar, luego realizamos un filtro el cual solo me de acciones que su future return sea arriba de 1, osea le gane al mercado, el siguiente filtro fue que me depurara la columna de p_final, el cual buscara acciones mayores a 0.65 y descartar las que estan por debajo, el 0.6 lo sacamos mediante un histograma y decidimos seleccionar los mas acercados a 1 (supera el mercado).
A continuación el siguiente filtro fue ocupar el logaritmo del market cap, el cual sea mayor a 16.5, para reactificar observamos en un histograma que sea mayor al promedio, dandonos referencia 16, de igual forma en nuestro modelo de regresion logistica, nos da una beta de (0.1), la cual nos dice que si se mueve en una unidad el mercado, nuestro logmarketcap se movera 0.1 arriba, de igual forma consideramos su z-value, el cual es el segundo de mayor importancia en nuestro modelo logistico.
Continuando asi, el siguiente filtro fue booktomarket que sea igual o menor a 0, esto debidio a que tenemos una beta negativa (en contra del mercado) y el mayor z-value del modelo logistico.
A continuación acomodamos nuestro portafolio con nuestra ROA Winsorizada, para clasificar nuestras empresas entorno al retorno sobre activo, y por ultimo utilizamos nuestro ratio de earning per share para acomodar de mayor a menor, debido a que utilizamos nuestro ROA winsorizado y por consecuencia tenemos valores iguales, y lo que realizamos con este ultimo filtro fue desempatar esa columna.
Concluyendo asi con 28 empresas finales.
Despues bajamos la data de Yahoo Finance de las 10 primeras empresas de los ultimos 4 meses, con el fin de poder sacar el retorno del ultimo trimestre.
getSymbols(c("YUM", "SBUX","HLT","VRSN","MO","HD","PM","LOW","ORLY","MSCI"
), from="2022-06-01", to="2022-09-30", src="yahoo", periodicity="monthly")
## pausing 1 second between requests for more than 5 symbols
## pausing 1 second between requests for more than 5 symbols
## pausing 1 second between requests for more than 5 symbols
## pausing 1 second between requests for more than 5 symbols
## pausing 1 second between requests for more than 5 symbols
## pausing 1 second between requests for more than 5 symbols
## [1] "YUM" "SBUX" "HLT" "VRSN" "MO" "HD" "PM" "LOW" "ORLY" "MSCI"
Aqui hicmos una nueva dataset con todos los adjusted prices de las 10 empresas.
adjustedprices_merge <- merge(YUM$YUM.Adjusted, SBUX$SBUX.Adjusted, HLT$HLT.Adjusted, VRSN$VRSN.Adjusted, MO$MO.Adjusted, HD$HD.Adjusted, PM$PM.Adjusted, LOW$LOW.Adjusted, ORLY$ORLY.Adjusted, MSCI$MSCI.Adjusted)
Aqui omitimos todos los valores NA
adjustedprices_merge <- na.omit(adjustedprices_merge)
A continuación realizamos el retorno por accion de los ultimos 3 meses de las 1o acciones.
returns_portafolio = adjustedprices_merge / stats::lag(adjustedprices_merge, n=1) -1
head(returns_portafolio)
## YUM.Adjusted SBUX.Adjusted HLT.Adjusted VRSN.Adjusted MO.Adjusted
## 2022-06-01 NA NA NA NA NA
## 2022-07-01 0.07955245 0.109831161 0.149228388 0.13046078 0.07046470
## 2022-08-01 -0.09221480 -0.008374634 -0.005543944 -0.03668853 0.02872769
## 2022-09-01 -0.03936170 0.007970672 -0.051853883 -0.04675669 -0.10505315
## HD.Adjusted PM.Adjusted LOW.Adjusted ORLY.Adjusted MSCI.Adjusted
## 2022-06-01 NA NA NA NA NA
## 2022-07-01 0.10416972 -0.003757198 0.09652482 0.113698265 0.16787577
## 2022-08-01 -0.04160298 -0.017087065 0.01938825 -0.009195741 -0.06668880
## 2022-09-01 -0.03702788 -0.130694285 -0.03260536 0.008936741 -0.05880591
En esta parte realizamos el retorno por accion del tercer trimestre del 2022.
retorno.q.accion = as.numeric(adjustedprices_merge[nrow(adjustedprices_merge)]) / as.numeric(adjustedprices_merge[1]) - 1
retorno.q.accion
## [1] -0.05857280 0.10930875 0.08359555 0.03806846 -0.01446961 0.01904884
## [7] -0.14875851 0.08133875 0.11331829 0.02589360
Dandonos como resultado un promedio del retorno del portafolio en el tercer trimestre de 0.02487713, lo que quiere decir que por cada dolar que se invierta en nuestro portafolio se ganaria 0.02487713.
mean(retorno.q.accion)
## [1] 0.02487713
Ya teniendo nuestro portafolio construido y nuestro retorno, vamos a realizar la comparación con el retorno del mercado del Q32022
getSymbols(c("^GSPC"), from="2022-06-01", to="2022-09-30", src="yahoo", periodicity= "monthly")
## Warning in read.table(file = file, header = header, sep = sep,
## quote = quote, : incomplete final line found by readTableHeader
## on 'https://query2.finance.yahoo.com/v7/finance/download/^GSPC?
## period1=1654041600&period2=1664496000&interval=1mo&events=history'
## [1] "^GSPC"
Aqui combinamos en una dataset el precio ajustado del mercado
mktret1 <- merge(GSPC$GSPC.Adjusted)
Omitimos los valores NA
mktret1 <- na.omit(mktret1)
Aqui realizamos el calculo de los retornos mensuales
mktret.r = mktret1/ stats::lag(mktret1, n=1)-1
Aqui realizamos el retorno de los Q3 del mercado dandonos como resultado de -0.05277139.
mktret.q = as.numeric(mktret1[nrow(mktret1)])/ as.numeric(mktret1[1])-1
mktret.q
## [1] -0.05277139
A partir del modelo logistico con la depuración de ratios finaniceros seleccionandolos por su p-value, su beta y su z-value. Concluimos nuestros bases para la creacion de nuestro modelo de machine learning, (la matriz de confusión), donde obtuvimos resultados confiables, y con este tipo de modelos puede pronosticar de una maneria optima los valores a futuro.
De igual forma a la hora de filtrar nuestro portafolio, estamos tomando ratios los cuales, tienen mucha importancia a la hora de tomar la decision si invertir o no respecto a las acciones.
Concluyendo que mi modelo puede ser aceptado por la empresa INVOPORTA.
-RPubs - Workshop 1 Solution - Algorithms and Data Analysis. (2022, October 3). Rpubs.com. https://rpubs.com/cdorante/fz2022_w1_sol
-RPubs - Workshop 2 Solution - Algorithms and Data Analysis. (2022, October 4). Rpubs.com. https://rpubs.com/cdorante/fz2022_w2_sol
-RPubs - Workshop 3 Solution - Algorithms and Data Analysis. (2022, October 13). Rpubs.com. https://rpubs.com/cdorante/fz2022_w3_sol
Baker, B. (2022, 1 agosto). 8 important financial ratios to know when analyzing a stock. Bankrate. Recuperado 21 de octubre de 2022, de https://www.bankrate.com/investing/important-financial-ratios/ BNamericas - Tasa de interés de México ya restringe creci. . . (s. f.). BNamericas.com. Recuperado 18 de octubre de 2022, de https://www.bnamericas.com/es/analisis/tasa-de-interes-de-mexico-ya-restringe-crecimiento-pero-lo-peor-esta-por-venir Brown, M. (2022, 29 septiembre). Quick Ratio or Acid Test Ratio. Double Entry Bookkeeping. Recuperado 21 de octubre de 2022, de https://www.double-entry-bookkeeping.com/liquidity-ratios/quick-ratio/ Dobaño, R. (2022, 26 julio). ROA Y ROE: qué son y cómo calcularlos. Autónomos, empresas y asesorías. Recuperado 21 de octubre de 2022, de https://getquipu.com/blog/que-es-el-roa-y-el-roe/ Dueñas, C. M. (s. f.). ROA | Definición e importancia para la rentabilidad de tu empresa. Recuperado 21 de octubre de 2022, de https://www.dripcapital.com/es-mx/recursos/blog/que-es-roa La Fed vuelve a subir las tasas de interés en un 0,75% por tercera vez consecutiva. (2022, 21 septiembre). CNN. Recuperado 18 de octubre de 2022, de https://cnnespanol.cnn.com/2022/09/21/reserva-federal-fed-tasas-interes-inflacion-trax/ La Fed vuelve elevar con fuerza tasas de interés, ve otro incremento importante este año. (2022, 21 septiembre). euronews. Recuperado 18 de octubre de 2022, de https://es.euronews.com/next/2022/09/21/economia-fed-tasas Garrote, P. A. (2021, 4 octubre). Análisis financiero: ¿Qué es el ROE? BBVA NOTICIAS. Recuperado 21 de octubre de 2022, de https://www.bbva.com/es/que-es-el-roe/ Interest Coverage Ratio: The Formula, How It Works, an Example. (2022, 17 junio). Investopedia. Recuperado 21 de octubre de 2022, de https://www.investopedia.com/terms/i/interestcoverageratio.asp Machine Learning | Qué es, tipos, ejemplos y cómo implementarlo. (2022, 21 septiembre). GraphEverywhere. Recuperado 21 de octubre de 2022, de https://www.grapheverywhere.com/machine-learning-que-es-tipos-ejemplos-y-como-implementarlo/ Martinez, L. (2022, 19 octubre). La Fed prepara otro aumento de tasas en noviembre. El Líbero. Recuperado 21 de octubre de 2022, de https://ellibero.cl/newsletter/nexnews-presenta-preven-nuevas-alzas-de-tasas-en-eeuu-inflacion-sobre-el-10-en-uk-taiwan-responde-a-xi-con-ejercicios-militares/ Morales, Y. (2022, 21 septiembre). La Fed sube su tasa de interés en 75 puntos base por tercera vez consecutiva. El Economista. Recuperado 21 de octubre de 2022, de https://www.eleconomista.com.mx/sectorfinanciero/La-Fed-sube-su-tasa-de-interes-en-75-puntos-base-por-tercera-vez-consecutiva-20220921-0053.html Orta, R. G. (2017, 12 agosto). Las tasas de interés y el bolsillo de los mexicanos. Deloitte México. Recuperado 18 de octubre de 2022, de https://www2.deloitte.com/mx/es/pages/about-deloitte/articles/tasas-de-interes-en-mexico.html