Моя цель - создать нейтральный к доллару и бета-нейтральный портфель, подверженный влиянию отдельных факторов, таких как размер, значение e cc ... Я попробовал r , используя пакет portfolioanalytics .
Я начал с сбора данных из S & P 500, содержащих цены на акции, а также другую переменную, которая мне была нужна. В этом случае я покажу вам, что я пытался сделать для создания портфеля с нейтральным размером доллара.
setwd("C...Factor Investing/Data")
data <- read.csv("prova_mktcap.csv",sep=";")
stocks <- read.csv("prova_price.csv",sep=";")
library(tidyverse)
library(timetk)
library(quantmod)
library(stringr)
library(purrr)
library(tbl2xts)
library(PortfolioAnalytics)
##############################################################################
############################### DEFINING PTF COMPONENTS ######################
colnames(data) <- colnames(stocks)
stocks_xts <- as.xts(data[,-1], order.by=as.Date(data$Index,
format="%d/%m/%Y"))
stocks_ret <- diff(log(stocks_xts))
data_xts <- as.xts(data[,-1], order.by=as.Date(data$Index,
format="%d/%m/%Y"))
data_tbk <-
data_xts %>%
tk_tbl(preserve_index=TRUE, rename_index="date")%>%
gather(asset, mktcap, -date) %>%
group_by(date)
data_tbk$mktcap <- data_tbk$mktcap %>% as.numeric
data_tbk$asset <- str_replace(data_tbk$asset,"..MARKET.VALUE","cap") ##essentials
data_SIZE <-data_tbk %>%
group_by(date) %>%
mutate(ptf = case_when(
mktcap>=quantile(mktcap,0.8, na.rm=TRUE)~TRUE,
mktcap<=quantile(mktcap,0.2, na.rm=TRUE)~FALSE,
TRUE~NA
)) #when TRUE -> long portfolio
#when FALSE -> short portfolio
Таким образом, я получил тибль data_SIZE
со следующей структурой:
> str(data_SIZE)
Classes ‘grouped_df’, ‘tbl_df’, ‘tbl’ and 'data.frame': 131805 obs. of 4 variables:
$ date : Date, format: "2015-01-01" "2015-01-02" ...
$ asset : chr "X3M" "X3M" "X3M" "X3M" ...
$ mktcap: num 104365 104200 101850 100764 101494 ...
$ ptf : logi TRUE TRUE TRUE TRUE TRUE TRUE ...
- attr(*, "groups")=Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 261 obs. of 2 variables:
..$ date : Date, format: "2015-01-01" "2015-01-02" ...
..$ .rows:List of 261
.. ..$ : int 1 262 523 784 1045 1306 1567 1828 2089 2350 ...
Он содержит для каждого месяца 2015 года и для всех акций в S & P500 его название эмитента, его рыночная капитализация и логическое значение, равное TRUE
, если акция падает в этот конкретный день в верхнем квинтиле рыночных капиталов, и FALSE
, если в тот же день она попадает в самый низкий квинтиль рыночных капиталов. В соответствии с этим критерием я собираюсь построить нейтральный к рынку портфель, подверженный фактору размера. Это пример, который я собираюсь воспроизвести для других факторов. Я храню названия акций, которые я собираюсь использовать, в списке, который содержит кадры данных с именами, соответствующими каждой дате.
long_components_size <- data_SIZE %>% filter(ptf==TRUE) %>%
select(asset,date) %>% group_by(date)
long_comps_size <- group_split(long_components_size, keep=FALSE)
names(long_comps_size) <- unique(long_components_size$date) #long
short_components_size <- data_SIZE %>% filter(ptf==FALSE) %>%
select(asset,date) %>% group_by(date)
short_comps_size <- group_split(short_components_size, keep=FALSE)
names(short_comps_size) <- unique(short_components_size$date) #short
Теперь пришло время использовать фрейм данных stocks_ret
для запуска оптимизации. Мне уже удалось совместить имена столбцов с именами, используемыми для различения рыночных ограничений.
> str(stocks_ret)
An ‘xts’ object on 2015-01-01/2015-12-31 containing:
Data: num [1:261, 1:505] NA -0.00158 -0.02281 -0.01072 0.00722 ...
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr [1:505] "X3M" "ABBOTT.LABORATORIES" "ABBVIE" "ABIOMED" ...
Indexed by objects of class: [Date] TZ: UTC
xts Attributes:
NULL
На этом этапе я запускаю оптимизацию , используя инструменты, предоставленные [Tag: PortfolioAnalytics], к сожалению, без успеха.
> port_size <- portfolio.spec(assets=colnames(stocks_ret))
> port_size <- add.constraint(port_size, type="group",
+ groups=list(groupA=stocks_ret[,long_comps_size$`2015-01-01`$asset],
+ groupB=stocks_ret[,short_comps_size$`2015-01-01`$asset]),
+ group_min=c(+1,-1),
+ group_max=c(+1,-1))
> port_size <- add.constraint(port_size,type="weight_sum", min_sum=0,max_sum=0)
> port_size <- add.objective(port_size,type="return",name="mean")
> opt_size <- optimize.portfolio(R=stocks_ret, portfolio=port_size,
+ optimize_method="random")
Leverage constraint min_sum and max_sum are restrictive,
consider relaxing. e.g. 'full_investment' constraint should be min_sum=0.99 and max_sum=1.01
Error in seq.default(from = round(min, rounding), to = round(max, rounding), :
'from' must be a finite number
Я знаю, что сделал Не добавляйте бета-нейтральное ограничение, но это уже испорчено. Позже я хотел бы установить add.objective
с настраиваемой функцией, которая рассчитывает бета-версию на самом S & P500.
Если бы кто-нибудь смог дать мне понимание моей проблемы или других решений насмешки над Fama & French с нуля, это было бы большим вкладом в мою последнюю диссертацию.