Problema de construcción de cartera óptima, implementación de Python

Este documento documenta el uso de herramientas de procedimiento para resolver carteras óptimas dado el rendimiento esperado y la matriz de covarianza esperada del conjunto invertible.

Descripción del problema

La construcción de una cartera óptima es un problema de optimización con restricciones. El objetivo de la optimización es maximizar el índice de Sharpe de la cartera, y la restricción es que la suma de los pesos de los activos sea igual a 1.

implementación de Python

# construct optimized portfolio
import numpy as np
import pandas as pd
import scipy.optimize as sco

fcst_style_sharpe = pd.read_csv('fcst_style_sharpe.csv')
style_cov = pd.read_csv('style_cov.csv')

selected_col = ['mkt','smb','hml','vmg','rmw','gms','pmo','mom']
noa = len(selected_col)

style_ret = fcst_style_sharpe['fcst_ret'#* 100

weights = np.random.random(noa)
weights /= np.sum(weights)


def port_ret(weights):
    return np.sum(style_ret * weights) * 252

def port_vol(weights):
    return np.sqrt(np.dot(weights.T, np.dot(style_cov * 252, weights)))

def min_func_sharpe(weights):
    return -port_ret(weights) / port_vol(weights)
    
# maximize sharpe ratio
eweights = np.array(noa * [1. / noa,])
#bnds = tuple((0, 1) for x in range(noa))
bnds = tuple((-22for x in range(noa))
cons = ({ 'type''eq''fun'lambda x:  np.sum(x) - 1})

opts = sco.minimize(min_func_sharpe, eweights,
                    method='SLSQP', bounds=bnds,
                    constraints=cons)

opt_weight = opts['x']
opt_weight.round(4)

opts_sharpe = port_ret(opt_weight) / port_vol(opt_weight)
opts_sharpe

# plot the optimized portfolio
from lets_plot import *
LetsPlot.setup_html()

fzoo = pd.read_csv('data/fzoo.csv')

opt_style = fzoo[['trading_date','mkt']].copy()
opt_style.columns = ['trading_date','style']
opt_style['style'] = np.dot(fzoo[selected_col],opt_weight)
opt_style['style_cum'] = np.log1p(opt_style['style']/100).cumsum()

x = pd.to_datetime(opt_style['trading_date'])[-1000:]
y = opt_style['style_cum'][-1000:]/opt_style['style_cum'].iloc[-1000]
ggplot({ 'date': x, 'port': y}, aes(x='date', y='port')) + geom_line()

# minimize volatility
optv = sco.minimize(port_vol, eweights,
                    method='SLSQP', bounds=bnds,
                    constraints=cons)

bnds = tuple((01for x in weights)

cons = ({ 'type''eq''fun'lambda x:  port_ret(x) - tret},
        { 'type''eq''fun'lambda x:  np.sum(x) - 1})

%time
trets = np.linspace(0.050.5100)
tvols = []
for tret in trets:
    res = sco.minimize(port_vol, eweights, method='SLSQP',
                       bounds=bnds, constraints=cons)
    tvols.append(res['fun'])
tvols = np.array(tvols)

# plot the front
from pylab import mpl, plt
plt.style.use('seaborn-v0_8-whitegrid')
mpl.rcParams['font.family'] = 'serif'
%matplotlib inline

prets = []
pvols = []
for p in range (5000):
    weights = np.random.random(noa)
    weights /= np.sum(weights)
    prets.append(port_ret(weights))
    pvols.append(port_vol(weights))
prets = np.array(prets)
pvols = np.array(pvols)


plt.figure(figsize=(106))
plt.scatter(pvols, prets, c=prets / pvols,
            marker='o', cmap='coolwarm')
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.colorbar(label='Sharpe ratio');

tvols = np.array(tvols)

plt.figure(figsize=(106))
plt.scatter(pvols, prets, c=prets / pvols,
            marker='.', alpha=0.8, cmap='coolwarm')
plt.plot(tvols, trets, 'b', lw=4.0)
plt.plot(port_vol(opts['x']), port_ret(opts['x']),
         'y*', markersize=15.0)
plt.plot(port_vol(optv['x']), port_ret(optv['x']),
         'r*', markersize=15.0)
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.colorbar(label='Sharpe ratio')


Este artículo es publicado por mdnice multiplataforma

Supongo que te gusta

Origin blog.csdn.net/amandus/article/details/130938191
Recomendado
Clasificación