風險

同等風險貢獻投資組合 scipy 優化不起作用

  • September 30, 2018

我正在嘗試為等風險貢獻投資組合創建一個工具,基本上遵循這篇文章(https://quantdare.com/risk-parity-in-python/),但它在最後一步(def risk_parity_weights)失敗了scipy 優化器不工作。它一直給我初始權重作為優化權重,我知道它們不是優化權重,因為即使 Excel Solver 也能夠優化它。所有其他功能均已檢查並且正確。不知道我做錯了什麼 - 請幫忙!

import pandas as pd
pd.core.common.is_list_like = pd.api.types.is_list_like
import pandas_datareader.data as web
import numpy as np
import datetime
from scipy.optimize import minimize
Tolerance = 1e-10

def calculate_risk_contribution(weights,covariances):

   #Convert weights array to numpy matrix
   weights = np.matrix(weights)

   #Calculate portfolio st.dev
   portfolio_stdev = np.sqrt(weights*covariances*weights.T)[0,0]

   #Calculate Marginal Risk Contribution of each asset
   MRC = covariances*weights.T/portfolio_stdev

   #Calculate Risk Contribution of each asset
   RC = np.multiply(MRC,weights.T)
   return RC

def risk_budget_objective_error(weights,*args):

   #Covariance table occupies the first position in args variable
   covariances = args[0]

   #State risk budgets
   assets_risk_budget = args[1]

   #Convert weights array to numpy matrix
   weights = np.matrix(weights)

   #Calculate portfolio st_dev
   portfolio_stdev = calculate_portfolio_stdev(ca_begweights,ca_cov)

   #Calculate risk contributions
   assets_risk_contribution = calculate_risk_contribution(ca_begweights,ca_cov)

   #Calculate desired risk contribution of each asset
   assets_risk_target = np.asmatrix(np.multiply(portfolio_stdev,assets_risk_budget))

   #Calculate error between desired contribution and calculated distribution of each asset
   error = sum(np.square(assets_risk_contribution - assets_risk_target.T))[0,0]

   return error

def risk_parity_weights(covariances,assets_risk_budget, initial_weights):

   #Constraints to optimization
   #sum equals 100%
   cons = ({'type':'eq','fun':lambda x: np.sum(x) - 1.0},
             {'type':'ineq','fun':lambda x: x})

   #Optimization in scipy
   optimize_result = minimize(risk_budget_objective_error,
                          x0 = initial_weights,
                          args = (covariances, assets_risk_budget),
                          method = 'SLSQP',
                          constraints = cons,
                          tol = Tolerance,
                          options = {'disp':True})

   #Get optimized weights
   weights = optimize_result.x

   return weights

risk_parity_weights(ca_cov,risk_budget_all, ca_begweights)給我

Optimization terminated successfully.    (Exit mode 0)
           Current function value: 9.54000328523598e-07
           Iterations: 1
           Function evaluations: 5
           Gradient evaluations: 1

見下面的數據

   ca_cov = array([[ 5.28024463e-06, 3.29734889e-07, -7.04781216e-08], [ 3.29734889e-07, 1.32373854e-05, 3.71807979e-08], [-7.04781216e-08, 3.71807979e-08, 3.50845569e-05]]) 

risk_budget_all = Unnamed: 1 0.333333 Unnamed: 2 0.333333 Unnamed: 3 0.333333 Name: Risk Budget, dtype: object 

ca_begweights = array([0.33333333, 0.33333333, 0.33333333]) 

除了我的評論之外,是因為您的函式正在返回已棄用的矩陣嗎?

為什麼不使用 ndarrays 重寫你的函式;

import numpy as np
ca_cov = np.array([[ 5.28024463e-06, 3.29734889e-07, -7.04781216e-08], [ 3.29734889e-07, 1.32373854e-05, 3.71807979e-08], [-7.04781216e-08, 3.71807979e-08, 3.50845569e-05]])
ca_ini_weights = np.array([0.33333333, 0.33333333, 0.33333333])

def risk_contribution(weights,covariances):
   # weights: ndarray of shape (n); covariances: ndarray of shape (n,n)
   s_dev = np.sqrt(np.einsum('i,ij,j->', weights, covariances, weights))
   risk_contrib = np.einsum('i,ij,j->i',weights, covariances, weights) / s_dev
   return risk_contrib

risk_contribution(ca_ini_weights, ca_cov):
>>> array([0.00025082, 0.00061599, 0.00158709])

當我想改進你的目標函式時,我注意到它有一個主要缺陷:

它接受weights作為參數,但隨後ca_begweights在其所有計算中使用,因此作為目標函式,它所做的只是返回初始值。在這種情況下,它返回已知的“最佳”值。

引用自:https://quant.stackexchange.com/questions/41820