時間序列

R計算未來價格範圍並繪製結果

  • November 24, 2017

首先我想說我已經閱讀了這篇文章(如何使用波動率計算未來的價格分佈?),但這並沒有多大幫助。

這是我想要做的(值不是真實的) 在此處輸入圖像描述

讓我們假設這個證券的最後價格是 20.85,我想做的是根據波動性確定價格在 n 天內應以 X % 的機率出現的範圍。

在我的情節中,讓我們假設藍色區域的機率為 41.5%,而兩個紫色點位於未來 20 天。我正在尋找一個函式,該函式將採用每日結束價格時間序列、機率和天數並返回價格範圍。例如基於我的情節:

  • 10 天內價格應該在 19.65 和 20.05 之間,有 93.4% 的機會
  • 20 天內價格應該在 20.20 和 21.50 之間,有 41.5% 的機會

我希望能夠使用這樣的功能來做到這一點:

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

根據我在這個問題頂部提到的文章,我已經設法做一些事情,但我不確定我是否做對了:

library(quantmod)
library(PerformanceAnalytics)

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

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

在我在問題頂部連結的文章中說:“股票價格在 n 天內的對數分佈是正態分佈,其平均值為 log(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)

“ …和波動率的標準差∗(√n/365.2425),如果你使用日曆日,並假設沒有股息和0%的無風險利率。”

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

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

由於我使用的是每日收益的波動性,我想我不應該將 n 除以 365.2425。我是對的嗎?

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

我不確定我應該為 rnorm 中的 n 參數取什麼數字。我拿了 10000,因為它看起來“足夠”,但這裡的規則是什麼?這是我得到的:

在此處輸入圖像描述

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

因此,在 100 天內,價格上漲/下跌的可能性如預期:

在此處輸入圖像描述

但現在我正在努力在我的函式中實現“機率”參數並返回該範圍內 2 個價格的向量。

您能否確認我的程式碼沒有犯任何錯誤,您是否有任何線索可以幫助我完成它。

如果我能輸出與本文開頭使用的相同類型的繪圖,那也很棒。我想我需要計算直到目標日期的每一天的價格範圍,並使用數據將其繪製在圖表上,但我不知道該怎麼做。

我想做的最後一件事:我採用一天結束的每日價格時間序列,我設置了天數,我得到了一組機率的價格範圍:

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

任何幫助將非常感激。非常感謝你。

編輯:@vanguard2k 的回答(非常感謝!)

我對@vanguard2k 的回答做了一些調整,以使程式碼可重現。更多詳情,請看下面的文章

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

在此處輸入圖像描述

編輯 2

我嘗試了“預測”週期為 1000 天的程式碼,只是為了看看。產生的值中有一些我不明白的東西:為什麼上限比下限寬?看起來預測考慮了上行趨勢,但如何?老實說,我預計該範圍與最後觀察到的價格是對稱的。我預計藍線和綠線的長度相同,但綠線更大……為什麼?

在此處輸入圖像描述

首先,你對你的問題是正確的 $ n $ (nb_of_days)。如果計算收益的每日波動率,只需將其乘以 $ n^{1/2} $ .

你想要得到的是波動率錐。讓 $ S $ 成為最後的股票價格, $ p $ 股價低於的機率和 $ Q $ 標準法線的分位數函式。

收益對數的分佈由下式給出:

$$ log(S_1/S_0) \approx N(\mu_s/365,\sigma_S/(365)^{1/2}) $$ 因此,對於整個地平線,圓錐的上邊界由下式給出

$$ S_0 \cdot \text{exp}\left(Q(p)\cdot \sigma_S\cdot (n/365)^{1/2} + \mu_s\cdot n /365\right). $$ 下界與 $ 1-p $ 分別。對於較短的時間範圍,我們只需要更改 $ n $ .

製作一個好的情節需要一些時間,但您可以使用 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

引用自:https://quant.stackexchange.com/questions/37049