关于恒定混合型配置策略主要介绍等权重投资组合(equally weighted portfolio)和60/40投资组合策略。
- 等权重投资组合:在有n种可投资的风险资产时,保持每种资产的投资权重为1/n。该策略实质上是一种反转策略,即在一段时间内,当某类资产获得超常上涨时,其持有数量将被调低;反之将被调高。因此,资产收益呈现均值反转的规律时,该策略能够以此获利。瑞士基金管理人Marc Faber认为,最理想的资产配置策略即等权重投资组合策略,将资产等分地投资在黄金、股票、房地产或房地产股票、债券或现金上,并且认为投资者的目的不应该是获取巨额收益,而应该是在各种环境中实现资产的保值增值。
基于中国市场的测试
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 4 14:46:55 2019
@author: Administrator
"""
###
#算法实现:利用华安黄金ETF,中证全指,南华工业品指数,中证全债均分构建等权重投资组合
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
###数据处理
#导入数据
stock = pd.read_excel('C:\\Users\\Administrator\\Desktop\\大类资产配置\\数据\\等权重投资组合\\中证全指全收益.xlsx')
gold = pd.read_excel('C:\\Users\\Administrator\\Desktop\\大类资产配置\\数据\\等权重投资组合\\华安黄金ETF.xlsx')
cash = pd.read_excel('C:\\Users\\Administrator\\Desktop\\大类资产配置\\数据\\等权重投资组合\\中证全债(利息再投资).xlsx')
goods = pd.read_excel('C:\\Users\\Administrator\\Desktop\\大类资产配置\\数据\\等权重投资组合\\南华指数:综合.xlsx')
#表格整理
stock_close = pd.DataFrame(list(zip(stock['交易时间'],stock['收盘价'])))
gold_value = pd.DataFrame(list(zip(gold['交易时间'],gold['净值'])))
stock_close.columns = ['交易时间','中证全指收盘价']
gold_value.columns = ['交易时间','黄金ETF净值']
goods.columns = ['交易时间','南华指数']
cash.columns = ['交易时间','中证全债收盘价']
#数据提取(时间:2013-12-31至2018-12-31)
def getData(data):
data = data[(data['交易时间'] > pd.to_datetime('20131231')) & (data['交易时间'] <= pd.to_datetime('20181231'))]
data = data.reset_index(drop = True)
return data
stock_close = getData(stock_close)
gold_value = getData(gold_value)
goods = getData(goods)
cash = getData(cash)
#连接表格
data_1 = pd.merge(gold_value, stock_close, how='outer',on=['交易时间'])
data_2 = pd.merge(data_1, cash, how='outer',on=['交易时间'])
data = pd.merge(data_2, goods, how='outer',on=['交易时间'])
#处理缺失值
data = data.sort_values(by = '交易时间')
data = data.fillna(method='pad') #用前一个非缺失值去填充该缺失值
data = data.reset_index(drop = True)
# (由价格计算收益,无需标准化)
##标准化
#def minmaxscale(data):
# data=(data-data.min())/(data.max()-data.min())
# return data
#
#A = data['交易时间']
#data = minmaxscale(data.drop(["交易时间"],axis=1))
#data =pd.concat([A,data],axis=1)
def price_process(year,period,data):
#功能:确定单个半年期四项资产的价格
# year,period为 int
# time_0,time_1均为 string ;返回值 price为半年期交易日*4的矩阵
if period%2 == 0:
time_0 = str(year)+'1231'
time_1 = str(year+1)+'0630'
else:
time_0 = str(year)+'0630'
time_1 = str(year)+'1231'
price = data[(data['交易时间'] > pd.to_datetime(time_0)) & (data['交易时间'] <= pd.to_datetime(time_1))]
return price
def calculate_income(money,price):
# 功能:实现一个调仓期间(半年)内收入的计算
# money:int,price:一位数组(dataFrame); 返回值income:一维数组
A = price['交易时间']
price = price.drop(["交易时间"],axis=1)
p0 = price.iloc[0] #初始价格
weight = [1/p0['黄金ETF净值'],1/p0['中证全指收盘价'],1/p0['中证全债收盘价'],1/p0['南华指数']]
B = np.multiply(weight,price)
C = B['中证全指收盘价']+B['黄金ETF净值']+B['南华指数']+B['中证全债收盘价']
income = pd.concat([A,C],axis=1)
return income
year = 2013
money = 10000
income=[]
for i in range(10):
if i%2 == 1:
year = year + 1
data_i = price_process( year , i ,data)
income_i = calculate_income( money , data_i )
income.append(income_i)
money = 0.25*money*income_i.iloc[-1][1]
Income = pd.concat(income)
Income.columns = ['交易时间','收益']
plt.plot(Income['交易时间'],Income['收益'])
- 60/40投资组合:将60%的资产投资于股票,另外40%投资于债券。60/40分拆的目的是在产生回报的同时将风险降至最低,即使在市场波动期间也是如此。潜在的缺点是它可能不会产生与全股票投资组合一样高的回报。但对于那些没有高风险承受能力但仍希望增长潜力的投资者来说,这是一个不错的选择。
作者:小洋独角兽 链接:https://xueqiu.com/1609209543/124408106 来源:雪球
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
与之相类似的60/40投资组合的对应代码如下,同时实现了两个恒定混合策略的比较
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdate
#导入数据
stock = pd.read_excel('C:\\Users\\Administrator\\Desktop\\大类资产配置\\模型\\Constant and mix Strategy\\data\\中证全指全收益.xlsx')
cash = pd.read_excel('C:\\Users\\Administrator\\Desktop\\大类资产配置\\模型\\Constant and mix Strategy\\data\\中证全债(利息再投资).xlsx')
same_weight = pd.read_excel('C:\\Users\\Administrator\\Desktop\\大类资产配置\\模型\\Constant and mix Strategy\\程序\\等权重投资组合.xlsx')
#表格整理
stock_close = pd.DataFrame(list(zip(stock['交易时间'],stock['收盘价'])))
stock_close.columns = ['交易时间','中证全指收盘价']
cash.columns = ['交易时间','中证全债收盘价']
#数据提取(时间:2013-12-31至2018-12-31)
def getData(data):
data = data[(data['交易时间'] > pd.to_datetime('20131231')) & (data['交易时间'] <= pd.to_datetime('20181231'))]
data = data.reset_index(drop = True)
return data
stock_close = getData(stock_close)
cash = getData(cash)
#连接表格
data = pd.merge(stock_close, cash, how='outer',on=['交易时间'])
#处理缺失值
data = data.sort_values(by = '交易时间')
data = data.fillna(method='pad') #用前一个非缺失值去填充该缺失值
data = data.reset_index(drop = True)
#数据按特定时间提取
def price_process(year,period,data):
#功能:确定单个半年期四项资产的价格
# year,period为 int
# time_0,time_1均为 string ;返回值 price为半年期交易日*4的矩阵
if period%2 == 0:
time_0 = str(year)+'1231'
time_1 = str(year+1)+'0630'
else:
time_0 = str(year)+'0630'
time_1 = str(year)+'1231'
price = data[(data['交易时间'] > pd.to_datetime(time_0)) & (data['交易时间'] <= pd.to_datetime(time_1))]
return price
# 收入计算
def calculate_income(money,price):
# 功能:实现一个调仓期间(半年)内收入的计算
# money:int,price:一位数组(dataFrame); 返回值income:一维数组
A = price['交易时间']
price = price.drop(["交易时间"],axis=1)
p0 = price.iloc[0] #初始价格
weight = [(money*0.6)/p0['中证全指收盘价'],(money*0.4)/p0['中证全债收盘价']]
B = np.multiply(weight,price)
C = B['中证全指收盘价']+B['中证全债收盘价']
income = pd.concat([A,C],axis=1)
return income
#等权重投资
year = 2013
money = 10000
income=[]
for i in range(10):
if i%2 == 1:
year = year + 1
data_i = price_process( year , i ,data)
income_i = calculate_income( money , data_i )
income.append(income_i)
money = income_i.iloc[-1][1]
Income = pd.concat(income)#采取等权重策略所获得的收益
Income.columns = ['交易时间','收益']
Income.to_excel('6040策略.xlsx',index= False)
plt.plot(Income['交易时间'],Income['收益'])
plt.gca().xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d'))
plt.xticks(rotation=45)
plt.xlabel('day')
plt.ylabel('Income')
plt.legend()
plt.show()
##加入股票的指数以及等权重策略的收益惊醒比较,其中same_weight来自与等权重投资组合中的Income
##计算单个资产的点位(可理解为单个资产标准化的过程)
def calculate_index(start,data):
S0 = data.iloc[0]
wt = start/S0
index = np.multiply(wt,data)
return index
stock_p = calculate_index(10000,data['中证全指收盘价'])
stock_t = data['交易时间']
stock_p = pd.DataFrame(stock_p)
stock_t = pd.DataFrame(stock_t)
stock_p = pd.concat([stock_t,stock_p],axis=1)
test1 = pd.merge(Income, stock_p, how='outer',on=['交易时间'])
test = pd.merge(test1, same_weight, how='outer',on=['交易时间'])
test = test.sort_values(by = '交易时间')
test = test.fillna(method='pad') #用前一个非缺失值去填充该缺失值
test = test.reset_index(drop = True)
plt.plot(test['交易时间'],test['收益_x'],label='6040')
plt.plot(test['交易时间'],test['收益_y'],label='Equal weight')
plt.plot(test['交易时间'],test['中证全指收盘价'],label='stock')
plt.gca().xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d'))
plt.xticks(rotation=45)
plt.xlabel('day')
plt.ylabel('Income')
plt.legend()
plt.show()