def portfolio_performance(<EOL>expected_returns, cov_matrix, weights, verbose=False, risk_free_rate=<NUM_LIT><EOL>):
if isinstance(weights, dict):<EOL><INDENT>if isinstance(expected_returns, pd.Series):<EOL><INDENT>tickers = list(expected_returns.index)<EOL><DEDENT>elif isinstance(cov_matrix, pd.DataFrame):<EOL><INDENT>tickers = list(cov_matrix.columns)<EOL><DEDENT>else:<EOL><INDENT>tickers = list(range(len(expected_returns)))<EOL><DEDENT>newweights = np.zeros(len(tickers))<EOL>for i, k in enumerate(tickers):<EOL><INDENT>if k in weights:<EOL><INDENT>newweights[i] = weights[k]<EOL><DEDENT><DEDENT>if newweights.sum() == <NUM_LIT:0>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT><DEDENT>elif weights is not None:<EOL><INDENT>newweights = np.asarray(weights)<EOL><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>sigma = np.sqrt(objective_functions.volatility(newweights, cov_matrix))<EOL>mu = newweights.dot(expected_returns)<EOL>sharpe = -objective_functions.negative_sharpe(<EOL>newweights, expected_returns, cov_matrix, risk_free_rate = risk_free_rate<EOL>)<EOL>if verbose:<EOL><INDENT>print("<STR_LIT>".format(<NUM_LIT:100> * mu))<EOL>print("<STR_LIT>".format(<NUM_LIT:100> * sigma))<EOL>print("<STR_LIT>".format(sharpe))<EOL><DEDENT>return mu, sigma, sharpe<EOL>
After optimising, calculate (and optionally print) the performance of the optimal
portfolio. Currently calculates expected return, volatility, and the Sharpe ratio.

:param expected_returns: expected returns for each asset. Set to None if
                         optimising for volatility only.
:type expected_returns: pd.Series, list, np.ndarray
:param cov_matrix: covariance of returns for each asset
:type cov_matrix: pd.DataFrame or np.array
:param weights: weights or assets
:type weights: list, np.array or dict, optional
:param verbose: whether performance should be printed, defaults to False
:type verbose: bool, optional
:param risk_free_rate: risk-free rate of borrowing/lending, defaults to 0.02
:type risk_free_rate: float, optional
:raises ValueError: if weights have not been calcualted yet
:return: expected return, volatility, Sharpe ratio.
:rtype: (float, float, float)