Initializing help system before first use

Portfolio optimization using pandas to calculate covariance


Type: Programming
Rating: 2 (easy-medium)
Description: Modeling a small QP problem to perform portfolio optimization using pandas Python library to calculate covariance matrix.
File(s): folioqp_pandas.mos
Data file(s): folioqp.dat, folioqphist.dat, folioqp_pandas.py


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

   file folioqp_py.mos
   ```````````````````
   Modeling a small QP problem
   to perform portfolio optimization.
   -- 1. QP: minimize variance
      2. MIQP: limited number of assets --
   -- Using Python to calculate covariance matrix --

  (c) 2018 Fair Isaac Corporation
      author: S. Lannez, J. Müller, April 2018
*******************************************************!)

model "Portfolio optimization with QP/MIQP"
 uses "mmxprs", "mmnl"
 uses "python3"                      ! Use Python 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 Python ****

! Copy array to Python environment
 initialisations to PY_IO_GLOBAL_VAR
  OPEN
  CLOSE
 end-initialisations
! Import functions from Python script
 writeln('Importing pandas and covariance function.')
 pyrun('folioqp_pandas.py')
! Print covariance of share value at market openings
 writeln("Covariances at market openings:")
 pyexec('covariance_of_series(pd.Series(OPEN))')
! Calculate and retrieve covariance of mean value
 writeln("Covariances of mean value of openings and closings:")
 pyexec('VAR = covariance_of_series((pd.Series(OPEN) + pd.Series(CLOSE)) / 2).to_dict()')
 initialisations from PY_IO_GLOBAL_VAR
  VAR
 end-initialisations

 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
 fixglobal(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

© 2001-2019 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.