com.opengamma.analytics.financial.calculator.PortfolioHedgingCalculator.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.calculator.PortfolioHedgingCalculator.java

Source

/**
 * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.analytics.financial.calculator;

import java.util.LinkedHashSet;

import org.apache.commons.lang.ArrayUtils;

import com.opengamma.analytics.financial.forex.method.FXMatrix;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity;
import com.opengamma.analytics.math.linearalgebra.SVDecompositionCommons;
import com.opengamma.analytics.math.linearalgebra.SVDecompositionResult;
import com.opengamma.analytics.math.matrix.CommonsMatrixAlgebra;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.util.money.Currency;
import com.opengamma.util.tuple.ObjectsPair;
import com.opengamma.util.tuple.Pair;

/**
 * Computes the optimal hedging portfolio made of reference instruments to hedge a given sensitivity.
 * <p> Reference: Portfolio hedging with reference securities, version 1.0, OG notes, October 2010.
 */
public class PortfolioHedgingCalculator {

    /**
     * The matrix algebra used (mainly multiplying matrices and solving systems).
     */
    private static final CommonsMatrixAlgebra MATRIX = new CommonsMatrixAlgebra();
    /**
     * The decomposition method used.
     */
    private static final SVDecompositionCommons DECOMPOSITION = new SVDecompositionCommons();

    /**
     * Computes the quantity of each reference instrument that optimally hedge a given sensitivity.
     * @param ps The parameter sensitivity of the portfolio to hedge.
     * @param rs The parameter sensitivities of the reference instruments.
     * @param w The related parameters weight matrix. The order of the curve should be their "natural" order.
     * @param order The ordered set of name.
     * @param fxMatrix The matrix with exchange rates.
     * @return The optimal hedging quantities. The quantities are in the same order as the reference instruments sensitivities.
     * Note that the output is the optimal hedge quantity and not the portfolio equivalent. The hedge has the opposite sign of wrt the equivalent.
     */
    public static double[] hedgeQuantity(final MultipleCurrencyParameterSensitivity ps,
            final MultipleCurrencyParameterSensitivity[] rs, final DoubleMatrix2D w,
            final LinkedHashSet<Pair<String, Integer>> order, final FXMatrix fxMatrix) {
        final Currency ccy = ps.getAllNamesCurrency().iterator().next().getSecond();
        // Implementation note: currency used for the conversion in a common currency. Any currency is fine.
        final int nbReference = rs.length;
        final MultipleCurrencyParameterSensitivity psConverted = ps.converted(fxMatrix, ccy);
        final MultipleCurrencyParameterSensitivity[] rsConverted = new MultipleCurrencyParameterSensitivity[nbReference];
        for (int loopref = 0; loopref < nbReference; loopref++) {
            rsConverted[loopref] = rs[loopref].converted(fxMatrix, ccy);
        }
        // Implementation note: converting the ParameterSensitivity into a matrix.
        final DoubleMatrix1D p = toMatrix(psConverted, order);
        final double[][] rsArray = new double[nbReference][];
        for (int loopref = 0; loopref < nbReference; loopref++) {
            rsArray[loopref] = toMatrix(rsConverted[loopref], order).getData();
        }
        final DoubleMatrix2D r = new DoubleMatrix2D(rsArray);
        final DoubleMatrix2D wtW = (DoubleMatrix2D) MATRIX.multiply(MATRIX.getTranspose(w), w);
        final DoubleMatrix2D rWtW = (DoubleMatrix2D) MATRIX.multiply(r, wtW);
        final DoubleMatrix2D rWtWRt = (DoubleMatrix2D) MATRIX.multiply(rWtW, MATRIX.getTranspose(r));
        final DoubleMatrix1D rWtWP = ((DoubleMatrix2D) MATRIX.scale(MATRIX.multiply(rWtW, p), -1.0))
                .getColumnVector(0);
        final SVDecompositionResult dec = DECOMPOSITION.evaluate(rWtWRt);
        final DoubleMatrix1D q = dec.solve(rWtWP);
        return q.getData();
    }

    /**
     * Convert the parameter sensitivity into a matrix (DoubleMatrix1D). All the sensitivities should be in the same currency.
     * The matrix is composed of the sensitivity vectors (currency is ignored) one after the other.
     * The matrix order is the one of the set.
     * @param sensi The sensitivity.
     * @param order The ordered set of name.
     * @return The sensitivity matrix.
     */
    public static DoubleMatrix1D toMatrix(final MultipleCurrencyParameterSensitivity sensi,
            final LinkedHashSet<Pair<String, Integer>> order) {
        double[] psArray = new double[0];
        final Currency ccy = sensi.getAllNamesCurrency().iterator().next().getSecond();
        // Implementation note: all the currencies are supposed to be the same, we choose any of them.
        for (final Pair<String, Integer> nameSize : order) {
            if (sensi.getSensitivities().containsKey(new ObjectsPair<>(nameSize.getFirst(), ccy))) {
                psArray = ArrayUtils.addAll(psArray, sensi.getSensitivity(nameSize.getFirst(), ccy).getData());
            } else { // When curve is not in the sensitivity, add zeros.
                psArray = ArrayUtils.addAll(psArray, new double[nameSize.getSecond()]);
            }
        }
        return new DoubleMatrix1D(psArray);
    }

}