Formulating the Mosel Model
Even if you are not a Mosel expert, you should be able to glean the intent of this code sample if you have some programming experience.
Copy and paste the code into your own editor. The source file is available in the examples folder in your Xpress installation directory.
![]() |
Note The following code fragment contains line numbers, so that they can be referenced in the subsequent commentary.
|
01: (! 02: Portfolio optimization app example 03: (c) 2020 Fair Isaac Corporation. 04: !) 05: model "Portfolio Optimization" 06: version 1.0.0 07: 08: options noimplicit 09: 10: uses "mmxprs" 11: 12: declarations 13: ! Constant 14: DATAFILE = "shares.csv" 15: end-declarations 16: 17: ! Declaration of the scenario data model for input and results 18: public declarations 19: ! Input entities 20: MaxHighRisk: real 21: MaxPerShare: real 22: MinNorthAmerica: real 23: ShareIds: set of string 24: 25: ! Input and result entities indexed over ShareIds 26: Shares_Return: array(ShareIds) of real 27: Shares_HighRisk: array(ShareIds) of boolean 28: Shares_NorthAmerica: array(ShareIds) of boolean 29: Shares_fraction: array(ShareIds) of mpvar 30: 31: ! Result entities 32: TotalReturn: linctr 33: end-declarations 34: 35: public procedure loaddata 36: writeln("Loading data.") 37: MaxHighRisk := 0.33 ! Max. investment into high-risk values 38: MaxPerShare := 0.25 ! Max. investment per share 39: MinNorthAmerica := 0.45 ! Min. investment into N.-American values 40: 41: initializations from "mmsheet.csv:skiph;" + DATAFILE 42: [Shares_Return, Shares_HighRisk, Shares_NorthAmerica] as '[A:D]' 43: end-initializations 44: 45: writeln("Loading finished.") 46: end-procedure 47: 48: procedure solvemodel 49: declarations 50: LimitHighRisk, LimitNorthAmerica : linctr 51: end-declarations 52: 53: ! Objective: expected total return 54: TotalReturn := sum(s in ShareIds) Shares_Return(s) * Shares_fraction(s) 55: 56: ! Limit the percentage of high-risk values 57: LimitHighRisk := 58: sum(s in ShareIds | Shares_HighRisk(s)) Shares_fraction(s) <= MaxHighRisk 59: 60: ! Minimum amount of North-American values 61: LimitNorthAmerica := 62: sum(s in ShareIds | Shares_NorthAmerica(s)) Shares_fraction(s) >= MinNorthAmerica 63: 64: ! Spend all the capital 65: sum(s in ShareIds) Shares_fraction(s) = 1 66: 67: ! Upper bounds on the investment per share 68: forall(s in ShareIds) do 69: Shares_fraction(s) <= MaxPerShare 70: end-do 71: 72: writeln('Starting optimization.') 73: 74: ! Solve optimization problem 75: maximize(TotalReturn) 76: 77: writeln('Optimization finished.') 78: end-procedure 79: 80: loaddata 81: solvemodel 82: 83: end-model
Commentary
Lines 12-33 contain the entity declarations.
Lines 35-46 establish the model's runtime parameters. The specified default values can be changed for every model execution without any need to edit the model source.
Line
41-43 initializes the entities with values from an external data file in csv format called
shares.csv (specified on line
14) which contains the following data:
! Data file for ‘shares.csv’ shareIds,returnOnInvestment,highRisk,northAmerica Bank,6.0,False,False Brewery,8.0,False,False Cars,7.0,False,False Electronics,21.0,True,False Hardware,17.0,True,True Highways,9.0,False,False Software,31.0,True,False Telecom,12.0,True,True Theater,26.0,True,True Treasury,5.0,False,True
![]() |
Note The
shares.csv file is a representation of the preferences made by the investor in the section
Introducing the Example Business Problem.
|
Line 54 contains an expression whose value is assigned to an entity called TotalReturn - the goal of the problem is ultimately to maximize this expression.
Lines 55-71 establish the constraints of the problem, while line 75 starts the optimization solver to maximize the value of TotalReturn.
Finally, lines 80 and 81 read the source data file and run the optimization.