https://www.joinquant.com/community/post/detailMobile?postId=15527&page=&limit=20&replyId=&tag=

目前看到的,介绍和改进风险评价模型最详细的文章。

核心部分摘录

1、主成分风险平价模型本质上是对资产组合的主成分风险因子进行风险平价配置,因此先对传统风险平价模型做个简单介绍。

R1.png

主成分分析是一种基于降维思想把多个资产利用数学变换转化为少数几个主成分(即综合变量)的多元统计分析方法,这些主成分能够反映原始资产的大部分信息,更具有现实意义,通常表现为原始资产的线性组合,为使得这些主成分所包含的信息互不重叠,要求各主成分之间互不相关。本报告模型的基本思路是运用主成分分析对投资组合中的标的资产进行旋转,提取所有不相关的资产进行风险平价模型分析,最后反推确定原资产的投资权重。

R2.png

2、get_smart_weight函数

get_smart_weight函数中参数cov_adjusted代表是否对协方差矩阵的估计做出修正,从而对预估风险做出修正,本文的后续将对此进行讨论。

get_smart_weight函数中的的fun1用来求解传统风险平价模型,fun2用来求解主成分风险平价模型。

a为资产收益率协方差矩阵的特征值,b为对应的特征向量。

def get_smart_weight(pct, method='risk parity', cov_adjusted=False, wts_adjusted=False):
    if cov_adjusted == False:
        #协方差矩阵
        cov_mat = pct.cov()
    else:
        #调整后的半衰协方差矩阵
        cov_mat = pct.iloc[:len(pct)/4].cov()*(1/10.) + pct.iloc[len(pct)/4+1:len(pct)/2].cov()*(2/10.) +\
            pct.iloc[len(pct)/2+1:len(pct)/4*3].cov()*(3/10.) + pct.iloc[len(pct)/4*3+1:].cov()*(4/10.)
    if not isinstance(cov_mat, pd.DataFrame):
        raise ValueError('cov_mat should be pandas DataFrame!')
        
    omega = np.matrix(cov_mat.values)  # 协方差矩阵

    a, b = np.linalg.eig(np.array(cov_mat)) #a为特征值,b为特征向量
    a = matrix(a)
    b = matrix(b)
    # 定义目标函数
    
    def fun1(x):
        tmp = (omega * np.matrix(x).T).A1
        risk = x * tmp/ np.sqrt(np.matrix(x) * omega * np.matrix(x).T).A1[0]
        delta_risk = [sum((i - risk)**2) for i in risk]
        return sum(delta_risk)
    
    def fun2(x):
        tmp = (b**(-1) * omega * np.matrix(x).T).A1
        risk = (b**(-1)*np.matrix(x).T).A1 * tmp/ np.sqrt(np.matrix(x) * omega * np.matrix(x).T).A1[0]
        delta_risk = [sum((i - risk)**2) for i in risk]
        return sum(delta_risk)
    
    # 初始值 + 约束条件 
    x0 = np.ones(omega.shape[0]) / omega.shape[0]  
    bnds = tuple((0,None) for x in x0)
    cons = ({'type':'eq', 'fun': lambda x: sum(x) - 1})
    options={'disp':False, 'maxiter':1000, 'ftol':1e-20}
        
    if method == 'risk parity':
        res = minimize(fun1, x0, bounds=bnds, constraints=cons, method='SLSQP', options=options)
    elif method == 'pc risk parity':
        res = minimize(fun2, x0, bounds=bnds, constraints=cons, method='SLSQP', options=options)
    else:
        raise ValueError('method error!!!')
        
    # 权重调整
    if res['success'] == False:
        # print res['message']
        pass
    wts = pd.Series(index=cov_mat.index, data=res['x'])
    
    if wts_adjusted == True:
        wts[wts < 0.0001]=0.0
        wts = wts / wts.sum()
    elif wts_adjusted == False:
        wts = wts / wts.sum()
    else:
        raise ValueError('wts_adjusted should be True/False!')
        
    risk = pd.Series(wts * (omega * np.matrix(wts).T).A1 / np.sqrt(np.matrix(wts) * omega * np.matrix(wts).T).A1[0],index = cov_mat.index)
    risk[risk<0.0] = 0.0
    return wts,risk

3、引入预期走势估计

趋势跟踪是一种利用在不同市场交易的长期变化进行投资的交易技术,可应用于所有时间交易模型。其基本假设是市场会保持上涨或者下跌的趋势,即在上涨时做多,在下跌时做空,并预期这种趋势会继续保持。本文以简单的均线法为例,测算预期走势估计对资产配置模型的改进作用。具体的,当资产价格上穿周期移动平均线时,可以判断为买入信号;当资产价格下穿周期移动平均线时,可以判断为卖出信号。

R3.png

虽然移动平均线所反映的信息存在一定的时滞性,但移动平均线是对历史趋势的有效呈现, 在一定程度上可以降低噪音对市场趋势判断的负面影响。

本文以月末资产价格为代理变量进行研究,均线窗口期为3个月,当预期走势看空时,选择卖出该资产,并以无风险资产(日收益率简化为1.25%%)进行替代。