3

This is a financial engineering problem for asset allocation. There are four asset class: stock, fixed income, CTA strategy and relative value strategy. Their return and covariance matrix are given. And for the result, it is expected to allocation more weight for fixed income asset and less weight for stock, not the initial weight.

The covariance matrix (4*4 matrix) is as follows(C in the code below):

sigma = [ [0.019828564,0.002498922,0.003100164,0.001272493],[0.002498922,0.005589884,0.000511829,0.000184773],[0.003100164,0.000511829,0.001559972,0.00019131],[0.001272493,0.000184773,0.00019131,0.0001306]]

sigma_p = np.matrix(sigma)

as 0,1,2,3 are 'stock_idx','CTA_idx','RelativeValue_idx','bond_idx' respectively

I am trying to find their optimal weight using the 'Risk - Parity' method, which is finally to solve the equation:

![The Risk Parity aim equation]https://i.stack.imgur.com/PdR73.png

I used the scipy.optimize in python, and the method "SLSQP" which is the only method that can apply the bounds and constraints in the solving progress. However, the mechanism did not work and always returned the initial guess, no matter how the initial guess were chosen. Codes are as follows:

def calculate_portfolio_var(W,C):
    # function that calculates portfolio risk
    sigma_p = np.sqrt(np.dot(np.dot(W.T,C),W))
    return sigma_p

def calculate_risk_contribution(W,C):
    MRC = np.dot(C,W)# Marginal Risk 
    RC = np.multiply(W,MRC)# Total Risk 
    return RC

def solve_weight(C,N): #C is the covariance matrix, and given as sigma_p before
    def risk_budget_objective(W,C,N):
        W = np.matrix(W).T        
        sig_p =  calculate_portfolio_var(W,C) # portfolio sigma      
        total_RC = calculate_risk_contribution(W,C)       
        risk_target = sig_p / N
        # sum of squared error
        J = sum(np.square(total_RC / sig_p - risk_target)) 

        print("SSE",J[0,0])
        return J[0,0]

    def total_weight_constraint(x):
        return np.sum(x)-1.0

    def long_only_constraint(x):
        return 
    w0 = [0.1, 0.2, 0.3, 0.4]
    w0 = np.matrix(w0).T 
    print('w0',w0,w0.shape)
    b_ = [(0., 1.) for i in range(N)] 
    c_ = ({'type': 'eq', 'fun': lambda W: np.sum(W) - 1.})
    optimized = scipy.optimize.minimize(risk_budget_objective, w0, (C,N), method='SLSQP', constraints=c_, bounds=b_)
    if not optimized.success: raise BaseException(optimized.message)
    w_rb = np.asmatrix(optimized.x)
    return w_rb

HW.Zoo
  • 31
  • 2
  • The expected results is to allocation more weight for fixed income asset and less weight for stock, not the initial weight. – HW.Zoo Apr 08 '19 at 03:40
  • Can you provide verifiable code . What are your "C" and "N" matrices ? Also the code for constraint definition c_ is incomplete. – Siva-Sg Apr 08 '19 at 04:21
  • Sorry, the constraint is as follows, paste error: c_ = ({'type': 'eq', 'fun': lambda W: np.sum(W) - 1.}) – HW.Zoo Apr 08 '19 at 05:33
  • and C is the covariance matrix which is the "sigma_p" in the previous context, and N is the number of the asset class, N = 4 here – HW.Zoo Apr 08 '19 at 05:35

1 Answers1

0

It seems to be a numerical precision issue , as the value of the cost function calculated is pretty small. Two ways to solve this issue. Either multiply the cost function by some scalar so that it returns a bigger value . for example J = sum(np.square(total_RC / sig_p - risk_target))*100 or set tolerance for convergence to a smaller value. The default value is 1e-6 .

optimized = minimize(risk_budget_objective, w0, (C,N), method='SLSQP', constraints=c_, bounds=b_  , options ={'ftol':1e-8})

The code works as expected after making the changes. Following is the output

matrix([[0.04780104, 0.12432431, 0.19918203, 0.62869262]]) 
Siva-Sg
  • 2,741
  • 19
  • 27