1 votos

Cómo calcular la cartera óptima utilizando restricciones sectoriales en python

En este momento estoy investigando CVXPY.

El objetivo principal sería poder calcular la cartera óptima, lo que en mi opinión significaría que hay que maximizar

(rendimiento esperado - libre de riesgo) / volatilidad

Para hacerlo más sencillo, me gustaría eliminar el riesgo de la ecuación (de todos modos es casi nulo en este momento).

Mi problema es el siguiente: me gustaría limitar las ponderaciones de la cartera en función de la asignación máxima que se puede asignar a un determinado sector.

Sector   Stocks
A        1
         2
         3
B        4
         5
         6

¿cómo puedo conseguir que el mínimo y el máximo de una asignación a cada sector se sitúe entre unas bandas?

Ya he visto este post: limitaciones del sector

Pero realmente me gustaría implementarlo con cvxpy como sugiere la respuesta. Lamentablemente no tengo idea de cómo implementar esto?

Ya tengo a mano la covarmatriz, las estimaciones de retorno y las bandas, pero simplemente no encuentro la forma de implementar esas restricciones. Cualquier ayuda será muy apreciada.

EDIT: He hecho lo que he podido y me ha salido este script: gracias al comentario de @Attack68 en combinación con este documento: Optimización cuadrática de Sharpe

import cvxpy as cp
import numpy as np 

np.random.seed(101)

## NUMBER OF ASSETS
n_assets = 4

## NUMBER OF OBSERVATIONS
n_obs = 1000

## GENERATE RANDOM RETURNS
return_vec = np.random.randn(n_assets, n_obs)

## SET UP PROBLEM
C = np.asmatrix(np.cov(return_vec))          # Covar Matrix
mu = np.asmatrix(np.mean(return_vec,axis=1)) # return estimat
mu0 = -0.0075                                # risk free rate

y = cp.Variable(n_assets)                    # "weights"

A = np.asmatrix([[0.6,0.6,0,0],[-1.2,-1.2,0,0],[0,0,0.2,0.2],[0,0,-1.2,-1.2]])
bounds = np.asmatrix([0.4,0.2,0.8,0.2])

# HOW CAN I SUBSTRACT THE BOUNDS FROM ONLY THE NON-NULL VALUES? (AS FAR AS THIS WILL BE NEEDED?)
A_mod = A #- bounds.T

## CREATE CONSTRAINTS
constraints = [(mu-mu0)@y==1,
               y >= 0,
               y@A_mod >= 0]

## FORM OBJECTIVE
obj = cp.Minimize(cp.quad_form(y,C))

## FORM AND SOLVE PROBLEM
prob = cp.Problem(obj, constraints)
prob.solve()
w = y.value/sum(y.value)
w

array([0.35386785, 0.17693393, 0.4034641 , 0.06573412])

Desgraciadamente, esta solución no se ajusta a las limitaciones. ¿Qué estoy haciendo mal?

1voto

dotnetcoder Puntos 1262

Esto se hace de forma muy sencilla. Se trata de garantizar que las restricciones se presenten como parte de la forma estándar de la matriz.

Por lo general, tendrá la restricción de que todos los activos sumen uno, es decir, la ecuación matriz-vectorial:

$$ \delta^T x = 1 $$

Si quieres crear una restricción de desigualdad para los activos de un sector sólo tienes que aislarlos:

$$ \begin{bmatrix} 1 & 1 & 1 & 0 & 0 & 0 \\ -1 & -1 & -1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & 1 & 1 \\ 0 & 0 & 0 & -1 & -1 & -1 \\ \end{bmatrix} x \leq \begin{bmatrix} a_1 \\ a_2 \\ b_1 \\ b_2 \end{bmatrix}$$

A continuación, añada (apile) estas filas de matriz-vector a cualquier restricción de desigualdad existente que tenga.

1voto

user44796 Puntos 172

Para aquellos que experimentan un problema similar, aquí está la solución que funcionó para mí:

## OPTIMIZE PORTFOLIO WEIGHTS UNDER THE OBJECTIVE OF MAXIMIZING THE SHARPE RATIO
## WHILE CONSTRAINING THE WEIGHTS TO SECTOR BOUNDS
## PAPER: # ACCORDING TO: http://people.stat.sc.edu/sshen/events/backtesting/reference/maximizing%20the%20sharpe%20ratio.pdf

np.random.seed(101)

## NUMBER OF ASSETS
n_assets = 4

## NUMBER OF OBSERVATIONS
n_obs = 1000

## GENERATE RANDOM RETURNS
return_vec = np.random.randn(n_assets, n_obs)

## SET UP PROBLEM
C = np.asmatrix(np.cov(return_vec))
mu = np.asmatrix(np.mean(return_vec,axis=1))
mu0 = np.asmatrix(-0.0075)

## INITIATE WEIGHT VARIABLE
y = cp.Variable(n_assets)

# DEFINE CONSTRAINTS AND MODIFY FOR QUADRATIC PROBLEM
A = np.asmatrix([[1,1,0,0],[-1,-1,0,0],[0,0,1,1],[0,0,-1,-1]])
bounds = np.asmatrix([0.2,-0.5,0.2,-0.8])
A_mod = A - bounds.T

## CREATE CONSTRAINTS
constraints = [(mu-mu0)@y==1,
               y >= 0,
               A_mod@y.T >= 0]

## FORM OBJECTIVE
obj = cp.Minimize(cp.quad_form(y,C))

## FORM AND SOLVE PROBLEM
prob = cp.Problem(obj, constraints)
prob.solve()

## TRANSFORM FINAL WEIGHTS
w = y.value/sum(y.value)

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X