# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Inclusión de un activo libre de riesgo en el portafolio

# > Vimos ya técnicas de optimización para obtener la frontera eficiente. También vimos como obtenerla mediante simulación montecarlo.
#
# > En esta clase obtendremos la frontera eficiente de un portafolio que inlcuye un bono (activo libre de riesgo).

#importar los paquetes que se van a usar
import pandas as pd
import pandas_datareader.data as web
import numpy as np
import datetime
from datetime import datetime
import scipy.stats as stats
import scipy as sp
import scipy.optimize as scopt
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn.covariance as skcov
# %matplotlib inline
#algunas opciones para Python
pd.set_option('display.notebook_repr_html', True)
pd.set_option('display.max_columns', 6)
pd.set_option('display.max_rows', 10)
pd.set_option('display.width', 78)
pd.set_option('precision', 3)


# ## 0. Descargar precios de cierre

def get_historical_closes(ticker, start_date, end_date=None):
    #closes = web.DataReader(name=ticker, data_source='yahoo', start=start_date, end=end_date).sort_index('major_axis')
    closes = web.YahooDailyReader(symbols=ticker, start=start_date, end=end_date).read()
    closes.set_axis(closes.loc['date',:,ticker[0]].values, axis=1, inplace=True)
    closes = closes.loc['adjclose'].sort_index().dropna()
    closes = pd.DataFrame(np.array(closes.as_matrix(), dtype=np.float64), columns=ticker, index=closes.index)
    closes.index.name = 'Date'
    return closes
def calc_daily_ret(closes):
    return np.log(closes/closes.shift(1)).dropna()


# Descargar precios de cierre de Apple, Amazon, Microsoft, American Airlines y Coca-Cola, entre el primero de enero del 2016 y hoy.

tickers = ['AAPL', 'AMZN', 'MSFT', 'AA', 'KO']
start_date = '2016-01-01'
closes = get_historical_closes(tickers, start_date=start_date)
closes.plot(figsize=(8,6));

# ## 1. Formulación de riesgo del portafolio

# Obtener rendimientos

daily_ret = calc_daily_ret(closes)
daily_ret.plot(figsize=(8,6));

# Agregar rendimientos fijos del bono...

daily_ret_b = calc_daily_ret(closes)
daily_ret_b.loc[:,'BOND'] = 0.015/252
daily_ret_b

# Media

daily_ret_mean = daily_ret.mean()
daily_ret_mean

daily_ret_b_mean = daily_ret_b.mean()
daily_ret_b_mean

# Covarianza

cov_matrix = daily_ret.cov()
cov_matrix

cov_matrix_b = daily_ret_b.cov()
cov_matrix_b

robust_cov_matrix= pd.DataFrame(skcov.ShrunkCovariance().fit(daily_ret).covariance_,columns=daily_ret.columns,index=daily_ret.columns)
robust_cov_matrix

robust_cov_matrix_b= pd.DataFrame(np.insert((np.insert(skcov.ShrunkCovariance().fit(daily_ret).covariance_,len(tickers),0,axis=0)),len(tickers),0,axis=1)
,columns=daily_ret_b.columns,index=daily_ret_b.columns)
robust_cov_matrix_b

# ## 2. Optimización de portafolios

# ### Portafolio sin bono

num_portfolios = 200000 # Cantidad de portafolios a simular
r=0.015/252             # Tasa libre de riesgo
num_stocks = len(tickers)

# +
results = np.zeros((num_portfolios, 3+num_stocks)) # Inicialización de vector de resultados

weights = np.random.random((num_portfolios, num_stocks))
weights /= np.sum(weights, axis=1)[:, None]

#Rendimiento y volatilidad
portfolio_return = weights.dot(daily_ret_mean) * 252
portfolio_std_dev = np.zeros(num_portfolios)
for i in range(num_portfolios):
    portfolio_std_dev[i]=np.sqrt(252*(((weights[i,:]).dot(robust_cov_matrix)).dot(weights[i,:].T))) 

#Resultados
results[:,0] = portfolio_return
results[:,1] = portfolio_std_dev
#Sharpe
results[:,2] = (results[:,0]-r) / results[:,1]
#Iteraciones
results[:,3:] = weights

results_frame = pd.DataFrame(results,columns=(['Rendimiento','SD','Sharpe']+list(daily_ret.columns)))
results_frame
# -

#Sharpe Ratio
max_sharpe_port = results_frame.iloc[results_frame['Sharpe'].idxmax()]
#Menor SD
min_vol_port = results_frame.iloc[results_frame['SD'].idxmin()]

plt.scatter(results_frame.SD,results_frame.Rendimiento,c=results_frame.Sharpe,cmap='RdYlBu')
plt.xlabel('Volatility')
plt.ylabel('Returns')
plt.colorbar()
#Sharpe Ratio
plt.scatter(max_sharpe_port[1],max_sharpe_port[0],marker=(5,1,0),color='r',s=500);
#Menor SD
plt.scatter(min_vol_port[1],min_vol_port[0],marker=(5,1,0),color='g',s=500);

max_sharpe_port

min_vol_port

# ### Portafolio con bono

# +
num_stocks_b=len(tickers)+1

results = np.zeros((num_portfolios, 3+num_stocks_b)) # Inicialización de vector de resultados

weights_b = np.random.random((num_portfolios,num_stocks_b))
weights_b /= np.sum(weights_b, axis=1)[:, None]
# Es importante ver qué pasa si solo se incluye el bono (no riesgo)
weights_b[0,:]=np.zeros(num_stocks_b) 
weights_b[0,:][-1]=1

#Rendimiento y volatilidad
portfolio_return = weights_b.dot(daily_ret_b_mean) * 252
portfolio_std_dev = np.zeros(num_portfolios)
for i in range(num_portfolios):
    portfolio_std_dev[i]=np.sqrt(252*(((weights_b[i,:]).dot(robust_cov_matrix_b)).dot(weights_b[i,:].T)))

#Resultados
results[:,0] = portfolio_return
results[:,1] = portfolio_std_dev
#Sharpe
results[0, 2] = 0
results[1:,2] = (results[1:,0]-r) / results[1:,1]
#Iteraciones
results[:,3:] = weights_b

results_frame_b = pd.DataFrame(results,columns=(['Rendimiento','SD','Sharpe']+list(daily_ret_b.columns)))
results_frame_b
# -

#Sharpe Ratio
max_sharpe_port_b = results_frame_b.iloc[results_frame_b['Sharpe'].idxmax()]
#Menor SD
min_vol_port_b = results_frame_b.iloc[results_frame_b['SD'].idxmin()]

plt.scatter(results_frame_b.SD,results_frame_b.Rendimiento,c=results_frame_b.Sharpe,cmap='RdYlBu')
plt.xlabel('Volatility')
plt.ylabel('Returns')
plt.colorbar()
#Sharpe Ratio
plt.scatter(max_sharpe_port_b[1],max_sharpe_port_b[0],marker=(5,1,0),color='r',s=500);
#Menor SD
plt.scatter(min_vol_port_b[1],min_vol_port_b[0],marker=(5,1,0),color='g',s=500);

max_sharpe_port_b

min_vol_port_b

results_frame_b.iloc[results_frame_b['Rendimiento'].idxmax()]

# <script>
#   $(document).ready(function(){
#     $('div.prompt').hide();
#     $('div.back-to-top').hide();
#     $('nav#menubar').hide();
#     $('.breadcrumb').hide();
#     $('.hidden-print').hide();
#   });
# </script>
#
# <footer id="attribution" style="float:right; color:#808080; background:#fff;">
# Created with Jupyter by <NAME>.
# </footer>

StarcoderdataJupyterScriptsDedupFiltered