首页 > > 详细

辅导 MIE 1622H: Assignment 2 – Risk-Based and Robust讲解 Python语言

MIE 1622H: Assignment 2 Risk-Based and Robust

Portfolio Selection Strategies

February 10, 2025

Due: Friday, March 7, 2025, not later than 11:59p.m. Use Python for all MIE1622H assignments.

You should hand in:

Your report (pdf file and docx file). Maximum page limit is 8 pages.

•  Compress all of your Python code  (i.e., ipynb notebook with plots and necessary outputs intact) into a zip file and submit it via Quercus portal no later than 11:59p.m. on March 7.

Where to hand in: Online via Quercus portal, both your code and report.

Introduction

The purpose of this assignment is to compare computational investment strategies based on select- ing portfolio with equal risk contributions, using robust mean-variance optimization and applying passive investment strategy via benchmark tracking optimization.  In Assignment 1, you have al- ready implemented and compared computational investment strategies based on minimizing port- folio variance, maximizing portfolio expected return, maximizing Sharpe ratio as well as “equally weighted” and “buy and hold” portfolio strategies.

You are proposed to test nine strategies (use your implementation of strategies 1-5 from Assign- ment 1):

1.  “Buy and hold” strategy;

2.  “Equally weighted” (also known as “1/n”) portfolio strategy;

3.  “Minimum variance” portfolio strategy;

4.  “Maximum expected return” portfolio strategy;

5.  “Maximum Sharpe ratio” portfolio strategy;

6.  “Equal risk contributions” portfolio strategy;

7.  “Leveraged max Sharpe Ratio” portfolio strategy;

8.  “Robust mean-variance optimization” portfolio strategy.

9.  “Benchmark tracking optimization” portfolio strategy.

If a portfolio strategy relies on some targets, e.g., target return estimation error, you need to select those targets consistently for each holding period.  It is up to you to decide how to select those targets.

Feel free to use Python prototypes provided in class.

Questions

1. (50 %) Implement investment strategies in Python:

You need to test four portfolio re-balancing strategies:

1.  “Equal risk contributions” portfolio strategy:  compute a portfolio that has equal risk contributions to standard deviation for each period and re-balance accordingly.  You can use IPOPT example from the lecture notes, but you need to compute the gradi- ent of the objective function yourself (to validate your gradient computations you may use finite differences method).   The  strategy  should be implemented in the function strat_equal_risk_contr.

2.  “Leveraged max Sharpe Ratio” portfolio strategy: take long 200% position in max Sharpe ratio portfolio and short risk-free asset for each period andre-balance accordingly, implement it in the function strat_lever_max_Sharpe. You do not have to include risk- free asset as an additional asset when calculating optimal positions.  Just make sure that you subtract amount borrowed (including interest at the risk-free rate) when calculating portfolio value in a similar way as you do for transaction cost at each time period.

3.  “Robust mean-variance optimization” portfolio strategy: compute a robust mean-variance portfolio for each period and re-balance accordingly. You can use CPLEX example from   the lecture notes, but you need to select target risk estimation error and target return   according to your preferences as an investor (provide justification of your choices). The   strategy should be implemented in the function strat_robust_optim.

4.  “Benchmark tracking” portfolio strategy:  for each period, select a portfolio that aims to replicate or closely track the provided benchmark portfolio (S&P30).  The S&P30 benchmark (index) portfolio is composed of the same 30 stocks used in this assignment, with each stock’s weight determined by its market capitalization relative to the total market cap of the 30 stocks.  Asset weights in the benchmark portfolio wb  are provided in the template code.  Your optimization formulation should minimize  tracking  error (squared), which is defined as the difference between your portfolio’s variance of re- turns and the benchmark’s variance of returns, subject to standard portfolio constraints plus a cardinality constraint.   The cardinality constraint should allow selection of at most ten stocks for your benchmark-tracking strategy.  Implement this in the function strat_tracking_index.

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 tore-balance portfolio, you correctly compute transaction costs, funds in your cash account are non-negative).

There is a file portf optim2.ipynb on the course web-page.  You are required to complete the code in the file and run your script for 3 CSV datasets explained below.

Your Python code should use only CPLEX and IPOPT optimization solvers.

For this assignment you need to use Google Colab and install the trial version of CPLEX (available on Colab) with  !pip  install  cplex.  To install IPOPT solver on Google Colab, please install necessary libraries as shown in ipopt_example .ipynb file from Lecture 1, and after that install cyipopt module with  !pip  install  cyipopt.

2. (15 %) Analyze your results:

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

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

Strategy  "Buy  and  Hold",  value  begin  =  $  1000016 .96,  value  end  =  $  887595 .87,  cash  account  =  $0 .00

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

Strategy  "Minimum  Variance  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Maximum  Expected  Return  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Maximum  Sharpe  Ratio  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Equal  Risk  Contributions  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Leveraged  Max  Sharpe  Ratio  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Robust  Optimization  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Benchmark  Tracking  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

...

Period  12:  start  date  11/01/2021,  end  date  12/31/2021

Strategy  "Buy  and  Hold",  value  begin  =  $  964589 .81,  value  end  =  $  942602 .39,  cash  account  =  $0 .00

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

Strategy  "Minimum  Variance  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Maximum  Expected  Return  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Maximum  Sharpe  Ratio  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Equal  Risk  Contributions  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Leveraged  Max  Sharpe  Ratio  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Robust  Optimization  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

Strategy  "Benchmark  Tracking  Portfolio",  value  begin  =  . . .  ,  value  end  =  . . .  ,  cash  account  =  . . .

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

•  Plot one chart in Python that illustrates maximum drawdown of your portfolio (for each of the nine trading strategies) for each of the 12 periods (years 2020 and 2021) using daily prices provided. Include the chart in your report.

•  Plot one chart in Python to show dynamic changes in portfolio allocations under strat- egy  8. 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.  Does your robust portfolio selection strategy reduce trading as compared with strategies 3, 4 and 5 that you have implemented in Assignment 1?

•  Compare your “equal risk contributions”,  “leveraged max Sharpe ratio”,  “robust mean- variance optimization” and “benchmark tracking” trading strategies between each other and to five strategies implemented in Assignment 1 and discuss their performance relative to each other.  Which strategy would you select for managing your own portfolio and why?

3. (20 %) Test your trading strategies for years 2008 and 2009:

•  Download daily closing prices for the same thirty stocks for years 2008 and 2009 (file adjclose 2008 2009.csv).  If necessary, transform data into a format that your code can read.

•  Test nine strategies that you have implemented for the 12 periods (years 2008 and 2009). Use the same initial portfolio that you are given in Assignment 1.  Produce the same output for your strategies as in Question 2.

•  Plot one chart in Python that illustrates the daily value of your portfolio (for each of the nine trading strategies) over the years 2008 and 2009 using daily prices that you have downloaded. Include the chart in your report.

•  Plot one chart in Python that illustrates maximum drawdown of your portfolio (for each of the nine trading strategies) for each of the 12 periods (years 2008 and 2009) using daily prices provided. Include the chart in your report.

•  Plot four charts in Python for strategies 3, 4,  5 and 8 to show dynamic changes in portfolio allocations using the new data set. Does your robust portfolio selection strategy reduce trading as compared with the strategies 3, 4 and 5?

•  Compare and discuss relative performance of your nine trading strategies during 2020-

2021 and 2008-2009 time periods.  Which strategy would you select for managing your own portfolio during 2008-2009 time period and why?

4. (15 %) Test your trading strategies for year 2022:

Download daily closing prices for the same thirty stocks for year 2022 (file adjclose 2022.csv). If necessary, transform data into a format that your code can read.

•  Test nine strategies that you have implemented for the 6 periods (year 2022).  Use the same initial portfolio that you are given in Assignment 1. Produce the same output for your strategies as in Question 2.

•  Plot one chart in Python that illustrates the daily value of your portfolio (for each of the nine trading strategies) over the year 2022 using daily prices that you have downloaded. Include the chart in your report.

•  Plot one chart in Python that illustrates maximum drawdown of your portfolio (for each of the nine trading strategies) for each of the 6 periods (year 2022) using daily prices provided. Include the chart in your report.

•  Compare the maximum drawdown for 2022 to the 2008-2009 maximum drawdown?  How do the two periods called “recessions” compare?

Python Code to be Completed (available on Quercus)

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

from  scipy  import  sparse

import  matplotlib.pyplot  as  plt %matplotlib  inline

#  Install  CPLEX  and  IPOPT,  if  necessary . import  cplex

import  cyipopt  as  ipopt

#  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_return(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

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

return  x_optimal,  cash_optimal

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

return  x_optimal,  cash_optimal

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

return  x_optimal,  cash_optimal

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

return  x_optimal,  cash_optimal

#  Input  file

input_file_prices  =  ’adjclose_2020_2021 .csv’

#  Read  data  into  a  dataframe.

df  =  pd.read_csv(input_file_prices)

#  Convert  dates  into  array  [year  month  day] #  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  2019  and

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

day_ind_end0  =  len(np .where(dates_array[:,0]==2019)[0])     #  for  2020-2021  csv

#day_ind_end0  =  len(np .where(dates_array[:,0]==2007)[0])     #  for  2008-2009  csv #day_ind_end0  =  len(np .where(dates_array[:,0]==2021)[0])     #  for  2022  csv

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  2019

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,  0,  0,  3447,  0,  0,  0,

0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  19385,  0])

#  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  2020-2021  is  1.5% r_rf  =  0 .015

#  Annual  risk-free  rate  for  years  2008-2009  is  4.5% r_rf2008_2009  =  0 .045

#  Annual  risk-free  rate  for  year  2022  is  3.75% r_rf2022  =  0 .0375

#  Weights  of  assets  in  the  benchmark  portfolio  S&P30  for  years  2020-2021

w_b  =  np .array([0 .14832533,  0 .15556291,  0.01990254,  0.05079846,  0.01302685,  0.01030985,  0.02252249,  0.00227124,  . . .]) #  Weights  of  assets  in  the  benchmark  portfolio  S&P30  for  years  2008-2009

w_b2008_2009  =  np.array([0.04515391,  0.09628167,  0.00962156,  0.04751553,  0.02738386,  0.00612178,  0.03599232,  . . .]) #  Weights  of  assets  in  the  benchmark  portfolio  S&P30  for  year  2022

w_b2022  =  np .array([0 .1994311,  0 .18518391,  0.05464191,  0.06021769,  0.00822679,  0.01771958,  0.01735487,  . . .])

#  Number  of  strategies

strategy_functions  =  [’strat_buy_and_hold’,  ’strat_equally_weighted’,  ’strat_min_variance’,  ’strat_max_return’,

’strat_max_Sharpe’,  ’strat_equal_risk_contr’,  ’strat_lever_max_Sharpe’,  ’strat_robust_optim’, ’strat_tracking_index’]

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

’Maximum  Expected  Return  Portfolio’,  ’Maximum  Sharpe  Ratio  Portfolio’,

’Equal  Risk  Contributions  Portfolio’,  ’Leveraged  Max  Sharpe  Ratio  Portfolio’, ’Robust  Optimization  Portfolio’,  ’Benchmark  Tracking  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_return,  strat_max_Sharpe, strat_equal_risk_contr,  strat_lever_max_Sharpe,  strat_robust_optim,  strat_tracking_index]

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

#  Depending  on  what  data/csv  (i .e  time  period)  uncomment  code if  dates_array[0,  0]  ==  20:

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

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

#  example  for  2008-2009  data #if  dates_array[0,  0]  ==  8:

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

#       cur_year    =  2008  +  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},  cash  account  =  ${3: .2f}’ .format( strategy_names[strategy],  portf_value[strategy][day_ind_start][0],

portf_value[strategy][day_ind_end][0],  cash[strategy,  period-1]))

#  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  ############################

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


联系我们
  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp
热点标签

联系我们 - QQ: 99515681 微信:codinghelp
程序辅导网!