ASH
ASH

Reputation: 20342

Python errors out on portfolio management exercise

When I try to run the chunk of code below I get some weird errors.

Here is the traceback:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 91, in display_simulated_ef_with_random
  File "<input>", line 71, in random_portfolios
  File "<input>", line 59, in portfolio_annualised_performance
  File "C:\Users\rms\PycharmProjects\untitled2\venv\lib\site-packages\pandas\core\ops.py", line 1583, in wrapper
    result = safe_na_op(lvalues, rvalues)
  File "C:\Users\rms\PycharmProjects\untitled2\venv\lib\site-packages\pandas\core\ops.py", line 1529, in safe_na_op
    return na_op(lvalues, rvalues)
  File "C:\Users\rms\PycharmProjects\untitled2\venv\lib\site-packages\pandas\core\ops.py", line 1505, in na_op
    result = expressions.evaluate(op, str_rep, x, y, **eval_kwargs)
  File "C:\Users\rms\PycharmProjects\untitled2\venv\lib\site-packages\pandas\core\computation\expressions.py", line 208, in evaluate
    return _evaluate(op, op_str, a, b, **eval_kwargs)
  File "C:\Users\rms\PycharmProjects\untitled2\venv\lib\site-packages\pandas\core\computation\expressions.py", line 68, in _evaluate_standard
    return op(a, b)
ValueError: operands could not be broadcast together with shapes (22,) (4,) 

I think I am missing something somewhat simple, but I'm not sure what the issue really is. Any thoughts?

import pandas as pd
import numpy as np
from pandas_datareader import data, wb
import datetime
import scipy.optimize as sco
from scipy import stats
from datetime import datetime, date, time
import matplotlib.pyplot as plt

pd.set_option('display.max_columns', None)

tickers = ['AAPL',
'BA',
'CAT',
'CSCO',
'CVX',
'XOM',
'GS',
'HD',
'IBM',
'INTC',
'JNJ',
'KO',
'JPM',
'MCD',
'MMM',
'MRK',
'MSFT',
'NKE',
'PFE',
'PG',
'VZ',
'DIS']
start = date(2019, 1, 1)
end = date(2019, 7, 16)

df = pd.DataFrame([data.DataReader(ticker, 'yahoo', start, end)['Adj Close'] for ticker in tickers]).T
df.columns = tickers

print(df)



plt.figure(figsize=(10, 5))
for c in df.columns.values:
    plt.plot(df.index, df[c], lw=3, alpha=0.8,label=c)
plt.legend(loc='upper left', fontsize=12)
plt.ylabel('price in $')

returns = df.pct_change()
plt.figure(figsize=(10, 5))
for c in returns.columns.values:
    plt.plot(returns.index, returns[c], lw=3, alpha=0.8,label=c)
plt.legend(loc='upper right', fontsize=12)
plt.ylabel('daily returns')


def portfolio_annualised_performance(weights, mean_returns, cov_matrix):
    returns = np.sum(mean_returns * weights) * 252
    std = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) * np.sqrt(252)
    return std, returns


def random_portfolios(num_portfolios, mean_returns, cov_matrix, risk_free_rate):
    results = np.zeros((3, num_portfolios))
    weights_record = []
    for i in range(num_portfolios):
        weights = np.random.random(4)
        weights /= np.sum(weights)
        weights_record.append(weights)
        portfolio_std_dev, portfolio_return = portfolio_annualised_performance(weights, mean_returns, cov_matrix)
        results[0, i] = portfolio_std_dev
        results[1, i] = portfolio_return
        results[2, i] = (portfolio_return - risk_free_rate) / portfolio_std_dev
    return results, weights_record


# calculate sharpe ratio
returns = df.pct_change()
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_portfolios = 250
risk_free_rate = 0.015


# generate random portfolio and gets the results (portfolio returns, portfolio volatility, portfolio Sharpe ratio)
# and weights for the corresponding result. Then by locating the one with the highest Sharpe ratio portfolio,
# it displays maximum Sharpe ratio portfolio as red star sign. And does similar steps for minimum volatility portfolio,
# and displays it as a green star on the plot.
def display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate):
    results, weights = random_portfolios(num_portfolios, mean_returns, cov_matrix, risk_free_rate)

    max_sharpe_idx = np.argmax(results[2])
    sdp, rp = results[0, max_sharpe_idx], results[1, max_sharpe_idx]
    max_sharpe_allocation = pd.DataFrame(weights[max_sharpe_idx], index=df.columns, columns=['allocation'])
    max_sharpe_allocation.allocation = [round(i * 100, 2) for i in max_sharpe_allocation.allocation]
    max_sharpe_allocation = max_sharpe_allocation.T


    min_vol_idx = np.argmin(results[0])
    sdp_min, rp_min = results[0, min_vol_idx], results[1, min_vol_idx]
    min_vol_allocation = pd.DataFrame(weights[min_vol_idx], index=df.columns, columns=['allocation'])
    min_vol_allocation.allocation = [round(i * 100, 2) for i in min_vol_allocation.allocation]
    min_vol_allocation = min_vol_allocation.T

    print("-" * 80)
    print("Maximum Sharpe Ratio Portfolio Allocation\n")
    print("Annualised Return:", round(rp, 2))
    print("Annualised Volatility:", round(sdp, 2))
    print("\n")
    print(max_sharpe_allocation)
    print("-" * 80)
    print("Minimum Volatility Portfolio Allocation\n")
    print("Annualised Return:", round(rp_min, 2))
    print("Annualised Volatility:", round(sdp_min, 2))
    print("\n")
    print(min_vol_allocation)

    plt.figure(figsize=(10, 7))
    plt.scatter(results[0, :], results[1, :], c=results[2, :], cmap='YlGnBu', marker='o', s=10, alpha=0.3)
    plt.colorbar()
    plt.scatter(sdp, rp, marker='*', color='r', s=500, label='Maximum Sharpe ratio')
    plt.scatter(sdp_min, rp_min, marker='*', color='g', s=500, label='Minimum volatility')
    plt.title('Simulated Portfolio Optimization based on Efficient Frontier')
    plt.xlabel('annualised volatility')
    plt.ylabel('annualised returns')
    plt.legend(labelspacing=0.8)


display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)

Upvotes: 0

Views: 216

Answers (1)

jeremy_rutman
jeremy_rutman

Reputation: 5768

I'm not 100% sure this is what you were after, but editing this line in random_portfolios allows the program to complete:

weights = np.random.random(len(mean_returns))

A bunch of allocation and volatility info is produced and the program exits without error.

Upvotes: 1

Related Questions