require(zoo)
require(xts)
require(rusquant)
OnDate <- start.date <- as.Date('2010-01-01')
ToDate <- end.date <- Sys.Date()
ROSN <- rusquant::getSymbols.Finam('ROSN', from = start.date) # роснефть
MICEX <- rusquant::getSymbols.Finam('MICEX', from = start.date) # ммвб
ROSN.rtn <- diff(log(ROSN$ROSN.Close))
MICEX.rtn <- diff(log(MICEX$MICEX.Close))
plot(ROSN.rtn, main = 'Дневная доходность Роснефти ')
plot(MICEX.rtn, main = 'Дневная доходность ММВБ')
Объединим два показателя – доходности Роснефти и ММВБ – в один объект с помощью функции merge
.
Функция merge гарантирует, что будут объединены значения с одинаковыми датами.
rtns <- merge(ROSN.rtn, MICEX.rtn)
names(rtns) <- c('ROSN', 'MICEX')
rtns <- rtns[complete.cases(rtns)]
plot(x = coredata(rtns$MICEX), y = coredata(rtns$ROSN),
xlab='Доходность ММВБ', ylab = 'Доходность ROSN')
Получить безрисковкую ставку (1-летние ОФЗ) с сайта Банка России (http://www.cbr.ru/scripts/Root.asp?PrtId=SEC) Посмотрите, что означает изотермный ряд бескупонной доходности (http://www.cbr.ru/gcurve/isoterm.asp)
source('https://raw.githubusercontent.com/quantviews/CBR/master/codes_new/CBR_web.R')
rf_rate <- Isoterm(start.date,end.date,I_Day = 1)
plot(rf_rate, main = 'Безрисковая ставка', ylab = '%')
rf_rate_d <- ((rf_rate+100)/100)^(1/365)-1 #посчитать дневные значения для безрисковой ставки
Для того, чтобы оценить модель CAPM необходимо рассчитать риск-премии (избыточные доходности относительно безрисковой ставки)
ex_rosn_rtns <- ROSN.rtn - rf_rate_d
ex_micex_rtns <- MICEX.rtn - rf_rate_d
fit <- lm(ex_rosn_rtns ~ ex_micex_rtns)
summary(fit)
##
## Call:
## lm(formula = ex_rosn_rtns ~ ex_micex_rtns)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.046689 -0.006731 -0.000707 0.006008 0.060354
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -5.588e-05 2.644e-04 -0.211 0.833
## ex_micex_rtns 1.010e+00 2.004e-02 50.402 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.01116 on 1780 degrees of freedom
## (1 observation deleted due to missingness)
## Multiple R-squared: 0.588, Adjusted R-squared: 0.5878
## F-statistic: 2540 on 1 and 1780 DF, p-value: < 2.2e-16
Является ли константа значимой? Какая доля дисперсии доходностей бумаги объяснется доходностью индекса?
Если константа незначимая, посчитайте регрессию без константы? На сколько отличаются коэффициенты и другие параметры в моделях с константой и без?
library(PerformanceAnalytics)
CAPM.beta(Ra = ROSN.rtn,Rb = MICEX.rtn,Rf = rf_rate_d)
## [1] 1.010523
CAPM.alpha(Ra = ROSN.rtn,Rb = MICEX.rtn,Rf = rf_rate_d)
## [1] -6.894596e-05
SharpeRatio.annualized(ROSN.rtn, Rf = rf_rate_d, geometric = FALSE)
## ROSN.Close
## Annualized Sharpe Ratio (Rf=4.9%) -0.04276415
SharpeRatio.annualized(MICEX.rtn, Rf = rf_rate_d, geometric = FALSE)
## MICEX.Close
## Annualized Sharpe Ratio (Rf=4.9%) 0.02638295
На что указывают значения показателя Шарпа для бумаги? Как показатель Шарпа для бумаги соотносится с показателем индекса?
Можно посчитать скользяющую бету и скользяющую альфу
chart.RollingRegression(Ra = ROSN.rtn,Rb = MICEX.rtn,Rf = rf_rate_d,width = 250, attribute = "Beta",
main = 'Скользящая бета для акций Роснефти')
chart.RollingRegression(Ra = ROSN.rtn,Rb = MICEX.rtn,Rf = rf_rate_d,width = 250, attribute = "Alpha",
main = 'Скользящая альфа для акций Роснефти')
Как изменялись значение альфы и беты в различные периоды времени? Являются ли значения показателей устойчивыми по времени:
Оценим модель CAPM для акций Google (американской рынок) на месячных данных.
Вам необходимо использовать собственный тикер (а не GOOG), который был назначен вам случайным образом
Сначала необходимо получить данные:
GOOG <- getSymbols('GOOG', src = 'yahoo',from = start.date,auto.assign = FALSE)
## As of 0.4-0, 'getSymbols' uses env=parent.frame() and
## auto.assign=TRUE by default.
##
## This behavior will be phased out in 0.5-0 when the call will
## default to use auto.assign=FALSE. getOption("getSymbols.env") and
## getOptions("getSymbols.auto.assign") are now checked for alternate defaults
##
## This message is shown once per session and may be disabled by setting
## options("getSymbols.warning4.0"=FALSE). See ?getSymbols for more details.
SPX <- getSymbols('^GSPC', src = 'yahoo',from = start.date,auto.assign = FALSE)
GOOG <- to.monthly(GOOG) # преобразовать дневные данные в месячные
SPX <- to.monthly(SPX)
GOOG.rtn <- diff(log(GOOG$GOOG.Adjusted)) # посчитать доходности
SPX.rtn <- diff(log(SPX$SPX.Adjusted))
rtns <- merge(GOOG.rtn, SPX.rtn) # Объединить в единый объект
names(rtns) <- c('GOOG', 'SPX') # переименовать переменные
rf <- getSymbols('DGS3MO', src = 'FRED', auto.assign = FALSE) #скачать данные по доходностям 3-месячных US Tresuaries
rf <- aggregate(rf, as.yearmon, mean, na.rm=TRUE ) # посчитать сремесячные значения для доходностей
rtns <- merge.xts(rtns, rf,join = 'left' )
rtns$rf <- (rtns$rf/100+1)^(1/12)-1 # преобразовать в месячные доходности
rtns$exret <- rtns$GOOG - rtns$rf # риск-премия для бумаги
rtns$exmkt <- rtns$SPX - rtns$rf # риск-премия для индекса
построить графики полученных переменных
plot(x=coredata(SPX.rtn), y=coredata(GOOG.rtn),
xlab = 'Месячная доходность SP500', ylab= 'Месячная доходность GOOG' )
plot(rtns$rf,
main = 'Среднемесячные значения UST (3m)')
Посчитаем модель CAPM c помощью функции lm
options(digits = 3)
capm_fit <- lm(formula = exret ~ exmkt, data = rtns)
summary(capm_fit)
##
## Call:
## lm(formula = exret ~ exmkt, data = rtns)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.15569 -0.03359 0.00167 0.02922 0.19457
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.00382 0.00644 0.59 0.56
## exmkt 1.04183 0.17484 5.96 5.9e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.0575 on 83 degrees of freedom
## (1 observation deleted due to missingness)
## Multiple R-squared: 0.3, Adjusted R-squared: 0.291
## F-statistic: 35.5 on 1 and 83 DF, p-value: 5.93e-08
Как можно интепретировать полученные результаты регрессии CAPM?
Для начала необходимо скачать данные по факторам Fama-French c сайта Кеннета Френча (http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/index.html)
Прочитайте описание факторов, которые используются в модели и как они рассчитываются – http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/Data_Library/f-f_factors.html
temp <- tempfile() #создать временный файл
download.file("http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip",temp, mode="wb")
unzip(temp, "F-F_Research_Data_Factors.CSV") #разархировать файл и сохранить его в рабочую папку
ff <- read.csv(file = 'F-F_Research_Data_Factors.CSV',skip = 3, sep = ',',stringsAsFactors = FALSE) # прочитать csv-файл
names(ff)[1] <- 'date' #изменить название первого столбца
str(ff) # посмотреть структуру объекта ff
## 'data.frame': 1180 obs. of 5 variables:
## $ date : chr "192607" "192608" "192609" "192610" ...
## $ Mkt.RF: chr " 2.96" " 2.64" " 0.36" " -3.24" ...
## $ SMB : chr " -2.30" " -1.40" " -1.32" " 0.04" ...
## $ HML : chr " -2.87" " 4.19" " 0.01" " 0.51" ...
## $ RF : chr " 0.22" " 0.25" " 0.23" " 0.32" ...
Переменные имеют тип character (chr) – это плохо, так как означает, что R считает их текстовыми переменными, а не числами. Необходимо преобразовать данные, чтобы с ними можно было дальше работать
ff$date <- as.yearmon(ff$date, '%Y%m') # преобразовать в месячные даты
ff$Mkt.RF <- as.numeric(ff$Mkt.RF)/100 # преобразовать в тип numeric и поделить на 100
ff$SMB <- as.numeric(ff$SMB)/100
ff$HML <- as.numeric(ff$HML)/100
ff$RF <- as.numeric(ff$RF)/100
str(ff)
## 'data.frame': 1180 obs. of 5 variables:
## $ date :Class 'yearmon' num [1:1180] 1926 1927 1927 1927 1927 ...
## $ Mkt.RF: num 0.0296 0.0264 0.0036 -0.0324 0.0253 0.0262 -0.0006 0.0418 0.0013 0.0046 ...
## $ SMB : num -0.023 -0.014 -0.0132 0.0004 -0.002 -0.0004 -0.0056 -0.001 -0.016 0.0043 ...
## $ HML : num -0.0287 0.0419 0.0001 0.0051 -0.0035 -0.0002 0.0483 0.0317 -0.0267 0.006 ...
## $ RF : num 0.0022 0.0025 0.0023 0.0032 0.0031 0.0028 0.0025 0.0026 0.003 0.0025 ...
построить графики для факторов модели FF
par(mfrow =c(4,1))
plot(x = ff$date, y=ff$Mkt.RF, type = 'l')
plot(x = ff$date, y=ff$SMB, type = 'l')
plot(x = ff$date, y=ff$HML, type = 'l')
plot(x = ff$date, y=ff$RF, type = 'l')
par(mfrow =c(1,1))
Как значения факторов модели FF менялись со временем?
Необходимо дальше преобразовать данные – в частности, необходимо использовать только те значения, которые находятся после start.date
ff <- ff[as.Date(ff$date) > as.Date(start.date),]
ff <- ff[complete.cases(ff),] # оставить только те значения для которых, есть значения всех переменных
ff <- xts(ff[,-1], order.by = ff[,1])
ff_rtns <- merge(ff,rtns)
tail(ff_rtns)
## Mkt.RF SMB HML RF GOOG SPX rf exret
## сен 2016 0.0025 0.0200 -0.0134 2e-04 0.01326 -0.00124 0.000245 0.01302
## окт 2016 -0.0202 -0.0441 0.0415 2e-04 0.00928 -0.01962 0.000276 0.00901
## ноя 2016 0.0486 0.0568 0.0844 1e-04 -0.03436 0.03360 0.000376 -0.03474
## дек 2016 0.0181 -0.0004 0.0352 3e-04 0.01802 0.01804 0.000426 0.01759
## янв 2017 0.0194 -0.0095 -0.0276 4e-04 0.03184 0.01773 0.000431 0.03141
## фев 2017 NA NA NA NA 0.03851 0.03123 0.000441 0.03807
## exmkt
## сен 2016 -0.00148
## окт 2016 -0.01989
## ноя 2016 0.03323
## дек 2016 0.01761
## янв 2017 0.01729
## фев 2017 0.03079
Оценить модель FF
ff_fit <- lm(exret ~ Mkt.RF + SMB + HML, data = ff_rtns)
summary(ff_fit)
##
## Call:
## lm(formula = exret ~ Mkt.RF + SMB + HML, data = ff_rtns)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.15689 -0.03763 0.00322 0.02792 0.18790
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 8.23e-05 6.43e-03 0.01 0.990
## Mkt.RF 1.20e+00 1.81e-01 6.61 3.9e-09 ***
## SMB -7.74e-01 3.01e-01 -2.57 0.012 *
## HML -4.91e-01 2.82e-01 -1.74 0.086 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.0561 on 80 degrees of freedom
## (2 observations deleted due to missingness)
## Multiple R-squared: 0.357, Adjusted R-squared: 0.333
## F-statistic: 14.8 on 3 and 80 DF, p-value: 9.1e-08
Сравните модели CAPM и Fama-French? Оличаются ли значения beta у моделей? Отличаются ли объяснительные силы моделей?
Вечером 7 декабря Роснефть объявила о том, что проведет приватизационную сделку (http://kremlin.ru/events/president/news/53431). Объявление проозошло вечером, после закрытия рынков. Цена закрытия 7 декабря составила 356,25 рублей. Цена открытия на следующий день составила 370,70 рублей, а цена закрытия 375,85 рублей. Таким образом, за день цена акции компании выросла на 5,5%.
Проведем event-study, на сколько изменение цен на акции 8 декабря 2016 года отличается от нормальной волатильности цен на акции Роснефти.
Определим, что дата события (event) = 8 декабря.
start.date <- as.Date('2015-12-08')
end.date <- as.Date('2016-12-08')
rtns_event <- merge(ROSN.rtn, MICEX.rtn, rf_rate_d)
rtns_event <- rtns_event[paste0(start.date, '::', end.date)]
event_day <- '2016-12-08'
chartSeries(ROSN[paste0(start.date, '::', end.date)], theme='white')
tail(rtns_event)
## ROSN.Close MICEX.Close rf_rate_d
## 2016-12-01 -0.00501 0.00803 0.000233
## 2016-12-02 0.00442 0.00335 0.000235
## 2016-12-05 0.03326 0.01369 0.000234
## 2016-12-06 0.00327 -0.00277 0.000232
## 2016-12-07 0.01016 0.00378 0.000232
## 2016-12-08 0.05356 0.02130 0.000232
посчитаем модель CAPM за предыдущий период (1 год)
rtns_event$exret <- rtns_event$ROSN.Close - rtns_event$rf_rate_d
rtns_event$exmkt <- rtns_event$MICEX.Close - rtns_event$rf_rate_d
capm_event <- lm(exret ~ exmkt, data = rtns_event[,-nrow(rtns_event)])
event_window <- rtns_event[nrow(rtns_event)]
event_window$pred.ret <- summary(capm_event)$coefficients[1]+summary(capm_event)$coefficients[2]*event_window$exmkt
event_window$ab.ret <- event_window$exret - event_window$pred.ret
event_window$tStat <- coredata(event_window$ab.ret)/summary(capm_event)$sigma
event_window$pvalue <- 2*(1-pt(abs(coredata(event_window$tStat)), df = nrow(rtns_event)-2))
event_window
## ROSN.Close MICEX.Close rf_rate_d exret exmkt pred.ret ab.ret
## 2016-12-08 0.0536 0.0213 0.000232 0.0533 0.0211 0.0268 0.0265
## tStat pvalue
## 2016-12-08 2.29 0.0227
Отличается ли изменение цен на акций Роснефти 8 декабря 2016 года от нормального уровня волатильности при общепринятых критерях статистической значимости?