Optimización de la cartera de inversiones mediante el método Markowitz





Un ejemplo de una implementación estándar en Python para la optimización de una cartera de inversiones utilizando el método Markowitz. Hay muchas implementaciones de este método. Incluyendo Python. Implementado nuevamente (ver enlace en GitHub ).



Fuentes



Tomemos un poco de teoría de estas fuentes:

Mejor cartera de inversión a través de la simulación de Monte Carlo en la teoría de cartera de Python

Markowitz (Wikipedia)



Descarga de datos sobre cotizaciones



Usamos datos del servicio Yahoo.Finance



! pip install yfinance
import yfinance as yf




Tomamos varias acciones del mercado estadounidense durante los últimos 3 meses.



data = yf.download(['AAPL','GE','BAC','AMD','PLUG','F'],period='3mo')




Tasas de cierre



Usaremos tasas de cierre diarias en nuestros cálculos.



closeData = data.Close
closeData








Gráficos del curso



import matplotlib.pyplot as plt

for name in closeData.columns:
    closeData[name].plot()
    plt.grid()
    plt.title(name)
    plt.show()




























Cambio de rumbo



A continuación, necesita cambios relativos al día anterior.



dCloseData = closeData.pct_change()
dCloseData








Gráficos de cambios de tasa relativa





for name in dCloseData.columns:
    dCloseData[name].plot()
    plt.title(name)
    plt.grid()
    plt.show()




























Rendimiento medio



Rendimiento diario promedio de cada acción para calcular el rendimiento de la cartera.



dohMean = dCloseData.mean()
dohMean








Covarianza





Para calcular el riesgo de la cartera, se requiere una matriz de covarianza.



cov = dCloseData.cov()
cov








Cartera aleatoria



Generaremos carteras aleatorias. En ellos, la suma de las acciones es igual a 1 (uno).



import numpy as np

cnt = len(dCloseData.columns)

def randPortf():
    res = np.exp(np.random.randn(cnt))
    res = res / res.sum()
    return res

r = randPortf()
print(r)
print(r.sum())




[0.07519908 0.07594622 0.20932539 0.40973202 0.1234458  0.10635148]
1.0




Rentabilidad de la cartera



El rendimiento de la cartera se calcula como la suma de las acciones de los rendimientos de cada acción de la cartera.



def dohPortf(r):
    return np.matmul(dohMean.values,r)

r = randPortf()
print(r)
d = dohPortf(r)
print(d)




[0.0789135  0.13031559 0.25977124 0.21157419 0.13506695 0.18435853]
0.006588795350151513




Riesgo de cartera



Calculamos el riesgo de la cartera a través de productos matriciales de acciones de cartera y matrices de covarianza.



def riskPortf(r):
    return np.sqrt(np.matmul(np.matmul(r,cov.values),r))

r = randPortf()
print(r)
rs = riskPortf(r)
print(rs)




[0.10999361 0.13739338 0.20412889 0.13648828 0.24021123 0.17178461]
0.02483674110724784




Nube de cartera



Generemos un conjunto de carteras y mostremos el resultado en un gráfico de riesgo-rendimiento. Encontremos los parámetros de la cartera óptima para el riesgo mínimo y el ratio máximo de Sharpe. Comparemos con los datos de la cartera promedio.




risk = np.zeros(N)
doh = np.zeros(N)
portf = np.zeros((N,cnt))

for n in range(N):
    r = randPortf()

    portf[n,:] = r
    risk[n] = riskPortf(r)
    doh[n] = dohPortf(r)

plt.figure(figsize=(10,8))

plt.scatter(risk*100,doh*100,c='y',marker='.')
plt.xlabel(', %')
plt.ylabel(', %')
plt.title(" ")

min_risk = np.argmin(risk)
plt.scatter([(risk[min_risk])*100],[(doh[min_risk])*100],c='r',marker='*',label=' ')

maxSharpKoef = np.argmax(doh/risk)
plt.scatter([risk[maxSharpKoef]*100],[doh[maxSharpKoef]*100],c='g',marker='o',label=' - ')

r_mean = np.ones(cnt)/cnt
risk_mean = riskPortf(r_mean)
doh_mean = dohPortf(r_mean)
plt.scatter([risk_mean*100],[doh_mean*100],c='b',marker='x',label=' ')

plt.legend()

plt.show()








Visualicemos los datos de las carteras encontradas.



import pandas as pd

print('----------   ----------')
print()
print(" = %1.2f%%" % (float(risk[min_risk])*100.))
print(" = %1.2f%%" % (float(doh[min_risk])*100.)) 
print()
print(pd.DataFrame([portf[min_risk]*100],columns=dCloseData.columns,index=[', %']).T)
print()

print('----------    ----------')
print()
print(" = %1.2f%%" % (float(risk[maxSharpKoef])*100.))
print(" = %1.2f%%" % (float(doh[maxSharpKoef])*100.)) 
print()
print(pd.DataFrame([portf[maxSharpKoef]*100],columns=dCloseData.columns,index=[', %']).T)
print()

print('----------   ----------')
print()
print(" = %1.2f%%" % (float(risk_mean)*100.)) 
print(" = %1.2f%%" % (float(doh_mean)*100.)) 
print()
print(pd.DataFrame([r_mean*100],columns=dCloseData.columns,index=[', %']).T)
print()




----------   ----------

 = 1.80%
 = 0.59%

        , %
AAPL  53.890706
AMD   12.793389
BAC    4.117541
F     16.547201
GE    10.945462
PLUG   1.705701

----------    ----------

 = 2.17%
 = 0.88%

        , %
AAPL  59.257114
AMD    8.317192
BAC    2.049882
F      8.689935
GE     4.772159
PLUG  16.913719

----------   ----------

 = 2.33%
 = 0.68%

        , %
AAPL  16.666667
AMD   16.666667
BAC   16.666667
F     16.666667
GE    16.666667
PLUG  16.666667




conclusiones



Repetimos el método clásico de calcular las acciones de una cartera de inversiones. Obtuvimos resultados muy específicos.



La optimización de la cartera mediante el método Markowitz presupone la conservación de parámetros en el futuro (correlaciones entre instrumentos individuales y su nivel de rentabilidad). Pero esto no está garantizado. Esto se comprobará en los siguientes trabajos.



Está claro que no se debe esperar un resultado positivo de la verificación anterior. Pero luego puedes buscar cómo modificar el método Markowitz para obtener un ingreso más garantizado en el futuro. Aquí hay un tema para otro estudio.



All Articles