FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserNext example

Portfolio optimization using pandas to calculate covariance

Description
Modeling a small QP problem to perform portfolio optimization using pandas Python library to calculate covariance matrix.

Further explanation of this example: see Chapter 'Python' in the 'Mosel Language Reference Manual'

folioqp_pandas.zip[download all files]

Source Files
By clicking on a file name, a preview is opened at the bottom of this page.
folioqp_pandas.mos[download]

Data Files





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

   !!! This example requires an installation of Python 3, see
   !!! chapter 'python3' of the 'Mosel Language Reference' for
   !!! compatible versions and setup instructions.

  (c) 2019 Fair Isaac Corporation
      authors: S. Lannez, J. Müller
*********************************************************!)

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 ****

! Import functions from Python script
 writeln('Importing pandas and covariance function.')
 pyinitpandas
 pyrun('folioqp_pandas.py')

! Copy multiple arrays as DataFrame to Python environment.
! It's also possible to use the Python IO driver to set global variables.
 pysetdf('share_values', [OPEN, CLOSE], ['open', 'close'])
 pyexec('share_values.index.names = ["shares", "dates"]')
 pyexec('print(share_values)')

! Print covariance of share value at market openings
 writeln("Covariances at market openings:")
 pyexec('covariance_of_series(share_values.open)')
! Calculate and retrieve covariance of mean value
 writeln("Covariances of mean value of openings and closings:")
 pyget('covariance_of_series(share_values.mean(axis=1))', 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
 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

Back to examples browserNext example