Predictor de precios de mercado - General Motors - Parte I
Desde hace tiempo los economistas han estudiado e intentado comprender los movimientos de los precios en la bolsa de valores, debido a que las inversiones en bolsa están sujetas a riesgos, los rendimientos son variables y su existencia es incierta. La predicción de la bolsa de valores es un tema de gran interés, en particular para quienes invierten en ella. Sería muy provechoso poder predecir la tendencia y, si fuera posible, el precio de las acciones, ya que con esta información los inversionistas podrían realizar movimientos apropiados y así ganar dinero.
En este ejercicio hemos querido realizar el estudio de diferentes modelos para intentar realizar la predicción del precio de valor para la compañía General Motor y describir cada uno de los pasos llevados a cabo, desde el análisis de los datos hasta el proceso de evaluación y comparación de las diferentes aproximaciones.
En este trabajo no se pretende llevar a cabo un predictor efectivo, sino más bien el explorar y aprender diferentes técnicas que pueden ser aplicadas para la resolución de problemas de esta índole, somos conscientes de la complejidad de este tipo de predictores de precios, puesto que los precios de valores de mercado pueden estar sujetos a altas variaciones que pueden depender de diferentes indicadores sociales, económicos y políticos, que no se incluyen en las variables del modelo..
En este set de diferentes notebooks trataremos de hacer un análisis de la serie temporal de los precios de cierre de mercado de la compañía General Motors en la bolsa de NY. Como objetivo se fijará crear un modelo de referencia y tratar de mejorarlo usando redes secuenciales.
Los datos serán obtenidos del proveedor de datos https://www.alphavantage.co/ por medio del uso de una librería.
En el primer post, Análisis de la serie temporal, haremos una limpieza inicial, un estudio de las tendencias y por último un estudio sobre la estacionaridad y transformación de esta a una serie estacionaria. El cual será clave para establecer un modelo de referencia correcto y ajustar después la red secuencial.
En un segundo post, Modelos de referencia, estudiaremos principalmente un modelo autorregresivo integrado de promedio móvil o ARIMA, dado que será el que mejor se ajuste a nuestra serie en función del pre-análisis del punto uno. También, se probarán otros métodos como Naïve method y random-forest para ver si nuestras premisas eran correctas.
En un último post, Modelos secuenciales intentaremos crear modelos de redes secuenciales que mejoren estos modelos de referencia.
En el post de hoy trataremos:
1.- Carga de Datos
2.- Análisis de los datos
3.- Estacionariedad
4.- Transformaciones
Carga de Datos¶
Obtenemos el "symbol" (NYSE:GM) valor del mercado sobre el que haremos el estudio. Hemos hecho el estudio de datos de diferentes valores decidiendonos finalmente por este. "General Motors"
from google.colab import drive
drive.mount('/content/drive')
cd /content/drive/My Drive/RedesSecuenciales
import requests
import json
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
%matplotlib inline
plt.rcParams['figure.figsize'] = (12, 5)
plt.rcParams['figure.dpi'] = 100
import numpy as np
import pandas as pd
pd.options.mode.chained_assignment = None
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error as sk_mse, mean_absolute_error as sk_mae, mean_squared_log_error as sk_msle
from keras.models import Model, model_from_json
from keras.layers import (Embedding, Conv1D, MaxPooling1D, LSTM, GRU, Dense, Flatten, Input, Dropout,
BatchNormalization, TimeDistributed,Reshape, Multiply)
from keras import regularizers
from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.losses import mean_squared_error
from keras.utils.vis_utils import plot_model
import keras.backend as K
def save_keras_model(export_path, model, model_name, create_folder=False, save_weights=False):
try:
if create_folder:
aux = model_name.split('_')[-1]
assert aux not in os.listdir(export_path), 'Directory "{0}" already created.'.format(aux)
os.mkdir(export_path + "/" + aux)
model_path = export_path + "/" + aux
else:
model_path = export_path
model_json = model.to_json()
with open(model_path + "/" + model_name + ".json", "w") as json_file:
json_file.write(model_json)
if save_weights:
model.save_weights(model_path + "/" + model_name + ".h5")
print("Saved model to disk as {0}/{1}".format(model_path, model_name))
return True, model_path
except Exception as err:
print('Save error: {0}'.format(err))
return False, err
def load_keras_model(import_path):
try:
path = import_path + ".json" if not import_path.endswith(".json") else import_path
print(path)
with open(path, "r") as json_file:
loaded_model_json = json_file.read()
loaded_model = model_from_json(loaded_model_json)
loaded_model.load_weights(path.replace('.json', '.h5'))
print("Loaded model from disk")
return loaded_model
except Exception as err:
print("Loading error: {0}".format(err))
return False
Para la obtencion de los datos es necesaria la instalacion de la libreria alpha_vanatage
#Instalacion de alpha_vantage para poder bajarnos los precios
!pip install alpha_vantage
#Para la obtencion de las TimeSeries necesitamos una clave que se nos proporciona de forma diaria para
# bajarnos los datos.
from alpha_vantage.timeseries import TimeSeries
API_KEY = 'JBMAO3WLU9Y4JWER'
#Le indicamos que queremos el formato en pandas
ts = TimeSeries(key=API_KEY, output_format='pandas')
data, metadata = ts.get_daily(symbol='NYSE:GM',outputsize='full') #Probamos con General Motors.
print("Datos precios General Motors")
display(data.head(10))
#Salvamos los datos a disco para que podamos trabajar con ellos despues.
file_data_GM = "daily_GM.csv"
data.to_csv(file_data_GM)
data = pd.read_csv(file_data_GM)
print(data.head(10))
Analisis de los datos¶
En este punto realizaremos un estudio desde el punto de vista de los datos puramente numerico. Valores fuera de banda o outliners, o datos incompletos o indeterminados. También realizaremos un estudio de las tendencias y por último un estudio sobre la estacionaridad y transformación de esta a una serie estacionaria.
Limpieza y preánalisis de los datos de precio¶
#Comprobamos que el fichero este completo, y no tengamos valores 0 o indeterminados.
missing_values_count = data.isnull().sum()
print(missing_values_count)
#Comprobamos si existen valores 0 en alguna de las columnas. Si es asi deberiamos rellenarlos con valores cercanos, media.
colMinValue = [(col, data[col].min()) for col in data.columns]
print(colMinValue)
Para este caso concreto de los datos, no tenemos valores desconocidos, que o bien sean 0 o nan y tampoco tenemos valores con unos maximos descontrolados.
#Sacamos un describe de los datos para ver como se distribuyen y si tenemos algunos datos raros
data.describe()
La variables de cierre tiene una distribucion normal, no tendremos que aplicar transformadores de Box Cox La asimetria tiene que estar [-1, 1] y el coeficiente de variabilidad menor 1
from scipy.stats import skew
import scipy.stats as ss
asimetria = skew(data['4. close'].values)
coef_var = ss.variation(data['4. close'])
print("Asimetria=",asimetria)
print("coef_variabilidad=", coef_var)
Pintamos la curvas del valor de cierre y vemos si nos aparece a simple vista algo que nos ayude a describir y comprender nuestros datos.
import seaborn as sns
sns.set()
%matplotlib inline
plt.rcParams['figure.figsize'] = (12, 5)
plt.rcParams['figure.dpi'] = 80
df = data['4. close']
df.index = data['date']
df.plot()
plt.title('Daily TimeSeries General Motors')
plt.show()
print('El valor maximo obtenido', df.idxmax(), "=", df.loc[df.idxmax()])
print('El valor minimo obtenido', df.idxmin(), "=", df.loc[df.idxmin()])
A simple vista vemos que desde finales de Julio del 2012 donde la empresa obtuvo su valor minimo del periodo, la empresa ha mantenido una tendencia creciente, obteniendo sus maximos en Octubre del 2017, pero actualemente el crecimiento se va manteniendo
Remuestreo y convirtiendo frecuencias¶
Veamos el comportamiento anual de la serie. Para ello, remuestreamos los datos al final del año comercial convirtiendo a frecuencias anuales. En cada punto, resample informa de la media del año anterior, mientras que asfreq informa el valor al final del año.
stock = data['4. close']
stock.index = pd.to_datetime(stock.index)
stock.index.name = 'date'
stock.plot(alpha=0.5, style='-')
stock.resample('BA').mean().plot(style=':')
stock.asfreq('BA').plot(style='--');
plt.legend(['input', 'resample', 'asfreq'],
loc='upper left');
import numpy as np
serie = data.copy(True)
serie.date = pd.to_datetime(data.date)
serie.index.name = 'date'
serie['year'] = [dat.year for dat in serie.date]
serie['month'] = [str(dat.strftime('%m')) for dat in serie.date]
years = serie['year'].unique()
import matplotlib as matplot
import datetime
np.random.seed(100)
colors = np.random.choice(list(matplot.colors.XKCD_COLORS.keys())[::-1], len(years), replace=False)
plt.clf()
plt.figure(figsize=(20, 8), dpi=80)
symbol = "GM"
for i, y in enumerate(years):
if i > 0:
year = serie[serie['year']==y].groupby('month').mean().reset_index(drop=False)
year['month'] = year['month'].map(lambda x: datetime.datetime.strptime(x, '%m').strftime('%b'))
plt.plot('month', '4. close', data=year, color=colors[i], label=y)
plt.text(year.shape[0] - 0.9, year['4. close'][-1:].values[0] - 0.25, y, fontsize=12, color=colors[i])
#plt.gca().set(xlim=(-0.3, 11), ylim=(2, 30), ylabel='Price', xlabel='Mes')
plt.yticks(fontsize=12, alpha=.7)
plt.title('Gráfica estacional anual del stock de '+symbol, fontsize=20)
plt.show()
En esta gráfica podemos ver que año tras año la evolución ha sido relativamente constante. Se aprecina una caída en el histórico a finales de 2011 y que perdura durante la primera mitad del año 2012, donde comienza a remontar nuevamente.
Media Movil
Uno de los indicadores tecnicos que podemos encontrar el AlphaVantage es el indicador MSA , correspondiente a la media movil. La media movil, nos permitira estudiar como evolucionan los precios es media para un determinada ventana de tiempo. Dentro de los indicadores podemos encontrar otro indicador similar que es el ema correspondiente a la media movil exponencial.
#Media movil
from alpha_vantage.techindicators import TechIndicators
symbol='NYSE:GM'
ti = TechIndicators(key=API_KEY,output_format='pandas')
#Obtenemos la media movil mensual.
data_msa, meta_msa = ti.get_sma(symbol=symbol, interval='daily',time_period=30, series_type='close')
#display(data_msa.head(10))
#Sacamos la exponencia
data_ema, meta_ema = ti.get_ema(symbol=symbol, interval='daily',time_period=30, series_type='close')
#Lo ploteamos para ver si vemos la tendecnia en los datos
plt.figure(figsize=(20,10))
data_msa.plot()
plt.title('Daily TimeSeries General Motors - MSE')
data_ema.plot()
plt.title('Daily TimeSeries General Motors - EMA')
plt.show()
Podemos también calcularla nosotros con respecto a una ventana de tiempo y la desviacion de los datos con respecto a la media:
def media_movil(serie, window_size, plotea=True):
roll_std = serie.rolling(window=window, center=False).std()
roll_mean = serie.rolling(window=window, center=False).mean()
if plotea:
date = data.date.astype('O')
plt.figure(figsize=(15,5))
plt.plot(serie, color='blue',label='Original')
plt.plot(roll_mean, color='red', label='Media')
plt.plot(roll_std, color='black', label = 'Std')
plt.legend(loc='best')
plt.xlabel('Index number')
plt.ylabel('Precio de cierre')
plt.title('Media móvil & Desviación típica')
plt.show()
return roll_std, roll_mean
window=30
roll_std, roll_mean = media_movil(data['4. close'], window, True)
Como podemos observar los primeros valores de la serie no aparecen puesto que se necesita acumular los winow_size primeros elementos antes de dar el primer valor.
Que nos aportan las medias moviles?. Las medias moviles se van recalculando a medida que vamos avanzando en el tiempo, el calculo de la media movil nos ayuda entre otras cosas a suavizar los picos o fluctuaciones en nuestros datos, se suelen usar para poder indentificar tendencias.
window = 130
roll_std_360, roll_mean_360 = media_movil(data['4. close'], window, True)
Si aumentamos la ventana suavizamos aun mas y vemos la tendencia en un intervalo de tiempo mayor.
Diagrama de caja de la distribución mensual (estacional) y anual (tendencia)¶
plt.clf()
fig, axes = plt.subplots(1, 2, figsize=(20,7), dpi= 80)
sns.boxplot(x='year', y='4. close', data=serie, ax=axes[0])
sns.boxplot(x='month', y='4. close', data=serie[~serie.year.isin([1991, 2008])])
axes[0].set_title('Distribución anual (tendencia)', fontsize=18);
axes[1].set_title('Distribución mensual (estacionalidad)', fontsize=18)
plt.show()
Vemos nuevamente el año 2011 como año con mayor variación negativa de los precios. En el gráfico de la derecha puede verse que mensualmente se mantiene más bien constante y se aprecian mayores flutuaciones de los precios a mitad y a final de año.
Preanálisis de las variables exógenas¶
Para aquellas variables que en un futuro puede ser interesante añadir de las que nos presenta el proveedor, es importante valorar cuáles pueden ser interesantes y cuáles no. Para ello, se hará uso de un analisis de sus correlaciones.
A parte de la media móvil y la media móvil exponencial, vamos a evaluar las que la propia página referencia como de alto uso, y que tengan sentido en nuestro análisis intra-día que serían:
- MACD, Media Móvil de Convergencia/Divergencia. Muy usado en el estado del arte y relevante, ya que es la diferencia entre medias móviles a corto y medio plazo, dando una alta sensibilidad del cambio.
- STOCH, Oscilador Estocástico. Está limitado por el rango entre 0 y 100. Esto lo convierte en un indicador útil de las condiciones de sobrecompra y sobreventa. Tradicionalmente, las lecturas de más de 80 se consideran en el rango de sobrecompra, y las lecturas de menos de 20 se consideran sobrevendidas.
- RSI, Índice de Fuerza Relativa. Fácil de interpretar, supone que cuando hay un valor alto de este indicador, los precios han seguido una tendencia que en el extremo se revertirá.
- ADX, Índice Direccional Medio. Evalua la fuerza de la tendencia actual y saber si estamos realmente en una tendencia (subida, bajada, estancamiento) ó rango (rebote del precio entre dos valores).
- CCI, Índice del Canal de Comodidad. Detección de tendencias y concretamente de la volatilidad. A partir de 10 indica tendencias alzistas y por debajo de -100 tendencias bajistas.
- AROON, identifica tendencias y su fortaleza en valor porcentual.
- BBANDS, Bandas de Bollinger. Compara la volatilidad de niveles de precio a lo largo de un periodo de tiempo.
- AD, Acumulación/Distribución. Si el precio o cotización del mercado se encuentra en una tendencia alcista, el indicador estará ascendente reflejando la presión compradora, en cambio, en una tendencia bajista, el indicador estará bajando y reflejando la presión vendedora. Así, puede servir de aviso a giros en el mercado.
- OBV, Balance de Volúmenes. Se basa en que el volumen precede al movimiento del precio, por lo tanto si un activo presenta un incremento en el OBV es una señal de que el volumen de trading se está elevando durante los periodos en que el precio sube, y viceversa.
data_indexed, metadata_indexed = ts.get_daily(symbol='NYSE:GM',outputsize='full')
data_msa, meta_msa = ti.get_sma(symbol=symbol, interval='daily',time_period=30, series_type='close')
data_ema, meta_ema = ti.get_ema(symbol=symbol, interval='daily',time_period=30, series_type='close')
data_macd, meta_macd = ti.get_macd(symbol=symbol, interval='daily',series_type='close')
data_stoch, meta_stoch = ti.get_stoch(symbol=symbol, interval='daily')
data_rsi, meta_rsi = ti.get_rsi(symbol=symbol, interval='daily',time_period=30, series_type='close')
data_adx, meta_adx = ti.get_adx(symbol=symbol, interval='daily',time_period=30)
data_cci, meta_cci = ti.get_cci(symbol=symbol, interval='daily',time_period=30)
data_aroon, meta_aroon = ti.get_aroon(symbol=symbol, interval='daily',time_period=30)
data_bbands, meta_bbands = ti.get_bbands(symbol=symbol, interval='daily',time_period=30, series_type='close')
data_ad, meta_ad = ti.get_ad(symbol=symbol, interval='daily')
data_obv, meta_obv = ti.get_obv(symbol=symbol, interval='daily')
Al tener cada dato una escala, lo más correcto es utilizar la correlación de Pearson, que independiza este factor:
from functools import reduce
dfs = [data_indexed,
data_msa, data_ema, data_macd, data_stoch,
data_rsi, data_adx, data_cci, data_aroon,
data_bbands, data_ad, data_obv]
df_corr = reduce(lambda left,right: pd.merge(left,right,on='date'), dfs)
import seaborn as sns
corrmat = df_corr.corr()
f, ax = plt.subplots(figsize =(9, 8))
sns.heatmap(corrmat, ax = ax, cmap ="YlGnBu", linewidths = 0.1)
La media móvil de convergenica/divergencia (MACD) tiene una covarianza suficientemente alta para tomarla como variable exógena de referencia. Se probará con la RNN simple más adelante y analizaremos su comportamiento y aportación.
Estacionaridad¶
A continuacion vamos a identificar si nuestra serie es estacionaria y en caso de no serlo convertirla en estacionaria. Para poder aplicar el metodo ARIMA debemos asegurarnos de que nuestra serie lo es.
Se dice que una serie de tiempo es estacionaria cuando su distribución y sus parámetros no varían con el tiempo. En términos más concretos, la media y la varianza de una serie estacionaria no cambian con el tiempo, y tampoco siguen una tendencia.
Una serie estacionaria es mucho más fácil de predecir. Si se comportaba de una manera en el pasado ( digamos con una determinada media y varianza) , podremos suponer que se seguirá comportando de la misma forma en el futuro. Bueno, o que tiene una gran probabilidad de continuar comportándose de la misma forma.
Prueba de Dicky Fuller¶
Esta prueba nos permite a priory identificar si una serie es estacionaria o no lo es.
El test de la raiz unitaria nos indicara como de marcada tiene una serie una determinada tendencia.
La hipotesis nula lo que nos indica es que si nuestra serie puede ser representada por una raiz unitaria es que NO es estacionaria y existe alguna dependencia temporal dentro de la serie. Esto lo comprobamos con el valor del p_value del test.
Si Valor p > 0.05: No se puede rechazar la hipótesis nula (H0), los datos tienen una raíz unitaria y NO son estacionarios.
Si Valor p <= 0.05: Rechaza la hipótesis nula (H0), los datos no tienen una raíz unitaria y son ESTACIONARIOS.
Pasamos el test inicialmente a nuestra serie sin procesar.
from statsmodels.tsa.stattools import adfuller
def test_fuller(df):
dftest = adfuller(df)
#Nos quedamos con los 4 primeros elementos de la tabla del test
dfoutput = pd.Series(dftest[0:4], index=['ADF Test Statistic','p-value','#Lags usados','Numero de observaciones'])
for key,value in dftest[4].items():
dfoutput['Valor crítico del Test Statistic (%s)'%key] = value
return dfoutput
testdffuller = test_fuller(df)
print(testdffuller)
El p_value en este caso > 0.05 con lo cual no se puede rechazar la hipotesis nula . NO ES UNA SERIE ESTACIONARIA. Deberemos entonces aplicar diferentes metodos para intentar convertirla en estacionaria.
Transformaciones¶
Transformar una serie no estacionaria en estacionaria.
Logaritmo¶
Estudio del Logaritmo de la funcion. La transformacion logaritmica puede en algunos casos estabilizar la dispersion de nuestros datos y hay veces que es mucho mejor trabajar con el logaritmo que con los datos en bruto y puede hacer que la media se estabilice, pero en nuestro caso no conseguimos eliminar la tendencia.
data['4. close'].hist()
Se parece a una distribucion gausiana pero esto ya nos esta indicando que nuestra serie no es estacionaria, podemos probar con el logaritmo y volver a realizar la distribucion y comprobar
import numpy as np
from matplotlib import pyplot
log_close = np.log(data['4. close'].values)
pyplot.hist(log_close)
pyplot.show()
window = 30
roll_std_log, roll_mean_log = media_movil(np.log(df), window, True)
si observamos la diferencia con la misma media movil, al mismo intervalo de tiempo, vemos que tanto la tendecia como la desviacion adoptan una forma mas uniforme.
Resta de Media Movil¶
Cuando restamos a nuestra serie inicial la media movil lo que conseguimos es eliminar su tendencia, en este caso, estamos restando la media movil referente con una ventana de tiempo de 30 dias.
plt.figure(figsize=(10,5))
resta_media_avg = data['4. close'].values - roll_mean
plt.plot(resta_media_avg, color='black', label = 'Rolling Std')
plt.show()
Diferenciacion¶
Eliminar tendencia y estacionalidad, se puede realizar con el proceso de diferenciacion. Este proceso de transformacion consiste en generar una nueva serie Snueva(t) = Sorig(t) - Sorig(t-1) A este proceso se le denomina diferenciacion de primer orden. Es posible que para convertir nuestra serie en estacionaria se necesesiten varios ordenes de diferenciacion.
diff_serie = data['4. close'].diff().dropna()
plt.figure(figsize=(10,5))
plt.plot(diff_serie)
plt.ylabel('Precios de Cierre')
plt.xlabel('Index number')
plt.show()
Aqui vemos claramente que nuestra serie no presenta tendencia, comprobamos con el test de Dicky Fuller que la serie diferenciada con diferencuacion de primer orden si lo es
test_diff = test_fuller(diff_serie)
print(test_diff)
Al resultado de la primera diferenciacion, le hemos pasado el test y vemos que el p_value se hace muy pequeno.
Descomposicion¶
Toda serie temporal se puede descomponer en 3 componetes, su tendencia, componente estacional, que es un patron que se repite en ciertos periodos de tiempo y el residuo.
from statsmodels.tsa.seasonal import seasonal_decompose
#Hemos puesto frecuencia de 30 dias, lo mismmo resulta ser mucho.
descomposicion = seasonal_decompose(data['4. close'].values, freq=12)
fig, ax = plt.subplots(figsize=(10, 10))
plt.subplot(411)
plt.plot(data['4. close'].values, label='Original')
plt.legend(loc='best')
plt.subplot(412)
plt.plot(descomposicion.trend, label='Tendencia')
plt.legend(loc='best')
plt.subplot(413)
plt.plot(descomposicion.seasonal[2000:],label='Estacionalidad')
plt.legend(loc='best')
plt.subplot(414)
plt.plot(descomposicion.resid, label='Residuo')
plt.legend(loc='best')
plt.tight_layout()
#eliminamos posibles valores nulos del residuo
residual = descomposicion.resid
#Eliminamos los valores nulos.
residual = residual[~np.isnan(descomposicion.resid)]
Volvemos a aplicar el Text De DickyFuller sobre el residuo para comprobar si es estacionario, que lo deberia de ser.
dftest = adfuller(residual)
dfoutput = pd.Series(dftest[0:4], index=['ADF Test Statistic','p-value','#Lags usados','Numero de observaciones'])
for key,value in dftest[4].items():
dfoutput['Valor crítico del Test Statistic (%s)'%key] = value
print(dfoutput)
En este caso vemos que p_value esta por debajo del 5% con lo cual podemos decir que el residuo lo es.
Autocorrelacion¶
La mayoría de los procesos físicos presentan una inercia y no cambian tan rápidamente. Esto, combinado con la frecuencia del muestreo, a menudo hace que las observaciones consecutivas estén correlacionadas. Esta correlación entre observaciones consecutivas se llama autocorrelación. Cuando los datos están autocorrelacionados, la mayoría de los métodos estadísticos estándares basados en la suposición de observaciones independientes pueden arrojar resultados engañosos o incluso ser inútiles.
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from pandas.plotting import autocorrelation_plot
autocorrelation_plot(data['4. close'].values)
Diagrama de autocorrelacion de la serie original. Observamos que la autocorrelacion en tiempo baja exponencialmente y lags altos de tiempo se hace casi 0. No parece que la serie presente autocorrelaciones visibles.
autocorrelation_plot(diff_serie)
pyplot.show()
Grafica de autocorrelaciones de la serie con el primer orden de diferenciacion. Como podemos observar las correlaciones en todos los retardos "lags" estan cercanos a cero. Estos resultados que estamos obteniendo nos hacen pensar que nuestra serie una vez diferenciada se parace a una Serie "Random Walk".
Una serie random Walk viene determinada, por la formula > Y(t) = Y(t-1) + Et siendo Et la componente aleatoria Las series random Walk, o de camino aleatorio, no son estacinarias, pero nosotros la hemos covertido en estacionaria con el proceso de diferenciacion , pero hemos obtenido un p_value bajisimo.
Si exploramos las graficas PACF ACF obtedriamos los siguiente (sobre la serie diferenciada)
plot_pacf(diff_serie, lags=60)
plt.show()
plot_acf(diff_serie, lags=60)
plt.show()
En ambas graficas vemos que solo tenemos correlacion en el primer retardo.
import seaborn as sns
sns.set_style('whitegrid')
sns.kdeplot(diff_serie, bw=0.5)
print(diff_serie.describe())
Las series que no presentan autocorrelacion se las denomina de ruido blanco, nuestra serie en
este caso se parece bastante al ruido blanco. https://otexts.com/fpp2/wn.html#fig:wnoise
El problema de las series radom walk o de camino aleatorio es que son mas impredecibles. Las mejores prediciones que podremos hacer seran las que tomen como partida el tiempo anterior y predigan el siguiente, a esto normalmente se le denomina pronostico ingenuo Una caminata aleatoria (random Walk) es aquella en la que los pasos o direcciones futuros no pueden predecirse sobre la base de la historia pasada. Cuando el término se aplica al mercado de valores, significa que los cambios a corto plazo en los precios de las acciones son impredecibles.
Por ahora, los resultados no son prometedores, esperemos al post II para ver que obtenemos.
Comentar