Initializing help system before first use

# Robust portfolio optimization

Topics covered in this section:

- Problem description
- Mathematical formulation
  - Highest protection
  - Budgeted protection
- Implementation
- Results
  - Input Data
  - Analysis
- References

## Problem description

The single-period portfolio selection problem is about selecting assets from a given list in order to create a portfolio that has the greatest expected value. The assets are bought at the market price and their value is subject to variation. The investment budget is fixed, and each selected asset is bought using a percentage of the available budget. The market price for each asset is known at the time of buying and corresponds to the payment to be made by the trader to buy one unit. The future asset value is not known, but we assume the distribution characteristics of the random variable is known. The trader is risk averse and wants to have some guarantees about the worst case value of the portfolio. She considers that in the worst case the downward variation of an asset value reaches 1.5 times the variance of the asset. In other words, the trader assumes it is very unlikely that the value of an asset decreases by more than 1.5 times its variance.

Example: Let's assume that asset #20 has a market price of 100$ and its variability is +/- 10$. Then the considered worst case value of the asset is 85$.

In this context, the objective of the trader is to maximize the expected value of her portfolio, but without taking too much risk. A conservative trader would definitely spend all her budget in the asset with the highest worst case value in order to be highly protected against the worst possible outcome. Unfortunately, this strategy would dramatically reduce the expected value of the portfolio. Another extreme policy would be an opportunistic trader who spends all her budget in the asset with the highest expected value, without paying much attention to the worst case realization. Both approaches are extreme and do not take into account the fact that it is quite unlikely to see all asset values going down (or going up) to the same degree. In practice traders often aim for portfolios with a guaranteed probability of having a value greater than a minimum target value. This is also known as chance constrained optimization. In the 'Results' section (Results) we will show how robust optimization can be used to provide solutions with a large expected value without sacrificing protection against worst case realization.

## Mathematical formulation

The set S contains the available assets, and the index s∈S represents an asset from this set. The market price of the asset s is noted PRICEs, and its variability range is given by VARs. For each asset s∈S, the variable xs represents the fraction of the budget spent to buy asset s. The variable w is used to represent the worst case value of the portfolio. The variable devs describes the possible variation of the value of the asset s. The value N describes the worst case the trader will consider and corresponds to the maximum decrease of the asset value expressed as a multiple of its standard deviation.

#### Highest protection

A conservative trader will want to maximize the worst case value of her portfolio. If she wants to get the best protection against worst case realization, then she will try to maximize the worst case value of her portfolio. In our example, this worst case realizes when the value of every asset decreases by N times its standard deviation.

max w
s.t. w ≤ ∑s∈S (PRICEs + N·devs)·xs (with devs = - VARs)
∑s∈S xs = 1
0 ≤ xs ≤ 1

#### Budgeted protection

As we will see in the discussion of the results (Section Results), achieving a high protection against worst case realization incurs an important loss of value in the average case. And hence, this strategy may not be such a clever choice because average cases are more likely to happen. The trader therefore might want to improve her model by adding a control parameter to limit the protection level. The overall variation budget G is defined by the following formula:

G =

∑
s∈S

(N· VARs) 2

The ellipsoidal uncertainty set
Let k be the percentage value representing the protection level. The possible asset value decrease is controlled by the uncertainty set U(k) that is defined as follows:

U(k) = { e :

∑
s∈S

es2 ≤ (k·G)2 }

Robust constraints
The resulting robust optimization problem can then be stated as:

max w
s.t. w ≤ ∑s∈S (PRICEs + es) · xs (∀ e∈U(k))
∑s∈S xs = 1
0 ≤ xs ≤ 1

## Implementation

The following Mosel model implements the mathematical model from the previous section. Notice how the ellipsoid uncertainty set is added to the original problem to create a robust optimization problem.

Also, take a look at how the Monte-Carlo simulation method is applied to quantify the quality of the solution: in NMC=5000 iterations we draw random values for the expected value of every asset by applying a normal distribution centered around its price (mean value) and using its known variance. We count the occurrence of objective function values (or more precisely, which value range the resulting solution value belongs to) to determine the probabilities of different solution qualities. This method is particularly helpful to gain some insight about the solution quality when it is difficult to determine the exact shape of the distribution function of a random variable.

    model "Robust portfolio optimization"
      uses "mmrobust", "random"
      uses "mmsystem"

      parameters
        ZEROTOL=1e-6
        SEED=12345
        NMC=500000
        N=1.5                              ! Worst case metric
      end-parameters

      declarations
        Problems: set of mpproblem
        ProtectLevel: set of real

        mp_problemA: mpproblem             ! Worst case optimization
        mp_problemB: array(ProtectLevel) of mpproblem  ! Robust optimization
        NSHARES = 25                       ! Max number of shares
        Shares = 1..NSHARES                ! Set of shares

        PRICE: array(Shares) of real       ! Expected return on investment
        VAR: array(Shares) of real         ! Uncertainty measure (deviation) per SHARE

        expReturn: mpvar                   ! Expected portfolio value
        wstReturn: mpvar                   ! Worst case portfolio value
        frac: array(Shares) of mpvar       ! Fraction of capital used per share
        frac_sol: array(Shares,Problems) of real
        obj: mpvar

        e: array(Shares) of uncertain      ! Deviation of share values
        PRICEthr: array(Problems,Shares) of real    ! The price threshold

      end-declarations

    !***************************Configuration*************************
     setparam("XPRS_LOADNAMES",true)

    !***************************Subroutines***************************
     !**** Create the nominal model ****
      procedure create_nominalmodel
        ! Nominal model
        expReturn = (sum(s in Shares) PRICE(s)*frac(s))
        wstReturn = sum(s in Shares) ( PRICE(s) - N*VAR(s) )*frac(s)

        ! Spend all the budget
        sum(s in Shares) frac(s) = 1
      end-procedure

     !**** Optimize for the worst case realization ****
      procedure solve_det
        obj = wstReturn
        maximize(obj)
      end-procedure

     !**** Optimize for a given protection level ****
      procedure solve_rob(k: real)
        ! The value variation domain

        assert(k>=0  and k<=1)
        sum(s in Shares) (e(s) / (N*VAR(s)))^2 <= (k)^2

        ! The robust constraint
        obj <= sum(s in Shares) (PRICE(s) + e(s)) * frac(s)

        maximize(obj)
      end-procedure

    !***************************Main model***************************
      !**** Input data generation ****
      setmtrandseed(12345)
      cnt := 0
      forall(s in Shares, cnt as counter) do
        PRICE(s) := round((100*(NSHARES-cnt+1)/NSHARES))
        c := (1+sqrt((NSHARES-s)/NSHARES))/3
        VAR(s) := round(PRICE(s)*c*100)/100
      end-do

      writeln("\n *** Input Data *** ")
      writeln
      writeln("Shares | Mean | S.Dev. | Worst value")
      forall(s in Shares)
        writeln(strfmt(s,6), " |", strfmt(PRICE(s),5), " |", strfmt(VAR(s),7,2),
          " |", strfmt(PRICE(s)-N*VAR(s),6,3))
      writeln

      !**** Optimize the worst case ****
      with mp_problemA do
        create_nominalmodel
        solve_det
        forall(s in Shares) frac_sol(s,mp_problemA) := frac(s).sol*100
        ! Price set by opponent is worst case price
        forall(s in Shares) PRICEthr(mp_problemA,s) := PRICE(s) - N*VAR(s)
      end-do

      !**** Optimize the 'budgeted' worst case ****
      Ks := [0.0,     ! No variation on average
             0.01,    ! +/-  1% variation on the list
             0.10,    ! +/- 10% variation on the list
             0.25,    ! +/- 25%
             1.0]     ! +/-100% variation on the list
      forall(k in Ks) do
        create(mp_problemB(k))
        with mp_problemB(k) do
          create_nominalmodel
          solve_rob(k)
          forall(s in Shares) frac_sol(s,mp_problemB(k)) := frac(s).sol*100
          forall(s in Shares) PRICEthr(mp_problemB(k),s) := (PRICE(s) + getsol(e(s)))
        end-do
      end-do

      !**** Print results ****
      writeln("\n *** Portfolio allocation results *** ")
      write("\n                                  |  protection level")
      write("\nShares | Wst price | Price |  A   |")
      forall(k in Ks) write(" ", strfmt(k*100,3), "% |" ) ; writeln
      forall(s in Shares) do
        write(strfmt(s,6), " |", strfmt(PRICE(s)-N*VAR(s),10,0), " |",
          strfmt(PRICE(s),6), " | ")
        forall(mp in Problems) do
          if (frac_sol(s,mp)>1) then
            write(strfmt(frac_sol(s,mp),3,0), "% | ")
          else
            write("     | ")
          end-if
        end-do
        writeln
      end-do

      writeln("\n *** Worst case price *** ")
      write("\n                                  |  protection level")
      write("\nShares | Wst price | Price |  A   |")
      forall(k in Ks) write(" ", strfmt(k*100,3), "% |" ) ; writeln
      forall(s in Shares) do
        write(strfmt(s,6), " |", strfmt(PRICE(s)-N*VAR(s),10,0), " |",
          strfmt(PRICE(s),6), " | ")
        forall(mp in Problems) do
          if (frac_sol(s,mp)>1) then
            write(strfmt(PRICEthr(mp,s),3,0), "* | ")
          else
            write(strfmt(PRICEthr(mp,s),4,0), " | ")
            ! write("     | ")
          end-if
        end-do
        writeln
      end-do

      !**** Simulate results (Monte-Carlo simulation) ****
      writeln("\nRunning Monte-Carlo simulation...")
      Values := {0,20,40,60,80,100}
      declarations
        cntV: dynamic array(Problems,Values) of real
        s1: real
        s2: real
      end-declarations
      forall(mp in Problems) do
        expRev(mp) := 0.0 ; wstRev(mp) := 0.0 ; expDev(mp) := 0.0
        forall(v in Values) cntV(mp,v) := 0
        c := 0.0 ! Number of draws
        s1 := 0 ; s2 := 0;
        forall(i in 1..NMC, c as counter) do
          totalVal := 0.0 ; totalRisk := 0.0
          forall(s in Shares | frac_sol(s,mp)>0) do
           	! draw a price
            p := normal(PRICE(s),VAR(s))
            ! calculate share revenue
            r := frac_sol(s,mp)*p/100
            ! calculate total revenue
            totalVal += r ! summing up revenue
          end-do
          forall(v in Values) do
            if (totalVal>v) then
              cntV(mp,v) += 1
            end-if
          end-do
          expRev(mp) += totalVal
          s1 += totalVal
          s2 += totalVal^2
        end-do
        expRev(mp) := expRev(mp) / c
        expDev(mp) := sqrt(NMC*s2 - s1^2)/(NMC)
        forall(v in Values) cntV(mp,v) := cntV(mp,v) / c
      end-do

      !**** Print simulation results ****
      write("\n                                   |  protection level")
      write("\n                            |  A   |")

      forall(k in Ks) write(" ", strfmt(k*100,3), "% |" )
      write("\n            Expected value  |")
      forall(mp in Problems) write(strfmt(round(expRev(mp)),5), " |")
      write("\n        Standard deviation  |")
      forall(mp in Problems) write(strfmt(round(expDev(mp)),5), " |")

      writeln
      forall(v in Values) do
        write("\n             P (value>"+textfmt(v,3)+"   |")
        forall(mp in Problems) write(strfmt(cntV(mp,v),5,2) , "  |")
      end-do

    end-model

## Results

In order to understand how the uncertainty set impacts the solution we will solve the portfolio allocation problem for various protection levels k and compare the proposed budget allocation against the conservative approach.

The trader knows that she can expect a portfolio value in the range of 0 to 100. She therefore wishes to calculate for various ranges the probability that the value of the portfolio will belong to this range. She also wants to reach a portfolio value of 60 with high probability.

#### Input Data

Table Asset value distribution shows the asset mean value which is also the market price (Mean), the standard variation of the value (S. Dev), and the considered worst case value with N=1.5 (Worst value).

Table 11: Asset value distribution
Shares | Mean | S.Dev. | Worst value
--- | --- | --- | ---
1 | 100 | 65.99 | 1.015
2 | 96 | 62.69 | 1.965
3 | 92 | 59.43 | 2.855
4 | 88 | 56.22 | 3.670
5 | 84 | 53.04 | 4.440
6 | 80 | 49.91 | 5.135
7 | 76 | 46.83 | 5.755
8 | 72 | 43.79 | 6.315
9 | 68 | 40.80 | 6.800
10 | 64 | 37.86 | 7.210
11 | 60 | 34.97 | 7.545
12 | 56 | 32.13 | 7.805
13 | 52 | 29.34 | 7.990
14 | 48 | 26.61 | 8.085
15 | 44 | 23.94 | 8.090
16 | 40 | 21.33 | 8.005
17 | 36 | 18.79 | 7.815
18 | 32 | 16.31 | 7.535
19 | 28 | 13.91 | 7.135
20 | 24 | 11.58 | 6.630
21 | 20 | 9.33 | 6.005
22 | 16 | 7.18 | 5.230
23 | 12 | 5.13 | 4.305
24 | 8 | 3.20 | 3.200
25 | 4 | 1.33 | 2.005

A quick glance at the input data reveals that asset #15 would be the best choice for the conservative trader because it has the highest worst case value, whereas asset #1 would be the preferred investment for an optimistic trader since it has the largest best case value.

#### Analysis

In order to understand how the robust optimization behaves compared to the nominal problem, we solve the nominal problem (A) and 5 robust optimization problems parameterized by the protection level k (ranging from 0 to 1=100%). With a protection level of k=0 the deviation budget is also zero, and hence the solution is a very optimistic one.

In a second step, we use a Monte-Carlo method to simulate the actual value of the assets selected by these solutions and calculate the probability with which the portfolio value lies in the various revenue ranges.

Table Results of the parameterized robust optimization presents the portfolio selection suggestion for each of these problems. For the sake of simplicity we list only those assets that are selected in at least one solution. The conservative solution (A) is to allocate all budget to the asset with highest worst case value. The optimistic solution (k=0.0) is to allocate the whole budget to the asset with the highest expected value. With an increasing protection level the suggested solutions improve the balance between assets with a high largest expected value and those with a high worst case value.

Table 12: Results of the parameterized robust optimization
Shares | Wst price | Price | A | k=0.0% | k=1% | k=10% | k=25% | k=100%
--- | --- | --- | --- | --- | --- | --- | --- | ---
1 | 1 | 100 |  | 100% | 100% | 60% | 33% | 11%
2 | 2 | 96 |  |  |  | 35% | 28% | 11%
3 | 3 | 92 |  |  |  | 5% | 22% | 11%
4 | 4 | 88 |  |  |  |  | 14% | 11%
5 | 4 | 84 |  |  |  |  | 3% | 11%
6 | 5 | 80 |  |  |  |  |  | 10%
7 | 6 | 76 |  |  |  |  |  | 10%
8 | 6 | 72 |  |  |  |  |  | 9%
9 | 7 | 68 |  |  |  |  |  | 7%
10 | 7 | 64 |  |  |  |  |  | 5%
11 | 8 | 60 |  |  |  |  |  | 2%
15 | 8 | 44 | 100% |  |  |  |  |

Table Results of the Monte-Carlo simulation presents the results of the Monte-Carlo simulation of the portfolio value for each portfolio selection suggestion. The conservative solution (A) is the one with highest worst case value, and as expected the probability of this portfolio's value to go above 60 is very low. From the trader's point of view this is not a good solution, even in the average case for which she will get a value of 44.

The optimistic solution (k=0%) and the solution with the lowest protection level (k=1%) have the largest expected value. However, the trader cannot use these two solutions because she won't be able to commit to achieving a minimum value of 60 since the probability of obtaining a portfolio value greater than 60 is only 73% for these two solutions.

The behavior of the other solutions (k≥10%) shows that with an increasing deviation budget, the probability of achieving a portfolio value higher than 60 also increases. The worst case value of the portfolio equally increases while the expected value decreases. The volatility of the distribution of the values against the three ranges tends to reduce.

Table 13: Results of the Monte-Carlo simulation
| A | k=0.0% | k=1% | k=10% | k=25% | 100%
--- | --- | --- | --- | --- | --- | ---
Expected value | 44 | 100 | 100 | 98 | 95 | 83
Standard deviation | 24 | 66 | 66 | 45 | 32 | 17
P (value≥0) | 97% | 94% | 93% | 98% | 100% | 100%
P (value≥20) | 84% | 89% | 89% | 96% | 99% | 100%
P (value≥40) | 57% | 82% | 82% | 90% | 96% | 99%
P (value≥60) | 25% | 73% | 73% | 80% | 86% | 91%
P (value≥80) | 07% | 62% | 62% | 66% | 68% | 58%
P (value≥100) | 01% | 50% | 50% | 48% | 44% | 17%

The solution with k=100% protects the trader against important losses and allows her to commit to a minimum portfolio value of 60 with a likelyhood of more than 90% and a total expected value of 83. A more risk-prone trader may want to reduce the protection level to say, 10% resulting in a considerably higher average outcome (98) and still having a 90% chance of achieving a portfolio value greater than 40.

## References

The presented problem is inspired by the Single-Period Portfolio selection problem described in [Bng09].

Applications of robust optimization to portfolio optimizations models date back to as early as 2000 [Bmn00].

Parent Topic Robust Optimization Guide

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