FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Folio - Advanced modelling and solving tasks

Description
Advanced modelling and solving tasks for a portfolio optimization problem:
  • Automated solver tuning (foliolptune.mos)
  • Defining an integer solution callback (foliocb.mos, callback specification by name: foliocbm.mos; using an 'mpsol' object: foliocb_sol.mos)
  • Using the solution enumerator for multiple MIP solutions (folioenumsol.mos)
  • Handling infeasibility
    • handling infeasibility through deviation variables (folioinfeas.mos)
    • retrieving infeasible row/column from presolve (folioinfcause.mos)
    • retrieving IIS - LP, MIP, NLP infeasible (folioiis.mos, foliomiis.mos, folionliis.mos)
    • using the built-in infeasibility repair functionality (foliorep.mos)
    • same as foliorep, using an 'mpsol' object (foliorep_sol.mos)
  • Data transfer in memory
    • running foliomemio.mos with data transfer in memory (runfolio.mos)
    • same running foliomemio2.mos, grouping tables with identical index sets in "initializations" blocks (runfolio2.mos)
    • main model running several model instances in parallel (runfoliopar.mos)
  • Remote models on a distributed architecture
    • running foliomemio.mos on a remote instance of Mosel (runfoliodistr.mos)
    • main model running several model instances in parallel, each on a different (remote) instance of Mosel (runfoliopardistr.mos)
  • Remote execution via XPRD
    • See examples in the Mosel Whitepapers directory moselpar/XPRD
  • XML and JSON data formats
    • reading data from an XML file, solution output in XML format on screen and to a new file (folioxml.mos, folioxmlqp.mos)
    • generate HTML output file as an XML document (runfolioxml.mos)
    • using JSON-format data files, reading data from a JSON file, solution output in JSON format on screen and to a new file (foliojson.mos)
  • HTTP
    • starting an HTTP server managing requests from HTTP clients (foliohttpsrv.mos)
    • HTTP client exchanging XML data files with an HTTP server (foliohttpclient.mos)


Source Files

Data Files





runfoliopar.mos

(!******************************************************
   Mosel Example Problems
   ======================

   file runfoliopar.mos
   ````````````````````
   Main model running several instances of the
   portfolio optimization model in parallel.

   Runs model foliomemio.mos.
   -- Data input/output in memory --

   *** ATTENTION: This model will return an error if ***
   *** no more than one Xpress licence is available. ***
   *** With a single license, use setting NUMPAR=1   ***
      
  (c) 2009 Fair Isaac Corporation
      author: S.Heipcke, Feb. 2009, rev. Dec. 2017 
*******************************************************!)

model "Run portfolio optimization model (parallel)"
 uses "mmjobs"                       ! Use multiple model handling
 uses "mmsystem", "mmxprs"

 parameters
  MODELFILE = "foliomemio.mos"       ! Optimization model
  INPUTFILE = "folio10.dat"          ! File with problem data
 
  MAXRISK = 1/3                      ! Max. investment into high-risk values
  MINREG = 0.2                       ! Min. investment per geogr. region
  MAXREG = 0.5                       ! Max. investment per geogr. region
  MAXSEC = 0.25                      ! Max. investment per ind. sector
  MAXVAL = 0.2                       ! Max. investment per share
  MINVAL = 0.1                       ! Min. investment per share
  MAXNUM = 9                         ! Max. number of different assets

  NUMPAR = 5                         ! Number of model instances to run
 end-parameters
 
 forward procedure write_html_header
 forward procedure write_html_line(i:integer)
 forward procedure write_html_line(i:integer,msg:string)
 forward procedure write_html_footer

 declarations
  SHARES: set of string              ! Set of shares
  RISK: set of string                ! Set of high-risk values among shares
  REGIONS: set of string             ! Geographical regions
  TYPES: set of string               ! Share types (ind. sectors)
  LOCTAB: dynamic array(REGIONS,SHARES) of boolean ! Shares per geogr. region
  RET: array(SHARES) of real         ! Estimated return in investment
  SECTAB: dynamic array(TYPES,SHARES) of boolean ! Shares per industry sector

  returnsol,totalreturn: real        ! Solution values
  numsharessol,status,totalnum,totalopt: integer
  fracsol: array(SHARES) of real     ! Fraction of capital used per share
  buysol: array(SHARES) of real      ! 1 if asset is in portfolio, 0 otherwise

  foliomod: dynamic array(Instances:range) of Model
 end-declarations

! Compile the optimization model
 if compile("", MODELFILE, "shmem:bim") <> 0 then
  writeln("Error during model compilation")
  exit(1)
 end-if
! Load several instances of the optimization model
 forall(i in 1..NUMPAR) do
  create(foliomod(i))
  load(foliomod(i), "shmem:bim")
 end-do
 fdelete("shmem:bim")

! Read in data from file
 initializations from INPUTFILE
  RISK RET LOCTAB SECTAB
 end-initializations

! Save data to memory
 initializations to "raw:"
  RISK as 'shmem:RISK'
  RET as 'shmem:RET'
  LOCTAB as 'shmem:LOCTAB'
  SECTAB as 'shmem:SECTAB'
 end-initializations

! Start all instances in parallel, using unique file location names for output
 forall(i in Instances)
  run(foliomod(i), "MAXRISK=" + MAXRISK + ",MINREG=" + MINREG + 
  ",MAXREG=" + MAXREG + ",MAXSEC=" + MAXSEC +
  ",MAXVAL=" + MAXVAL + ",MINVAL=" + MINVAL + 
  ",MAXNUM=" + (MAXNUM-i) + ",DATAFILE='raw:',OUTPUTFILE='raw:'," +
  "RISKDATA='shmem:RISK',RETDATA='shmem:RET',LOCDATA='shmem:LOCTAB'," +
  "SECDATA='shmem:SECTAB',FRACSOL='shmem:FRAC" + i +"',BUYSOL='shmem:BUY" +
  i + "',NUMSHARES='shmem:NUMSHARES" + i + "',RETSOL='shmem:RETSOL" + i + 
  "',SOLSTATUS='shmem:SOLSTATUS" + i + "'" ) 

! Wait until all models have finished
! (alternatively: could retrieve results as soon as a run finishes)
 forall(i in Instances) do
  wait                              ! Wait for model terminations
  dropnextevent                     ! Ignore termination event message
 end-do

! Output: generate an HTML page with all solutions
 write_html_header

 forall(i in Instances) do
  forall(s in SHARES) do
   fracsol(s):=0; buysol(s):=0
  end-do 

  initializations from  "raw:"
   returnsol as 'shmem:RETSOL'+i
   numsharessol as 'shmem:NUMSHARES'+i
   fracsol as 'shmem:FRAC'+i
   buysol as 'shmem:BUY'+i
   status as 'shmem:SOLSTATUS'+i
  end-initializations

  case status of
   XPRS_OPT: do
              write_html_line(i)
              totalreturn+=returnsol
              totalnum+=numsharessol
              totalopt+=1
             end-do 
   XPRS_UNF: write_html_line(i,"Problem solving unfinished")
   XPRS_INF: write_html_line(i,"Problem is infeasible")
   XPRS_UNB,XPRS_OTH: write_html_line(i,"No solution available")
  end-case 

 end-do
 
 write_html_footer

! *********** Writing an HTML result file ***********
 procedure write_html_header
  setparam("datetimefmt", "%0d-%N-%y, %0H:%0M:%0S")

  HTMLFILE:= INPUTFILE + "_sol.html"
  fopen(HTMLFILE, F_OUTPUT)
  writeln("<html>")
  writeln("<head>")
  writeln("<style type='text/css'>")
  writeln("body {font-family: Verdana, Geneva, Helvetica, Arial, sans-serif; color: 000055 }")
  writeln("table td {background-color: ffffaa; text-align: left }")
  writeln("table th {background-color: 053055; color: ffcc88}")
 writeln("</style>")
  writeln("</head>")

  writeln("<body>")
  writeln("<center><h2>Portfolio Optimization Summary Results</h2></center>")
  writeln("<table width='100%' cellpadding='5' cellspacing='0' border=0>")
  writeln("<tr><td width='55%'><font color='#000055'><b> </b></font></td><td><font color='#885533'><b>Problem data: ",
          INPUTFILE,"</b></font></td></tr>")
  writeln("<tr><td><font color='#000055'><b> </b></font></td><td><font color='#885533'><b>Date: ", datetime(SYS_NOW),"</b></font></td></tr>")
  writeln("<tr><td colspan='2'>&nbsp;</td></tr>")
  writeln("</table>")

  writeln("<table cellpadding='2' cellspacing='1' width='100%'>")
  writeln("<tr><th>Instance</th><th>Return</th><th>No. shares</th><th>Value: Percentage</th></tr>")
 end-procedure

 procedure write_html_line(i:integer)
  write("<tr><td><center>", i, "</center></td><td>", returnsol, "</td><td><center>", numsharessol, "</center></td><td>")
  writeln("<table cellpadding='2' cellspacing='0' width='100%'>")
  ct:=0
  forall(s in SHARES | fracsol(s)>0) do
   ct+=1   
   writeln(if(ct mod 4=1, "<tr>", ""),
           "<td><font size='-1'>", s, ": ", strfmt(fracsol(s)*100,4,2), "%,</font></td>", 
           if(ct mod 4=0, "</tr>", ""))
  end-do  
  writeln(if(ct mod 4<>0, "</tr>", ""), "</table></td></tr>") 
 end-procedure

 procedure write_html_line(i:integer,msg:string)
  writeln("<tr><td><center>", i, "</center></td><td align='left' colspan='3'>", msg, "</td></tr>")
 end-procedure

 procedure write_html_footer
  writeln("<tr><th>Average</th><th>", totalreturn/totalopt, "</th><th>", totalnum/totalopt, "</th><th></th></tr>")
  writeln("</table>")
  writeln("</body>")
  writeln("</html>")
  fclose(F_OUTPUT)
 end-procedure

end-model

Back to examples browserPrevious exampleNext example