En la clase anterior vimos como importar datos de activos de la base de datos de Yahoo Finance, tanto descargándolos como archivos separados por comas (.csv), como usando el paquete pandas-datareader. En esta clase, veremos como pronosticar escenarios de evolución de precios, suponiendo que los rendimientos diarios se distribuyen normalmente.
Referencias:
Hace menos de una década, los instrumentos financieros estaban en la cúspide de la popularidad. Las instituciones financieras de todo el mundo estaban negociando miles de millones de dólares de estos instrumentos a diario, y los analistas cuantitativos estaban modelándolos utilizando el cálculo estocástico y el poderoso C++
.
Sin embargo, el avance en los últimos años ha sido impresionante y las cosas han cambiado. Por una parte, la crisis financiera del 2008 fue producida por los instrumentos financieros llamados derivados. Por otra parte, los volúmenes transaccionales han bajado y la demanda de modelado con C++
se ha marchitado con ellos. Además, un nuevo jugador entró en la competencia... ¡Python!
Python
ha estado ganando muchos seguidores en la industria financiera en los últimos años y con razón. No en vano, junto a R
son los lenguajes de programación más utilizados en cuanto a análisis financiero.
Antes que nada, para poder hacer simular escenarios de predicción de precios, vamos a recordar lo que hicimos en la clase pasada de descargar los datos de Yahoo Finance, utilizando el paquete data
de la librería pandas_datareader
.
Esta vez, utilizaremos los datos de precios de cierre ajustados de activos de la compañía Apple en el año 2016 para nuestra aplicación.
In [1]:
# Importamos librerías
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pandas_datareader import data
%matplotlib inline
In [16]:
# Descargamos datos...
# Instrumento: Apple
ticker = ['AAPL']
# Fuente: Yahoo Finance
data_source = 'yahoo'
# Fechas de interés (inicio y fin): 2016
start_date = '2016-01-04'
end_date = '2016-12-31'
# Función DataReader
panel_data = data.DataReader(ticker, data_source, start_date, end_date)
In [17]:
# Solo nos interesa los precios de cierre ajustados...
closes = panel_data.loc['Adj Close']
# Generamos todos los días del 2016 en orden
all_weekdays = pd.date_range(start_date, end_date)
# Reindizamos
closes = closes.reindex(all_weekdays)
# Llenamos huecos en los precios de cierre
closes = closes.fillna(method='ffill')
In [20]:
# Graficamos
closes.plot(figsize=(8,6));
Ver en el pizarrón: aproximación con logaritmo, además mencionar validez estadística suponiendo distribución lognormal.
Entonces, los rendimientos diarios se pueden calcular como:
In [25]:
# Función para calcular los rendimientos diarios a partir de los precios de cierre...
def calc_daily_returns(closes):
return np.log(closes/closes.shift(1))[1:]
In [28]:
# Calcular rendimientos diarios y graficarlos
daily_returns = calc_daily_returns(closes)
daily_returns.plot(figsize=(8,6));
Entonces, suponemos que la diferencia logaritmica de los precios (rendimientos diarios) tiene una distribución normal.
¿Cómo se caracteriza una distribución normal?
In [29]:
mu=daily_returns.mean().AAPL
sigma=daily_returns.std().AAPL
mu, sigma
Out[29]:
Habiendo caracterizado los rendimientos diarios como una variable aleatoria normal con la media y la varianza muestral obtenida de los datos del 2016, podemos generar números aleatorios con estas características para simular el comportamiento de los precios de las acciones en el 2017.
Sin embargo, cada simulación que hagamos nos conducirá a distintos resultados (los precios siguen evolucionando aleatoriamente). Entonces, lo que haremos es simular varios escenarios para así ver alguna tendencia y tomar decisiones (próxima clase).
Pero, ¿cómo generar vectores de números aleatorios que distribuyen normalmente con una media y varianza dadas?
In [5]:
help(np.random.randn)
Generamos un data frame de rendimientos diarios proyectados (10 trayectorias)
In [33]:
ndays = 360
ntraj=10
dates=pd.date_range('20170101',periods=ndays)
simret = pd.DataFrame(sigma*np.random.randn(ndays,ntraj)+mu,index=dates)
simret
Out[33]:
Con los rendimientos, calculamos los precios de cierre... (explicar en el tablero)
In [34]:
simdata=(closes.loc['2016-12-30',:].AAPL)*np.exp(simret.cumsum())
simdata
Out[34]:
Concatenamos y graficamos...
In [35]:
simul=pd.concat([closes.T, simdata.T]).T
simul.plot(figsize=(8,6),legend=False);
Entonces, ya aprendimos a bajar datos con pandas-datareader. En específico, a partir de los precios de cierre ajustados obtuvimos los rendimientos diarios.
Suponiendo que los rendimientos diarios son un proceso estocástico estacionario de distribución normal, pudimos caracaterizarlo y proyectar varios escenarios de evolución de los precios (montecarlo).
La próxima clase veremos cómo tomar decisiones estableciendo un umbral de precio.