#1. Imprime lo siguiente:
#a)
#*******************
#*******************
#*******************
#*******************

n <- 4
m <- 19
for (i in 1:n) {
  for (j in 1:m) {
    cat("* ")
  }
  cat("\n")
}
## * * * * * * * * * * * * * * * * * * * 
## * * * * * * * * * * * * * * * * * * * 
## * * * * * * * * * * * * * * * * * * * 
## * * * * * * * * * * * * * * * * * * *
#b)
#*******************
#* *
#* *
#*******************

for(i in 1:4) {
  if(i == 1 || i == 4) {
    cat(rep("*", n), "\n", sep = "")
  } else {
    cat("*", rep(" ", n-2), "*\n", sep = "")
  }
}
## ****
## *  *
## *  *
## ****
#c) 
#*
#**
#***
#****
#***
#** 
#*
for(i in c(1:4, 3:1))
  cat( paste(strrep(" ", j-1), strrep("* ", i), "\n") )
##                    *  
##                    * *  
##                    * * *  
##                    * * * *  
##                    * * *  
##                    * *  
##                    *
#2. Escriba una función que realice la figura 1 c) donde el usuario pueda ingresar el máximo número de *

user <- readline(prompt="Ingresa el numero de asteriscos")
## Ingresa el numero de asteriscos
MA<- function(EA,EB){
  for(i in c(1:EA, EB:1))
  cat( paste(strrep(" ", j-1), strrep("* ", i), "\n") )
}

EV<-MA(3,4)  
##                    *  
##                    * *  
##                    * * *  
##                    * * * *  
##                    * * *  
##                    * *  
##                    *
#3. Escribe una función que imprima los números del 1 a n (n es parámetro), y el valor al cubo. Por defecto, n = 10. Ejemplo: 1 --- 1
#2 --- 8
#3 --- 27
#4 --- 64

power_function <- function(x, exponent = 3) {
  result <- x ^ exponent
  for (x in 1:10)
  return(result)
}

# Usage
power_of_3 <- power_function(1:10)
cat(paste(1:10, "---",power_of_3))
## 1 --- 1 2 --- 8 3 --- 27 4 --- 64 5 --- 125 6 --- 216 7 --- 343 8 --- 512 9 --- 729 10 --- 1000
#5. Escribe una función que imprima los números primos entre 1 y n. Donde n es parámetro.
# Función optimizada para verificar primalidad
es_primo <- function(n) {
  if (n <= 1) return(FALSE)
  if (n == 2 || n == 3) return(TRUE)
  if (n %% 2 == 0 || n %% 3 == 0) return(FALSE)
  
  # Verificar divisores en forma de 6k ± 1
  i <- 5
  w <- 2
  while (i * i <= n) {
    if (n %% i == 0) return(FALSE)
    i <- i + w
    w <- 6 - w  # Alterna entre 2 y 4 (para 6k±1)
  }
  return(TRUE)
}

# Función para mostrar primos en un rango
mostrar_primos <- function(limite) {
  if (limite < 2) {
    cat("No hay números primos en el rango especificado\n")
    return()
  }
  
  cat("Números primos hasta", limite, ":\n")
  for (num in 2:limite) {
    if (es_primo(num)) {
      cat(num, " ")
    }
  }
  cat("\n")
}
mostrar_primos(30)
## Números primos hasta 30 :
## 2  3  5  7  11  13  17  19  23  29
#6. Crea una función en R que dada una serie de datos, grafique la serie y sus promedios móviles exponenciales de orden n y k. Recuerda que es importante colocar título y etiquetas adecuadas así mostrar colores y formas que identifiquen a cada una de las series.

library(quantmod)
## 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
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.1.3
library(xts)
library(zoo)

graficar_EMA_AAPL <- function(n = 12, k = 26) {
  # Descargar datos de AAPL
  getSymbols("AAPL", from = "2024-01-01", to = "2025-06-07")
  
  # Extraer precios ajustados
  aapl_adj <- Ad(AAPL)
  
  # Calcular EMAs
  ema_n <- EMA(aapl_adj, n = n)
  ema_k <- EMA(aapl_adj, n = k)
  
  # Crear dataframe para ggplot
  df <- data.frame(
    Fecha = index(aapl_adj),
    Precio = as.numeric(aapl_adj),
    EMA_n = as.numeric(ema_n),
    EMA_k = as.numeric(ema_k)
  )
  
  # Nombres para la leyenda
  nombre_ema_n <- paste("EMA", n)
  nombre_ema_k <- paste("EMA", k)
  
  # Graficar
  ggplot(df, aes(x = Fecha)) +
    geom_line(aes(y = Precio, color = "Precio Ajustado"), linewidth = 0.8) +
    geom_line(aes(y = EMA_n, color = nombre_ema_n), linewidth = 0.8, linetype = "dashed") +
    geom_line(aes(y = EMA_k, color = nombre_ema_k), linewidth = 0.8, linetype = "dotted") +
    labs(title = paste("AAPL: Precio Ajustado y EMAs(", n, ",", k, ") - 2024-01-01 a 2025-06-07"),
         x = "Fecha",
         y = "Precio ($)",
         color = "Series") +
    scale_color_manual(values = c("Precio Ajustado" = "black", 
                                 nombre_ema_n = "blue", 
                                 nombre_ema_k = "red")) +
    theme_minimal() +
    theme(legend.position = "bottom",
          plot.title = element_text(hjust = 0.5))
}

# Ejemplo de uso:
graficar_EMA_AAPL(n = 10, k = 20)
## Warning: Removed 9 rows containing missing values (`geom_line()`).
## Warning: Removed 19 rows containing missing values (`geom_line()`).

#7. Con la función anterior grafica las medias móviles de dolar.csv e ipc.csv, recuerda que puedes leer estos archivos con reed.delim o read.table, dependiendo de los parámetros y separadores

library(quantmod)
library(ggplot2)
library(xts)

graficar_EMA_Yahoo <- function(simbolo = "AAPL", 
                               n = 12, 
                               k = 26, 
                               desde = "2024-01-01", 
                               hasta = Sys.Date()) {
  
  # Intenta descargar los datos
  tryCatch({
    getSymbols(simbolo, src = "yahoo", from = desde, to = hasta, auto.assign = TRUE)
    
    # Manejar símbolos con caracteres especiales
    nombre_datos <- gsub("\\^", "", simbolo)
    nombre_datos <- gsub("=X", "", nombre_datos)
    
    # Obtener los datos
    if(exists(nombre_datos)) {
      datos <- get(nombre_datos)
    } else {
      stop("No se pudo descargar los datos para el símbolo proporcionado")
    }
    
    # Extraer precios (ajustados si existen, de cierre si no)
    if(has.Ad(datos)) {
      precio <- Ad(datos)
    } else if(has.Cl(datos)) {
      precio <- Cl(datos)
    } else {
      precio <- datos[,paste0(nombre_datos, ".Close")]  # Para índices
    }
    
    # Eliminar NA's y asegurar que haya suficientes datos
    precio <- na.omit(precio)
    if(nrow(precio) < max(n, k)) {
      stop("No hay suficientes datos después de eliminar NA's para calcular los EMAs")
    }
    
    # Calcular EMAs con manejo de NA's
    ema_n <- EMA(precio, n = n)
    ema_k <- EMA(precio, n = k)
    
    # Crear dataframe para ggplot
    df <- data.frame(
      Fecha = index(precio),
      Precio = as.numeric(precio),
      EMA_n = as.numeric(ema_n),
      EMA_k = as.numeric(ema_k)
    )
    
    # Nombres para la leyenda
    nombre_ema_n <- paste("EMA", n)
    nombre_ema_k <- paste("EMA", k)
    nombre_precio <- ifelse(has.Ad(datos), "Precio Ajustado", 
                           ifelse(has.Cl(datos), "Precio de Cierre", "Precio"))
    
    # Graficar
    ggplot(df, aes(x = Fecha)) +
      geom_line(aes(y = Precio, color = nombre_precio), linewidth = 0.8) +
      geom_line(aes(y = EMA_n, color = nombre_ema_n), linewidth = 0.8, linetype = "dashed") +
      geom_line(aes(y = EMA_k, color = nombre_ema_k), linewidth = 0.8, linetype = "dotted") +
      labs(title = paste(simbolo, ":", nombre_precio, "y EMAs(", n, ",", k, ") -", desde, "a", hasta),
           x = "Fecha",
           y = "Precio",
           color = "Series") +
      scale_color_manual(values = c("black", "blue", "red"),
                         labels = c(nombre_precio, nombre_ema_n, nombre_ema_k)) +
      theme_minimal() +
      theme(legend.position = "bottom",
            plot.title = element_text(hjust = 0.5))
    
  }, error = function(e) {
    message("Error al procesar los datos: ", e$message)
    message("Posibles soluciones:")
    message("1. Verifica que el símbolo ", simbolo, " existe en Yahoo Finance")
    message("2. Prueba con un rango de fechas diferente")
    message("3. Intenta con un valor mayor para n o k")
    return(NULL)
  })
}
graficar_EMA_Yahoo("^MXX", n = 5, k = 20, desde = "2024-01-01")
## Warning: Removed 4 rows containing missing values (`geom_line()`).
## Warning: Removed 19 rows containing missing values (`geom_line()`).

graficar_EMA_Yahoo("MXN=X", n = 30, k = 30, desde = "2025-01-01")
## Warning: MXN=X contains missing values. Some functions will not work if objects
## contain missing values in the middle of the series. Consider using na.omit(),
## na.approx(), na.fill(), etc to remove or replace them.
## Error al procesar los datos: No se pudo descargar los datos para el símbolo proporcionado
## Posibles soluciones:
## 1. Verifica que el símbolo MXN=X existe en Yahoo Finance
## 2. Prueba con un rango de fechas diferente
## 3. Intenta con un valor mayor para n o k
## NULL
#8. Crea 3 muestras de tamaño 100, una muestra utilizando la función anterior con p=0.1 y n=50, la segunda con p=0.1 y n=200, y la tercera con con p=0.1 y n=500. Realiza un histograma de cada una ¿Qué puede observar?

D1<-rbinom(50,100,0.1)
D2<-rbinom(200,100,0.1)
D3<-rbinom(500,100,0.1)

par(mfrow = c(1, 3))  
hist(D1)
hist(D2)
hist(D3)

#9. Escriba una aplicación que reciba como entrada un entero que contenga sólo dígitos 0 y 1 (es decir, un entero binario), y que imprima su equivalente decimal


binario_a_decimal <- function(binario) {
  decimal <- 0
  posicion <- 1  # Valor posicional inicial (2^0 = 1)
  
  while (binario > 0) {
    digito <- binario %% 10  # Extrae el dígito más a la derecha
    if (digito != 0 && digito != 1) {
      stop("El número ingresado no es binario (contiene dígitos diferentes de 0 y 1)")
    }
    decimal <- decimal + digito * posicion
    binario <- binario %/% 10  # Elimina el dígito más a la derecha
    posicion <- posicion * 2    # Actualiza el valor posicional (potencia de 2)
  }
  
  return(decimal)
}

binario_a_decimal(1101011101)
## [1] 861
#10. Un palíndromo es una secuencia de caracteres que se lee igual al derecho y al revés. Por ejemplo, cada uno de los siguientes enteros de cinco dígitos es un palíndromo: 12321,55555,45554 y 11611. Escriba una función que lea un entero de cinco dígitos y determine si es un palíndromo. Si el número no es de cinco dígitos, el programa debe mostrar un mensaje de error.

# Define a function to check if a given number is a palindrome using recursion
is_palindrome <- function(number) {
    # Convert the number to a character string
    num_str <- as.character(number)
    
    # Define a helper function to check if a string is a palindrome
    is_palindrome_helper <- function(str) {
        if (nchar(str) <= 1) {
            return(TRUE)  # Base case: Single character or empty string is a palindrome
        } else {
            first_char <- substr(str, 1, 1)  # Get the first character
            last_char <- substr(str, nchar(str), nchar(str))  # Get the last character
            
            # Check if the first and last characters are equal
            if (first_char != last_char) {
                return(FALSE)  # If not equal, not a palindrome
            } else {
                # Recursively check the substring without the first and last characters
                return(is_palindrome_helper(substr(str, 2, nchar(str) - 1)))
            }
        }
    }
    
    # Call the helper function with the number converted to a string
    return(is_palindrome_helper(num_str))
}

# Test the function with example inputs
number1 <- 42324
number2 <- 1234

# Check if the numbers are palindromes and print the result
cat("Number", number1, "is a palindrome!", is_palindrome(number1), "\n")
## Number 42324 is a palindrome! TRUE
cat("Number", number2, "is a palindrome!", is_palindrome(number2), "\n")
## Number 1234 is a palindrome! FALSE
#11. Movimiento Browniano Geométrico.Tomando los datos del IPC, determine sus rendimientos, así como la media y varianza de estos. Si 𝑊𝑡 es una normal estándar. Determine una trayectoria a 250 días y grafique.

# Función para simular trayectorias del IPC
simular_trayectoria_IPC <- function(S0, mu, sigma, dias, n_trayectorias = 1) {
  # Parámetros de tiempo
  t <- (1:dias) / 365  # Convertir días a años
  
  # Matriz para almacenar las trayectorias
  trayectorias <- matrix(NA, nrow = dias, ncol = n_trayectorias)
  
  # Generar trayectorias
  for (j in 1:n_trayectorias) {
    # Generar incrementos brownianos
    W <- c(0, cumsum(rnorm(dias - 1, mean = 0, sd = sqrt(1/365))))
    
    # Calcular trayectoria
    trayectorias[, j] <- S0 * exp((mu - 0.5 * sigma^2) * t + sigma * W)
  }
  
  return(trayectorias)
}

# Análisis de datos históricos del IPC (ejemplo con datos simulados)
# En la práctica aquí cargarías datos reales como:
# ipc <- read.csv("IPC.csv")$Cierre

# Simular datos históricos del IPC (365 días)
set.seed(123)
ipc_historico <- 45000 * exp(cumsum(rnorm(365, mean = 0.0002, sd = 0.01)))

# Calcular rendimientos diarios históricos
rendimientos <- diff(ipc_historico) / ipc_historico[-length(ipc_historico)]

# Media y varianza de rendimientos históricos
mu_historico <- mean(rendimientos) * 365  # Anualizar
sigma_historico <- sd(rendimientos) * sqrt(365)  # Anualizar

cat("Parámetros estimados del IPC:\n")
## Parámetros estimados del IPC:
cat("  - Rendimiento anualizado (μ):", round(mu_historico, 6), "\n")
##   - Rendimiento anualizado (µ): 0.212416
cat("  - Volatilidad anualizada (σ):", round(sigma_historico, 6), "\n")
##   - Volatilidad anualizada (s): 0.185323
# Simular y graficar una trayectoria a 250 días
trayectoria <- simular_trayectoria_IPC(
  S0 = ipc_historico[length(ipc_historico)],  # Último precio disponible
  mu = mu_historico,
  sigma = sigma_historico,
  dias = 250
)

# Graficar
plot(1:250, trayectoria[, 1], type = "l", lwd = 2, col = "blue",
     main = "Trayectoria Simulada del IPC (250 días)",
     xlab = "Días", ylab = "Precio del IPC",
     ylim = c(min(trayectoria) * 0.95, max(trayectoria) * 1.05))
grid()

#12. Existe un contrato por el que puedes entrar por $100.00 y 250 días después te paga de acuerdo con lo siguiente:
#-Si el rendimiento del IPC se -10% y el 10%, te regresan los $100.
#-Si el rendimiento del IPC es mayor al 10%, te duplican el rendimiento. Por ejemplo, un rendimiento 15% del IPC, bajo el contrato te pagarían $130.
#-Si el rendimiento del IPC es menor de -10%, el contrato te regresa el mismo rendimiento. #Por ejemplo. Un rendimiento del -15% en el IPC, bajo el contrato te regresa $85.
#Realice 1,000 trayectorias del IPC a 250 días. Y en cada trayectoria determine el precio del contrato (vector de tamaño 1000).
#Al final determine la media y desviación de la ganancia de este contrato.
# Parámetros del modelo
S0 <- 1.0           # Precio inicial del IPC (normalizado a 1)
mu <- 0.08          # Rendimiento anual esperado (8%)
sigma <- 0.20       # Volatilidad anual (20%)
T_days <- 250       # Periodo en días
T <- T_days / 365   # Periodo en años
n_simulations <- 1000 # Número de trayectorias

set.seed(123) # Semilla para reproducibilidad

# Simular rendimientos del IPC
Z <- rnorm(n_simulations, mean = 0, sd = 1)
R <- exp((mu - 0.5 * sigma^2) * T + sigma * sqrt(T) * Z) - 1

# Calcular pagos del contrato
calculate_payoff <- function(r) {
  if (r >= -0.10 && r <= 0.10) {
    return(100)
  } else if (r > 0.10) {
    return(100 * (1 + 2 * (r - 0.10)))
  } else {
    return(100 * (1 + r))
  }
}

payoffs <- sapply(R, calculate_payoff)

# Calcular ganancias (pago - inversión inicial)
ganancias <- payoffs - 100

# Estadísticas descriptivas
media_ganancia <- mean(ganancias)
desviacion_ganancia <- sd(ganancias)

# Resultados
cat("Media de la ganancia:", round(media_ganancia, 2), "\n")
## Media de la ganancia: 7.16
cat("Desviación estándar de la ganancia:", round(desviacion_ganancia, 2), "\n")
## Desviación estándar de la ganancia: 22.84
# Visualización
hist(ganancias, breaks = 30, main = "Distribución de las Ganancias del Contrato",
     xlab = "Ganancia", ylab = "Frecuencia", col = "lightblue")
abline(v = media_ganancia, col = "red", lwd = 2, lty = 2)
legend("topright", legend = paste("Media =", round(media_ganancia, 2)), 
       col = "red", lwd = 2, lty = 2)