Package com.opengamma.analytics.financial.calculator

Source Code of com.opengamma.analytics.financial.calculator.PortfolioHedgingCalculatorTest

/**
* 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 static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;

import org.testng.annotations.Test;

import com.google.common.collect.Maps;
import com.opengamma.analytics.financial.forex.method.FXMatrix;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity;
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;

/**
* Tests the portfolio hedging calculator, with simplified examples and then with full scale data.
*/
public class PortfolioHedgingCalculatorTest {

  private static final Currency EUR = Currency.EUR;
  private static final Currency USD = Currency.USD;
  private static final String NAME_1 = "Dsc";
  private static final String NAME_2 = "Fwd";
  private static final Pair<String, Currency> NAME_1_EUR = new ObjectsPair<>(NAME_1, EUR);
  private static final Pair<String, Currency> NAME_1_USD = new ObjectsPair<>(NAME_1, USD);
  private static final Pair<String, Currency> NAME_2_EUR = new ObjectsPair<>(NAME_2, EUR);
  private static final double EUR_USD = 1.25;
  private static final FXMatrix FX_MATRIX = new FXMatrix(EUR, USD, EUR_USD);

  private static final double[] SENSI_1 = {1.0, 2.0, 3.0, 0.4};
  private static final int NB_SENSI_1 = SENSI_1.length;
  private static final double[] SENSI_2 = {0.5, 1.0, 0.5, 1.0, 0.5};
  private static final int NB_SENSI_2 = SENSI_2.length;

  private static final LinkedHashSet<Pair<String, Integer>> ORDER = new LinkedHashSet<>();
  static {
    ORDER.add(new ObjectsPair<>(NAME_1, NB_SENSI_1));
    ORDER.add(new ObjectsPair<>(NAME_2, NB_SENSI_2));
  }

  private static final CommonsMatrixAlgebra MATRIX = new CommonsMatrixAlgebra();

  private static final double TOLERANCE = 1.0E-8;

  @Test
  /**
   * Test the hedging portfolio with reference instruments equal to the curve construction instruments.
   */
  public void exactSolution() {
    final LinkedHashSet<Pair<String, Integer>> order = new LinkedHashSet<>();
    order.add(new ObjectsPair<>(NAME_1, NB_SENSI_1));
    final double[] sensiOpposite = new double[NB_SENSI_1];
    for (int loopnode = 0; loopnode < NB_SENSI_1; loopnode++) {
      sensiOpposite[loopnode] = -SENSI_1[loopnode];
    }
    MultipleCurrencyParameterSensitivity ps = new MultipleCurrencyParameterSensitivity();
    ps = ps.plus(NAME_1_EUR, new DoubleMatrix1D(SENSI_1));
    final MultipleCurrencyParameterSensitivity[] rs = new MultipleCurrencyParameterSensitivity[NB_SENSI_1];
    for (int loopnode = 0; loopnode < NB_SENSI_1; loopnode++) {
      rs[loopnode] = new MultipleCurrencyParameterSensitivity();
      final double[] r = new double[NB_SENSI_1];
      r[loopnode] = 1.0;
      rs[loopnode] = rs[loopnode].plus(NAME_1_EUR, new DoubleMatrix1D(r));
    }
    // Unit weights
    final DoubleMatrix2D w1 = new DoubleMatrix2D(NB_SENSI_1, NB_SENSI_1);
    for (int loopnode = 0; loopnode < NB_SENSI_1; loopnode++) {
      w1.getData()[loopnode][loopnode] = 1.0;
    }
    final double[] hedging1 = PortfolioHedgingCalculator.hedgeQuantity(ps, rs, w1, order, FX_MATRIX);
    assertArrayEquals("PortfolioHedgingCalculator: ", sensiOpposite, hedging1, TOLERANCE);
    // Non-uniform diagonal weights
    final DoubleMatrix2D w2 = new DoubleMatrix2D(NB_SENSI_1, NB_SENSI_1);
    for (int loopnode = 0; loopnode < NB_SENSI_1; loopnode++) {
      w2.getData()[loopnode][loopnode] = loopnode + 1.0;
    }
    final double[] hedging2 = PortfolioHedgingCalculator.hedgeQuantity(ps, rs, w2, order, FX_MATRIX);
    assertArrayEquals("PortfolioHedgingCalculator: ", sensiOpposite, hedging2, TOLERANCE);
    // Tri-diagonal weights
    final double[][] w3Array = { {1.0, 0.5, 0, 0}, {0.5, 1.0, 0.5, 0}, {0, 0.5, 1.0, 0.5}, {0, 0, 0.5, 1.0}};
    final DoubleMatrix2D w3 = new DoubleMatrix2D(w3Array);
    final double[] hedging3 = PortfolioHedgingCalculator.hedgeQuantity(ps, rs, w3, order, FX_MATRIX);
    assertArrayEquals("PortfolioHedgingCalculator: ", sensiOpposite, hedging3, TOLERANCE);
  }

  @Test
  /**
   * Test the hedging portfolio. The answer is perturbed to check that it is at a minimum.
   */
  public void checkMin() {
    final int nbSensi = NB_SENSI_1 + NB_SENSI_2;
    MultipleCurrencyParameterSensitivity ps = new MultipleCurrencyParameterSensitivity();
    ps = ps.plus(NAME_1_EUR, new DoubleMatrix1D(SENSI_1));
    ps = ps.plus(NAME_1_USD, new DoubleMatrix1D(SENSI_1));
    ps = ps.plus(NAME_2_EUR, new DoubleMatrix1D(SENSI_2));
    final int nbReference = 4;
    final MultipleCurrencyParameterSensitivity[] rs = new MultipleCurrencyParameterSensitivity[nbReference];
    rs[0] = new MultipleCurrencyParameterSensitivity();
    rs[0] = rs[0].plus(NAME_1_EUR, new DoubleMatrix1D(new double[] {1.0, 0.0, 0.0, 0.0}));
    rs[0] = rs[0].plus(NAME_2_EUR, new DoubleMatrix1D(new double[] {1.0, 0.0, 0.0, 0.0, 0.0}));
    rs[1] = new MultipleCurrencyParameterSensitivity();
    rs[1] = rs[1].plus(NAME_1_EUR, new DoubleMatrix1D(new double[] {0.0, 0.5, 0.0, 0.0}));
    rs[1] = rs[1].plus(NAME_2_EUR, new DoubleMatrix1D(new double[] {0.0, 1.0, 0.0, 0.0, 0.0}));
    rs[2] = new MultipleCurrencyParameterSensitivity();
    rs[2] = rs[2].plus(NAME_1_EUR, new DoubleMatrix1D(new double[] {0.0, 0.0, 1.0, 2.0}));
    rs[2] = rs[2].plus(NAME_2_EUR, new DoubleMatrix1D(new double[] {0.0, 0.0, 0.0, 0.0, 0.0}));
    rs[3] = new MultipleCurrencyParameterSensitivity();
    rs[3] = rs[3].plus(NAME_1_EUR, new DoubleMatrix1D(new double[] {0.0, 0.0, 0.0, 0.0}));
    rs[3] = rs[3].plus(NAME_2_EUR, new DoubleMatrix1D(new double[] {0.0, 0.0, 1.0, 1.0, 1.0}));
    // Weights: tridiagonal + sum by curve
    final DoubleMatrix2D w = new DoubleMatrix2D(nbSensi + 2, nbSensi);
    for (int loopnode = 0; loopnode < nbSensi; loopnode++) {
      w.getData()[loopnode][loopnode] = 1.0;
    }
    for (int loopnode = 0; loopnode < nbSensi - 1; loopnode++) {
      w.getData()[loopnode][loopnode + 1] = 0.5;
      w.getData()[loopnode + 1][loopnode] = 0.5;
    }
    w.getData()[NB_SENSI_1 + NB_SENSI_2] = new double[] {1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Order?
    w.getData()[NB_SENSI_1 + NB_SENSI_2 + 1] = new double[] {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0};
    final DoubleMatrix2D wtW = (DoubleMatrix2D) MATRIX.multiply(MATRIX.getTranspose(w), w);
    // Hedging
    final double[] hedging = PortfolioHedgingCalculator.hedgeQuantity(ps, rs, w, ORDER, FX_MATRIX);
    MultipleCurrencyParameterSensitivity psMin = new MultipleCurrencyParameterSensitivity();
    psMin = psMin.plus(ps);
    for (int loopref = 0; loopref < nbReference; loopref++) { // To created the hedge portfolio
      psMin = psMin.plus(rs[loopref].multipliedBy(hedging[loopref]));
    }
    final DoubleMatrix1D psMinMatrix = PortfolioHedgingCalculator.toMatrix(psMin.converted(FX_MATRIX, EUR), ORDER);
    final DoubleMatrix2D psMinMatrixT = new DoubleMatrix2D(new double[][] {psMinMatrix.getData()});
    final double penalty = ((DoubleMatrix2D) MATRIX.multiply(psMinMatrixT, MATRIX.multiply(wtW, psMinMatrix))).getEntry(0, 0);

    final double shift = 0.01;
    final double[] penaltyPlus = new double[nbReference];
    final double[] penaltyMinus = new double[nbReference];
    for (int loopref = 0; loopref < nbReference; loopref++) { // Shift on each quantity
      MultipleCurrencyParameterSensitivity psPertPlus = new MultipleCurrencyParameterSensitivity();
      psPertPlus = psPertPlus.plus(psMin);
      psPertPlus = psPertPlus.plus(rs[loopref].multipliedBy(shift));
      final DoubleMatrix1D psPertPlusMat = PortfolioHedgingCalculator.toMatrix(psPertPlus.converted(FX_MATRIX, EUR), ORDER);
      final DoubleMatrix2D psPertPlusMatT = new DoubleMatrix2D(new double[][] {psPertPlusMat.getData()});
      penaltyPlus[loopref] = ((DoubleMatrix2D) MATRIX.multiply(psPertPlusMatT, MATRIX.multiply(wtW, psPertPlusMat))).getEntry(0, 0);
      assertTrue("PortfolioHedgingCalculator: minimum", penalty < penaltyPlus[loopref]);

      MultipleCurrencyParameterSensitivity psPertMinus = new MultipleCurrencyParameterSensitivity();
      psPertMinus = psPertMinus.plus(psMin);
      psPertMinus = psPertMinus.plus(rs[loopref].multipliedBy(-shift));
      final DoubleMatrix1D psPertMinusMat = PortfolioHedgingCalculator.toMatrix(psPertMinus.converted(FX_MATRIX, EUR), ORDER);
      final DoubleMatrix2D psPertMinusMatT = new DoubleMatrix2D(new double[][] {psPertMinusMat.getData()});
      penaltyMinus[loopref] = ((DoubleMatrix2D) MATRIX.multiply(psPertMinusMatT, MATRIX.multiply(wtW, psPertMinusMat))).getEntry(0, 0);
      assertTrue("PortfolioHedgingCalculator: minimum " + loopref, penalty < penaltyMinus[loopref]);
    }

  }

  private static final DoubleMatrix1D SENSITIVITY_1_1 = new DoubleMatrix1D(4.0, 2.0, 5.0, 1.5);
  private static final DoubleMatrix1D SENSITIVITY_2_1 = new DoubleMatrix1D(5.0, 1.0, 2.0, 5.0, 1.5);

  @Test
  public void testToMatrix() {
    final LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> map1 = Maps.newLinkedHashMap();
    map1.put(NAME_1_EUR, SENSITIVITY_1_1);
    map1.put(NAME_2_EUR, SENSITIVITY_2_1);
    final MultipleCurrencyParameterSensitivity sensitivity1 = MultipleCurrencyParameterSensitivity.of(map1);
    final LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> map2 = Maps.newLinkedHashMap();
    map2.put(NAME_1_EUR, SENSITIVITY_1_1);
    map2.put(NAME_2_EUR, SENSITIVITY_1_1);
    final MultipleCurrencyParameterSensitivity sensitivity2 = MultipleCurrencyParameterSensitivity.of(map2);
    final LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> map3 = Maps.newLinkedHashMap();
    map3.put(NAME_2_EUR, SENSITIVITY_2_1);
    map3.put(NAME_1_EUR, SENSITIVITY_1_1);
    final MultipleCurrencyParameterSensitivity sensitivity3 = MultipleCurrencyParameterSensitivity.of(map3);
    final double[] total1 = new double[SENSITIVITY_1_1.getNumberOfElements() + SENSITIVITY_2_1.getNumberOfElements()];
    int j = 0;
    for (int i = 0; i < SENSITIVITY_1_1.getNumberOfElements(); i++, j++) {
      total1[j] = SENSITIVITY_1_1.getEntry(i);
    }
    for (int i = 0; i < SENSITIVITY_2_1.getNumberOfElements(); i++, j++) {
      total1[j] = SENSITIVITY_2_1.getEntry(i);
    }
    final DoubleMatrix1D expectedMatrix1 = new DoubleMatrix1D(total1);
    assertEquals("PortfolioHedgingCalculator: toMatrix", expectedMatrix1, PortfolioHedgingCalculator.toMatrix(sensitivity1, ORDER));
    assertEquals("PortfolioHedgingCalculator: toMatrix", expectedMatrix1, PortfolioHedgingCalculator.toMatrix(sensitivity3, ORDER));
    assertFalse("Test toMatrix, unequal sensitivities: ", expectedMatrix1.equals(PortfolioHedgingCalculator.toMatrix(sensitivity2, ORDER)));
  }

}
TOP

Related Classes of com.opengamma.analytics.financial.calculator.PortfolioHedgingCalculatorTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.