Loading...
Searching...
No Matches
Form1.cs
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Data;
5using System.Drawing;
6using System.Linq;
7using System.Text;
8using System.Windows.Forms;
9using GAMS;
10using System.IO;
11using System.Reflection;
12using System.Windows.Forms.DataVisualization.Charting;
13
14namespace Markowitz
15{
23 public partial class Form1 : Form
24 {
25 public Form1()
26 {
28 if (Environment.GetCommandLineArgs().Length > 1)
29 ws = new GAMSWorkspace(systemDirectory: Environment.GetCommandLineArgs()[1]);
30 else
31 ws = new GAMSWorkspace();
32
33 GAMSJob job = ws.AddJobFromString(GetModelText());
34 GAMSOptions opt = ws.AddOptions();
35 opt.AllModelTypes = "conopt";
36 opt.Defines.Add("data", "\"" + Path.Combine(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"..\..\..\..\Data\Markowitz.gdx") + "\"");
37
39 job.Run(opt, cp);
40
42 GAMSParameter l = mi.SyncDB.AddParameter("lambda", 0, "");
43 mi.Instantiate("markowitz use nlp max z", new GAMSModifier(l));
44
45 // a list for collecting the data points
46 List<Tuple<double, double>> dataPoints = new List<Tuple<double, double>>();
47
48 // get minimum and maximum return (lambda=0/1)
49 l.AddRecord().Value = 0;
50 mi.Solve();
51 double minRet = mi.SyncDB.GetVariable("ret").FirstRecord().Level;
52 dataPoints.Add(Tuple.Create(minRet, mi.SyncDB.GetVariable("var").FirstRecord().Level));
53 l.FindRecord().Value = 1;
54 mi.Solve();
55 double maxRet = mi.SyncDB.GetVariable("ret").FirstRecord().Level;
56 dataPoints.Add(Tuple.Create(maxRet, mi.SyncDB.GetVariable("var").FirstRecord().Level));
57
58 // gap that specifies the max distance (return) between two data points
59 double gap = 0.02;
60
61 // a stack of intervals, where an interval is represented by a 2-tuple containing two data points
62 // each represented by a 2-tuple as well (lambda, return)
63 Stack<Tuple<Tuple<double, double>, Tuple<double, double>>> intervals = new Stack<Tuple<Tuple<double, double>, Tuple<double, double>>>();
64 intervals.Push(Tuple.Create(Tuple.Create(0.0, minRet), Tuple.Create(1.0, maxRet)));
65
66 // Algorithm that solves the model instance for multiple lambda values
67 // using a max gap between two data points to achieve a smooth graph.
68 // Lambda is dynamically calculated for an even distribution of data points
69 while(intervals.Count > 0){
70 // pick the first interval and calculate a new value for lambda
71 var i = intervals.Pop();
72 double minL = i.Item1.Item1;
73 minRet = i.Item1.Item2;
74 double maxL = i.Item2.Item1;
75 maxRet = i.Item2.Item2;
76
77 double lVal = (minL+maxL)/2;
78 l.FirstRecord().Value = lVal;
79 // solve the model instance with the new lambda value
80 mi.Solve();
81 // retrieve the return and variance results
82 double curRet = mi.SyncDB.GetVariable("ret").FirstRecord().Level;
83 dataPoints.Add(Tuple.Create(curRet, mi.SyncDB.GetVariable("var").FirstRecord().Level));
84 // add new intervals if the gap is still to big
85 if (curRet - minRet > gap)
86 intervals.Push(Tuple.Create(Tuple.Create(minL, minRet), Tuple.Create(lVal, curRet)));
87 if (Math.Abs(curRet - maxRet) > gap)
88 intervals.Push(Tuple.Create(Tuple.Create(lVal, curRet), Tuple.Create(maxL, maxRet)));
89 }
90
91 // Sort data points
92 dataPoints.Sort((a, b) => a.Item1.CompareTo(b.Item1));
93
94 InitializeComponent();
95 this.chart1.Series.Clear();
96 Series s = this.chart1.Series.Add("s");
97 s.ChartType = SeriesChartType.Line;
98 s.MarkerStyle = MarkerStyle.Circle;
99 s.MarkerSize = 5;
100 this.chart1.ChartAreas[0].AxisX.Title = "return";
101 this.chart1.ChartAreas[0].AxisY.Title = "variance";
102 this.chart1.ChartAreas[0].AxisX.Interval = 0.1;
103 this.chart1.ChartAreas[0].AxisX.Minimum = 0;
104
105 foreach(Tuple<double,double> p in dataPoints)
106 s.Points.AddXY(p.Item1, p.Item2);
107 }
108
109 static String GetModelText()
110 {
111 String model = @"
112$title Standard Markowitz Portfolio Selection Model
113
114set s selected stocks
115 upper(s,s), lower(s,s) parts of covar matrix;
116alias(s,t);
117
118parameter mean(s) mean of daily return
119 covar(s,s) covariance matrix of returns (upper);
120
121$if not set data $abort 'no include file name for data file provided'
122$gdxin %data%
123$load s covar upper lower mean
124
125variables z objective variable
126 ret return
127 var variance
128 x(s) investments;
129
130positive variables x;
131
132equations obj objective
133 budget
134 varcon variance constraint
135 retcon return constraint;
136
137scalar lambda /0/;
138
139obj.. z =e= lambda*ret - (1-lambda)*var;
140budget.. sum(s, x(s)) =e= 1.0;
141varcon.. var =e= sum(upper(s,t), x(s)*covar(s,t)*x(t)) +
142 sum(lower(s,t), x(s)*covar(t,s)*x(t));
143retcon.. ret =e= sum(s, mean(s)*x(s));
144
145model markowitz /all/
146";
147 return model;
148 }
149 }
150}
GAMSModelInstance AddModelInstance(string modelInstanceName=null)
GAMSVariable GetVariable(string variableIdentifier)
GAMSParameter AddParameter(string identifier, int dimension, string explanatoryText="")
void Run(GAMSOptions gamsOptions=null, GAMSCheckpoint checkpoint=null, TextWriter output=null, Boolean createOutDB=true)
void Solve(SymbolUpdateType updateType=SymbolUpdateType.BaseCase, TextWriter output=null, GAMSModelInstanceOpt miOpt=null)
void Instantiate(string modelDefinition, params GAMSModifier[] modifiers)
Dictionary< string, string > Defines
new GAMSParameterRecord FindRecord(params string[] keys)
new GAMSParameterRecord FirstRecord()
new GAMSParameterRecord AddRecord(params string[] keys)
new GAMSVariableRecord FirstRecord()
GAMSJob AddJobFromString(string gamsSource, GAMSCheckpoint checkpoint=null, string jobName=null)
GAMSCheckpoint AddCheckpoint(string checkpointName=null)
GAMSOptions AddOptions(GAMSOptions optFrom=null)
This is a small graphical program that plots the efficient frontier of Markowitz' portfolio selection...
Definition: Form1.cs:24