Aplicando Python para análisis de precios: probabilidad precio-umbral

Ya habíamos visto como importar precios de cierre de acciones desde Yahoo Finance con la libreria pandas-datareader. En la clase pasada, además, vimos como pronosticar escenarios de evolución de precios suponiendo que los rendimientos diarios distribuyen normalmente. Como esta evolución de precios es aleatoria, utilizaremos la simulación montecarlo (hacer muchas simulaciones de escenarios de evolución de precios) para obtener probabilidades de que los precios de cierre estén encima de un valor umbral y tomar decisiones con base en estas probabilidades.

Referencias:

1. Descargando datos, una vez más

Recordamos una vez más como descargar los precios de cierre ajustados desde yahoo finance.

Esta vez haremos una función.


In [ ]:
# Importamos librerías

In [ ]:
# Creamos la función

In [ ]:
# Descargamos datos de microsoft en el 2016

In [ ]:
# Grafiquemos

2. Proyección de rendimientos diarios

Recordemos que los precios diarios de cierre ajustados no son un proceso estocástico estacionario, pero los rendimientos diarios si lo son. Por tanto calculamos los rendimientos a partir de los precios de cierre, obtenemos sus propiedades estadísticas muestrales y proyectamos los rendimientos. Luego, obtenemos la proyección de los precios.

Los rendimientos diarios se pueden calcular con los precios de cierre de la siguiente manera:

$$r_i=\frac{p_i-p_{i-1}}{p_{i-1}},$$

donde $r_i$ es el rendimiento en el día $i$ y $p_i$ es el precio de cierre ajustado en el día $i$.

En la clase pasada, vimos que una buena aproximación de la anterior expresión es:

$$r_i=\frac{p_i-p_{i-1}}{p_{i-1}}\approx \ln\left(\frac{p_i}{p_{i-1}}\right).$$

Además, supusimos que los rendimientos diarios eran una variable aleatoria con distribución normal (que se caracteriza con su media y varianza). Por tanto obtenemos la media y desviación estandar muestrales. Hagamos una función que retorne lo anterior.


In [ ]:
# Función que devuelve rendimientos diarios, media y desviación estándar

In [ ]:
# Calculamos con la función anterior

In [ ]:
# Graficamos rendimientos diarios

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 cierre de las acciones en el 2017 (hay un supuesto de que las cosas no cambiarán fundamentalmente).

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.

Hagamos una una función que simule varios escenarios de rendimientos diarios rendimientos diarios y que devuelva un dataframe con esta simulación.


In [ ]:
# Función que simula varios escenarios de rendimientos diarios

In [ ]:
# Simulamos 100 escenarios para todoo el 2017

3. Proyección de precios de cierre

Por tanto, para calcular los precios, tenemos:

$$\begin{align} p_i&=p_{i-1}\exp(r_i)\\ p_{i+1}&=p_i\exp(r_{i+1})=p_{i-1}\exp(r_i)\exp(r_{i+1})=p_{i-1}\exp(r_i+r_{i+1})\\ &\vdots\\ p_{i+k}&=p_{i-1}\exp(r_i+\cdots+r_{i+k}). \end{align}$$

Si hacemos $i=0$ en la última ecuación, tenemos que $p_{k}=p_{-1}\exp(r_0+\cdots+r_{k})$, donde $p_{-1}$ es el último precio reportado en el 2016.


In [ ]:
# Función de proyección de precios

In [ ]:
# Proyección de precios y concatenación con precios de 2016

In [ ]:
# Gráfico

4. Probabilidad Precio-Umbral

Ya que tenemos muchos escenarios de precios proyectados, podemos ver varias cosas. Por ejemplo, ¿cuál es la probabilidad de que el precio de cierre sobrepase algún valor umbral en algún momento?


In [99]:
K = 65
dates = pd.date_range('20170101',periods=ndays)
strike = pd.DataFrame({'Strike':K*np.ones(ndays)},index=dates)
simul = pd.concat([closes.T,simdata.T,strike.T]).T
simul.plot(figsize=(8,6),legend=False);



In [101]:
strike = pd.DataFrame(K*np.ones(ndays*ntraj).reshape((ndays,ntraj)),index=dates)
count = simdata>strike
prob = count.T.sum()/ntraj
prob.plot(figsize=(8,6),legend=False);



In [104]:
((K-closes.iloc[-1,:])/closes.iloc[-1,:]).values


Out[104]:
array([ 0.06403781])

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).

Con estas proyecciones pudimos calcular probabilidades de sobrepasar cierto precio umbral: toma de decisiones.

Recordar... Clase de reposición: mañana Miércoles 18 de Octubre de 16:00-18:00, aula D-206 (Clase de repaso).

  1. Viernes 28 de Octubre y Martes 21 de Noviembre no hay clase.
  2. Clase de reposición: mañana Miércoles 18 de Octubre de 16:00-18:00, aula D-206 (Clase de repaso).
  3. Para el próximo viernes: proyecto definido, subir a moodle un cuaderno con nombre del proyecto, objetivos y una breve introducción.
  4. Tarea la pongo hoy o mañana en la noche.
Created with Jupyter by Esteban Jiménez Rodríguez.