构建投资组合与再平衡策略的实现

张剑

2020/04/11

Categories: 投资学 Tags: 投资 R

目标

本次主要实现投资组合收益、累计收益、标准差、夏普比率的计算与实现。同时使用介绍再平衡策略在投资组合中的简单应用。

主要接口、包及流程:

  1. 使用Tushare下载原始资产数据;
  2. 利用tidyquant、tidyverse、timetk对原始资产数据进行加工,使其满足教材所需经典条件;
  3. 实现50-50的再平衡策略,测试月度再平衡和季度在平衡策略;

回归投资组合基本思路

投资组合收益率

1.日收盘价转换为日收益率

Rt2=Pt2Pt1Pt1

2.日收益率转换为年度收益率,假设一天有252个交易日。周收益率和日收益率同理可得

平均年化收收益率=(1+Rt)2521

3. 投资组合的收益率与方差(两资产)

E(rP)=wAE(rA)+wBE(rB) wA+wB=1 wAwB分别是事前投资与A资产与B资产的权重,E(rA)E(rB)分别是A与B标的资产的历史期望收益率。

两种资产组合的方差为: σ2(rP)=wA2σ2(rA)+wB2σ2(rB)+2wAwBCov(rA,rB)

ρAB=COV(A,B)σAσB

COV(A,B)=ρABσAσB

其中ρAB为资产A与资产B的相关系数

如果多个资产,用简洁的矩阵形式表示为:

δ2(rp)=i=2nwiwjcov(ri,rj)E(rp)=wiri

下载原始数据

我们构建一个50-50的两资产的投资组合,即wA=50,wB=50 资产标的我们选择沪深300指数(000300.SH)以及余额宝对应的天弘基金(000198.OF)。

pacman::p_load(tidyquant,tidyverse,timetk,Tushare,DT)

api <- pro_api(token = '5adce34e8c81bf7085828754a8e09590c3630032d0f61aad6483eaaa')

bar <- pro_bar(token = '5adce34e8c81bf7085828754a8e09590c3630032d0f61aad6483eaaa')

hs300 <- api(api_name = 'index_daily',ts_code = '000300.SH',
             start_date='20140101', end_date = '20200407')
hs300 <- hs300 %>%
  select(ts_code,trade_date,close) %>%
  mutate(trade_date = as.Date(trade_date,format="%Y%m%d") )
yeb <- api(api_name = 'fund_nav',ts_code = '000198.OF',market ='O')
# 基金净值接口,无法设定开始时间,数据下载后需要自行处理
yeb <- yeb %>%
  rename(close = adj_nav ) %>%
  mutate(trade_date = as.Date(end_date,format="%Y%m%d")) %>%
  filter(trade_date >= as.Date('20140101',format="%Y%m%d"),trade_date <= as.Date('20200407',format="%Y%m%d")) %>%
  select(ts_code,trade_date,close) 

# 合并数据,左合并,数据整理成long形
stock <- hs300 %>%
  left_join(yeb,by="trade_date", suffix=c('_hs300','_yeb')) %>%
  as_tibble()

stock_long <- stock %>%
  pivot_longer(cols = c(close_hs300,close_yeb),names_to = 'name',
               values_to = 'price') %>%
  select(name,trade_date,price) %>% drop_na()
stock_long %>% datatable()

上面进行数据合并的时候,用了和之前不一样的方法,使用了left_jion这个函数,这个函数具体帮助见链接!!!

左合并的主要思想是:保持“左”边的数据集为主集,“右”边的数据集配合“左”边数据集进行合并,合并的key是用by参数控制的,这里的key是匹配的关键词,也就是两个数据集里都具有的特征变量。在左合并时,如果右数据集大于左数据集,那么删除部分右边数据从而实现匹配左边数据的方式。

先看一下我们希望构建的两个资产的价格趋势

ggplot(stock_long,aes(x=trade_date,y = price,color=name))+
  geom_line() + theme_tq() + xlab("时间") + ylab("股价") +
  scale_color_tq() + ggtitle("沪深300和余额宝投资组合——2014-2020")

计算投资组合的收益率、组合的方差

使用tidyquant中的tq_portfolio来计算收益率,手动计算也完全没有问题,思路是把50-50权重合并到数据集上,生成一个新的组合收益率即可。

# 给出权重50-50
wts <- c(0.5,0.5)
#计算日收益率
stock_long_daily_r <-stock_long %>%
  group_by(name) %>%
  tq_transmute(select = price,
               mutate_fun = periodReturn,
               period = 'daily',
               col_rename = "Ra")
stock_long_daily_r
## # A tibble: 3,052 x 3
## # Groups:   name [2]
##    name        trade_date        Ra
##    <chr>       <date>         <dbl>
##  1 close_hs300 2014-01-02  0       
##  2 close_hs300 2014-01-03 -0.0134  
##  3 close_hs300 2014-01-06 -0.0228  
##  4 close_hs300 2014-01-07 -0.000284
##  5 close_hs300 2014-01-08  0.00175 
##  6 close_hs300 2014-01-09 -0.00878 
##  7 close_hs300 2014-01-10 -0.00782 
##  8 close_hs300 2014-01-13 -0.00507 
##  9 close_hs300 2014-01-14  0.00874 
## 10 close_hs300 2014-01-15 -0.00176 
## # ... with 3,042 more rows
port_daily_r <- stock_long_daily_r %>%
  tq_portfolio(assets_col = name,
               returns_col = Ra,
               weights = wts,
               col_rename = "port_RA")
port_daily_r
## # A tibble: 1,526 x 2
##    trade_date    port_RA
##    <date>          <dbl>
##  1 2014-01-02  0        
##  2 2014-01-03 -0.00663  
##  3 2014-01-06 -0.0110   
##  4 2014-01-07 -0.0000473
##  5 2014-01-08  0.000950 
##  6 2014-01-09 -0.00422  
##  7 2014-01-10 -0.00373  
##  8 2014-01-13 -0.00220  
##  9 2014-01-14  0.00433  
## 10 2014-01-15 -0.000772 
## # ... with 1,516 more rows

展示我们构建的投资组合的收益率的分布情况

ggplot(port_daily_r , aes(x=port_RA)) +
  geom_histogram(bins=100 ,alpha=0.5) + geom_vline(xintercept = 0,color='red',alpha=0.6)+
  theme_tq() + xlab("时间") + ylab('频率')+
  ggtitle('沪深300和余额宝投资50-50投资组合日收益率')

获得我们构建的投资组合的日收益率均值和标准差

#汇报组合均值和方差
paste("我们构建的组合的日收益率均值为:",mean(port_daily_r$port_RA, na.rm = TRUE))
## [1] "我们构建的组合的日收益率均值为: 0.000275597816601841"
paste("我们构建的组合的日收益率标准差为:",sd(port_daily_r$port_RA, na.rm = TRUE))
## [1] "我们构建的组合的日收益率标准差为: 0.00883183214352526"

组合的累计收益率(Cumulative portfolio returns)

投资者一般对日、月收益率不敏感,但是对累计收益率相对容易理解。上次的课程已经介绍过累计收益率的计算,只不过是计算单个资产,现在我们进行计算投资组合的累计收益率。

所谓累计收益率,在本例中可以理解为2014年1月1日投入1元钱,到2020年4月7日这一块钱变成了多少

port_cumulative_ret <- port_daily_r %>%
  mutate(cr = cumprod(1 + port_RA))

#作图展示
ggplot(port_cumulative_ret,aes(x=trade_date,y=cr)) + geom_line(size=1.05,alpha=0.6)+
  theme_tq() + xlab("时间") + ylab("累计收益")+
  ggtitle("沪深300和余额宝50-50投资组合累计收益")+
  geom_hline(yintercept = 1,color="red",alpha = 0.6)

50-50投资组合下的再平衡展示

思路

  1. 展示沪深300累计收益;
  2. 展示余额宝累计收益
  3. 展示不进行再平衡投资组合的累计收益
  4. 展示进行月度再平衡策略的投资组合累计收益

再平衡的核心逻辑

  • 所谓再平衡就是通过定期的买入卖出操作维持投资组合的目标配比,和定投一样是一种简单的公式化操作。

  • 再平衡的核心逻辑可以用四个点来概括,即通过公式化的定期操作,降低投资组合的波动风险,提升同等风险水平下的收益率,实现被动的高抛低吸。

对于50-50 组合来说,再平衡的操作流程: 1. 到达预定的再平衡时间,重新计算组合总净值; 2. 计算指数基金和货币基金的当前实际占比; 3. 卖出占比超过 50% 的资产,买出占比低于 50% 的资产,使比例重新回到 50:50。

具体2014年1月1日至2020年4月7日回测结果如下:

hs300_cr <- stock_long_daily_r %>%
  filter(name=="close_hs300") %>%
  mutate(cr = cumprod(1 + Ra))

yeb_cr <- stock_long_daily_r %>%
  filter(name=="close_yeb") %>%
  mutate(cr = cumprod(1 + Ra))


port_daily_r_rebanmonth <- stock_long_daily_r %>%
  tq_portfolio(assets_col = name,
               returns_col = Ra,
               weights = wts,
               rebalance_on = 'quarters',
               col_rename = "port_RA")
port_cumulative_ret_reban <- port_daily_r_rebanmonth %>%
  mutate(cr = cumprod(1 + port_RA)) 

fig<-ggplot()+
  geom_line(data=hs300_cr,mapping = aes(x=trade_date,y=cr,color="沪深300"))+
  geom_line(data=yeb_cr,mapping = aes(x=trade_date,y=cr,color='余额宝') ) +
  geom_line(data=port_cumulative_ret,mapping = aes(x=trade_date,y=cr,color='无再平衡组合'))+
  geom_line(data=port_cumulative_ret_reban,mapping = aes(x=trade_date,y=cr,color='季度再平衡组合')) +
  theme_tq() + scale_color_tq() + xlab("时间") +
  ylab("累计收益")+ ggtitle("50-50再平衡策略累计收益")
pacman::p_load(plotly)

ggplotly(fig,width = 900,height = 500)
20142016201820201.21.62.0
沪深300余额宝无再平衡组合季度再平衡组合50-50再平衡策略累计收益时间累计收益colour