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





foliomemio.mos

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

   file foliomemio.mos
   ```````````````````
   Modeling a MIP problem 
   to perform portfolio optimization.

   Same model as in foliomip3.mos with
   simplified data structures (replaced arrays of structured types).
   -- Data input/output in memory --
   
   Run modes for this model:
   1. Stand-alone: data I/O to text files
      (run this model from Workbench or from Mosel command line) 
   2. Submodel to another Mosel model: data exchange in memory
      (run model 'runfolio.mos' or 'runfoliopar.mos' to execute this model)
   3a. C: I/O to C program runfolio.c or runfoliod.c
      (compile and run C program 'runfolio.c' or 'runfoliod.c')
   3b. Java: I/O to Java program runfolio.java, runfoliob.java, or
      runfoliod.java
      (compile and run Java program 'runfolio.java', 'runfoliob.java',
      or 'runfoliod.java')
   3c. (Windows only) C#: I/O to C# program runfolio.cs or runfoliob.cs
      (compile and run C# program 'runfolio.cs' or 'runfoliob.cs')
   4. Remote execution from another Mosel model: 
      (run model 'runfoliodistr.mos' or 'runfoliopardistr.mos' to execute 
      this model)   
   5a. Remote execution from C: I/O to C program distfolio.c or distfoliopar.c
      (compile and run C program 'distfolio.c' or 'distfoliopar.c')
   5b. Remote execution from Java: I/O to Java program distfolio.java or
      distfoliopar.java
      (compile and run Java program 'distfolio.java' or 'distfoliopar.java')
   
  (c) 2009 Fair Isaac Corporation
      author: S.Heipcke, Jan. 2009, rev. Sep. 2018
*******************************************************!)

model "Portfolio optimization with MIP"
 uses "mmxprs"

 parameters
  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 = 15                        ! Max. number of different assets

  DATAFILE = "folio10.dat"           ! File with problem data
  OUTPUTFILE = "sol10out.dat"        ! File for solution output
  RISKDATA = "RISK"                  ! Locations of input data
  RETDATA = "RET"
  LOCDATA = "LOCTAB"
  SECDATA = "SECTAB"
  FRACSOL = "FRAC"                   ! Locations for solution output
  BUYSOL = "BUY"
  NUMSHARES = "NUMSHARES"
  RETSOL = "RETSOL"
  SOLSTATUS = "SOLSTATUS"
 end-parameters

 declarations
  SHARES,S: 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
 end-declarations

 initializations from DATAFILE
  RISK as RISKDATA
  RET as RETDATA
  LOCTAB as LOCDATA
  SECTAB as SECDATA
 end-initializations

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 end-declarations

! Objective: total return
 Return:= sum(s in SHARES) RET(s)*frac(s) 

! Limit the percentage of high-risk values
 sum(s in RISK) frac(s) <= MAXRISK

! Limits on geographical distribution
 forall(r in REGIONS) do
  sum(s in SHARES | exists(LOCTAB(r,s))) frac(s) >= MINREG
  sum(s in SHARES | exists(LOCTAB(r,s))) frac(s) <= MAXREG
 end-do 

! Diversification across industry sectors
 forall(t in TYPES) sum(s in SHARES | exists(SECTAB(t,s))) frac(s) <= MAXSEC

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Limit the total number of assets
 sum(s in SHARES) buy(s) <= MAXNUM

 forall(s in SHARES) do
  buy(s) is_binary                  ! Turn variables into binaries
  frac(s) <= MAXVAL*buy(s)                 ! Linking the variables
  frac(s) >= MINVAL*buy(s)                 ! Linking the variables
 end-do


! Display Optimizer log
 setparam("XPRS_verbose", true)

! Solve the problem
 maximize(Return)


! Adapt Mosel comparison tolerance to Optimizer feasibility tolerance
 setparam("zerotol", getparam("XPRS_feastol")/10)

! Solution output
 function getvalues(v: array(SHARES) of mpvar): dynamic array(S) of real
  forall(s in SHARES | v(s).sol<>0) returned(s):= v(s).sol  
 end-function
 
 initializations to OUTPUTFILE
  evaluation of Return.sol as RETSOL
  evaluation of sum(s in SHARES | buy(s).sol<>0) 1 as NUMSHARES
  evaluation of getvalues(frac) as FRACSOL
  evaluation of getvalues(buy) as BUYSOL
  evaluation of getprobstat as SOLSTATUS
 end-initializations

end-model 

Back to examples browserPrevious exampleNext example