Estoy buscando calcular la cartera de tangencia de la frontera eficiente, pero teniendo en cuenta min_allocations
y max_allocations
para los pesos de activos en la cartera. Estas restricciones me hacen pensar que necesito usar una herramienta de optimización como cvxopt
. La cartera de tangencia es la cartera que maximiza el ratio de Sharpe y creo que calcular la cartera de tangencia requiere los inputs compute_tanp(exp_ret_vec, cov_mat, min_allocations, max_allocations, rf)
.
Estas notas de clase pueden transformar el problema de optimización anterior al formato cuadrático estándar que se muestra a continuación, pero no estoy seguro de cómo formar correctamente las matrices para este enfoque.
¿Cómo formo las matrices para usar correctamente cvoxpt
y encontrar la cartera con el máximo ratio de Sharpe? También estoy abierto a otras técnicas para calcular la cartera de tangencia con restricciones.
A continuación tengo una función de trabajo que encontrará los pesos de la cartera eficiente $W$ cuando se pase un retorno objetivo deseado. Utiliza cvxopt
para manejar la optimización de la forma:
import pandas as pd
import numpy as np
import cvxopt as opt
def compute_ep(target_ret, exp_ret_vec, cov_mat, min_allocations, max_allocations):
"""
calcula la cartera eficiente con mínima varianza para un retorno objetivo dado
"""
# número de activos
n = len(exp_ret_vec)
one_vec = np.ones(n)
# objetivo
# minimizar (0.5)x^TPx _ q^Tx
P = opt.matrix(cov_mat.values) # matriz de covarianza
q = opt.matrix(np.zeros(n)) # cero
# restricciones Gx <= h
# >= retorno objetivo, >= mínimas asignaciones, <= máximas asignaciones
G = opt.matrix(np.vstack((-exp_ret_vec,-np.identity(n), np.identity(n))))
h = opt.matrix(np.hstack((-target_ret,-min_allocations, max_allocations)))
# restricciones Ax = b
A = opt.matrix(np.ones(n)).T
b = opt.matrix(1.0) # sum(w) = 1; no es neutral en el mercado
# optimización convexa
opt.solvers.options['show_progress'] = False
sol = opt.solvers.qp(P, q, G, h, A, b)
weights = pd.Series(sol['x'], index = cov_mat.index)
w = pd.DataFrame(weights, columns=['peso'])
return(w)