代码如下:
####### step1import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom sklearn.preprocessing import StandardScalerfrom scipy.optimize import minimize# 读取收盘价数据def read_data(file):s="C:/Users\Anita\Desktop"file_address=s+filedf= pd.read_excel(file_address,sheetname="data") # 保证金比例marginal_cost=[0.15,0.3,0.02,0.15,1,1]# 删除前两行说明行df.drop(0,inplace=True)df.drop(1,inplace=True)# 删除最后一行的3月数据df.drop(1497,inplace=True)# 把日期列设置为索引df.set_index('Date',inplace=True)# 缺失值检验:没有缺失值df.isnull().any() # 把日数据转换为月数据period_type = 'M'__df= df.resample(period_type).last()monthly_df=pd.concat([df.iloc[0,0::].T,__df.T],axis=1).Treturn monthly_df# 计算对数收益率def calculate_log_return(file):data=read_data(file)variable_list=['IF00.CFE','IC00.CFE','TF00.CFE','AU00.SHF','159920.OF','511880.SH']for j in variable_list:data['return_'+str(j)]=0.0for i in range(1,len(data)):data['return_'+str(j)][i]=np.log(float(data[j][i])/float(data[j][i-1]))return data.iloc[1::,0::]# 将收益率进行标准化处理,形成新的表格std_datadef standardlize_process(file):data=calculate_log_return(file)scaler=StandardScaler()scaler.fit(data)column_list=['IF00.CFE','IC00.CFE','TF00.CFE','AU00.SHF','159920.OF','511880.SH','return_IF00.CFE','return_IC00.CFE','return_TF00.CFE','return_AU00.SHF','return_159920.OF','return_511880.SH']std_data=pd.DataFrame(scaler.transform(data),columns=column_list,index=data.index)std_data=std_data.iloc[:,6::] return std_data#资产收益率序列相关性检验:滚动计算资产的协方差矩阵def cov_asset(file):return standardlize_process(file).rolling(window=12).cov().iloc[66::,0::] # 风险度量期间为一年,故滚动窗口设置为12个月,从-12月末到-02月末共计 63个月,每个月6条记录,共63*6=378条记录# 协方差矩阵cov_matrix=np.matrix(cov_asset("\数据.xlsx"))##### step2# 计算每类资产对总资产组合的风险贡献def calculate_risk_contribution(weight,one_cov_matrix):weight=np.matrix(weight) sigma=np.sqrt(weight*one_cov_matrix*np.matrix(weight).T)# 边际风险贡献 Marginal Risk Contribution (MRC)MRC=one_cov_matrix*weight.T/sigma# 风险贡献 Risk Contribution (RC)RC=np.multiply(MRC,weight.T)return RC# 定义优化问题的目标函数,即最小化资产之间的风险贡献差def risk_budget_objective(x_weight,parameters): # x_weight是带求解的各个大类资产下面子标的的权重,parameters是下面函数中的args=[one_cov_matrix,RC_set_ratio]参数传递# x_weight的初始值是函数 calculate_portfolio_weight中的 weight0# 协方差矩阵,也即函数 calculate_portfolio_weight 中传递的 args中的第一个参数 one_cov_matrixone_cov_matrix=parameters[0]# 风险平价下的目标风险贡献度向量,也即函数 calculate_portfolio_weight 中传递的 args中的第二个参数 RC_set_ratioRC_target_ratio=parameters[1] # RC_target为风险平价下的目标风险贡献,一旦参数传递以后,RC_target就是一个常数,不随迭代而改变sigma_portfolio=np.sqrt(x_weight*one_cov_matrix*np.matrix(x_weight).T)RC_target=np.asmatrix(np.multiply(sigma_portfolio,RC_target_ratio))# RC_real是 每次迭代以后最新的真实风险贡献,随迭代而改变RC_real=calculate_risk_contribution(x_weight,one_cov_matrix)sum_squared_error= sum(np.square(RC_real-RC_target.T))[0,0] return sum_squared_error# 优化问题的第一个约束条件def constraint1(x_weight):return np.sum(x_weight)-1.0# 优化问题的第二个约束条件def constraint2(x_weight):return x_weight# 根据资产预期目标风险贡献度来计算各资产的权重def calculate_portfolio_weight(RC_set_ratio,one_cov_matrix):weight0=[0.2, 0.2, 0.2, 0.1, 0.1, 0.2] cons=({'type': 'eq', 'fun': constraint1},{'type': 'ineq', 'fun': constraint2})res= minimize(risk_budget_objective, weight0, args=[one_cov_matrix,RC_set_ratio], method='SLSQP',constraints=cons, options={'disp': True})weight_final= np.asmatrix(res.x)return weight_finaldef calculate_monthly_weight(RC_set_ratio):result={}year=['','','','','','','']month=['01','02','03','04','05','06','07','08','09','10','11','12']for i in range(63):date=str(+int((i+11)/12))+'-'+ month[(i-1)%12]one_cov_matrix=cov_matrix[i*6:(i*6+6)]result[date]=pd.DataFrame(calculate_portfolio_weight(RC_set_ratio,one_cov_matrix)).iloc[0,0::]#xx=pd.DataFrame(result,index=date)return result## 计算风险平价下每月的资产配置权重 # 假设1:四个资产的风险贡献度相等# 假设2:同类资产下每个标的的风险贡献相同df_monthly_weight=pd.DataFrame(calculate_monthly_weight([0.25/3, 0.25/3, 0.25, 0.25, 0.25/3, 0.25])).Tdf_monthly_weight.columns=['IF00.CFE','IC00.CFE','TF00.CFE','AU00.SHF','159920.OF','511880.SH']df_monthly_weight#### step3:回测Backtest## 基于过去一年的风险分配权重,计算各资产的月度收益率def calculate_RC_monthly_return(file):std_df=standardlize_process(file) date_list=[]for i in range(63):date_list.append(str(+int((i+11)/12))+'-'+ month[(i-1)%12])#date_list_std_df=std_df.iloc[11::,0::].T_std_df.columns=date_list__std__df=_std_df.T__std__df['key']=__std__df.indexdf_monthly_weight['key']=df_monthly_weight.index# 合并表,将月收益数据和权重表横向合并monthly_return=pd.merge(__std__df, df_monthly_weight,on='key')monthly_return.set_index('key',inplace=True)column_list=['return_IF00.CFE','return_IC00.CFE','return_TF00.CFE','return_AU00.SHF','return_159920.OF','return_511880.SH','IF00.CFE','IC00.CFE','TF00.CFE','AU00.SHF','159920.OF','511880.SH']# 计算加权后的各资产收益率:权重乘以资产收益率for i in range(6):monthly_return['weight'+'_'+column_list[i]]=monthly_return[column_list[i]]*monthly_return[column_list[i+6]]monthly__return=monthly_return.iloc[0::,-6::]monthly__return['all_portfolio_return']=monthly__return.apply(lambda x: x.sum(), axis=1)# 用债券收益率作为benchmarkmonthly__return['benchmark']=monthly_return['return_TF00.CFE']return monthly__return## 收益回测,模型评价def backtest_model1(monthly_data):# 设置评价指标total_return={}annual_return={}excess_return={}annual_volatility={}sharpe={}information_ratio={}win_prob={}drawdown={}tr={}# 单独计算benchmark的相关指标portfolio_list=['weight_return_IF00.CFE','weight_return_IC00.CFE','weight_return_TF00.CFE','weight_return_AU00.SHF','weight_return_159920.OF','weight_return_511880.SH','all_portfolio_return']bench_total_return=(monthly_data['benchmark']+1).T.cumprod()[-1]-1 bench_annual_return=(float(bench_total_return)+1.0)**(1./(5+1/6))-1 # 每一种指标的具体构建方法for i in portfolio_list: monthly=monthly_data[i] total_return[i]=(monthly+1).T.cumprod()[-1]-1 annual_return[i]=(float(total_return[i])+1.0)**(1./(5+1/6))-1 annual_volatility[i]=monthly.std() sharpe[i]=(annual_return[i]-bench_annual_return)/annual_volatility[i] drawdown[i]=monthly.min() win_excess=monthly-monthly_data['benchmark'] win_prob[i]=win_excess[win_excess>0].count()/float(len(win_excess))# 将字典转换为dataframear=pd.DataFrame(annual_return,index=monthly.index).drop_duplicates().Ttr=pd.DataFrame(total_return,index=monthly.index).drop_duplicates().Tav=pd.DataFrame(annual_volatility,index=monthly.index).drop_duplicates().Tsp=pd.DataFrame(sharpe,index=monthly.index).drop_duplicates().Tdd=pd.DataFrame(drawdown,index=monthly.index).drop_duplicates().Twp=pd.DataFrame(win_prob,index=monthly.index).drop_duplicates().Tar['key']=ar.index #年化收益tr['key']=tr.index #累积收益av['key']=av.index #年化波动sp['key']=sp.index #夏普比率dd['key']=dd.index #最大回撤wp['key']=wp.index #胜率backtest_df=pd.merge(ar,pd.merge(tr,pd.merge(av,pd.merge(sp,pd.merge(dd,wp,on='key'),on='key'),on='key'),on='key'),on='key')backtest_df.set_index('key',inplace=True)backtest_df.columns=['annual return','total return','annual volatility','sharpe ratio','drawdown','win prob']return backtest_dfhh=backtest_model1(calculate_RC_monthly_return("\数据.xlsx"))hh