При использовании scipy.optimize и метода «SLSQP» конечный результат остается на начальном значении - PullRequest
3 голосов
/ 08 апреля 2019

Это проблема финансового инжиниринга для распределения активов.Существует четыре класса активов: акции, фиксированный доход, стратегия CTA и стратегия относительной стоимости.Даны их возврат и ковариационная матрица.В результате ожидается, что для актива с фиксированным доходом будет выделен больший вес, а для запаса - меньший, а не начальный вес.

Ковариационная матрица (матрица 4 * 4) выглядит следующим образом (C в коде).ниже):

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)

, поскольку 0,1,2,3 равны 'stock_idx', 'CTA_idx', 'RelativeValue_idx', 'bond_idx' соответственно

Я пытаюсь найти их оптимальныевес, используя метод «Риск-Паритет», который, наконец, должен решить уравнение:

! [Уравнение цели Паритет риска] https://i.imgur.com/9nxx7xU.png

Я использовал scipy.optimize в Python,и метод "SLSQP", который является единственным методом, который может применять границы и ограничения в процессе решения.Однако механизм не работал и всегда возвращал первоначальное предположение, независимо от того, как было выбрано первоначальное предположение.Коды следующие:

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

1 Ответ

0 голосов
/ 08 апреля 2019

Кажется, это проблема числовой точности, так как значение вычисленной функции стоимости довольно мало. Два способа решить эту проблему. Либо умножьте функцию стоимости на некоторый скаляр, чтобы он вернул большее значение. например J = sum(np.square(total_RC / sig_p - risk_target))*100 или установить допуск для сходимости к меньшему значению. Значением по умолчанию является 1e-6.

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

Код работает должным образом после внесения изменений. Ниже выводится

matrix([[0.04780104, 0.12432431, 0.19918203, 0.62869262]]) 
...