markowitz.py
Go to the documentation of this file.
9 
10 from gams import *
11 import sys
12 import os
13 from math import fabs
14 
15 try:
16  import matplotlib.pyplot as plt
17 except:
18  raise Exception("This example requires the matplotlib module")
19 
21  return '''
22 $title Standard Markowitz Portfolio Selection Model
23 
24 set s selected stocks
25  upper(s,s), lower(s,s) parts of covar matrix;
26 alias(s,t);
27 
28 parameter mean(s) mean of daily return
29  covar(s,s) covariance matrix of returns (upper);
30 
31 $if not set data $abort 'no include file name for data file provided'
32 $gdxin %data%
33 $load s covar upper lower mean
34 
35 variables z objective variable
36  ret return
37  var variance
38  x(s) investments;
39 
40 positive variables x;
41 
42 equations obj objective
43  budget
44  varcon variance constraint
45  retcon return constraint;
46 
47 scalar lambda /0/;
48 
49 obj.. z =e= lambda*ret - (1-lambda)*var;
50 budget.. sum(s, x(s)) =e= 1.0;
51 varcon.. var =e= sum(upper(s,t), x(s)*covar(s,t)*x(t)) +
52  sum(lower(s,t), x(s)*covar(t,s)*x(t));
53 retcon.. ret =e= sum(s, mean(s)*x(s));
54 
55 model markowitz /all/; '''
56 
57 if __name__ == "__main__":
58  if len(sys.argv) > 1:
59  ws = GamsWorkspace(system_directory = sys.argv[1])
60  else:
61  ws = GamsWorkspace()
62 
63  job = ws.add_job_from_string(get_model_text())
64  opt = ws.add_options()
65  opt.all_model_types = "conopt"
66  opt.defines["data"] = "\"" + os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\Data\\markowitz.gdx") + "\""
67 
68  cp = ws.add_checkpoint()
69  job.run(opt, cp)
70  mi = cp.add_modelinstance()
71  l = mi.sync_db.add_parameter("lambda", 0, "")
72  mi.instantiate("markowitz use nlp max z", GamsModifier(l))
73 
74  # a list for collecting the data points
75  data_points = []
76 
77  # get minimum and maximum return (lambda=0/1)
78  l.add_record().value = 0
79  mi.solve()
80  min_ret = mi.sync_db["ret"].first_record().level
81  data_points.append( (min_ret, mi.sync_db["var"].first_record().level) )
82  l.first_record().value = 1
83  mi.solve()
84  max_ret = mi.sync_db["ret"].first_record().level
85  data_points.append( (max_ret, mi.sync_db["var"].first_record().level) )
86 
87  # gap that specifies the max distance (return) between two data points
88  gap = 0.02
89  # a list (stack) of intervals, where an interval is represented by a 2-tuple containing two data points
90  # each represented by a 2-tuple as well (lambda, return)
91  intervals = [((0.0, min_ret), (1.0, max_ret))]
92 
93  # Algorithm that solves the model instance for multiple lambda values
94  # using a max gap between two data points to achieve a smooth graph.
95  # Lambda is dynamically calculated for an even distribution of data points
96  while intervals:
97  # pick the first interval and calculate a new value for lambda
98  i = intervals.pop()
99  min_l, min_ret = i[0][0], i[0][1]
100  max_l, max_ret = i[1][0], i[1][1]
101 
102  l_val = (min_l+max_l)/2
103  l.first_record().value = l_val
104  # solve the model instance with the new lambda value
105  mi.solve()
106  # retrieve the return and variance results
107  cur_ret = mi.sync_db["ret"].first_record().level
108  data_points.append( (cur_ret, mi.sync_db["var"].first_record().level) )
109  # add new intervals if the gap is still to big
110  if cur_ret - min_ret > gap:
111  intervals.append(((min_l, min_ret), (l_val, cur_ret)))
112  if fabs(cur_ret - max_ret) > gap:
113  intervals.append(((l_val, cur_ret), (max_l, max_ret)))
114 
115  # Sort data points and make two list for the plot function
116  data_points.sort(key=lambda tup: tup[0])
117  ret = map(lambda x: x[0], data_points)
118  var = map(lambda x: x[1], data_points)
119  plt.plot(ret, var, marker=".", markersize=10)
120  plt.xlabel('return')
121  plt.ylabel('variance')
122  plt.show()
def get_model_text()
Definition: markowitz.py:20