<jupyter_start><jupyter_text>The Efficient Frontier - Part IILet's start by loading the returns and generating the expected returns vector and the covariance matrix<jupyter_code>%load_ext autoreload
%autoreload 2
%matplotlib inline
import edhec_risk_kit as erk

ind = erk.get_ind_returns()
er = erk.annualize_rets(ind["1996":"2000"], 12)
cov = ind["1996":"2000"].cov()<jupyter_output><empty_output><jupyter_text>As a first exercise, let's assume we have some weights, and let's try and compute the returns and volatility of a portfolio, given a set of weights, returns, and a covariance matrix.The returns are easy, so let's add this to our toolkit```pythondef portfolio_return(weights, returns):    """    Computes the return on a portfolio from constituent returns and weights    weights are a numpy array or Nx1 matrix and returns are a numpy array or Nx1 matrix    """    return weights.T @ returns```The volatility is just as easy in matrix form:```pythondef portfolio_vol(weights, covmat):    """    Computes the vol of a portfolio from a covariance matrix and constituent weights    weights are a numpy array or N x 1 maxtrix and covmat is an N x N matrix    """    return (weights.T @ covmat @ weights)**0.5```<jupyter_code>l = ["Food", "Beer", "Smoke", "Coal"]
er[l]
cov.loc[l,l]
import pandas as pd
import numpy as np
ew = np.repeat(0.25, 4)
erk.portfolio_return(ew, er[l])
erk.portfolio_vol(ew, cov.loc[l,l])<jupyter_output><empty_output><jupyter_text>The 2-Asset CaseIn the case of 2 assets, the problem is somewhat simplified, since the weight of the second asset is 1-the weight of the first asset.Let's write a function that draws the efficient frontier for a simple 2 asset case.Start by generating a sequence of weights in a list of tuples. Python makes it easy to generate a list by using something called a _list comprehension_ ... which you can think of as an efficient way to generate a list of values instead of writing a for loop.<jupyter_code>import numpy as np

n_points = 20
weights = [np.array([w, 1-w]) for w in np.linspace(0, 1, n_points)]

type(weights)
len(weights)
weights[0]
weights[4]
weights[19]
l = ["Games", "Fin"]
rets = [erk.portfolio_return(w, er[l]) for w in weights]
vols = [erk.portfolio_vol(w, cov.loc[l,l]) for w in weights]
ef = pd.DataFrame({"R": rets, "V": vols})
ef.plot.scatter(x="V", y="R")<jupyter_output><empty_output><jupyter_text>We can create function that plots the frontier:```pythondef plot_ef2(n_points, er, cov):    """    Plots the 2-asset efficient frontier    """    if er.shape[0] != 2 or er.shape[0] != 2:        raise ValueError("plot_ef2 can only plot 2-asset frontiers")    weights = [np.array([w, 1-w]) for w in np.linspace(0, 1, n_points)]    rets = [portfolio_return(w, er) for w in weights]    vols = [portfolio_vol(w, cov) for w in weights]    ef = pd.DataFrame({        "Returns": rets,         "Volatility": vols    })    return ef.plot.line(x="Volatility", y="Returns", style=".-")```A useful summary of the visualization features in pandas is [here](https://pandas.pydata.org/pandas-docs/stable/user_guide/visualization.html)<jupyter_code>l = ["Fin", "Beer"]
erk.plot_ef2(25, er[l].values, cov.loc[l,l])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11709747742136406, 'fraction_numerical': 0.017128620367486764, 'mean_word_length': 4.79783393501805, 'pattern_counts': {'":': 6, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, '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': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '50056', 'license': 'CNRI-Python-GPL-Compatible', 'n_tokens_mistral': 1098, 'n_tokens_neox': 1020, 'n_words': 382, 'path': 'Investment Management/Course1/lab_108.ipynb', 'repo_name': 'djoye21school/python', 'size': '3211'}