<jupyter_start><jupyter_text>Selección de portafolios usando simulación Montecarlo > Durante el curso, específicamente en los módulos dos y tres, elaboramos toda la fundamentación de la teoría moderna de portafolios de Markowitz. Ésta se basa en la existencia de una línea especial en el espacio de rendimiento esperado vs. volatilidad, llamada **frontera de mínima varianza**.> Al finalizar el módulo 3, vimos que no importa la cantidad de activos riesgosos que se tengan, si encontramos dos portafolios sobre la frontera eficiente, podemos reconstruirla. Dos portafolios importantes que hallamos en el curso fueron:> - **Portafolio de mínima varianza**: minimizando la varianza.> - **Portafolio eficiente en media varianza**: maximizando el radio de Sharpe.> Por otra parte, resolver problemas de optimización cuando la cantidad de variables crece, se vuelve un problema complejo, computacionalmente hablando. Así que desarrollar métodos alternativos a la optimización que nos permitan encontrar los anteriores portafolios es de gran interés...  1. Descargamos activos de la BMVPor simplicidad, y para entender las ideas alrededor de la selección de portafolios usando simulación montecarlo, utilizaremos únicamente tres activos de la BMV: Cemex, Grupo Carso y Grupo Financiero Banorte. 1.1. Descargar precios mensuales ajustados en el cierre para los tres activos mencionados anteriormente en los últimos 5 años:<jupyter_code># Importar librerías
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

%matplotlib inline
# Función para descargar precios de cierre ajustados:
def get_adj_closes(tickers, start_date=None, end_date=None, freq='m'):
    # Fecha inicio por defecto (start_date='2010-01-01') y fecha fin por defecto (end_date=today)
    # Descargamos DataFrame con todos los datos
    closes = web.YahooDailyReader(symbols=tickers, start=start_date, end=end_date, interval=freq).read()['Adj Close']
    # Se ordenan los índices de manera ascendente
    closes.sort_index(inplace=True)
    return closes
# Descargar precios y graficar
closes = get_adj_closes(['CEMEXCPO.MX', 'GFNORTEO.MX', 'GCARSOA1.MX'],
                        start_date='2014-05-01',
                        end_date='2019-04-01')
closes.plot(grid=True)<jupyter_output><empty_output><jupyter_text>1.2. A partir de los precios, obtener los rendimientos mensuales:<jupyter_code># Obtener rendimientos mensuales y graficar
ret = closes.pct_change().dropna()
ret.plot(grid=True)<jupyter_output><empty_output><jupyter_text>1.3. Finalmente, a partir de los rendimientos mensuales, estimar la tendencia central de los rendimientos (rendimiento esperado), y caracterizar el riesgo de los activos (varianzas y covarianzas)<jupyter_code># Resumen: rendimiento medio mensual y volatilidad
summary = pd.DataFrame({'RE':ret.mean(), 'Vol':ret.std()})
summary
# Matriz de covarianza
cov = ret.cov()
cov
# Matriz de correlación
corr = ret.corr()
corr<jupyter_output><empty_output><jupyter_text>___ 2. Selección de portafolios mediante montecarloAntes de continuar, consultamos la tasa libre de riesgo al día de hoy en [Banxico](http://www.banxico.org.mx/):<jupyter_code># Tasa libre de riesgo
rf = 0.082/12
rf<jupyter_output><empty_output><jupyter_text>¿Alguien tiene alguna idea de lo que es simulación montecarlo?En cuanto a la selección de portafolios, lo que hacemos es simular una gran cantidad de posibles portafolios que se pueden construir con los activos dados (generamos muchas ponderaciones posibles), y calculamos su rendimiento esperado y volatilidad para dibujarlos, y así poder identificar objetos de interés:- frontera eficiente;- portafolio de mínima varianza;- portafolio EMV...<jupyter_code># Definimos el número de portafolios que simularemos, y la cantidad de activos que tenemos
n_port = 10000
n_act = summary.shape[0]<jupyter_output><empty_output><jupyter_text>2.1. Generamos los portafolios<jupyter_code># Generar una matriz de pesos de n_port x n_act, tal que cada fila sume uno (recordar restricción)
w = np.random.random((n_port, n_act))
w /= w.sum(axis=1, keepdims=True)
#w#.sum(axis=1)
# Rendimientos y volatilidad de cada portafolios
Er = w.dot(summary['RE'])
s = np.sqrt((w.dot(cov).dot(w.T)).diagonal())
# Radio de Sharpe
SR = (Er-rf)/s
# Data frame de resultados
resultados = pd.DataFrame({'RE':Er,
                           'Vol': s,
                           'SR': SR,
                           'Cemex': w[:,0],
                           'GCarso': w[:,1],
                           'Banorte': w[:,2]})
resultados<jupyter_output><empty_output><jupyter_text>2.2. Aproximar portafolio de mínima varianza y portafolio eficiente en media varianza<jupyter_code># Portafolio EMV
EMV = resultados.loc[resultados['SR'].idxmax()]
# Portafolio mínima varianza
min_var = resultados.loc[resultados['Vol'].idxmin()]<jupyter_output><empty_output><jupyter_text>2.3. Dibujar todos los portafolios en el espacio de rendimiento esperado vs. volatilidad<jupyter_code># Gráfica
plt.figure(figsize=(8,6))
plt.scatter(resultados['Vol'], 
            resultados['RE'], 
            c=resultados['SR'],
            cmap='RdYlBu'
           )
plt.colorbar()
plt.xlabel('Volatility')
plt.ylabel('Rendimiento esperado')
# EMV
plt.plot(EMV['Vol'], EMV['RE'], '*r', ms=20)
# Min var
plt.plot(min_var['Vol'], min_var['RE'], '*g', ms=20)
plt.xlim([0.045, 0.07])
plt.ylim([0, 0.01])<jupyter_output><empty_output><jupyter_text>3. Comparar con los resultados obtenidos por optimización 3.1. Portafolio de mínima varianza<jupyter_code># Importamos funcion minimize del modulo optimize de scipy
import scipy.optimize as opt
## Construcción de parámetros
# 1. Sigma: matriz de varianza-covarianza
Sigma = cov
# 2. Eind: rendimientos esperados activos individuales
Eind = summary['RE']
# Función objetivo
def var(w, Sigma):
    return w.dot(Sigma).dot(w)
# Dato inicial
n = len(Eind)
w0 = np.ones((n,))/n
# Cotas de las variables
bnds = ((0,1),)*n
# Restricciones
cons = {'type': 'eq', 'fun': lambda w: np.sum(w)-1}
# Portafolio de mínima varianza
min_var_opt = opt.minimize(var, w0, args=(Sigma,), bounds=bnds, constraints=cons)
min_var_opt
# Comparar
min_var<jupyter_output><empty_output><jupyter_text>3.2. Portafolio EMV<jupyter_code># Función objetivo
def m_sharpe(w, Sigma, rf, Eind):
    Erp = Eind.dot(w)
    sp = np.sqrt(w.dot(Sigma).dot(w))
    return -(Erp - rf)/sp
# Dato inicial
n = len(Eind)
w0 = np.ones((n,))/n
# Cotas de las variables
bnds = ((0,1),)*n
# Restricciones
cons = {'type': 'eq', 'fun': lambda w: np.sum(w)-1}
# Portafolio EMV
EMV_opt = opt.minimize(m_sharpe, w0, args=(Sigma, rf, Eind), bounds=bnds, constraints=cons)
EMV_opt
# Comparar
EMV<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10563904180925457, 'fraction_numerical': 0.013688439220354114, 'mean_word_length': 4.830008673026886, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '664559', 'license': 'MIT', 'n_tokens_mistral': 2485, 'n_tokens_neox': 2419, 'n_words': 692, 'path': 'Adicional1_PortafoliosMontecarlo.ipynb', 'repo_name': 'apaolavr/PorInv2019-1', 'size': '6721'}