Nos gustaría saber el precio final de una acción que tiene ciertas variaciones a lo largo del tiempo. Para empezar cargamos la librería tidyverse.
Procedemos leyendo la tabla de variaciones, conviertiéndola en un vector, finalmente como suponemos que el precio inicial de la acción es 0 solo sumamos los elementos del vector para obtener el precio final.
precio <- apply(read.table("C:/Users/LuisAlberto/Downloads/variaciones.txt"), 2, as.vector) %>%
sum()
precio## [1] 1379.159
Por lo tanto el precio resultante de la acción es 1379.1591749.
En este ejercicio suponemos que las variaciones del ejercicio anterior se repiten todo el tiempo, por lo que nuestro objetivo será encontrar el primer precio que ocurre dos veces. Con el siguiente código encontramos dicho precio:
var <- read.table("C:/Users/LuisAlberto/Downloads/variaciones.txt")
var <- as.vector(var$V1)
precio1 <- c()
precio1[1] <- 0
j <- 1
aux <- duplicated(precio1)
while(length(aux[aux!=FALSE])==0){
for(i in 1:length(var)){
j <- j+1
precio1[j] <- precio1[j-1] + var[i]
aux <- duplicated(precio1)
if(length(aux[aux!=FALSE])==1){
break
}
}
}
duplicado <- precio1[duplicated(precio1)]Y corriendo duplicado en la consola obtenemos que el primer precio que se repite es 914671.6. Si por curiosidad quisieras conocer los dos índices donde se encuentra este precio, bastará con correr which(precio1 == duplicado) (los índices son 375771 y 515145).
Para encontrar la suma de todos los multiplos de 3 o 5 menores a 1000 inicializamos la variable suma con el valor 0, para ir sumándole los números menores a 1000 que sean módulo 0 con 3 o 5.
## [1] 233168
Esta suma nos da como resultado: 233,168.
Para este ejercicio creamos una función que replica un juego donde se ganan 20 pesos por cada 6 que salga al lanzar tres dados. El costo de este juego es de 10 pesos.
Esta funcion llamada casino solo recibe el número de juegos y devuelve un vector con la cantidad que se gana en cada juego.
#n: no. de juegos
#aux: no. de 6's obtenidos al lanzar los 3 dados en el juego i
#gan: vector de ganancias de tamaño n
casino <- function(n){
set.seed(1)
gan <- rep(0,n)
for (i in 1:n){
aux <- rbinom(1,3,1/6)
gan[i] <- 20*aux -10
}
return(gan)
}Procedemos simulando 100, 1,000 y 10,000 juegos y calculándole la media y la varianza a cada uno de estos escenarios.
x <- casino(100) #100 juegos
y <- casino(1000) #1,000 juegos
z <- casino(10000) #10,000 juegos
medias <- c(mean(x), mean(y), mean(z))
names(medias) <- c("Media x", "Media y", "Media z")
var <- c(var(x), var(y), var(z))
names(var) <- c("Varianza x", "Varianza y", "Varianza z")Las medias son:
## Media x Media y Media z
## -0.400 0.040 -0.026
Las varianzas son:
## Varianza x Varianza y Varianza z
## 133.1717 177.7762 167.7761
Parece que el juego es justo, es decir, teóricamente deberíamos tener una media de 0 y los valores de estas simulaciones son cercanos a dicho valor. Sin embargo, las varianzas apuntan a una dispersión grande, es decir, la mayoría de las veces vamos a ganar 10 pesos o perder 10 pesos. Esto queda más claro al observar los summary de cada escenario.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -10.0 -10.0 -10.0 -0.4 10.0 30.0
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -10.00 -10.00 -10.00 0.04 10.00 50.00
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -10.000 -10.000 -10.000 -0.026 10.000 50.000
Adaptando casino para que reciba el número de juegos, dinero inicial, costo del juego y apuesta del juego obtenermos la función casino1. (Para nuestra función es necesario llamar a la librería ggplot2)
casino1 <- function(n_juegos, din_inicial, costo, apuesta){
set.seed(1)
gan <- rep(0,n_juegos)
acum <- rep(0,n_juegos)
for (i in 1:n_juegos){
aux <- rbinom(1,3,1/6)
gan[i] <- apuesta*aux - costo
acum[i] <- din_inicial + sum(gan[1:i])
}
ganancias <- data.frame(Ganancia = gan, Acumulado = acum)
x <- 1:n_juegos
pl <- ggplot(ganancias, aes(x, Acumulado)) +
geom_line() + labs(x="Juego i") + theme_minimal()
mylist <- list(ganancias, pl)
return(mylist)
}Esta función nos devuelve una lista que contiene un data frame con la ganancia del i-ésimo juego y la ganancia acumulada hasta el juego \(i\) junto con el gráfico de la ganancia acumulada.
Analizaremos los siguientes escenarios, dejando fijo el número de juegos en 100.
esc1 <- casino1(100,10,10,10) #Escenario 1
esc2 <- casino1(100,10,2,5) #Escenario 2
esc3 <- casino1(100,100,10,20) #Escenario 3
esc4 <- casino1(100,1000,5,10) #Escenario 4## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -10.0 -10.0 -10.0 -5.2 0.0 10.0
Podemos ver que debido a que la apuesta es igual al costo y que en promedio estamos perdiendo 5.2 pesos por juego se presenta una tendencia a perder. En este caso en particular terminamos con un acumulado de -510.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -2.0 -2.0 -2.0 0.4 3.0 8.0
Aquí el costo es menos de la mitad de la apuesta, dado que la probabilidad de sacar un 6 en tres lanzamientos es de \(\frac{1}{2}\), esto nos da una tendencia a ganar alrededor de 50 centavos por juego. En este caso en particular terminamos con un acumulado de 50.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -10.0 -10.0 -10.0 -0.4 10.0 30.0
En este escenario la apuesta es el doble del costo, teóricamente deberiamos tener un juego justo (una media de 0), pero dada esta muestra podemos ver que en promedio perdemos 40 centavos por juego. En este caso en particular terminamos con un acumulado de 60.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -5.0 -5.0 -5.0 -0.2 5.0 15.0
Este escenario es similar al escenario 3, la diferencia es el dinero con el que empezamos, el cual es mayor. Además esperamos perder 20 centavos, la mitad de lo que perdemos en el escenario 3, ya que aqui el costo y la ganancia es la mitad de lo que eran en el escenario anterior. En este caso en particular terminamos con un acumulado de 980.
También es importante notar que las gráficas de los escenarios 3 y 4 son las mismas por el set.seed(1), aun así, sin ella se pueden esperar gráficas similares ya que son escenarios que guardan la misma proporción entre apuesta y costo.
En este ejercicio implementamos el algortimo de Luhn dentro de una función en R y lo usamos para verificar la validez de algunos números de tarjeta. La función luhn no toma en cuenta caracteres que contengan letras en ellos, pude recibir un vector o un data frame que contenga en la primera columna los números (la columna no debe tener nombre).
luhn <- function(num){
k <- 0 #Contador de numeros validos encontrados
validas <- c() #vector que almacenara los numeros validos
if(is.data.frame(num) == T){
num <- as.vector(num$V1) #En caso de recibir un data frame se convierte a vector
}
for (i in 1:length(num)){
num[i] <- gsub(" ", "", num[i]) #eliminamos los espacios
temp <- c() #vector auxiliar que tendra como elementos el numero de tarjeta i
if(!grepl("\\D", num[i]) == T){
temp <- as.numeric(strsplit(as.character(num[i]),"")[[1]])
temp <- rev(temp) #volteamos el vector
#Aplicamos el algoritmo de Luhn
for (j in 1:floor(length(temp)/2)){
temp[2*j] <- 2*temp[2*j]
if(temp[2*j] > 9){
temp[2*j] <- trunc(temp[2*j]/10) + (temp[2*j] - 10*trunc(temp[2*j]/10))
}
}
if((sum(temp)%%10 == 0)&& sum(temp)>10){ #se revisa su validez
k <- k+1
validas[k] <- num[i]
}
}
}
#creamos un data frame con los numeros validos, sin repetirlos
res <- data.frame(NumTarjetaValida = unique(validas))
return(res)
}Probamos la función con una serie de caracteres:
numeros <- read.table("C:/Users/LuisAlberto/Downloads/card_numbers.txt", sep = "\n")
head(numeros) #observemos los primeros caracteres de la serie ## V1
## 1 9004211705099316
## 2 6666666666666
## 3 6366 0797 0977 2705
## 4 f2k8f0y4f1r9f2k1
## 5 9999999999999
## 6 4444444444444444
## NumTarjetaValida
## 1 6666666666666
## 2 2223016768739313
## 3 7380882140483393
## 4 30569309025904
## 5 9108287699545120
## 6 2979301841083400
## 7 8888888888888888
## 8 5105105105105100
## 9 8898477385433469
## 10 9892469714302907
## 11 4111111111111111
## 12 4415495406715485
## 13 5631738954202660
## 14 3530111333300000
## 15 8776159835266726
## 16 6219944813127845
## 17 9343520555498223
## 18 378734493671000
## 19 6011000990139424
## 20 1998721796410234
## 21 5555555555554444
## 22 378282246310005
## 23 8496697349896438
## 24 6161593324615380
## 25 9889748024195522
## 26 2221000000000009
## 27 6011111111111117
## 28 4222222222222
## 29 3566002020360505
## 30 0329801946021750
## 31 4012888888881881
## 32 1884449070342249
## 33 2223000048400011
## 34 1329209250512448
## 35 1334315215732501
## 36 4663457647815036
## 37 371449635398431
En este ejercicio simulamos el comportamiento de la caja de un banco, específicamente creamos una función que recibe el número de cajas disponibles y un vector con los tiempos de atención de cada cliente y devuelve el tiempo en el que fueron atendidos todos los clientes. Consideramos que en cuanto se desocupa una caja, el siguiente cliente se dirige a la caja vacía (como una unifila).
La función es la siguiente:
fila <- function(n_cajas, espera){
if(n_cajas < length(espera)){
cajas <- rep(0, n_cajas)
for(i in 1:length(cajas)){
c <- i
cajas[i] <- cajas[i] + espera[i]
}
c <- c + 1
for(j in c:length(espera)){
cajas[which.min(cajas)] <- cajas[which.min(cajas)] + espera[j]
}
} else {
cajas <- rep(0, length(espera))
for(k in 1:length(espera)){
cajas[k] <- cajas[k] + espera[k]
}
}
tiempo <- unique(max(cajas))
return(tiempo)
}Veamoslo con un ejemplo, consideremos que hay 3 cajas abiertas y tenemos los siguientes tiempos:
## [1] 12
Por lo tanto se atenderán a los 6 clientes en 12 minutos.
Se nos pide crear una función para un amigo que le diga cuanto tiempo en años debe dejar su dinero invertido para conseguir cierta cantidad, se supone que la tasa de interés se paga a fin de año y que la tasa de impuestos se paga sobre el interés ganado.
#d <- dinero inicial
#i <- tasa de interes (efectiva anual)
#r <- tasa de impuestos (efectiva anual)
#c <- cantidad deseada
tiempo <- function(d, i, r, c){
t <- log((c-r*d)/(d-r*d))/log(1+i)
#los intereses se pagan a final de año, entonces se redondea al sig. entero
t <- ceiling(t)
return(t)
}Como ejemplo supogamos que invierte 1000 pesos a una tasa de interés del 5% anual, que la tasa de impuestos es del 18% anual y que desea tener 1100 pesos. Entonces el tiempo que debe dejarlo estará dado por:
## [1] 3
Por lo tanto debe dejar sus 1000 pesos invertidos durante 3 años.
Ahora, si nuestro amigo además de la cantidad inicial quiere invertir otra cantidad variable cada año, la función debe cambiar para ser más amigable. Mientras no se alcance la cantidad deseada, se imprimirá el año que finaliza y se le preguntará cuanto dinero quiere agregar a través de readline() para que introduzca la cantidad en la consola. Nuestra nueva función queda de la siguiente manera:
tiempo1 <- function(d, i, r, c){
total <- d
t <- 0
while(total <= c){
t <- t + 1
ac <- total*(1+i) - total*i*r
if(ac <= c){
print(paste("Año ", t))
aux <- readline(prompt = "Cantidad desea agregar al inicio del año: " )
aux <- as.double(aux)
}
total <- ac + aux
}
cat("\nEl tiempo necesario para alcanzar ", c, " es de ", t, " años")
}Podríamos automatizar algún script que necesitemos correr continuamente en caso de que los datos necesarios para alguna tarea cambien continuamente, por ejemplo, el llevar ciertas estadísticas de los últimos 252 precios de determinada acción.
Usaríamos R desde la importación de datos, por medio de library(tidyquant), esta librería obtiene los datos de Yahoo Finance, luego con la función getSymbols() o con tq_get() obtendríamos la información de las acciones que nos interesan (es de más ayuda la segunda función porque nos regresa un data frame). El análisis estadístico lo podríamos hacer fácilmente y apoyarnos para darle mejor forma al data frame usando library(tidyverse).
Posteriormente creamos un reporte en R Markdown con los datos y la estructura que queramos, una vez hecho esto, llegaría la parte de la automatización, donde usaremos Windows Task Scheduler donde crearemos un New Task, luego New Action, elegimos Start Program, buscamos Rscript.exe, metemos el nombre de nuestro archivo en parameters, su path donde diga Start in y finalmente vamos a la pestaña de Triggers para crear uno nuevo donde elegimos la periodicidad.
Los usuarios finales serían los interesados en el mercado accionario y el reporte generado deberá de ser muy visual para que sea sencillo de comprender para que el lector se quede con la información más relevante.