com.idylwood.utils.OptimizationUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.idylwood.utils.OptimizationUtils.java

Source

/*
 * ====================================================
 * Copyright (C) 2013 by Idylwood Technologies, LLC. All rights reserved.
 *
 * Developed at Idylwood Technologies, LLC.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice 
 * is preserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * The License should have been distributed to you with the source tree.
 * If not, it can be found at
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Authors: Charles Cooper, Harry C Kim
 * Date: 2013
 * ====================================================
 */

package com.idylwood.utils;

import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.RealVector;
import org.apache.commons.math3.linear.SingularValueDecomposition;

// Holder class for new stuff which hasn't had the dependencies gotten rid of yet.
public final class OptimizationUtils {

    private OptimizationUtils() {
    }

    /**
     * Solves for Markowitz optimal portfolio by means of lagrange multiplier.
     * Returns null if it does not exist (the matrix is singular)
     * Otherwise it attempts to find the lowest variance portfolio for
     * the given <code>portfolio_return</code>
     * @param covariance Precalculated covariance matrix
     * @param returns Precalculated vector of returns
     * @param portfolio_return Return to optimize risk for
     * @author Harry C Kim
     * @return
     */
    static final double[] MarkowitzSolve(final double[][] covariance, final double[] returns,
            final double portfolio_return) {
        if (covariance.length != covariance[0].length)
            throw new IllegalArgumentException("Covariance needs to be square matrix");
        if (returns.length != covariance.length)
            throw new IllegalArgumentException("Returns must be same length as covariance");

        /*
        for (int i = 0; i < covariance.length; i++)
           MathUtils.printArray(covariance[i]);
        System.out.println();
        MathUtils.printArray(returns);
        System.out.println();
        */

        final int timePoints = covariance.length;
        final double[][] lagrangeMatrix = new double[timePoints + 2][timePoints + 2];
        //b as in Ax = b
        final double[] b = new double[timePoints + 2];
        for (int i = 0; i < timePoints; i++) {
            for (int j = 0; j < timePoints; j++) {
                lagrangeMatrix[i][j] = 2 * covariance[i][j];
                b[i] = 0;
                // this is like riskTolerance*returns[i]; but since
                // returns[i]*weights[i] = portfolio_return it will go away in the derivative
            }
        }

        for (int j = 0; j < timePoints; j++) {
            lagrangeMatrix[timePoints][j] = returns[j];
            lagrangeMatrix[timePoints + 1][j] = 1;
            lagrangeMatrix[j][timePoints] = returns[j];
            lagrangeMatrix[j][timePoints + 1] = 1;
        }
        b[timePoints] = portfolio_return; //**** what is the constraint on total expected return?
        b[timePoints + 1] = 1;

        /*
        // Print out lagrangeMatrix augmented with b vector
        for(int i=0; i<timePoints+2; i++)
        {
           for(int j=0; j<timePoints+2;j++)
           {
        System.out.print(lagrangeMatrix[i][j] + " ");
           }
           System.out.println(b[i]);
        }
        */
        // TODO use Gaussian elimination solver, may be faster
        // TODO maybe refactor to use idylblas
        RealMatrix lagrangeReal = MatrixUtils.createRealMatrix(lagrangeMatrix);
        RealVector bReal = MatrixUtils.createRealVector(b);
        SingularValueDecomposition svd = new SingularValueDecomposition(lagrangeReal);

        if (!svd.getSolver().isNonSingular())
            return null;

        RealVector solution = svd.getSolver().solve(bReal);

        final double weights[] = new double[timePoints];

        // last two elements of solution are just lagrange multipliers
        for (int i = 0; i < weights.length; i++)
            weights[i] = solution.getEntry(i);

        // put these in some test class
        if (!MathUtils.fuzzyEquals(1, MathUtils.sum(weights)))
            throw new RuntimeException();
        if (!MathUtils.fuzzyEquals(portfolio_return, MathUtils.linearCombination(returns, weights)))
            throw new RuntimeException();
        //The following calculates the risk(variance) for the weights found
        // final double risk = MathUtils.linearCombination(MathUtils.matrixMultiply(covariance, weights),weights);
        return weights;
    }

    /*
       private static final class MarkowitzFunction implements org.apache.commons.math3.analysis.MultivariateFunction
       {
          final double[][] S;
          final double[]R;
          final double q;
          MarkowitzFunction(final double[][] S, final double[]R, final double q)
          {
     this.S = S; this.R = R; this.q = q;
          }
          // this is gonna be so effing slow! haha
          // see http://en.wikipedia.org/wiki/Modern_portfolio_theory
          @Override public final double value(double[] w)
          // w weights, S cov matrix, R expected returns, q risk tolerance
          {
     final double foo = MathUtils.linearCombination(w,MathUtils.matrixMultiply(S,w));
     final double bar = MathUtils.linearCombination(R,w) * q;
     return foo - bar;
          }
       }
       // TODO make this work
       static final double[] cvxSolve(final double[][] S, final double []R, final double q)
       {
          ObjectiveFunction f = new ObjectiveFunction(new MarkowitzFunction(S,R,q));
          final double[] startPoint = new double[S.length];
          java.util.Arrays.fill(startPoint,1.0/S.length);
        
          final double[] ret =
     new NonLinearConjugateGradientOptimizer(
           NonLinearConjugateGradientOptimizer.Formula.FLETCHER_REEVES,
           new SimpleValueChecker(.1,.1)
        )
     .optimize(f,
           GoalType.MINIMIZE,
           new InitialGuess(startPoint)
        )
     .getPoint();
          return ret;
       }
        
       // returns double[] x such that T(c)*x is maximized, A*x <= b, and x>=0
       // TODO debug!
       static final double[] lpSolve(final double[][] A, final double[] b, final double[] c)
       {
          // TODO implement Feynman's simplex solver!
          // all apache stuff
          LinearObjectiveFunction f = new LinearObjectiveFunction(c, 0);
          List<LinearConstraint> constraints = new ArrayList<LinearConstraint>(A.length);
          for (int i = 0; i < A.length; ++i)
     constraints.add(new LinearConstraint(A[i],Relationship.GEQ,b[i]));
        
          final double ret[] = new SimplexSolver()
     .optimize(f,
           new LinearConstraintSet(constraints),
           GoalType.MINIMIZE,
           new NonNegativeConstraint(false),
           new MaxIter(100)
         )
     .getPoint();
        
          return ret;
       }
       */

}