4 votos

R Calcular el precio futuro de un rango y graficar el resultado

Primero quiero decir que he leído este post (Cómo calcular el futuro de la distribución de precios utilizando la volatilidad?) pero no ayuda mucho.

Aquí es lo que estoy tratando de hacer (valores no son reales) enter image description here

Vamos a suponer que el último precio de esta seguridad es 20.85 y lo que yo estoy tratando de hacer es determinar, con base en la volatilidad, el rango en el que el precio debe ser en n días con X % de probabilidad.

En mi parcela vamos a suponer que la zona azul es una probabilidad de 41,5% y los dos pruple puntos en 20 días en el futuro. Estoy buscando una función que tome un diario al final del día el precio del tiempo de la serie, una probabilidad, y un número de día y de retorno de un rango de precio. Por ejemplo basado en mi parcela:

  • En 10 días el precio debería estar entre 19.65 y 20.05 con 93.4% posibilidades
  • En 20 días el precio debería estar entre las 20.20 y 21.50 con el 41,5% de posibilidades de que

Me gustaría ser capaz de hacer eso con una función como esta :

future_price_range(eod_prices_time_serie, nb_of_days, probability)

#with the first exemple it would look like this:
future_price_range(pcef_eod, 10, 0.934)

# And return
[1] 19.65 20.05

Basado en el post me estoy refiriendo a en la parte superior de esta pregunta, ya he conseguido hacer algo pero no estoy seguro de si estoy haciendo lo correcto:

library(quantmod)
library(PerformanceAnalytics)

# Retrieving daily prices from yahoo finance 
pcef <- getSymbols("PCEF")

# Selecting only the column of adjusted prices
pcef_ad <- Ad(PCEF)

En el post que he enlazado en la parte superior de mi pregunta es, dijo : "La distribución del logaritmo del precio de una acción en n días, es una distribución normal con una media de registro(currentprice) ..."

# So i take the last price
tail(pcef_ad, 1)
# PCEF.Adjusted
# 2017-11-22         23.62

# And a convert it to log 
mean_last_price_log <- log(23.62)

"... y la desviación estándar de la volatilidad∗(√n/365.2425) si usted está utilizando el calendario de días, y suponiendo que no hay dividendos y 0% de tasa de interés sin riesgo."

# I calculate daily returns 
pcef_daily_return <- dailyReturn(pcef_ad)

# To calculate the standard dev of returns
sd(pcef_daily_return)
# [,1]
# 0.005932502

Ya estoy usando la volatilidad diaria de la devuelve supongo que no debe dividir n por 365.2425. Yo estoy en lo correcto acerca de esto ?

# Let's say we want the price range in 10 days
n <- 10

sd_pcef_daily_return <- 0.005932502 * sqrt(n)

lg_dist <- rnorm(n = 10000, mean = mean_last_price_log, sd = sd)

# I convert it back to USD
us_dist <- exp(log_dist)
hist(us_dist)

No estoy seguro de a qué número debo tomar para el parámetro n en rnorm. Tomé 10000 porque parece "suficiente", pero ¿cuál es la regla aquí ? Esto es lo que obtengo:

enter image description here

### making a function of this



future_price_range <- function(eod_prices, days, probability){
  last_price <- tail(eod_prices,1)
  mean_log_price <- log(last_price)
  sd_daily_returns <- sd(dailyReturn(eod_prices)) * sqrt(days)
  log_dist <- rnorm(n = 10000, mean = mean_log_price, sd = sd_daily_returns)
  usd_dist <- exp(log_dist)
  return(hist(usd_dist))
}

future_price_range(eod_prices = pcef_ad, days = 100)

Así que con 100 días de la probabilidad de tener un mayor/menor precio aumenta a medida que se esperaba:

enter image description here

Pero ahora estoy luchando para poner en práctica la "probabilidad" de parámetro en la función y devolver un vector de la 2 los precios de la gama.

Podría usted confirmar que yo no he hecho ningún error en mi código y ¿tiene usted alguna pista que me ayude a terminar.

También sería genial si pudiera salida el mismo tipo de diagrama que se utiliza al principio de este post. Creo que es necesario para calcular el rango de precios para cada uno de los días hasta la fecha de destino y uso de los datos para trazar en el gráfico, pero no tengo idea de cómo hacerlo.

Hay una última cosa que me gustaría hacer: me tome un fin de la jornada diaria de los precios de series de tiempo, me puse un número de días y me da un rango de precios para un conjunto de probabilidades:

function(price_data, nb_of_days)

99%    55.12    20.90
95%    54.34    21.36
90%    53.26    22.35
80%    49.78    24.12
...    ...      ...
10%    ...      ...
5%     ...      ...
1%     ...      ...

Cualquier ayuda sería muy apreciada. Muchas gracias de antemano.

EDIT : Respuesta de @vanguard2k (muchas Gracias !)

Hice un par de ajuste de @vanguard2k respuesta para hacer el código reproductible. Para más detalles, mira el post de abajo

library(PerformanceAnalytics)
library(quantmod)
library(ggplot2)
library(lubridate)

# Retrieving price data from yahoo
pcef <- getSymbols("PCEF", auto.assign = FALSE)

# Selecting only adjusted EOD prices
pcef_ad <- Ad(pcef)

# tail(pcef_ad)
# PCEF.Adjusted
# 2017-11-15      23.21980
# 2017-11-16      23.40866
# 2017-11-17      23.51800
# 2017-11-20      23.53000
# 2017-11-21      23.57000
# 2017-11-22      23.62000

# Computing daily returns
pcef_daily_returns <- dailyReturn(pcef_ad)

# tail(pcef_daily_returns)
# daily.returns
# 2017-11-15 -0.0004278567
# 2017-11-16  0.0081334892
# 2017-11-17  0.0046709639
# 2017-11-20  0.0005102900
# 2017-11-21  0.0016999149
# 2017-11-22  0.0021213831

# Annualized Standard Deviation of daily returns
sigma <- sd(pcef_daily_returns)*sqrt(365)

# Why do we set a mean of zero ???
mean <- 0
probability <- 0.95

# Last observed price as "S"
S <- coredata(tail(pcef_ad,1))[1,1]

# Number of days to "forecast" as "n"
n <- 10

upper.bounds <- qnorm(probability,mean=mean*(0:n)/365,sd=sigma*sqrt((0:n)/365))
# [1] 0.000000000 0.009768138 0.013814233 0.016918911 0.019536276
# [6] 0.021842220 0.023926954 0.025844064 0.027628466 0.029304414
# [11] 0.030889564


lower.bounds <- qnorm(1-probability,mean=mean*(0:n)/365,sd=sigma*sqrt((0:n)/365))
# [1]  0.000000000 -0.009768138 -0.013814233 -0.016918911 -0.019536276
# [6] -0.021842220 -0.023926954 -0.025844064 -0.027628466 -0.029304414
# [11] -0.030889564

upper.cone <- S*exp(upper.bounds)
# [1] 23.62000 23.85185 23.94856 24.02303 24.08598 
# [6] 24.14159 24.19197 24.23839 24.28168 24.32241 
# [11] 24.36100

lower.cone <- S*exp(lower.bounds)
# [1] 23.62000 23.39040 23.29595 23.22374 23.16303 
# [6] 23.10968 23.06155 23.01738 22.97635 22.93787 
# [11] 22.90154

foo <- ggplot(data=data.frame(date=index(pcef_ad),data=coredata(pcef_ad)),aes(x=index(pcef_ad),y=coredata(pcef_ad))) + 
  geom_line() + 
  geom_polygon(data=data.frame(date=c(today()+0:n,today()+n:0),data=c(lower.cone,rev(upper.cone))),mapping=aes(x=date,y=data),alpha=1, fill = "pink")

foo

enter image description here

EDIT 2

He probado el código con un "pronóstico" período de los 1000 días, sólo para ver. Y hay algo en el producido de los valores que no entiendo: ¿por Qué es el rango superior más ancha que la inferior rango ? Parece que la predicción se tiene en cuenta la tendencia al alza pero, ¿cómo ? Honestamente yo esperaba que el rango para ser simétricos con respecto al último precio observado. Yo esperaba que la línea azul y la línea verde que tienen la misma longitud, pero el verde es más grande ... ¿por qué ?

enter image description here

3voto

Wim Coenen Puntos 225

En primer lugar, usted tiene razón acerca de su problema con $n$ (el nb_of_days). Si se calcula la volatilidad diaria de los rendimientos, sólo es necesario multiplicar por $n^{1/2}$.

Lo que usted está tratando de conseguir es la volatilidad de cono. Vamos a $S$ ser el último precio de la acción, $p$ la probabilidad de que el precio de la acción está por debajo de y $Q$ la función cuantil de la normal estándar.

La distribución de los registro de devoluciones está dada por:

$$ log(S_1/S_0) \aprox N(\mu_s/365,\sigma_S/(365)^{1/2})$$

Así, para todo el horizonte, el borde superior del cono está dada por

$$ S_0 \cdot \text{exp}\left(Q(p)\cdot \sigma_S\cdot (n/365)^{1/2} + \mu_s\cdot n /365\derecho).$$

El límite inferior es el mismo término con $1-p$ respectivamente. Para los más cortos plazos de tiempo, solo tenemos que cambiar el valor de $n$.

Se necesita algún tiempo para producir una buena trama pero podría intentar algo como esto con el paquete ggplot2:

sigma <- sd(pcef_daily_return)*sqrt(365)
mean <- 0
probability <- 0.95

S <- coredata(tail(pcef_ad,1))[1,1]

upper.bounds <- qnorm(probability,mean=mean*(0:n)/365,sd=sigma*sqrt((0:n)/365))
lower.bounds <- qnorm(1-probability,mean=mean*(0:n)/365,sd=sigma*sqrt((0:n)/365))
upper.cone <- S*exp(upper.bounds)
lower.cone <- S*exp(lower.bounds)


foo <- ggplot(data=data.frame(date=index(pcef),data=coredata(pcef)),aes(x=index(pcef),y=coredata(pcef))) + 
  geom_line() + 
  geom_polygon(data=data.frame(date=c(today()+0:n,today()+n:0),data=c(lower.cone,rev(upper.cone))),mapping=aes(x=date,y=data),alpha=0.25)

foo

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X