1. Taller 1

1.1 Integrantes

Amaya Anthony, Amaya Daniela, Diaz Enmanuel, Lopez Mauricio

1.2 Paquetes requeridos

Para la extracción, procesamiento y analisis exploratorio, hacemos uso de estos paquetes.

library(readxl)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(Amelia)
## Cargando paquete requerido: Rcpp
## ## 
## ## Amelia II: Multiple Imputation
## ## (Version 1.8.3, built: 2024-11-07)
## ## Copyright (C) 2005-2025 James Honaker, Gary King and Matthew Blackwell
## ## Refer to http://gking.harvard.edu/amelia/ for more information
## ##
library(scales)
library(readr)
## 
## Adjuntando el paquete: 'readr'
## The following object is masked from 'package:scales':
## 
##     col_factor
library(ggplot2)
library(tidyr)

2. Extracción de datos

2.1 Decision de la base de datos a examinar

Decidimos examinar 20 stock del merado de valores, particularmente los primeros 20 en el ranking por ā€œMarket capā€ que se calcula de la siguiente manera:

\[ \text{Market Cap} = \text{Precio de la Acción} \times \text{Número de acciones en circulación} \]

2.2 Metodos de extracción de datos

Usamos la API de AlphaVantage, un servicio que proporciona datos financieros y de mercado en tiempo real y históricos.

2.3 Codigo para la obtención del archivo .xlsx

import requests
import pandas as pd
import numpy as np
import time
from datetime import datetime, timedelta

# ==================== CONFIGURACIƓN CON TU API KEY ====================
API_KEY = "Censurado"  # āœ… TU API KEY REAL

# TUS 20 TICKERS EXACTOS (corregĆ­ AMAZ → AMZN)
TICKERS = [
    "NVDA",       # 1. NVIDIA
    "MSFT",       # 2. MSFT
    "AAPL",       # 3. AAPL
    "GOOG",       # 4. GOOG
    "AMZN",       # 5. AMAZ → corregido a AMZN
    "META",       # 6. META
    "AVGO",       # 7. AVGO
    "TSM",        # 8. TSM
    "TSLA",       # 9. TSLA
    "TCEHY",      # 10. TCEHY
    "ORCL",       # 11. ORCL
    "NFLX",       # 12. NFLX
    "PLTR",       # 13. PLTR
    "005930.KS",  # 14. 005930.KS (Samsung Electronics Korea)
    "SAP",        # 15. SAP
    "ASML",       # 16. ASML
    "BABA",       # 17. BABA
    "AMD",        # 18. AMD
    "CSCO",       # 19. CSCO
    "CRM"         # 20. CRM
]

SLEEP_TIME = 60  # 60 segundos entre llamadas (OBLIGATORIO)

# ==================== FUNCIONES ====================
def obtener_datos_semanales(ticker, api_key):
    """
    Obtiene datos semanales de Alpha Vantage (TIME_SERIES_WEEKLY)
    """
    try:
        print(f"šŸ“” Solicitando datos semanales de {ticker}...")
        
        url = "https://www.alphavantage.co/query"
        params = {
            "function": "TIME_SERIES_WEEKLY",
            "symbol": ticker,
            "apikey": api_key,
            "datatype": "json"
        }
        
        # Headers para evitar bloqueos
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
        
        response = requests.get(url, params=params, headers=headers, timeout=30)
        data = response.json()
        
        # Verificar si hay error en la respuesta
        if "Error Message" in data:
            print(f"āŒ Error API para {ticker}: {data['Error Message']}")
            return None
            
        if "Note" in data:
            print(f"⚠ Nota API para {ticker}: {data['Note']}")
            return None
            
        if "Weekly Time Series" not in data:
            print(f"āŒ {ticker}: No se encontraron datos semanales")
            return None
            
        print(f"āœ… {ticker}: Datos recibidos correctamente")
        return data["Weekly Time Series"]
        
    except Exception as e:
        print(f"šŸ’€ Error de conexión con {ticker}: {str(e)}")
        return None

def procesar_datos_semanales(datos_json, ticker):
    """
    Convierte los datos JSON a DataFrame y filtra últimos 4 años
    """
    if not datos_json:
        return None
    
    try:
        # Crear DataFrame
        df = pd.DataFrame.from_dict(datos_json, orient='index')
        df.columns = ['Open', 'High', 'Low', 'Close', 'Volume']
        
        # Convertir tipos de datos
        for col in df.columns:
            df[col] = pd.to_numeric(df[col], errors='coerce')
        
        # Convertir Ć­ndice a datetime
        df.index = pd.to_datetime(df.index)
        df.sort_index(inplace=True)
        
        # Filtrar últimos 4 años
        fecha_limite = datetime.now() - timedelta(days=4*365)
        df = df[df.index >= fecha_limite]
        
        # Agregar solo columna de Ticker (sin Return ni Volatility)
        df['Ticker'] = ticker
        
        print(f"šŸ“Š {ticker}: {len(df)} semanas (Ćŗltimos 4 aƱos)")
        return df
        
    except Exception as e:
        print(f"āŒ Error procesando {ticker}: {str(e)}")
        return None

def guardar_en_excel(datos_por_ticker, filename):
    """
    Guarda todos los datos en un archivo Excel
    """
    try:
        with pd.ExcelWriter(filename, engine='openpyxl') as writer:
            # Guardar cada ticker en hoja separada
            for ticker, df in datos_por_ticker.items():
                if df is not None and not df.empty:
                    # Limpiar nombre de hoja para caracteres especiales
                    sheet_name = ticker.replace('.', '').replace('-', '')[:31]
                    df.to_excel(writer, sheet_name=sheet_name, index=True)
            
            # Crear hoja de resumen con RANK original
            resumen_data = []
            ranking_original = {
                "NVDA": 1, "MSFT": 2, "AAPL": 3, "GOOG": 4, "AMZN": 5,
                "META": 6, "AVGO": 7, "TSM": 8, "TSLA": 9, "TCEHY": 10,
                "ORCL": 11, "NFLX": 12, "PLTR": 13, "005930.KS": 14, "SAP": 15,
                "ASML": 16, "BABA": 17, "AMD": 18, "CSCO": 19, "CRM": 20
            }
            
            for ticker, df in datos_por_ticker.items():
                if df is not None and not df.empty:
                    resumen_data.append({
                        'Rank': ranking_original.get(ticker, 99),
                        'Ticker': ticker,
                        'Semanas': len(df),
                        'Desde': df.index.min().strftime('%Y-%m-%d'),
                        'Hasta': df.index.max().strftime('%Y-%m-%d'),
                        'Precio Actual': f"${df['Close'].iloc[-1]:.2f}"
                    })
            
            if resumen_data:
                df_resumen = pd.DataFrame(resumen_data)
                df_resumen = df_resumen.sort_values('Rank')  # Ordenar por ranking
                df_resumen.to_excel(writer, sheet_name='RESUMEN', index=False)
        
        print(f"šŸ’¾ Archivo guardado: {filename}")
        return True
        
    except Exception as e:
        print(f"āŒ Error guardando Excel: {e}")
        return False

# ==================== EJECUCIƓN PRINCIPAL ====================
if _name_ == "_main_":
    print("šŸš€ INICIANDO DESCARGA ALPHA VANTAGE")
    print("āœ… API KEY CONFIRMADA: G94TPEJXOD8UL29E")
    print("šŸ“… PerĆ­odo: 4 aƱos | ā° Intervalo: Semanal")
    print(f"šŸ“‹ Total tickers: {len(TICKERS)}")
    print("=" * 60)
    
    todos_datos = {}
    
    for i, ticker in enumerate(TICKERS, 1):
        print(f"\n{i}/{len(TICKERS)}. šŸ”„ Procesando {ticker} (Rank {i})...")
        
        # Obtener datos
        datos_json = obtener_datos_semanales(ticker, API_KEY)
        
        if datos_json:
            # Procesar datos
            df_procesado = procesar_datos_semanales(datos_json, ticker)
            todos_datos[ticker] = df_procesado
        else:
            todos_datos[ticker] = None
            print(f"⚠ Saltando {ticker} debido a error")
        
        # Espera CRƍTICA (60 segundos entre llamadas)
        if i < len(TICKERS):
            print(f"ā° Esperando {SLEEP_TIME} segundos (lĆ­mite API)...")
            time.sleep(SLEEP_TIME)
    
    # Guardar resultados
    if any(df is not None for df in todos_datos.values()):
        fecha = datetime.now().strftime("%Y%m%d_%H%M")
        archivo = f"top20_stocks_4aƱos_{fecha}.xlsx"
        guardar_en_excel(todos_datos, archivo)
        
        # Mostrar resumen final
        print("\n" + "=" * 60)
        print("šŸ“Š RESUMEN FINAL")
        print("=" * 60)
        exitosos = sum(1 for df in todos_datos.values() if df is not None and not df.empty)
        print(f"āœ… Tickers exitosos: {exitosos}/{len(TICKERS)}")
        
        # Mostrar preview de los primeros 5 tickers por ranking
        ranking_original = {
            "NVDA": 1, "MSFT": 2, "AAPL": 3, "GOOG": 4, "AMZN": 5,
            "META": 6, "AVGO": 7, "TSM": 8, "TSLA": 9, "TCEHY": 10,
            "ORCL": 11, "NFLX": 12, "PLTR": 13, "005930.KS": 14, "SAP": 15,
            "ASML": 16, "BABA": 17, "AMD": 18, "CSCO": 19, "CRM": 20
        }
        
        print("\nšŸ† TOP 5 POR RANKING:")
        for ticker in ["NVDA", "MSFT", "AAPL", "GOOG", "AMZN"]:
            df = todos_datos.get(ticker)
            if df is not None and not df.empty:
                print(f"   #{ranking_original[ticker]} {ticker}: ${df['Close'].iloc[-1]:.2f}")
                
    else:
        print("\nšŸ’€ No se pudo descargar ningĆŗn dato"

2.4 Conversion del archivo a .csv

Debido a que el archivo de excel es mas conveniente analizarlo en el formato csv, debemos juntar las 20 hojas en 1 sola. Para esto nos aseguraremos de que todas las columnas y filas tengan las mismas fechas y nombres.

2.4.1 Nombres de Paginas

Primero, obtenemos los nombres de las paginas para poder analizarlas.

excel_file <- "C:/Users/enmad/OneDrive/Desktop/Database/Univ/EstInferencial/ESTADISTICA_INFERENCIAL/top20_stocks_4aƱos_20250823_2326.xlsx"
sheet_names <- excel_sheets(excel_file)
print(sheet_names)
##  [1] "NVDA"    "MSFT"    "AAPL"    "GOOG"    "AMZN"    "META"    "AVGO"   
##  [8] "TSM"     "TSLA"    "TCEHY"   "ORCL"    "NFLX"    "PLTR"    "SAP"    
## [15] "ASML"    "BABA"    "AMD"     "CSCO"    "CRM"     "RESUMEN"

2.4.2 Nombres de Columnas

Segundo, obtenemos los nombres de las columnas en cada pagina

column_names_list <- lapply(sheet_names, function(sheet) {
  df <- read_excel(excel_file, sheet = sheet, n_max = 1)
  colnames(df)
})
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## • `` -> `...1`
for (i in seq_along(sheet_names)) {
  cat("Sheet:", sheet_names[i], "\n")
  print(column_names_list[[i]])
  cat("\n")
}
## Sheet: NVDA 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: MSFT 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: AAPL 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: GOOG 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: AMZN 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: META 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: AVGO 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: TSM 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: TSLA 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: TCEHY 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: ORCL 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: NFLX 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: PLTR 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: SAP 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: ASML 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: BABA 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: AMD 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: CSCO 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: CRM 
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"
## 
## Sheet: RESUMEN 
## [1] "Rank"          "Ticker"        "Semanas"       "Desde"        
## [5] "Hasta"         "Precio Actual"

Debido a que tenemos una hoja con un resumen de los datos obtenidos, vamos a eliminarla de la variable ā€˜sheet names’

sheet_names <- sheet_names[sheet_names != "RESUMEN"]
head(sheet_names,20)
##  [1] "NVDA"  "MSFT"  "AAPL"  "GOOG"  "AMZN"  "META"  "AVGO"  "TSM"   "TSLA" 
## [10] "TCEHY" "ORCL"  "NFLX"  "PLTR"  "SAP"   "ASML"  "BABA"  "AMD"   "CSCO" 
## [19] "CRM"

2.4.3 Combinar todas las paginas en 1

Ahora procedemos a combinar todas las hojas en uno solo y exportar el excel en formato csv

df_list <- lapply(sheet_names, function(sheet) {
  read_excel(excel_file, sheet = sheet)
})
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## • `` -> `...1`
df <- bind_rows(df_list)

write.csv(df, "df.csv", row.names = FALSE)

Con esto, ahora tenemos nuestra base de datos en un tipo de archivo mas familiar de analizar

3 Analisis Inicial

3.1 Verificación del archivo

3.1.1 Contextualización de la base de datos y variables

¿En qué consiste?

La base contiene información histórica de 209 semanas (aproximadamente 4 años) sobre las 20 principales empresas tecnológicas que cotizan en bolsa (por ejemplo: Nvidia, Microsoft, Apple, Google, Tesla, Netflix, entre otras).

Cada pestaña corresponde a una empresa y muestra sus precios de mercado semana a semana, lo que permite analizar el comportamiento individual de cada acción. La pestaña RESUMEN concentra la visión global de todo el conjunto: el ranking de las empresas, el rango de fechas analizado, el número de semanas consideradas y el precio mÔs reciente de cada acción.

Este tipo de información se utiliza para realizar comparaciones entre empresas, identificar tendencias de crecimiento o caída, evaluar la volatilidad de los precios y aplicar métodos de estadística inferencial para inferir el comportamiento futuro del mercado.

Variables de la base de datos

Aqui describiremos que variables tenemos

Variables en las pestaƱas individuales (por empresa)
  • Fecha: indica la semana registrada en el periodo de anĆ”lisis. Permite organizar la información en orden cronológico y hacer un seguimiento de la evolución temporal de la acción.
  • Open (Precio de apertura): corresponde al precio con el que inicia la acción al comienzo de la semana. Es un indicador de la expectativa inicial de los inversionistas en ese periodo.
  • High (Precio mĆ”ximo): refleja el mayor valor alcanzado por la acción dentro de la semana. Es Ćŗtil para medir hasta quĆ© punto se valorizó la empresa en ese intervalo de tiempo.
  • Low (Precio mĆ­nimo): muestra el precio mĆ”s bajo registrado durante la semana. Permite identificar la caĆ­da mĆ”xima que experimentó la acción en ese lapso.
  • Close (Precio de cierre): es el precio final de la acción al concluir la semana. Se considera una de las medidas mĆ”s relevantes en anĆ”lisis financiero, ya que resume la tendencia del mercado en ese periodo.
  • Volume (Volumen de transacciones): indica la cantidad de acciones negociadas en la semana. Un volumen alto refleja mayor liquidez e interĆ©s de los inversionistas, mientras que un volumen bajo puede indicar menor actividad en el mercado.
  • Ticker: es el código bursĆ”til que identifica a la empresa (por ejemplo, NVDA = Nvidia). Permite distinguir entre diferentes acciones dentro de la base.
Variables en la pestaƱa RESUMEN:
  • Rank: muestra la posición que ocupa la empresa dentro del top 20. El orden refleja la relevancia de cada compaƱƭa dentro de la selección de la base.
  • Ticker: código de la acción que identifica a la empresa en el mercado. Sirve como referencia estĆ”ndar en las transacciones bursĆ”tiles.
  • Semanas: nĆŗmero total de semanas incluidas en el anĆ”lisis (209 en todos los casos). Asegura que todas las empresas tengan la misma ventana temporal de comparación.
  • Desde: fecha de inicio de la serie temporal (27/08/2021). Marca el comienzo del periodo histórico analizado.
  • Hasta: fecha de cierre de la serie temporal (22/08/2025). SeƱala el final del periodo analizado y permite calcular el rango total cubierto.
  • Precio Actual: valor mĆ”s reciente de la acción al final del periodo considerado. Es el precio vigente al 22/08/2025 y sirve como referencia de la situación mĆ”s actual de cada empresa.
Categorización Estadistica de las variables
  • Fecha: numerica de intervalo
  • Open (Precio de apertura): numerica continua
  • High (Precio mĆ”ximo): numerica continua
  • Low (Precio mĆ­nimo): numerica continua
  • Close (Precio de cierre): numerica continua
  • Volume (Volumen de transacciones): numĆ©rica continua
  • Ticker: categorica nominal
  • Rank: categorica ordinal
  • Semanas: categorica ordinal
  • Desde: numerica de intervalo
  • Hasta: numerica de intervalo
  • Precio Actual: numerica continua

3.1.2 CaracterĆ­sticas generales de la base de datos

NĆŗmero de filas y columnas

Tenemos 3971 filas y 7 columnas en la base de datos completa

dim(df)
## [1] 3971    7

Nombres de las x

names(df)
## [1] "...1"   "Open"   "High"   "Low"    "Close"  "Volume" "Ticker"

Tipos de x (numéricas, categóricas, texto, etc.)

str(df)
## tibble [3,971 Ɨ 7] (S3: tbl_df/tbl/data.frame)
##  $ ...1  : POSIXct[1:3971], format: "2021-08-27" "2021-09-03" ...
##  $ Open  : num [1:3971] 210 228 228 227 211 ...
##  $ High  : num [1:3971] 227 230 229 230 225 ...
##  $ Low   : num [1:3971] 210 221 220 218 207 ...
##  $ Close : num [1:3971] 226 228 225 219 221 ...
##  $ Volume: num [1:3971] 1.76e+08 1.19e+08 8.98e+07 1.11e+08 1.29e+08 ...
##  $ Ticker: chr [1:3971] "NVDA" "NVDA" "NVDA" "NVDA" ...

Completitud de los datos

missmap(df)
## Warning: Unknown or uninitialised column: `arguments`.
## Unknown or uninitialised column: `arguments`.
## Warning: Unknown or uninitialised column: `imputations`.

3.1.3 Ordenamiento de datoss

Para facilitar el trabajo y analisis de los datos, ordenaremos por fechas el df.

df <- df %>%
  mutate(...1 = as.Date(...1)) %>%
  arrange(...1)

# Export to CSV
write.csv(df, "dataorden.csv", row.names = FALSE)

3.2 Segmentación Base de datos

3.2.1 Estratificacion empresas segun ā€œRankā€ en resumen

resumen <- read_excel(excel_file, sheet = "RESUMEN")

print(resumen)
## # A tibble: 19 Ɨ 6
##     Rank Ticker Semanas Desde      Hasta      `Precio Actual`
##    <dbl> <chr>    <dbl> <chr>      <chr>      <chr>          
##  1     1 NVDA       209 2021-08-27 2025-08-22 $177.99        
##  2     2 MSFT       209 2021-08-27 2025-08-22 $507.23        
##  3     3 AAPL       209 2021-08-27 2025-08-22 $227.76        
##  4     4 GOOG       209 2021-08-27 2025-08-22 $206.72        
##  5     5 AMZN       209 2021-08-27 2025-08-22 $228.84        
##  6     6 META       209 2021-08-27 2025-08-22 $754.79        
##  7     7 AVGO       209 2021-08-27 2025-08-22 $294.00        
##  8     8 TSM        209 2021-08-27 2025-08-22 $232.99        
##  9     9 TSLA       209 2021-08-27 2025-08-22 $340.01        
## 10    10 TCEHY      209 2021-08-27 2025-08-22 $77.88         
## 11    11 ORCL       209 2021-08-27 2025-08-22 $236.37        
## 12    12 NFLX       209 2021-08-27 2025-08-22 $1204.65       
## 13    13 PLTR       209 2021-08-27 2025-08-22 $158.74        
## 14    15 SAP        209 2021-08-27 2025-08-22 $271.11        
## 15    16 ASML       209 2021-08-27 2025-08-22 $754.89        
## 16    17 BABA       209 2021-08-27 2025-08-22 $122.94        
## 17    18 AMD        209 2021-08-27 2025-08-22 $167.76        
## 18    19 CSCO       209 2021-08-27 2025-08-22 $67.32         
## 19    20 CRM        209 2021-08-27 2025-08-22 $248.29

En resumen podemos ver que el df tiene un error de conteo de # de empresas, lo cual tendremos en cuenta a lo largo del proyecto y no hubieramos notado sin esta parte del trabajo. Originalmente pensamos que teniamos 20 empresas y vamos a trabajar con las 19 que la base de datos tiene por simplicidad.

Vamos a separar los df en 4, teniendo en los diferentes las empresas (1-4), (5-9), (10-14) y (15-19)

tickers_4 <- c("NVDA", "MSFT", "AAPL", "GOOG")
df_4 <- df %>%
  filter(Ticker %in% tickers_4)

tickers_9 <- c("AMZN", "META", "AVGO", "TSM", "TSLA")
df_9 <- df %>%
  filter(Ticker %in% tickers_9)

tickers_14 <- c("TCEHY", "ORCL", "NFLX", "PLTR", "SAP")
df_14 <- df %>%
  filter(Ticker %in% tickers_14)

tickers_19 <- c("ASML", "BABA", "AMD", "CSCO", "CRM ")
df_19 <- df %>%
  filter(Ticker %in% tickers_19)
head(df_4,5)
## # A tibble: 5 Ɨ 7
##   ...1        Open  High   Low Close    Volume Ticker
##   <date>     <dbl> <dbl> <dbl> <dbl>     <dbl> <chr> 
## 1 2021-08-27  210.  227.  210.  226. 176346915 NVDA  
## 2 2021-08-27  303.  306.  297.  300. 101283798 MSFT  
## 3 2021-08-27  148.  151.  147.  149. 272129118 AAPL  
## 4 2021-08-27 2780. 2900. 2775. 2891.   4427462 GOOG  
## 5 2021-09-03  228.  230.  221.  228. 119313808 NVDA
head(df_9,5)
## # A tibble: 5 Ɨ 7
##   ...1        Open  High   Low Close   Volume Ticker
##   <date>     <dbl> <dbl> <dbl> <dbl>    <dbl> <chr> 
## 1 2021-08-27 3212. 3352. 3210. 3350. 12001408 AMZN  
## 2 2021-08-27  359.  374.  359.  373. 48969499 META  
## 3 2021-08-27  476.  496.  476.  496.  6245198 AVGO  
## 4 2021-08-27  110.  119.  109.  118. 55079882 TSM   
## 5 2021-08-27  685.  717.  681.  712. 73041547 TSLA
head(df_14,5)
## # A tibble: 5 Ɨ 7
##   ...1        Open  High   Low Close    Volume Ticker
##   <date>     <dbl> <dbl> <dbl> <dbl>     <dbl> <chr> 
## 1 2021-08-27  56.2  62.6  56.2  59.0  45104349 TCEHY 
## 2 2021-08-27  89.5  89.6  88.0  89.4  33736160 ORCL  
## 3 2021-08-27 546.  564.  544.  559.   11625250 NFLX  
## 4 2021-08-27  24.0  26.1  23.9  25.7 226059011 PLTR  
## 5 2021-08-27 148.  149.  147.  149.    1506968 SAP
head(df_19,5)
## # A tibble: 5 Ɨ 7
##   ...1        Open  High   Low Close    Volume Ticker
##   <date>     <dbl> <dbl> <dbl> <dbl>     <dbl> <chr> 
## 1 2021-08-27 795.  835.  795.  833.    2758381 ASML  
## 2 2021-08-27 159.  174.  153.  159.  228075458 BABA  
## 3 2021-08-27 105.  112.  105.  111.  278032644 AMD   
## 4 2021-08-27  57.8  60.3  57.7  59.0  80477904 CSCO  
## 5 2021-09-03 840.  863.  827.  858.    3097969 ASML

Analisis Estadistico descriptivo

1. Separacion empresas segun ā€œresumenā€

resumen <- read_excel(excel_file, sheet = "RESUMEN")

print(resumen)
## # A tibble: 19 Ɨ 6
##     Rank Ticker Semanas Desde      Hasta      `Precio Actual`
##    <dbl> <chr>    <dbl> <chr>      <chr>      <chr>          
##  1     1 NVDA       209 2021-08-27 2025-08-22 $177.99        
##  2     2 MSFT       209 2021-08-27 2025-08-22 $507.23        
##  3     3 AAPL       209 2021-08-27 2025-08-22 $227.76        
##  4     4 GOOG       209 2021-08-27 2025-08-22 $206.72        
##  5     5 AMZN       209 2021-08-27 2025-08-22 $228.84        
##  6     6 META       209 2021-08-27 2025-08-22 $754.79        
##  7     7 AVGO       209 2021-08-27 2025-08-22 $294.00        
##  8     8 TSM        209 2021-08-27 2025-08-22 $232.99        
##  9     9 TSLA       209 2021-08-27 2025-08-22 $340.01        
## 10    10 TCEHY      209 2021-08-27 2025-08-22 $77.88         
## 11    11 ORCL       209 2021-08-27 2025-08-22 $236.37        
## 12    12 NFLX       209 2021-08-27 2025-08-22 $1204.65       
## 13    13 PLTR       209 2021-08-27 2025-08-22 $158.74        
## 14    15 SAP        209 2021-08-27 2025-08-22 $271.11        
## 15    16 ASML       209 2021-08-27 2025-08-22 $754.89        
## 16    17 BABA       209 2021-08-27 2025-08-22 $122.94        
## 17    18 AMD        209 2021-08-27 2025-08-22 $167.76        
## 18    19 CSCO       209 2021-08-27 2025-08-22 $67.32         
## 19    20 CRM        209 2021-08-27 2025-08-22 $248.29

En resumen podemos ver que el df tiene un error de conteo de # de empresas, lo cual tendremos en cuenta a lo largo del proyecto y no hubieramos notado sin esta parte del trabajo. Originalmente pensamos que teniamos 20 empresas y vamos a trabajar con las 19 que la base de datos tiene por simplicidad.

Vamos a separar los df en 4, teniendo en los diferentes las empresas (1-4), (5-9), (10-14) y (15-19). Esto es equivalente a una estratificación por posicion en el ranking.

tickers_4 <- c("NVDA", "MSFT", "AAPL", "GOOG")
df_4 <- df %>%
  filter(Ticker %in% tickers_4)

tickers_9 <- c("AMZN", "META", "AVGO", "TSM", "TSLA")
df_9 <- df %>%
  filter(Ticker %in% tickers_9)

tickers_14 <- c("TCEHY", "ORCL", "NFLX", "PLTR", "SAP")
df_14 <- df %>%
  filter(Ticker %in% tickers_14)

tickers_19 <- c("ASML", "BABA", "AMD", "CSCO", "CRM ")
df_19 <- df %>%
  filter(Ticker %in% tickers_19)
head(df_4,5)
## # A tibble: 5 Ɨ 7
##   ...1        Open  High   Low Close    Volume Ticker
##   <date>     <dbl> <dbl> <dbl> <dbl>     <dbl> <chr> 
## 1 2021-08-27  210.  227.  210.  226. 176346915 NVDA  
## 2 2021-08-27  303.  306.  297.  300. 101283798 MSFT  
## 3 2021-08-27  148.  151.  147.  149. 272129118 AAPL  
## 4 2021-08-27 2780. 2900. 2775. 2891.   4427462 GOOG  
## 5 2021-09-03  228.  230.  221.  228. 119313808 NVDA
head(df_9,5)
## # A tibble: 5 Ɨ 7
##   ...1        Open  High   Low Close   Volume Ticker
##   <date>     <dbl> <dbl> <dbl> <dbl>    <dbl> <chr> 
## 1 2021-08-27 3212. 3352. 3210. 3350. 12001408 AMZN  
## 2 2021-08-27  359.  374.  359.  373. 48969499 META  
## 3 2021-08-27  476.  496.  476.  496.  6245198 AVGO  
## 4 2021-08-27  110.  119.  109.  118. 55079882 TSM   
## 5 2021-08-27  685.  717.  681.  712. 73041547 TSLA
head(df_14,5)
## # A tibble: 5 Ɨ 7
##   ...1        Open  High   Low Close    Volume Ticker
##   <date>     <dbl> <dbl> <dbl> <dbl>     <dbl> <chr> 
## 1 2021-08-27  56.2  62.6  56.2  59.0  45104349 TCEHY 
## 2 2021-08-27  89.5  89.6  88.0  89.4  33736160 ORCL  
## 3 2021-08-27 546.  564.  544.  559.   11625250 NFLX  
## 4 2021-08-27  24.0  26.1  23.9  25.7 226059011 PLTR  
## 5 2021-08-27 148.  149.  147.  149.    1506968 SAP
head(df_19,5)
## # A tibble: 5 Ɨ 7
##   ...1        Open  High   Low Close    Volume Ticker
##   <date>     <dbl> <dbl> <dbl> <dbl>     <dbl> <chr> 
## 1 2021-08-27 795.  835.  795.  833.    2758381 ASML  
## 2 2021-08-27 159.  174.  153.  159.  228075458 BABA  
## 3 2021-08-27 105.  112.  105.  111.  278032644 AMD   
## 4 2021-08-27  57.8  60.3  57.7  59.0  80477904 CSCO  
## 5 2021-09-03 840.  863.  827.  858.    3097969 ASML

2. Series de tiempo

Primero, haremos 4 series de tiempo que representen todos nuestros datos y una que las junte todas

2.1 Primeras 4 empresas (Estrat. 1)

ggplot(df_4, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre a lo largo del tiempo",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

2.2 Empresas [5-9] (Estrat. 2)

ggplot(df_9, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre a lo largo del tiempo",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

2.3 Empresas [10-14] (Estrat. 3)

ggplot(df_14, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre a lo largo del tiempo",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

2.4 Empresas [15-20] (Estrat. 4)

ggplot(df_19, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre a lo largo del tiempo",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

2.5 Grafico unificado

ggplot(df, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre a lo largo del tiempo",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

3 Creación de Cuartiles

3.1 Divisiones de los cuartiles

Para analizar el rendimiento general de nuestras estratificaciones de empresas, decidimos dividir nuestras series de tiempo en 4 partes, y determinaremos el rendimiento de la empresa dependiendo del precio de cierre al inicio del cuartil y el final del cuartil

Eso seria:

paste0("Dividimos el numero de semanas de cada stock en 4")
## [1] "Dividimos el numero de semanas de cada stock en 4"
209 / 4
## [1] 52.25
paste0("Puesto que no es un numero divisible por 4, definimos el primer cuartil como 53 semanas y el resto como 52")
## [1] "Puesto que no es un numero divisible por 4, definimos el primer cuartil como 53 semanas y el resto como 52"
53+52+52+52
## [1] 209
paste0("Multiplicamos el numero de semanas deseado por el # de stocks para saber cada cuantos datos hacer la division")
## [1] "Multiplicamos el numero de semanas deseado por el # de stocks para saber cada cuantos datos hacer la division"
53*19
## [1] 1007
52*19
## [1] 988
paste0("En total tenemos 3971 filas, entonces esta suma de multiplicaciones nos debe de dar 3971 y asi sabremos si lo hemos hecho bien")
## [1] "En total tenemos 3971 filas, entonces esta suma de multiplicaciones nos debe de dar 3971 y asi sabremos si lo hemos hecho bien"
53*19 + 52*19 + 52*19 + 52*19
## [1] 3971
paste0("De esta forma el primer cuartil estara definido como")
## [1] "De esta forma el primer cuartil estara definido como"
paste0("[", 1, "-", 53*19, "]")
## [1] "[1-1007]"
paste0("El segundo cuartil estara definido como")
## [1] "El segundo cuartil estara definido como"
paste0("[", 1 + 53*19, "-", 53*19 + 52*19, "]")
## [1] "[1008-1995]"
paste0("El tercer cuartil estara definido como")
## [1] "El tercer cuartil estara definido como"
paste0("[", 1 + 53*19 + 52*19, "-", 53*19 + 52*19 + 52*19, "]")
## [1] "[1996-2983]"
paste0("El cuarto cuartil estara definido como")
## [1] "El cuarto cuartil estara definido como"
paste0("[", 1 + 53*19 + 52*19 + 52*19, "-", 53*19 + 52*19 + 52*19 + 52*19, "]")
## [1] "[2984-3971]"

3.2 Creacion de los DF.

Ya teniendo los cuartiles, hacemos la división del df, lo cual nos servira para hacer diversos analisis

c1_start <- 1
c1_end   <- 1007

c2_start <- 1008
c2_end   <- 1995

c3_start <- 1996
c3_end   <- 2983

c4_start <- 2984
c4_end   <- 3971

# Dividir df
df_c1 <- df[c1_start:c1_end, ]
df_c2 <- df[c2_start:c2_end, ]
df_c3 <- df[c3_start:c3_end, ]
df_c4 <- df[c4_start:c4_end, ]

3.3 Graficación de los cuartiles

Revisemos los diferentes cuartiles graficamente

ggplot(df_c1, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Q1",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_c2, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Q2",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_c3, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Q3",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_c4, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Q4",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

De esta forma, hemos dividido nuestros datos en 4 aƱos

3.4 Cuartiles de estratificaciones

Ahora usemos los DF estratificados por ranking y saquemosles cuartiles de la misma manera

# Cuartiles df_4
c1_start <- 1;   c1_end <- 212
c2_start <- c1_end + 1; c2_end <- c2_start + 260 - 1
c3_start <- c2_end + 1; c3_end <- c3_start + 260 - 1
c4_start <- c3_end + 1; c4_end <- c4_start + 260 - 1

df_4_c1 <- df_4[c1_start:c1_end, ]
df_4_c2 <- df_4[c2_start:c2_end, ]
df_4_c3 <- df_4[c3_start:c3_end, ]
df_4_c4 <- df_4[c4_start:c4_end, ]
# Cuartiles df_9
c1_start <- 1;   c1_end <- 265
c2_start <- c1_end + 1; c2_end <- c2_start + 260 - 1
c3_start <- c2_end + 1; c3_end <- c3_start + 260 - 1
c4_start <- c3_end + 1; c4_end <- c4_start + 260 - 1

df_9_c1 <- df_9[c1_start:c1_end, ]
df_9_c2 <- df_9[c2_start:c2_end, ]
df_9_c3 <- df_9[c3_start:c3_end, ]
df_9_c4 <- df_9[c4_start:c4_end, ]

# Lo mismo para df_14 y df_19
df_14_c1 <- df_14[c1_start:c1_end, ]
df_14_c2 <- df_14[c2_start:c2_end, ]
df_14_c3 <- df_14[c3_start:c3_end, ]
df_14_c4 <- df_14[c4_start:c4_end, ]

df_19_c1 <- df_19[c1_start:c1_end, ]
df_19_c2 <- df_19[c2_start:c2_end, ]
df_19_c3 <- df_19[c3_start:c3_end, ]
df_19_c4 <- df_19[c4_start:c4_end, ]

Y nos aseguramos que la columna ā€œ1ā€¦ā€ este en formato date

# Lista de data frames y nombres de estratificacion
dfs <- list(
  "Estratificacion 1" = list(df_4_c1, df_4_c2, df_4_c3, df_4_c4),
  "Estratificacion 2" = list(df_9_c1, df_9_c2, df_9_c3, df_9_c4),
  "Estratificacion 3" = list(df_14_c1, df_14_c2, df_14_c3, df_14_c4),
  "Estratificacion 4" = list(df_19_c1, df_19_c2, df_19_c3, df_19_c4)
)

# Recorrer todos los df y convertir columna de fecha a Date
for(estrat in names(dfs)){
  for(i in 1:4){
    df_actual <- dfs[[estrat]][[i]]
    # Convertir columna ...1 a Date
    df_actual$Fecha <- as.Date(df_actual$...1)
    # Guardar de nuevo
    dfs[[estrat]][[i]] <- df_actual
  }
}

3.5 Cuartiles (Estrat. 1)

Ahora veremos el rendimiento de los cuartiles de la estratificación 1

# Estratificacion 1 - df_4
ggplot(df_4_c1, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 1 Q1",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_4_c2, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 1 Q2",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_4_c3, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 1 Q3",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_4_c4, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 1 Q4",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )
## Warning: Removed 156 rows containing missing values or values outside the scale range
## (`geom_line()`).

3.6 Cuartiles (Estrat. 2)

Ahora veremos el rendimiento de los cuartiles de la estratificación 2

# Estratificacion 2 - df_9
ggplot(df_9_c1, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 2 Q1",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_9_c2, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 2 Q2",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_9_c3, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 2 Q3",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_9_c4, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 2 Q4",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

3.7 Cuartiles (Estrat. 3)

Ahora veremos el rendimiento de los cuartiles de la estratificación 3

# Estratificacion 3 - df_14
ggplot(df_14_c1, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 3 Q1",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_14_c2, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 3 Q2",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_14_c3, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 3 Q3",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_14_c4, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 3 Q4",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

3.8 Cuartiles (Estrat. 4)

Ahora veremos el rendimiento de los cuartiles de la estratificación 4

# Estratificacion 4 - df_19
ggplot(df_19_c1, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 4 Q1",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_19_c2, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 4 Q2",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_19_c3, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 4 Q3",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )

ggplot(df_19_c4, aes(x = ...1, y = Close, color = Ticker)) +
  geom_line() +
  labs(
    title = "Precio de cierre Estratificacion 4 Q4",
    x = "Fecha",
    y = "Precio de cierre",
    color = "Empresa"
  )
## Warning: Removed 209 rows containing missing values or values outside the scale range
## (`geom_line()`).

Conclusiones

Casi todas lasempresas comparten ritmos crecimiento y decrecimiento

Sin embargo GOOGL y AMAZON se comportan muy parecido, creciendo y decreciendo bruscamente casi juntas

igualmente, TSLA y META van de la mano.

4 Rendimiento por cuartil a nivel empresa

4.1 Definición de Rendimiento

Ahora queremos revisar el % de rendimiento de cada empresa, dado por la siguiente formula, Donde P sera dado por la variable Close \[ R = \frac{P_{\text{Ćŗltima semana}} - P_{\text{primera semana}}}{P_{\text{primera semana}}} \times 100 \] Y ademas de eso veremos al final cuantas empresas crecieron o decrecieron por cuartil y en la totalidad de los datos

Con esto tendremos 2 variables nuevas con las que podemos trabajar

  • rendimiento: Numerica continua
  • estado: Categorica nominal

4.2 Creación del codigo

Definimos las fechas de innicio de los cuartiles, y desde el dato 1 del cuartil hasta el 19 seran las empresas, al final del cuartil seran el dato n-19 hasta el n

calcular_rendimiento <- function(df_cuartil) {
  df_cuartil %>%
    group_by(Ticker) %>%
    summarise(
      primer_precio = first(Close),
      ultimo_precio = last(Close),
      rendimiento = (ultimo_precio - primer_precio)/primer_precio * 100,
      estado = ifelse(rendimiento > 0, "Crecio", "Decrecio")
    )
}

df_c1 <- df[c1_start:c1_end, ]
df_c2 <- df[c2_start:c2_end, ]
df_c3 <- df[c3_start:c3_end, ]
df_c4 <- df[c4_start:c4_end, ]

rendimiento_c1 <- calcular_rendimiento(df_c1)
rendimiento_c2 <- calcular_rendimiento(df_c2)
rendimiento_c3 <- calcular_rendimiento(df_c3)
rendimiento_c4 <- calcular_rendimiento(df_c4)

rendimiento_c1
## # A tibble: 19 Ɨ 5
##    Ticker primer_precio ultimo_precio rendimiento estado  
##    <chr>          <dbl>         <dbl>       <dbl> <chr>   
##  1 AAPL           149.          157.        5.52  Crecio  
##  2 AMD            111.          155.       39.0   Crecio  
##  3 AMZN          3350.         3505.        4.63  Crecio  
##  4 ASML           833.          782.       -6.11  Decrecio
##  5 AVGO           496.          547.       10.2   Crecio  
##  6 BABA           159.          133.      -16.4   Decrecio
##  7 CRM            267.          301.       13.0   Crecio  
##  8 CSCO            59.0          54.7      -7.37  Decrecio
##  9 GOOG          2891.         2856.       -1.21  Decrecio
## 10 META           373.          333.      -10.6   Decrecio
## 11 MSFT           300.          330.       10.00  Crecio  
## 12 NFLX           559.          666.       19.1   Crecio  
## 13 NVDA           226.          315.       39.2   Crecio  
## 14 ORCL            89.4          92.3       3.34  Crecio  
## 15 PLTR            25.7          21.0     -18.2   Decrecio
## 16 SAP            149.          131.      -12.1   Decrecio
## 17 TCEHY           59.0          59.3       0.594 Crecio  
## 18 TSLA           712.         1082.       52.0   Crecio  
## 19 TSM            118.          117.       -1.18  Decrecio
rendimiento_c2
## # A tibble: 19 Ɨ 5
##    Ticker primer_precio ultimo_precio rendimiento estado  
##    <chr>          <dbl>         <dbl>       <dbl> <chr>   
##  1 AAPL           162.          163.        0.822 Crecio  
##  2 AMD            144.          121.      -15.9   Decrecio
##  3 AMZN          3390.         2913.      -14.1   Decrecio
##  4 ASML           772.          667.      -13.5   Decrecio
##  5 AVGO           558.          596.        6.79  Crecio  
##  6 BABA           112.          108.       -3.59  Decrecio
##  7 CRM            284.          208.      -26.8   Decrecio
##  8 CSCO            56.2          56.0      -0.338 Decrecio
##  9 GOOG          2850.         2642.       -7.30  Decrecio
## 10 META           307.          200.      -34.8   Decrecio
## 11 MSFT           323.          290.      -10.3   Decrecio
## 12 NFLX           602.          362.      -39.9   Decrecio
## 13 NVDA           307.          229.      -25.3   Decrecio
## 14 ORCL            88.2          76.5     -13.3   Decrecio
## 15 PLTR            19.0          11.5     -39.6   Decrecio
## 16 SAP            129.          115.      -10.8   Decrecio
## 17 TCEHY           56.8          50.4     -11.2   Decrecio
## 18 TSLA          1015.          838.      -17.4   Decrecio
## 19 TSM            119.          105.      -12.0   Decrecio
rendimiento_c3
## # A tibble: 19 Ɨ 5
##    Ticker primer_precio ultimo_precio rendimiento estado  
##    <chr>          <dbl>         <dbl>       <dbl> <chr>   
##  1 AAPL           155.         137.        -11.4  Decrecio
##  2 AMD            108.         106.         -1.95 Decrecio
##  3 AMZN          2910.         110.        -96.2  Decrecio
##  4 ASML           594.         564.         -5.16 Decrecio
##  5 AVGO           578.         563.         -2.51 Decrecio
##  6 BABA           101.          93.2        -7.35 Decrecio
##  7 CRM            203.         185.         -8.92 Decrecio
##  8 CSCO            56.5         45.2       -19.9  Decrecio
##  9 GOOG          2610.        2229.        -14.6  Decrecio
## 10 META           188.         176.         -6.42 Decrecio
## 11 MSFT           280.         253.         -9.67 Decrecio
## 12 NFLX           340.         199.        -41.5  Decrecio
## 13 NVDA           221          170.        -23.2  Decrecio
## 14 ORCL            77.8         71.8        -7.75 Decrecio
## 15 PLTR            11.0          8.94      -18.4  Decrecio
## 16 SAP            106.         100.         -5.34 Decrecio
## 17 TCEHY           44.8         46.0         2.75 Crecio  
## 18 TSLA           795.         704.        -11.5  Decrecio
## 19 TSM            101.          93.8        -7.53 Decrecio
rendimiento_c4
## # A tibble: 19 Ɨ 5
##    Ticker primer_precio ultimo_precio rendimiento estado  
##    <chr>          <dbl>         <dbl>       <dbl> <chr>   
##  1 AAPL          132.          157.         19.6  Crecio  
##  2 AMD            94.8          85.4        -9.88 Decrecio
##  3 AMZN          106.          133.         25.5  Crecio  
##  4 ASML          522.          501          -3.94 Decrecio
##  5 AVGO          541.          522.         -3.49 Decrecio
##  6 BABA          110.           92.1       -16.1  Decrecio
##  7 CRM           178.          163.         -8.89 Decrecio
##  8 CSCO           43.5          45.8         5.24 Crecio  
##  9 GOOG         2157.          112.        -94.8  Decrecio
## 10 META          164.          169.          3.30 Crecio  
## 11 MSFT          248.          264.          6.79 Crecio  
## 12 NFLX          183.          234.         27.7  Crecio  
## 13 NVDA          159.          144.         -9.40 Decrecio
## 14 ORCL           67.1          75.9        13.1  Crecio  
## 15 PLTR            8.26          7.79       -5.69 Decrecio
## 16 SAP            94.2          87.1        -7.54 Decrecio
## 17 TCEHY          49.4          38.8       -21.5  Decrecio
## 18 TSLA          697.          300.        -57.0  Decrecio
## 19 TSM            88.7          81.5        -8.06 Decrecio

4.3 Graficos de barras agrupados Crecimiento vs Decrecimiento

# Combinar rendimientos de los 4 cuartiles
rendimientos <- rbind(
  mutate(rendimiento_c1, Cuartil="Q1"),
  mutate(rendimiento_c2, Cuartil="Q2"),
  mutate(rendimiento_c3, Cuartil="Q3"),
  mutate(rendimiento_c4, Cuartil="Q4")
)

# Contar empresas por estado y cuartil
conteo <- rendimientos %>%
  group_by(Cuartil, estado) %>%
  summarise(n = n(), .groups="drop")

# Graffito de barras agrupadas
ggplot(conteo, aes(x=Cuartil, y=n, fill=estado)) +
  geom_bar(stat="identity", position="dodge") +
  labs(title="Crecimiento vs Decrecimiento por Cuartil",
       x="Cuartil", y="Numero de empresas") +
  scale_fill_manual(values=c("Crecio"="steelblue", "Decrecio"="tomato"))

Conclusiones

Podemos observar que en el Q1 casi todas las empresas decrecieron, y los siguientes cuartiles fueron creciendo

4.4 Diagrama de cajas de rendimiento por cuartil

ggplot(rendimientos, aes(x=Cuartil, y=rendimiento, fill=Cuartil)) +
  geom_boxplot(outlier.shape=21, outlier.color="red", outlier.size=2, notch=FALSE) +
  stat_summary(fun=mean, geom="point", shape=23, size=3, fill="yellow") + # muestra media
  scale_y_continuous(labels=scales::number_format(accuracy=0.1)) +          # decimales
  labs(title="Comparacion de Rendimientos por Cuartil", y="Rendimiento (%)") +
  scale_fill_brewer(palette="Set2") +
    theme(legend.position="none")

  • Punto Amarillo es la media
  • La linea es la mediana
  • Puntos rojos son Outliers

Conclusiones

Los cuartiles 2 y 4 tuvieron los mejores rendimientos, con el cuartil 4 mostrando el valor atípico mÔs alto de todo el conjunto de datos. El cuartil 1 tuvo los peores rendimientos, siendo el único con valores mayoritariamente negativos.

5 Analisis de precios de cierre (Tabla de Frec. Agr.)

5.1 Explicación y generacion de la tabla de frecuencias agrupadas

Haremos un pequeƱo analisis de los precios de cierre de todas las empresas, pero debido a la gran variedad que hay, los agruparemos y trabajaremos con la base de datos entera por simplicidad

FORMULAS A USAR

  • Formula para agrupar variables en intervalos

\[ a = \frac{X_{\text{max}} - X_{\text{min}}}{c} \]

  • Formula de Sturges para el numero de clases c

\[ c = 1 + 3.3 \log_{10}(n) \]

Codigo

— Cargar datos —

csco <- df[, c(1,5)]   # columna 1 = fecha, columna 5 = cierre

— Función para tabla de frecuencias —

tabla_frecuencias <- function(csco, c=NULL){
  n <- length(csco)
  
  if(is.null(c)){
    c <- 1 + 3.3 * log10(n)  # Fórmula de Sturges
  }
  
  min_val <- min(csco, na.rm = TRUE)
  max_val <- max(csco, na.rm = TRUE)
  r <- max_val - min_val
  a <- r / c
  
  li <- seq(min_val, max_val - a, by = a)
  ls <- li + a
  mc <- (li + ls)/2
  
  cortes <- cut(csco, breaks = c(li, max_val + 1e-8), include.lowest = TRUE, right = FALSE)
  
  fi <- as.numeric(table(cortes))
  Fi <- cumsum(fi)
  fri <- fi / n
  Fri <- cumsum(fri)
  
  data.frame(
    clase = paste0("[", round(li,2), ",", round(ls,2), "]"),
    li = round(li,2),
    ls = round(ls,2),
    mc = round(mc,2),
    fi = fi,
    Fi = Fi,
    fri = round(fri,2),
    Fri = round(Fri,2)
  )
}

— Generar tabla de frecuencias —

tabla_precios_csco <- tabla_frecuencias(csco$Close)

cat("\nTabla de frecuencia de precios:\n")
## 
## Tabla de frecuencia de precios:
print(tabla_precios_csco)
##                clase      li      ls      mc   fi   Fi  fri  Fri
## 1      [6.29,291.33]    6.29  291.33  148.81 2862 2862 0.72 0.72
## 2    [291.33,576.37]  291.33  576.37  433.85  536 3398 0.13 0.86
## 3    [576.37,861.41]  576.37  861.41  718.89  333 3731 0.08 0.94
## 4   [861.41,1146.45]  861.41 1146.45 1003.93  108 3839 0.03 0.97
## 5  [1146.45,1431.49] 1146.45 1431.49 1288.97   39 3878 0.01 0.98
## 6  [1431.49,1716.53] 1431.49 1716.53 1574.01    4 3882 0.00 0.98
## 7  [1716.53,2001.57] 1716.53 2001.57 1859.05    1 3883 0.00 0.98
## 8  [2001.57,2286.61] 2001.57 2286.61 2144.09    8 3891 0.00 0.98
## 9  [2286.61,2571.65] 2286.61 2571.65 2429.13   12 3903 0.00 0.98
## 10 [2571.65,2856.69] 2571.65 2856.69 2714.17   24 3927 0.01 0.99
## 11 [2856.69,3141.73] 2856.69 3141.73 2999.21   19 3946 0.00 0.99
## 12 [3141.73,3426.77] 3141.73 3426.77 3284.25   25 3971 0.01 1.00

Con esto hemos hecho la tabla de frecuencias agrupadas, donde podemos ver 10 agrupaciones con sus respectivas marcas de clase

5.2 Diagrama de Pareto

p <- ggplot(tabla_precios_csco, aes(x = factor(mc))) +
  geom_col(aes(y = fri, fill = "Frecuencia Relativa"), width = 0.9, alpha = 0.8) +
  geom_line(aes(y = Fri, group = 1, color = "Frecuencia Acumulada"), linewidth = 1.5) +
  geom_point(aes(y = Fri, color = "Frecuencia Acumulada"), size = 3.5) +
  geom_text(aes(y = fri, label = percent(fri, accuracy = 0.1)), vjust = -0.8, size = 4, fontface = "bold") +
  scale_y_continuous(
    name = "Frecuencia (%)",
    labels = percent_format(accuracy = 1),
    limits = c(0,1.1),
    sec.axis = sec_axis(~., name = "Frecuencia Acumulada (%)")
  ) +
  scale_x_discrete(
    name = "Rango de precios (USD)",
    labels = tabla_precios_csco$clase
  ) +
  scale_fill_manual(name = "", values = c("Frecuencia Relativa" = "#E41A1C")) +
  scale_color_manual(name = "", values = c("Frecuencia Acumulada" = "#377EB8")) +
  labs(title = "Distribucion del Precio de CSCO",
       subtitle = paste("Total de semanas:", nrow(csco))) +
  theme_minimal(base_size = 14) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1.1),
    legend.position = "top",
    plot.title = element_text(face = "bold", size = 16, hjust = 0.5),
    plot.subtitle = element_text(size = 12, hjust = 0.5),
    panel.grid.minor = element_blank()
  )

print(p)

Conclusiones

La gran mayoria de los precios de close estan por debajo de los 600 dolares

Podemos identificar que los precios por encima de 1146 son outliers en este caso, Es buena idea hacer una tabla de frecuencias acumulada para ver como se distribuyen con mas precisión

5.3 Tabla de frecuencias acumuladas

ggplot(tabla_precios_csco, aes(x = mc, y = fi)) +
  geom_col(fill = "#E41A1C", color = "black", alpha = 0.8, width = 300
          ) +
  labs(
    title = "Histograma aproximado de precios de cierre",
    x = "Marca de clase (mc)",
    y = "Frecuencia"
  ) +
  theme_minimal()
## Warning: `position_stack()` requires non-overlapping x intervals.

Conclusiones

Podemos ver una distribución muy sesgada positivamente

Medidas de tendencia central (Aproximadas)

TODAS LAS MEDIDAS SON MUESTRALES POR QUE SE CALCULAN A PARTIR DE LA MUESTRA AGRUPADA

  • Media aprox. con marcas de clase \[ \bar{x} \approx \frac{\sum_{i=1}^{k} mc_i \cdot f_i}{n} \]
n <- sum(tabla_precios_csco$fi)
media <- sum(tabla_precios_csco$mc * tabla_precios_csco$fi) / n
media
## [1] 331.204
  • Mediana usando frecuencia acumulada \[ \text{Mediana} \approx L_m + \frac{\frac{n}{2} - F_a}{f_m} \cdot a \]
mediana_clase <- tabla_precios_csco$clase[which(cumsum(tabla_precios_csco$fi) >= n/2)[1]]
mediana_clase
## [1] "[6.29,291.33]"

La mediana cae en la m.c. 1

  • Desviacion estandar y varianza \[ s^2 \approx \frac{\sum_{i=1}^{k} f_i \cdot (mc_i - \bar{x})^2}{n-1}, \quad s = \sqrt{s^2} \]
varianza <- sum(tabla_precios_csco$fi * (tabla_precios_csco$mc - media)^2) / (n - 1)
desviacion <- sqrt(varianza)
varianza
## [1] 204716.7
desviacion
## [1] 452.4563
  • Rango promedio \[ \text{Rango} = X_{\max} - X_{\min} \]
rango <- max(tabla_precios_csco$ls) - min(tabla_precios_csco$li)
rango
## [1] 3420.48