Class MarkowitzModel

All Implemented Interfaces:
Comparable<FinancePortfolio>, FinancePortfolio.Context

public final class MarkowitzModel extends OptimisedPortfolio

The Markowitz model, in this class, is defined as:

min (RAF/2) [w]T[C][w] - [w]T[r]
subject to |[w]| = 1

RAF stands for Risk Aversion Factor. Instead of specifying a desired risk or return level you specify a level of risk aversion that is used to balance the risk and return.

The expected returns for each of the assets must be excess returns. Otherwise this formulation is wrong.

The total weights of all assets will always be 100%, but shorting can be allowed or not according to your preference. ( OptimisedPortfolio.setShortingAllowed(boolean) ) In addition you may set lower and upper limits on any individual asset. ( setLowerLimit(int, BigDecimal) and setUpperLimit(int, BigDecimal) )

Risk-free asset: That means there is no excess return and zero variance. Don't (try to) include a risk-free asset here.

Do not worry about the minus sign in front of the return part of the objective function - it is handled/negated for you. When you're asked to supply the expected excess returns you should supply precisely that.

Basic usage instructions

After you've instantiated the MarkowitzModel you need to do one of three different things:
  1. invalid reference
    #setRiskAversion(Number)
    unless this was already set in the MarketEquilibrium or FinancePortfolio.Context used to instantiate the MarkowitzModel
  2. setTargetReturn(BigDecimal)
  3. setTargetVariance(BigDecimal)

Optionally you may setLowerLimit(int, BigDecimal), setUpperLimit(int, BigDecimal) or OptimisedPortfolio.setShortingAllowed(boolean).

To get the optimal asset weighs you simply call EquilibriumModel.getWeights() or EquilibriumModel.getAssetWeights().

If the results are not what you expect the first thing you should try is to turn on optimisation model validation: model.optimisation().validate(true);

  • Field Details

    • _0_0

      private static final double _0_0
    • INIT

      private static final double INIT
    • MAX

      private static final double MAX
    • MIN

      private static final double MIN
    • TARGET_CONTEXT

      private static final NumberContext TARGET_CONTEXT
    • myConstraints

      private final HashMap<int[],LowerUpper> myConstraints
    • myOptimisationModel

      private transient ExpressionsBasedModel myOptimisationModel
    • myTargetReturn

      private BigDecimal myTargetReturn
    • myTargetVariance

      private BigDecimal myTargetVariance
  • Constructor Details

  • Method Details

    • addConstraint

      public LowerUpper addConstraint(BigDecimal lowerLimit, BigDecimal upperLimit, int... assetIndeces)
      Will add a constraint on the sum of the asset weights specified by the asset indices. Either (but not both) of the limits may be null.
    • clearAllConstraints

      public void clearAllConstraints()
    • setLowerLimit

      public void setLowerLimit(int assetIndex, BigDecimal lowerLimit)
    • setTargetReturn

      public void setTargetReturn(BigDecimal targetReturn)

      Will set the target return to whatever you input and the target variance to null.

      Setting the target return implies that you disregard the risk aversion factor and want the minimum risk portfolio with return that is equal to or as close to the target as possible.

      There is a performance penalty for setting a target return as the underlying optimisation model has to be solved several (many) times with different pararmeters (different risk aversion factors).

      Setting a target return (or variance) is not recommnded. It's much better to simply modify the risk aversion factor.

      See Also:
    • setTargetVariance

      public void setTargetVariance(BigDecimal targetVariance)

      Will set the target variance to whatever you input and the target return to null.

      Setting the target variance implies that you disregard the risk aversion factor and want the maximum return portfolio with risk that is equal to or as close to the target as possible.

      There is a performance penalty for setting a target variance as the underlying optimisation model has to be solved several (many) times with different pararmeters (different risk aversion factors).

      Setting a target variance is not recommnded. It's much better to modify the risk aversion factor.

      See Also:
    • setUpperLimit

      public void setUpperLimit(int assetIndex, BigDecimal upperLimit)
    • toString

      public String toString()
      Overrides:
      toString in class EquilibriumModel
    • generateOptimisationModel

      private ExpressionsBasedModel generateOptimisationModel(double riskAversion)
    • calculateAssetWeights

      protected MatrixR064 calculateAssetWeights()
      Constrained optimisation.
      Specified by:
      calculateAssetWeights in class EquilibriumModel
    • reset

      protected void reset()
      Overrides:
      reset in class OptimisedPortfolio
    • calculatePortfolioReturn

      Scalar<?> calculatePortfolioReturn(Access1D<?> weightsVctr, MatrixR064 returnsVctr)
    • calculatePortfolioVariance

      Scalar<?> calculatePortfolioVariance(Access1D<?> weightsVctr)