Análisis de Suavizado en Series Financieras
Análisis de Correlación y Procesamiento de Series Temporales Financieras: Acciones de Nintendo y Tesco
Este análisis explora cómo diferentes métodos de suavizado y normalización de series temporales afectan la correlación entre los precios de dos acciones: Nintendo (NTDOY) y Tesco (TSCO). Se utilizan técnicas comunes en el análisis técnico y la preparación de datos financieros para trading algorítmico, gestión de carteras y análisis de riesgo.
Preparación del Entorno
1!pip install pyportfolioopt
2
3import pandas as pd
4import numpy as np
5import matplotlib.pyplot as plt
6import yfinance as yf
7import seaborn as sns
8sns.set_style('whitegrid')
9
10from pypfopt import EfficientFrontier
11from pypfopt import risk_models
12from pypfopt import expected_returns
13from pypfopt import objective_functions
14from pypfopt import HRPOpt
15from datetime import datetime
Descarga de Datos y Cálculo de Correlación
Se descargan los precios de cierre diarios para 'NTDOY' y 'TSCO' para el año 2023 utilizando `yfinance`, se calcula y visualiza la matriz de correlación de los precios de cierre originales utilizando un heatmap de `seaborn`. También se grafica la evolución de los precios.
1tickets = ['NTDOY', 'TSCO']
2data = yf.download(tickets, start='2023-01-01', end='2023-12-31', rounding=True)
3price = data['Close']
4corr = price.corr()
5print(corr)
6sns.heatmap(corr)
7plt.plot(price)
Suavizado con Logaritmo:
Se aplica el logaritmo base 10 a los precios. Se calcula y visualiza la correlación de los precios logarítmicos y se grafican. Esto a menudo se hace para estabilizar la varianza y hacer que los retornos sean más simétricos.
1log_price = np.log10(price)
2log_price_corr = log_price.corr()
3print(log_price_corr)
4sns.heatmap(log_price_corr)
5plt.plot(log_price)
1plt.plot(log_price)
Suavizado Exponencial Simple (SES):
Se implementa manualmente el suavizado exponencial simple para cada serie de precios utilizando un factor de suavizado (`alfa`) de 0.2. Los datos suavizados se almacenan en un nuevo DataFrame. Se calcula y visualiza la correlación de los datos suavizados por SES y se grafican. Este método reduce el ruido en la serie temporal.
1alfa = 0.2
2price_1 = price['NTDOY']
3price_2 = price['TSCO']
4prices = price
5
6# Suavizado para NTDOY
7nivel_inicial = price_1[0]
8suavizado_exponencial_1 = np.array([nivel_inicial])
9for p in price_1[1:]:
10 nivel_previo = suavizado_exponencial_1[-1]
11 nivel_nuevo = alfa * p + (1 - alfa) * nivel_previo
12 suavizado_exponencial_1 = np.append(suavizado_exponencial_1, nivel_nuevo)
13
14# Suavizado para TSCO
15nivel_inicial_columna2 = price_2[0]
16suavizado_exponencial_columna2 = np.array([nivel_inicial_columna2])
17for valor in price_2[1:]:
18 nivel_previo = suavizado_exponencial_columna2[-1]
19 nivel_nuevo = alfa * valor + (1 - alfa) * nivel_previo
20 suavizado_exponencial_columna2 = np.append(suavizado_exponencial_columna2, nivel_nuevo)
1# Crear un nuevo DataFrame vacío
2datos_suavizados = pd.DataFrame()
3
4# Agregar columna de fecha
5datos_suavizados["Fecha"] = price.index # Suponiendo que el índice de 'price' contiene las fechas
6
7datos_suavizados.set_index('Fecha', inplace=True)
8
9# Agregar columna de SES para NTDOY
10datos_suavizados["SES NTDOY"] = suavizado_exponencial_1
11
12# Agregar columna de SES para TSCO
13datos_suavizados["SES TSCO"] = suavizado_exponencial_columna2
1suavizados_corr = datos_suavizados.corr()
2print(suavizados_corr)
3sns.heatmap(suavizados_corr)
4plt.plot(datos_suavizados)
Normalización Z-Score:
Se calcula el Z-score (normalización estándar) para cada serie de precios. Esto centra los datos alrededor de cero con una desviación estándar de uno. Se crea un DataFrame con los datos normalizados Z-score, se calcula y visualiza su correlación y se grafican. La normalización Z-score permite comparar series con diferentes escalas.
1prices_z_score = price.copy()
2price_array_1 = np.array(price['NTDOY'])
3price_array_2 = np.array(price['TSCO'])
4
5media_price_array_1 = np.mean(price_array_1)
6media_price_array_2 = np.mean(price_array_2)
7
8std_price_array_1 = np.std(price_array_1)
9std_price_array_2 = np.std(price_array_2)
10
11z_score_price_array_1 = (price_array_1 - media_price_array_1) / std_price_array_1
12z_score_price_array_2 = (price_array_2 - media_price_array_2) / std_price_array_2
13
14datos_normalizados_z_score = pd.DataFrame()
15datos_normalizados_z_score['Fecha'] = price.index
16datos_normalizados_z_score.set_index('Fecha', inplace=True)
17datos_normalizados_z_score['NTDOY'] = z_score_price_array_1
18datos_normalizados_z_score['TSCO'] = z_score_price_array_2
19
20corr = datos_normalizados_z_score.corr()
21print(corr)
22sns.heatmap(corr)
23plt.plot(datos_normalizados_z_score)
Filtro de Savitzky-Golay:
Se aplica un filtro de Savitzky-Golay a cada serie de precios. Este filtro ajusta un polinomio a una ventana deslizante de datos para suavizarlos. Se especifican el tamaño de la ventana y el orden del polinomio. Se crea un DataFrame con los datos filtrados, se calcula y visualiza su correlación y se grafican. Similar al SES, se usa para reducir el ruido, pero con un enfoque basado en ajuste polinomial local.
1from scipy.signal import savgol_filter
2
3prices_filter1 = np.array(price['NTDOY'])
4prices_filter2 = np.array(price['TSCO'])
5
6# parámetros
7window = 17
8polyorder = 2
9
10price_suavizado_filter_1 = savgol_filter(prices_filter1, window, polyorder)
11price_suavizado_filter_2 = savgol_filter(prices_filter2, window, polyorder)
12
13datos_suavizados_filter_sv = pd.DataFrame()
14datos_suavizados_filter_sv['Fecha'] = price.index
15datos_suavizados_filter_sv.set_index('Fecha', inplace=True)
16datos_suavizados_filter_sv['NTDOY'] = price_suavizado_filter_1
17datos_suavizados_filter_sv['TSCO'] = price_suavizado_filter_2
18
19corr = datos_suavizados_filter_sv.corr()
20print(corr)
21sns.heatmap(corr)
22plt.plot(datos_suavizados_filter_sv)
23
24print(len(price), len(datos_suavizados_filter_sv)) # 250 250
Método de Deciles:
Se implementa un método de normalización basado en deciles para una de las series de precios ('TSCO'). Los precios se asignan a un rango de 1 a 10 basado en el decil en el que caen. Se imprime una muestra de los datos originales y normalizados por deciles y se grafican. Este método transforma los datos a una escala basada en su distribución percentil.
1import numpy as np
2import matplotlib.pyplot as plt
3
4# Datos de ejemplo: precios de acciones diarios durante un año (ficticios)
5np.random.seed(0) # Para reproducibilidad
6precios_acciones = np.array(price['TSCO']) # Datos simulados
7
8# Calcular los deciles
9deciles = np.percentile(precios_acciones, [10 * i for i in range(1, 10)])
10
11# Normalizar los datos basados en deciles
12def asignar_decil(valor, deciles):
13 for i, decil in enumerate(deciles):
14 if valor <= decil:
15 return i + 1
16 return 10
17
18precios_normalizados = np.array([asignar_decil(valor, deciles) for valor in precios_acciones])
19
20# Imprimir resultados (muestra de los primeros 10 valores)
21print("Precios originales (primeros 10 valores):", precios_acciones[:10])
22print("Precios normalizados (primeros 10 valores):", precios_normalizados[:10])
23
24# Plotear los datos
25plt.figure(figsize=(14, 7))
26plt.plot(precios_acciones, label='Precios originales')
27plt.plot(precios_normalizados * 10, label='Precios normalizados (escalados por 10)', linewidth=2)
28plt.legend()
29plt.title('Normalización con Deciles')
30plt.xlabel('Día')
31plt.ylabel('Precio')
32plt.grid(True)
33plt.show()
Normalización Min-Max (Escalado):
Se aplica la normalización Min-Max a ambas series de precios utilizando `MinMaxScaler` de `sklearn`. Esto escala los datos a un rango específico (por defecto, entre 0 y 1). Se crea un DataFrame con los datos escalados, se calcula y visualiza su correlación y se grafican. La normalización Min-Max es útil cuando se necesita que los datos estén dentro de un rango fijo.
1from sklearn.preprocessing import MinMaxScaler
2
3precios_min_max_1 = np.array(price['NTDOY']).reshape(-1, 1)
4precios_min_max_2 = np.array(price['TSCO']).reshape(-1, 1)
5
6scaler1 = MinMaxScaler()
7scaler2 = MinMaxScaler()
8
9preios_escalados1 = scaler1.fit_transform(precios_min_max_1)
10preios_escalados2 = scaler2.fit_transform(precios_min_max_2)
11
12precios_escalados = pd.DataFrame()
13precios_escalados['Fecha'] = price.index
14precios_escalados.set_index('Fecha', inplace=True)
15precios_escalados['NTDOY'] = preios_escalados1.flatten()
16precios_escalados['TSCO'] = preios_escalados2.flatten()
17
18corr = precios_escalados.corr()
19print(corr)
20sns.heatmap(corr)
21plt.plot(precios_escalados)
Este script permite un análisis de datos financieros que carga precios históricos de acciones, calcula la correlación entre ellos y luego aplica y visualiza el efecto de varios métodos de suavizado y normalización (logaritmo, suavizado exponencial, Z-score, Savitzky-Golay, deciles y Min-Max) en la correlación y la forma de las series temporales de precios.
Comentarios
Cargando comentarios...