R計算未來價格範圍並繪製結果
首先我想說我已經閱讀了這篇文章(如何使用波動率計算未來的價格分佈?),但這並沒有多大幫助。
讓我們假設這個證券的最後價格是 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