Initializing help system before first use

Folio - performing simple statistics with R


Type: Portfolio optimization
Rating: 2 (easy-medium)
Description: Using R to calculate the covariance matrix that serves as input to a quadratic optimization problem minimizing the variance of an investment portfolio.
Model version 'folioqpgraphr.mos' uses R graph drawing functionality to plot the deviation and display a correlation heatmap.
File(s): folioqpr.mos, folioqpgraphr.mos
Data file(s): folioqphist.dat, folioqp.dat, folioqpgraph.dat

folioqpr.mos
(!******************************************************
   Mosel Example Problems
   ======================

   file folioqpr.mos
   `````````````````
   Modeling a small QP problem 
   to perform portfolio optimization.
   -- 1. QP: minimize variance
      2. MIQP: limited number of assets --
   -- Using R to calculate covariance matrix --
  
   !!! This example requires an installation of R, see the
   !!! chapter 'R' of the 'Mosel Language Reference' for
   !!! compatible versions and setup instructions
   
  (c) 2015 Fair Isaac Corporation
      author: S.Lannez, Jul. 2015, rev. Sep. 2022
*******************************************************!)

model "Portfolio optimization with QP/MIQP"
 uses "mmxprs", "mmnl"
 uses "r"                            ! Use R functions

 parameters
  MAXVAL = 0.3                       ! Max. investment per share
  MINAM = 0.5                        ! Min. investment into N.-American values
  MAXNUM = 4                         ! Max. number of different assets
  TARGET = 9.0                       ! Minimum target yield
 end-parameters

 declarations
  SHARES = 1..10                     ! Set of shares
  RISK: set of integer               ! Set of high-risk values among shares
  NA: set of integer                 ! Set of shares issued in N.-America
  DATES: set of string               ! Historical dates
  RET: array(SHARES) of real         ! Estimated return in investment
  VAR: array(SHARES,SHARES) of real  ! Variance/covariance matrix of
                                     ! estimated returns
  OPEN: array(SHARES,DATES) of real  ! Historical share value at market opening
  CLOSE: array(SHARES,DATES) of real ! Historical share value at market closing
 end-declarations

 initializations from "folioqp.dat"
  RISK RET NA
 end-initializations

! Load historical values to compute the covariance 
 initializations from "folioqphist.dat"
  OPEN CLOSE
 end-initializations

! **** Perform some statistics using R **** 

! Copy array to R environments
 Rset('open',OPEN) 
 Rset('close',CLOSE)
! Print covariance of share value at market openings
 writeln("Covariances at market openings:")
 Rprint('cov(t(open))')
! Calculate and retrieve covariance of mean value
 Rgetarr('cov(t((open+close)/2))',VAR)

 declarations
  frac: array(SHARES) of mpvar      ! Fraction of capital used per share
 end-declarations

! **** First problem: unlimited number of assets ****

! Objective: mean variance
 Variance:= sum(s,t in SHARES) VAR(s,t)*frac(s)*frac(t) 

! Minimum amount of North-American values
 sum(s in NA) frac(s) >= MINAM

! Spend all the capital
 sum(s in SHARES) frac(s) = 1
 
! Target yield
 sum(s in SHARES) RET(s)*frac(s) >=  TARGET

! Upper bounds on the investment per share
 forall(s in SHARES) frac(s) <= MAXVAL

! Solve the problem
 minimize(Variance)

! Solution printing
 writeln("With a target of ", TARGET, " minimum variance is ", getobjval)
 forall(s in SHARES) writeln(s, ": ", getsol(frac(s))*100, "%")  

! **** Second problem: limit total number of assets ****

 declarations
  buy: array(SHARES) of mpvar       ! 1 if asset is in portfolio, 0 otherwise
 end-declarations

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

 forall(s in SHARES) do
  buy(s) is_binary
  frac(s) <= buy(s)
 end-do

! Solve the problem
 minimize(Variance)
 writeln("With a target of ", TARGET," and at most ", MAXNUM,
          " assets,\n minimum variance is ", getobjval)
 forall(s in SHARES) writeln(s, ": ", getsol(frac(s))*100, "%") 

! Round integer values and resolve
 fixmipentities(true)
 minimize(Variance)
 writeln("With all binary variables rounded to the nearest integer:")
 forall(s in SHARES) writeln(s, ": ", getsol(frac(s))*100, "%") 
 
end-model 

folioqpgraphr.mos
(!******************************************************
   Mosel R Example Problems
   ========================

   file folioqpgraphr.mos
   ``````````````````````
   Modeling a small QP problem 
   to perform portfolio optimization.
   Minimize variance subject to different target return.
   -- Using R to calculate covariance matrix --
   -- Graphical output via R --
  
   !!! This example requires an installation of R, see the
   !!! chapter 'R' of the 'Mosel Language Reference' for
   !!! compatible versions and setup instructions
   
  (c) 2015 Fair Isaac Corporation
      author: S.Lannez, Jul. 2015, rev. Sep. 2017
*******************************************************!)

model "Portfolio optimization with QP, graphical output"
 uses "mmxprs", "mmnl"
 uses "mmsystem"
 uses "r"                            ! Use R functions

 parameters
  MAXVAL = 0.3     ! Max. investment per share
  MINAM = 0.5      ! Min. investment into N.-American values
  GRDEVICE = "png" ! Set to 'png' or 'pdf' to change the type of document.  
 end-parameters

 declarations
  SHARES = 1..10                     ! Set of shares
  RISK: set of integer               ! Set of high-risk values among shares
  NA: set of integer                 ! Set of shares issued in N.-America
  DATES: set of string               ! Historical dates
  RET: array(SHARES) of real         ! Estimated return in investment
  VAR: array(SHARES,SHARES) of real  ! Variance/covariance matrix of
                                     ! estimated returns
  OPEN: array(SHARES,DATES) of real  ! Historical share value at market opening
  CLOSE: array(SHARES,DATES) of real ! Historical share value at market closing				     
  SOLRET: array(range) of real       ! Solution values (total return)
  SOLDEV: array(range) of real       ! Solution values (average deviation)
 end-declarations

 initializations from "folioqp.dat"
  RISK RET NA
 end-initializations

! Load historical values to compute the covariance 
 initializations from "folioqphist.dat"
  OPEN CLOSE
 end-initializations

! **** Perfom some statistics using R **** 

! Copy array to R environments
 Rset('open',OPEN) 
 Rset('close',CLOSE)
! Print covariance of share value at market openings
 writeln("Covariances at market openings:")
 Rprint('cov(t(open))')
! Calculate and retrieve covariance of mean value
 Rgetarr('cov(t((open+close)/2))',VAR)

! **** Mathematical model **** 

 declarations
  frac: array(SHARES) of mpvar       ! Fraction of capital used per share
 end-declarations

! Objective: mean variance
 Variance:= sum(s,t in SHARES) VAR(s,t)*frac(s)*frac(t) 

! Minimum amount of North-American values
 sum(s in NA) frac(s) >= MINAM

! 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

! Solve the problem for a range of returns: this is the efficient frontier
 target:= min(s in SHARES) RET(s)
 RMAX:= max(s in SHARES) RET(s)

 while(target < RMAX) do
   Return:= sum(s in SHARES) RET(s)*frac(s) >= target    ! Target yield
   minimize(Variance)                ! Solve the problem
   
   if (getprobstat = XPRS_OPT) then  ! Save the optimal solution value
    ct+=1
    SOLDEV(ct):= getobjval
    SOLRET(ct):= target
    writeln("Solution for target ", target, "%")
   else
    writeln("No solution for target return >= ", target, "%")
    break
   end-if
   target += 1
 end-do

! **** Drawing graphs to represent results and data ****

 declarations
  DEV: array(SHARES) of real         ! Standard deviation
  NAMES: array(SHARES) of string     ! Names of shares
  t: text
 end-declarations

 initializations from "folioqpgraph.dat"
  NAMES ! DEV
 end-initializations

! Compute the standard deviation
 forall(s in SHARES) DEV(s) := sqrt(VAR(s,s))

! Setting up the R environment
 Reval('require(graphics)')          ! plot() and heatmap() functions
 Reval('require(grDevices)')         ! heatmap dependency

 if (GRDEVICE.size>0) then 
   Reval(GRDEVICE+'("folioqpgraphr%03d.'+GRDEVICE+'")') ! Open graphical file
 end-if

! **** Drawing the efficient frontier ****

! Copy arrays to R
 Rset('solval',SOLRET)      
 Rset('soldev',SOLDEV) 
 
! Plot the graphs
 Reval('plot(solval,soldev,color="black",type="l",'+
   'main="Portfolio Return",'+
   'xlab="Solution Value",ylab="Solution Variance")')
 Reval('points(solval,soldev,pch=21,cex=1,col="dark red")')
 if (GRDEVICE.size=0) then           ! Wait for user entry
  Reval('dev.flush()')               ! Print plots
  writeln("Press enter to continue...")
  dummy := readtextline(t)
 end-if
 
! Clean up arrays
 Reval('rm(solval)')        
 Reval('rm(soldev)')

! **** Drawing the shares characteristics ****

! Copy arrays to R
 Rset('ret',RET)            
 Rset('dev',DEV)
 Rset('names',NAMES)
 Rset('risk',RISK)
 Rset('shares',SHARES)
 
! Create the color vectors
 Reval('h <- c()')          
 Reval('h[shares] <- "green"')
 Reval('h[risk] <- "red"')  

! Plot the graphs
 Reval('plot(ret,dev,col=h,bg=h,type="p",pch=21,'+
   'main="Shares",'+
   'xlab="Share Value",ylab="Share Deviation",'+
   'xlim=c(-5,max(ret)+5),ylim=c(min(dev)-5,max(dev)+5))')
 Reval('legend("topleft",c("high risk","low risk"),'+
   'col=c("red","green"),pch=21)') 
 Reval('text(ret,dev,names,pos=3)')
 if (GRDEVICE.size=0) then           ! Wait for user entry
  Reval('dev.flush()')               ! Print plots
  writeln("Press enter to continue...")
  dummy := readtextline(t)
 end-if

! Clean up arrays 
 forall(ar in {"ret","dev","risk","shares"}) 
   Reval('rm('+ar+')')

! **** Drawing the correlation heat map ****

 Reval('z <- cor(t(open+close)/2)')  ! Compute the correlation matrix
 Reval('rownames(z) <- names')       ! Set the name of the rows
 Reval('colnames(z) <- names')       ! Set the name of the columns
 Rprint('symnum(z)')                 ! Textual representation of the correlation
 Reval('heatmap(z,Rowv=NA,Colv=NA,symm=TRUE,main="Share Value Correlation")')
 if (GRDEVICE.size=0) then           ! Wait for user entry
  Reval('dev.flush()')               ! Print plots
  writeln("Press enter to continue...")
  dummy := readtextline(t)
 end-if

 Reval('dev.off()')                  ! Close current document

end-model 

© 2001-2025 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.