Starting from:

$30

Assignment 1 { Mean-Variance Portfolio Selection Strategies

Introduction

The purpose of this assignment is to compare computational investment strategies based on min-imizing portfolio variance and maximizing Sharpe ratio. You will need to take into account the e ect of trading costs.

We start with the classical Markowitz model of portfolio optimization. We are trading only stocks S1; : : : ; Sn, and the total number of stocks is n = 20. At holding period t the expected (daily) return of stock i is ti, the standard deviation of the return is it. The correlation between the returns of stocks i 6= j is tij. To abbreviate notation we introduce the return vector t = ( t1; : : : ; tn)T and the covariance matrix Qt = [ tij it jt]i;j=1;:::;n. At time period t we estimate t and Qt from the period t 1 time series. There are 12 holding periods and each holding period lasts 2 months (2 years in total). As a result, you can re-balance your portfolio at most 12 times.

Each transaction has a cost composed of a variable portion only. The variable fee is due to the di erence between the selling and bidding price of a stock, and is 0.5% of the traded volume. This means that if a stock is quoted at 30 dollars and the investor buys 10 shares, then they are going to pay 0:005 30 10 = 1:50 dollars on top of the 300 dollars the 10 shares would cost otherwise. If they sell 20 shares at the same 30 dollar price then they get 600 dollars, minus the 0:005 600 = 3 dollar transaction cost. Your may not need to account for transaction fees in your optimization, but you need to take them into account when computing portfolio value.

The goal of your optimization e ort is to create a tool that allows the user to make regular decisions about re-balancing their portfolio and compare di erent investment strategies. The user wants to consider the total return, the risk and Sharpe ratio. They may want to minimize/maximize any of these components, while limiting one or more of the other components. The basic building block is a decision made at the rst trading day of each 2-month holding period: given a current portfolio, the market prices on that day, and the estimates of the mean and covariance of the daily returns, make a decision about what to buy and sell according to a strategy. You are proposed to test four strategies:

1. \Buy and hold" strategy;
    2. \Equally weighted" (also known as \1=n") portfolio strategy;

    3. \Minimum variance" portfolio strategy;

    4. \Maximum Sharpe ratio" portfolio strategy.

To test your bi-monthly decisions, you are given daily closing prices of 20 stocks over a two-year period. Obviously, you cannot use the actual future prices when making a decision, only the price at that day, the return and covariance estimates. These estimates were derived from the actual data and are quite accurate. Once you are done with trades for a current holding period, you should move on to the next period, use new prices (and new estimates), and make another decision. You also need to track the value of your portfolio on each day, so that you have it handy at the rst trading day of a new period. You re-balance your portfolio on the rst trading day of each 2-month holding period (up to 12 re-balances during 2 years).

The stocks for the assignment are from the US stock markets and are quoted in US dollars. Quotes are given on trading days, which are the days for which a price is given. The data is from 2019 and 2020.

The initial portfolio is as follows: \IBM" = 980 shares, \BK" = 20000 shares.

The value of the initial portfolio is about one million dollars. The initial cash account is zero USD. The cash account must be nonnegative at all times. Your optimization algorithm may suggest buying or selling a non-integer number of shares, which is not allowed. You need to round the number of shares bought or sold to integer values and subtract transaction fees. If the value of your portfolio after re-balancing plus the transaction fees are smaller than the portfolio value before re-balancing, the remaining funds are accumulated in the cash account. Cash account does not pay any interest, but cash funds should be used toward stock purchases when portfolio is re-balanced next time.

An estimate of the daily returns of the stocks (for trading days) and the covariances of the returns are computed for you. These estimates are based on the previous two-month data and are updated every second month. You can only use the current estimate for the calculations and are not allowed to change or update the estimates in any way.

Note that for buying and selling asset shares, you need to optimize over asset weights. Current weight of asset i in a portfolio is wi = viVxi , where V is the current portfolio value, vi is current price of asset i and xi is the number of units (shares) of asset i in your portfolio. As initial portfolio value is 1000070:06 USD, price of IBM stock at the rst trading day of holding period 1 is 104.46 USD,




1


1





and we hold 980 shares, then w
1
=
v10
x10
=
104:46

980
= 0:102.

10

V
1













1000070:06


Questions


    1. (70 %) Implement investment strategies in Python: You need to test four portfolio re-balancing strategies:
        1. \Buy and hold" strategy: it is the simplest strategy where you hold initial portfolio for the entire investment horizon of 2 years. The strategy is already implemented in the function strat_buy_and_hold.



2
    2. \Equally weighted" (also known as \1=n") portfolio strategy: asset weights are se-lected as wit = 1=n, where n is the number of assets. You may need to re-balance your portfolio in each period as the number of shares xti changes even when wit = 1=n stays the same in each period. The strategy should be implemented in the function strat_equally_weighted.

    3. \Minimum variance" portfolio strategy: compute minimum variance portfolio for each period and re-balance accordingly. The strategy should be implemented in the function strat_min_variance.

    4. \Maximum Sharpe ratio" portfolio strategy: compute a portfolio that maximizes Sharpe ratio for each period and re-balance accordingly. The strategy should be implemented in the function strat_max_Sharpe.

Design and implement a rounding procedure, so that you always trade (buy or sell) an integer number of shares.

Design and implement a validation procedure in your code to test that each of your strategies is feasible (you have enough budget to re-balance portfolio, you correctly compute transaction costs, funds in your cash account are non-negative).

There is a le portf optim.py on the course web-page. You are required to complete the code in the le.


Your Python code should use only CPLEX optimization solver without CVXPY module.

Make commenting of your code for important logics.
    2. (20ˆ %) Analyze your results:

Produce the following output for the 12 periods (years 2019 and 2020):

Period 1: start date 01/02/2019, end date 02/28/2019

Strategy "Buy and Hold", value begin = $ 1000070.06, value end = $ 1121179.83

Strategy "Equally Weighted Portfolio", value begin = ... , value end = ...

...

Period 12: start date 11/02/2020, end date 12/31/2020

Strategy "Buy and Hold", value begin = $ 811070.20, value end = $ 972162.37
    • Strategy "Equally Weighted Portfolio", value begin = ... , value end = ...

Plot one chart in Python that illustrates the daily value of your portfolio (for each trading strategy) over the years 2019 and 2020 using daily prices provided. Include the
        ◦ chart in your report.

Plot two charts in Python for strategy 3 and 4 to show dynamic changes in portfolio allocations. In each chart, x-axis represents the rolling up time horizon, y-axis denotes portfolio weights between 0 and 1, and distinct lines display the position of selected assets
        ◦ over time periods. You may use these  gures to support your analysis or discussion.

Compare your trading strategies and discuss their performance relative to each other. Which strategy would you select for managing your own portfolio and why?

    3. (10ˆ %) Discuss possible improvements to your trading strategies:

Test your Python program for di erent variations of your strategies, e.g., select \1/n" portfolio at the beginning of period 1 and hold it till the end of period 12 (as if the re-balancing strategy required large transaction costs). Discuss if you are able to achieve
    • better results.

Can you suggest any improvements of the trading strategies that you have implemented?

3
Python File to be Completed

    • Import libraries import pandas as pd import numpy as np import math

    • Complete the following functions

def strat_buy_and_hold(x_init, cash_init, mu, Q, cur_prices):

x_optimal = x_init

cash_optimal = cash_init

return x_optimal, cash_optimal

def strat_equally_weighted(x_init, cash_init, mu, Q, cur_prices):

return x_optimal, cash_optimal

def strat_min_variance(x_init, cash_init, mu, Q, cur_prices):

return x_optimal, cash_optimal

def strat_max_Sharpe(x_init, cash_init, mu, Q, cur_prices):

return x_optimal, cash_optimal

# Input file

input_file_prices = ’Daily_closing_prices.csv’

# Read data into a dataframe

df = pd.read_csv(input_file_prices)

    • Convert dates into array [year month day] def convert_date_to_array(datestr):

temp = [int(x) for x in datestr.split(’/’)] return [temp[-1], temp[0], temp[1]]

dates_array = np.array(list(df[’Date’].apply(convert_date_to_array)))

data_prices = df.iloc[:, 1:].to_numpy()

dates = np.array(df[’Date’])

    • Find the number of trading days in Nov-Dec 2018 and

    • compute expected return and covariance matrix for period 1 day_ind_start0 = 0

day_ind_end0 = len(np.where(dates_array[:,0]==2018)[0])

cur_returns0 = data_prices[day_ind_start0+1:day_ind_end0,:] / data_prices[day_ind_start0:day_ind_end0-1,:] - 1 mu = np.mean(cur_returns0, axis = 0)

Q = np.cov(cur_returns0.T)

    • Remove datapoints for year 2018

data_prices = data_prices[day_ind_end0:,:]

dates_array = dates_array[day_ind_end0:,:]

dates = dates[day_ind_end0:]

# Initial positions in the portfolio

init_positions = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 980, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20000])

# Initial value of the portfolio

init_value = np.dot(data_prices[0,:], init_positions)

print(’\nInitial portfolio value = $ {}\n’.format(round(init_value, 2)))

# Initial portfolio weights

w_init = (data_prices[0,:] * init_positions) / init_value

# Number of periods, assets, trading days

N_periods = 6*len(np.unique(dates_array[:,0])) # 6 periods per year

N = len(df.columns)-1

N_days = len(dates)

    • Annual risk-free rate for years 2019-2020 is 2.5% r_rf = 0.025


4
# Number of strategies

strategy_functions = [’strat_buy_and_hold’, ’strat_equally_weighted’, ’strat_min_variance’, ’strat_max_Sharpe’]

strategy_names    = [’Buy and Hold’, ’Equally Weighted Portfolio’, ’Mininum Variance Portfolio’,

’Maximum Sharpe Ratio Portfolio’]

N_strat = 1    # comment this in your code

#N_strat = len(strategy_functions)    # uncomment this in your code

fh_array = [strat_buy_and_hold, strat_equally_weighted, strat_min_variance, strat_max_Sharpe]

portf_value = [0] * N_strat

x = np.zeros((N_strat, N_periods),    dtype=np.ndarray)

cash = np.zeros((N_strat, N_periods),    dtype=np.ndarray)

for period in range(1, N_periods+1):

    • Compute current year and month, first and last day of the period if dates_array[0, 0] == 19:

cur_year = 19 + math.floor(period/7) else:

cur_year  = 2019 + math.floor(period/7)

cur_month = 2*((period-1)%6) + 1

day_ind_start =

min([i for i, val in enumerate((dates_array[:,0] == cur_year) & (dates_array[:,1] == cur_month)) if val]) day_ind_end =

max([i for i, val in enumerate((dates_array[:,0] == cur_year) & (dates_array[:,1] == cur_month+1)) if val])

print(’\nPeriod {0}: start date {1}, end date {2}’.format(period, dates[day_ind_start], dates[day_ind_end]))

# Prices for the current day

cur_prices = data_prices[day_ind_start,:]

    • Execute portfolio selection strategies for strategy in range(N_strat):

    • Get current portfolio positions if period == 1:

curr_positions = init_positions curr_cash = 0

portf_value[strategy] = np.zeros((N_days, 1)) else:

curr_positions = x[strategy, period-2] curr_cash = cash[strategy, period-2]

    • Compute strategy

x[strategy, period-1], cash[strategy, period-1] = fh_array[strategy](curr_positions, curr_cash, mu, Q, cur_prices)

    • Verify that strategy is feasible (you have enough budget to re-balance portfolio)

    • Check that cash account is >= 0

    • Check that we can buy new portfolio subject to transaction costs

###################### Insert your code here ############################

# Compute portfolio value

p_values = np.dot(data_prices[day_ind_start:day_ind_end+1,:], x[strategy, period-1]) + cash[strategy, period-1] portf_value[strategy][day_ind_start:day_ind_end+1] = np.reshape(p_values, (p_values.size,1))

print(’    Strategy "{0}", value begin = $ {1:.2f}, value end = $ {2:.2f}’.format( strategy_names[strategy], portf_value[strategy][day_ind_start][0], portf_value[strategy][day_ind_end][0]))

# Compute expected returns and covariances for the next period

cur_returns = data_prices[day_ind_start+1:day_ind_end+1,:] / data_prices[day_ind_start:day_ind_end,:] - 1

mu = np.mean(cur_returns, axis = 0)

Q = np.cov(cur_returns.T)

# Plot results

###################### Insert your code here ############################









5
Sample Python Function for Trading Strategy


def strat_buy_and_hold(x_init, cash_init, mu, Q, cur_prices):

x_optimal = x_init

cash_optimal = cash_init

return x_optimal, cash_optimal




























































6

More products