Profesor, MAF ITESO
En primer lugar, para poder bajar precios y información sobre opciones de Yahoo, es necesario cargar algunos paquetes de Python. En este caso, el paquete principal será Pandas. También, se usarán el Scipy y el Numpy para las matemáticas necesarias y, el Matplotlib y el Seaborn para hacer gráficos de las series de datos. Finalmente, se usará el paquete cvxopt para optimización convexa, para instalar ingrese en terminal la instrucción: conda install -c anaconda cvxopt
In [1]:
#importar los paquetes que se van a usar
import pandas as pd
import numpy as np
import datetime
from datetime import datetime
import scipy.stats as stats
import scipy as sp
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn.covariance as skcov
import cvxopt as opt
from cvxopt import blas, solvers
solvers.options['show_progress'] = False
%matplotlib inline
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)
#Funciones para portafolios
import portfolio_func
from pyomo.environ import *
infinity = float('inf')
import statsmodels.api as sm
In [2]:
assets = ['AAPL','MSFT','AA','AMZN','KO','QAI']
closes = portfolio_func.get_historical_closes(assets, '2016-01-01', '2017-09-22')
In [3]:
daily_returns=portfolio_func.calc_daily_returns(closes)
huber = sm.robust.scale.Huber()
#Mean and standar deviation returns
returns_av, scale = huber(daily_returns)
In [21]:
model.assets = Set()
model.T = Set(initialize = range(1994, 2014))
model.max_risk = Param(mutable = True, initialize = .00305)
model.R = Param(model.T, model.assets)
def mean_init(model, j):
return sum(model.R[i, j] for i in model.T)/len(model.T)
model.mean = Param(model.assets, initialize = mean_init)
def Q_init(model, i, j):
return sum((model.R[k, i] - model.mean[i])*(model.R[k, j] - model.mean[j]) for k in model.T)
model.Q = Param(model.assets, model.assets, initialize = Q_init)
model.alloc = Var(model.assets, within=NonNegativeReals)
def risk_bound_rule(model):
return (sum(sum(model.Q[i, j] * model.alloc[i] * model.alloc[j] for i in model.assets)for j in model.assets) <= model.max_risk)
model.risk_bound = Constraint(rule=risk_bound_rule)
def tot_mass_rule(model):
return (sum(model.alloc[j] for j in model.assets) == 1)
model.tot_mass = Constraint(rule=tot_mass_rule)
def objective_rule(model):
return summation(model.mean, model.alloc)
model.objective = Objective(sense=maximize, rule=objective_rule)
In [5]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [6]:
!type dietdata.dat
In [7]:
!pyomo solve --solver=glpk diet.py dietdata.dat
In [8]:
!type results.yml
In [ ]:
Una vez cargados los paquetes, es necesario definir los tickers de las acciones que se usarán, la fuente de descarga (Yahoo en este caso, pero también se puede desde Google) y las fechas de interés. Con esto, la función DataReader del paquete pandas_datareader bajará los precios solicitados.
Nota: Usualmente, las distribuciones de Python no cuentan, por defecto, con el paquete pandas_datareader. Por lo que será necesario instalarlo aparte. El siguiente comando instala el paquete en Anaconda: conda install -c conda-forge pandas-datareader
In [ ]:
In [ ]:
In [9]:
r=0.0001
results_frame = portfolio_func.sim_mont_portfolio(daily_returns,100000,r)
In [10]:
#Sharpe Ratio
max_sharpe_port = results_frame.iloc[results_frame['Sharpe'].idxmax()]
#Menor SD
min_vol_port = results_frame.iloc[results_frame['SD'].idxmin()]
In [11]:
plt.scatter(results_frame.SD,results_frame.Returns,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=1000);
#Menor SD
plt.scatter(min_vol_port[1],min_vol_port[0],marker=(5,1,0),color='g',s=1000);
In [12]:
pd.DataFrame(max_sharpe_port)
Out[12]:
In [13]:
pd.DataFrame(min_vol_port)
Out[13]:
In [14]:
N=5000
results_frame_optim = portfolio_func.optimal_portfolio(daily_returns,N,r)
In [15]:
#Montecarlo
plt.scatter(results_frame.SD,results_frame.Returns,c=results_frame.Sharpe,cmap='RdYlBu')
plt.xlabel('Volatility')
plt.ylabel('Returns')
plt.colorbar()
#Markowitz
plt.plot(results_frame_optim.SD, results_frame_optim.Returns, 'b-o');
In [16]:
#Sharpe Ratio
max_sharpe_port_optim = results_frame_optim.iloc[results_frame_optim['Sharpe'].idxmax()]
#Menor SD
min_vol_port_optim = results_frame_optim.iloc[results_frame_optim['SD'].idxmin()]
In [17]:
#Markowitz
plt.scatter(results_frame_optim.SD,results_frame_optim.Returns,c=results_frame_optim.Sharpe,cmap='RdYlBu');
plt.xlabel('Volatility')
plt.ylabel('Returns')
plt.colorbar()
#Sharpe Ratio
plt.scatter(max_sharpe_port_optim[1],max_sharpe_port_optim[0],marker=(5,1,0),color='r',s=1000);
#SD
plt.scatter(min_vol_port_optim[1],min_vol_port_optim[0],marker=(5,1,0),color='g',s=1000);
In [18]:
pd.DataFrame(max_sharpe_port_optim)
Out[18]:
In [19]:
pd.DataFrame(min_vol_port_optim)
Out[19]: