/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.tutorial.analysis.swap; import java.io.FileWriter; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import org.testng.annotations.Test; import org.threeten.bp.Period; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.datasets.CalendarTarget; import com.opengamma.analytics.financial.instrument.index.GeneratorSwapFixedIbor; import com.opengamma.analytics.financial.instrument.index.GeneratorSwapFixedIborMaster; import com.opengamma.analytics.financial.instrument.index.IborIndex; import com.opengamma.analytics.financial.instrument.index.IndexIborMaster; import com.opengamma.analytics.financial.instrument.swap.SwapFixedIborDefinition; import com.opengamma.analytics.financial.interestrate.payments.derivative.Coupon; import com.opengamma.analytics.financial.interestrate.swap.derivative.SwapFixedCoupon; import com.opengamma.analytics.financial.provider.calculator.discounting.CrossGammaMultiCurveCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.CrossGammaSingleCurveCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueCurveSensitivityDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueDiscountingCalculator; import com.opengamma.analytics.financial.provider.curve.CurveBuildingBlockBundle; import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderDiscount; import com.opengamma.analytics.financial.provider.description.interestrate.ParameterProviderInterface; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityParameterCalculator; import com.opengamma.analytics.financial.schedule.ScheduleCalculator; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.math.matrix.DoubleMatrix2D; import com.opengamma.analytics.math.matrix.OGMatrixAlgebra; import com.opengamma.analytics.tutorial.datasets.AnalysisMarketDataEURJun13Sets; import com.opengamma.financial.convention.calendar.ExceptionCalendar; import com.opengamma.util.money.Currency; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.time.DateUtils; import com.opengamma.util.tuple.Pair; /** * Analysis of cross-gamma to zero-coupon and market rates. */ public class SwapGammaMultiCurveProfitEURAnalysis { private static final ExceptionCalendar TARGET = new CalendarTarget("TARGET"); private static final ZonedDateTime REFERENCE_DATE = DateUtils.getUTCDate(2013, 6, 13); private static final ZonedDateTime SPOT_DATE = ScheduleCalculator.getAdjustedDate(REFERENCE_DATE, 2, TARGET); private static final GeneratorSwapFixedIborMaster MASTER_SWAP_FIXED_IBOR = GeneratorSwapFixedIborMaster.getInstance(); private static final GeneratorSwapFixedIbor EUR1YEURIBOR3M = MASTER_SWAP_FIXED_IBOR.getGenerator("EUR1YEURIBOR3M", TARGET); private static final IndexIborMaster MASTER_IBOR_INDEX = IndexIborMaster.getInstance(); private static final IborIndex EURIBOR3M = MASTER_IBOR_INDEX.getIndex("EURIBOR3M"); private static final Currency EUR = EURIBOR3M.getCurrency(); private static final Period TENOR_START = Period.ofMonths(150); private static final Period TENOR_SWAP = Period.ofYears(5); private static final boolean IS_PAYER = true; private static final double NOTIONAL = 1.0E6; // 1m private static final ZonedDateTime START_DATE = ScheduleCalculator.getAdjustedDate(SPOT_DATE, TENOR_START, EURIBOR3M, TARGET); private static final SwapFixedIborDefinition SWAP_EUR_DEFINITION = SwapFixedIborDefinition.from(START_DATE, TENOR_SWAP, EUR1YEURIBOR3M, NOTIONAL, 0.02, IS_PAYER); private static final SwapFixedCoupon<Coupon> SWAP_EUR = SWAP_EUR_DEFINITION.toDerivative(REFERENCE_DATE); private static final PresentValueDiscountingCalculator PVDC = PresentValueDiscountingCalculator.getInstance(); private static final PresentValueCurveSensitivityDiscountingCalculator PVCSDC = PresentValueCurveSensitivityDiscountingCalculator.getInstance(); private static final ParameterSensitivityParameterCalculator<ParameterProviderInterface> PSC = new ParameterSensitivityParameterCalculator<>(PVCSDC); private static final CrossGammaMultiCurveCalculator CGMCC = new CrossGammaMultiCurveCalculator(PVCSDC); private static final CrossGammaSingleCurveCalculator CGSCC = new CrossGammaSingleCurveCalculator(PVCSDC); private static final Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_PAIR_0 = AnalysisMarketDataEURJun13Sets.getMulticurveEUR(); private static final MulticurveProviderDiscount MULTICURVE = MULTICURVE_PAIR_0.getFirst(); private static final Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle> SINGLECURVE_PAIR_0 = AnalysisMarketDataEURJun13Sets.getSingleCurveEUR(); private static final MulticurveProviderDiscount SINGLECURVE = SINGLECURVE_PAIR_0.getFirst(); private static final String[] CURVE_NAME = new String[2]; static { CURVE_NAME[0] = MULTICURVE_PAIR_0.getFirst().getName(EUR); CURVE_NAME[1] = MULTICURVE_PAIR_0.getFirst().getName(EURIBOR3M); } private static final double BP1 = 1.0E-4; private static final double SHIFT = 1 * BP1; private static final OGMatrixAlgebra ALGEBRA = new OGMatrixAlgebra(); private static final CrossGammaSingleCurveCalculator GC = new CrossGammaSingleCurveCalculator(BP1, PVCSDC); private static final int NB_NODE_EUR = AnalysisMarketDataEURJun13Sets.getCurveEURNumberNodeForward(); private static final DoubleMatrix2D GAMMA_EUR = GC.calculateCrossGamma(SWAP_EUR, SINGLECURVE_PAIR_0.getFirst()); private static final double[] GAMMA_SUM_EUR = new double[GAMMA_EUR.getNumberOfColumns()]; static { for (int loopcol = 0; loopcol < GAMMA_EUR.getNumberOfColumns(); loopcol++) { for (int looprow = 0; looprow < GAMMA_EUR.getNumberOfRows(); looprow++) { GAMMA_SUM_EUR[loopcol] += GAMMA_EUR.getEntry(looprow, loopcol); } } } @Test(enabled = false) public void crossGammaZeroSingleExport() { try { final FileWriter writer = new FileWriter("swap-x-gamma-single.csv"); for (int loopnodei = 0; loopnodei < NB_NODE_EUR; loopnodei++) { String line = ""; for (int loopnode2 = 0; loopnode2 < NB_NODE_EUR; loopnode2++) { line = line + "," + GAMMA_EUR.getEntry(loopnodei, loopnode2); } writer.append(line + "0 \n"); } writer.flush(); writer.close(); } catch (final IOException e) { e.printStackTrace(); } } @SuppressWarnings("unused") @Test(enabled = false) public void crossGammaDiagonalComp() { double[] marketMvtArray = new double[NB_NODE_EUR]; Arrays.fill(marketMvtArray, 0.0010); marketMvtArray[5] = -0.0020; marketMvtArray[7] = -0.0020; marketMvtArray[9] = -0.0020; marketMvtArray[11] = -0.0020; DoubleMatrix2D marketMvt = new DoubleMatrix2D(new double[][] {marketMvtArray }); double plTotal = (Double) ALGEBRA.multiply(ALGEBRA.multiply(marketMvt, GAMMA_EUR), ALGEBRA.getTranspose(marketMvt)).getEntry(0, 0); double plDiag = 0; for (int loopdiag = 0; loopdiag < NB_NODE_EUR; loopdiag++) { plDiag += GAMMA_EUR.getEntry(loopdiag, loopdiag) * marketMvtArray[loopdiag] * marketMvtArray[loopdiag]; } double plCol = 0; for (int loopcol = 0; loopcol < NB_NODE_EUR; loopcol++) { plCol += GAMMA_SUM_EUR[loopcol] * marketMvtArray[loopcol] * marketMvtArray[loopcol]; } } @SuppressWarnings("unused") @Test(enabled = false) public void crossGammaMulticurveIntraCurve() { HashMap<String, DoubleMatrix2D> crossGammaIntra = CGMCC.calculateCrossGammaIntraCurve(SWAP_EUR, MULTICURVE); HashMap<String, DoubleMatrix2D> crossGammaSingle1 = CGMCC.calculateCrossGammaIntraCurve(SWAP_EUR, SINGLECURVE); DoubleMatrix2D crossGammaSingle2 = CGSCC.calculateCrossGamma(SWAP_EUR, SINGLECURVE); for (String name : crossGammaIntra.keySet()) { exportMatrix(crossGammaIntra.get(name).getData(), "cross-gamma-eur-" + name + ".csv"); } int t = 0; } @Test(enabled = false) public void crossGammaZeroMulti() { MulticurveProviderDiscount multicurve = MULTICURVE_PAIR_0.getFirst(); MultipleCurrencyParameterSensitivity ps0 = PSC.calculateSensitivity(SWAP_EUR, multicurve); DoubleMatrix1D[] ps0Mat = new DoubleMatrix1D[2]; for (int i = 0; i < 2; i++) { ps0Mat[i] = ps0.getSensitivity(CURVE_NAME[i], EUR); } DoubleMatrix1D[][][] psShift = new DoubleMatrix1D[2][2][]; DoubleMatrix1D[][][] gamma = new DoubleMatrix1D[2][2][]; // Curve shifted, curve impacted int[] nbNode = new int[2]; nbNode[0] = AnalysisMarketDataEURJun13Sets.getCurveEURNumberNodeDiscounting(); nbNode[1] = AnalysisMarketDataEURJun13Sets.getCurveEURNumberNodeForward(); MultipleCurrencyParameterSensitivity[] psShiftDsc = new MultipleCurrencyParameterSensitivity[nbNode[0]]; for (int i = 0; i < 2; i++) { psShift[0][i] = new DoubleMatrix1D[nbNode[0]]; gamma[0][i] = new DoubleMatrix1D[nbNode[0]]; } for (int loopdsc = 0; loopdsc < nbNode[0]; loopdsc++) { MulticurveProviderDiscount multicurveShift = AnalysisMarketDataEURJun13Sets.getMulticurvesEURShiftParameterPoint(SHIFT, loopdsc, true); psShiftDsc[loopdsc] = PSC.calculateSensitivity(SWAP_EUR, multicurveShift); for (int i = 0; i < 2; i++) { psShift[0][i][loopdsc] = psShiftDsc[loopdsc].getSensitivity(CURVE_NAME[i], EUR); gamma[0][i][loopdsc] = (DoubleMatrix1D) ALGEBRA.add(psShift[0][i][loopdsc], ALGEBRA.scale(ps0Mat[i], -1.0)); } } for (int i = 0; i < 2; i++) { psShift[1][i] = new DoubleMatrix1D[nbNode[1]]; gamma[1][i] = new DoubleMatrix1D[nbNode[1]]; } MultipleCurrencyParameterSensitivity[] psShiftFwd = new MultipleCurrencyParameterSensitivity[nbNode[1]]; for (int loopfwd = 0; loopfwd < nbNode[1]; loopfwd++) { MulticurveProviderDiscount multicurveShift = AnalysisMarketDataEURJun13Sets.getMulticurvesEURShiftParameterPoint(SHIFT, loopfwd, false); psShiftFwd[loopfwd] = PSC.calculateSensitivity(SWAP_EUR, multicurveShift); for (int i = 0; i < 2; i++) { psShift[1][i][loopfwd] = psShiftFwd[loopfwd].getSensitivity(CURVE_NAME[i], EUR); gamma[1][i][loopfwd] = (DoubleMatrix1D) ALGEBRA.add(psShift[1][i][loopfwd], ALGEBRA.scale(ps0Mat[i], -1.0)); } } try { final FileWriter writer = new FileWriter("swap-x-gamma-multicurve.csv"); for (int i = 0; i < 2; i++) { for (int loopnodei = 0; loopnodei < nbNode[i]; loopnodei++) { String line = ""; for (int j = 0; j < 2; j++) { for (int loopnode2 = 0; loopnode2 < nbNode[j]; loopnode2++) { line = line + "," + gamma[i][j][loopnodei].getEntry(loopnode2); } } writer.append(line + "0 \n"); } } writer.flush(); writer.close(); } catch (final IOException e) { e.printStackTrace(); } } private void exportMatrix(double[][] matrix, String fileName) { try { final FileWriter writer = new FileWriter("swap-x-gamma-multicurve.csv"); for (int i = 0; i < 2; i++) { for (int loop1 = 0; loop1 < matrix.length; loop1++) { String line = ""; for (int j = 0; j < 2; j++) { for (int loop2 = 0; loop2 < matrix[loop1].length; loop2++) { line = line + "," + matrix[loop1][loop2]; } } writer.append(line + "0 \n"); } } writer.flush(); writer.close(); } catch (final IOException e) { e.printStackTrace(); } } @SuppressWarnings("unused") @Test(enabled = false) public void performance() { long startTime, endTime; final int nbTest = 1000; startTime = System.currentTimeMillis(); for (int looptest = 0; looptest < nbTest; looptest++) { MultipleCurrencyAmount pv = SWAP_EUR.accept(PVDC, MULTICURVE); } endTime = System.currentTimeMillis(); System.out.println("CrossGammaMultiCurveCalculator - " + nbTest + " pv - 2 curves: " + (endTime - startTime) + " ms"); // Performance note: PVD: 04-Aug-2014: On Mac Book Pro 2.6 GHz Intel Core i7: 20 ms for 1000 sets. startTime = System.currentTimeMillis(); for (int looptest = 0; looptest < nbTest; looptest++) { MultipleCurrencyMulticurveSensitivity pvcs = SWAP_EUR.accept(PVCSDC, MULTICURVE); } endTime = System.currentTimeMillis(); System.out.println("CrossGammaMultiCurveCalculator - " + nbTest + " pvcs - 2 curves: " + (endTime - startTime) + " ms"); // Performance note: PVCSD: 04-Aug-2014: On Mac Book Pro 2.6 GHz Intel Core i7: 25 ms for 1000 sets. startTime = System.currentTimeMillis(); for (int looptest = 0; looptest < nbTest; looptest++) { HashMap<String, DoubleMatrix2D> crossGammaIntra = CGMCC.calculateCrossGammaIntraCurve(SWAP_EUR, MULTICURVE); } endTime = System.currentTimeMillis(); System.out.println("CrossGammaMultiCurveCalculator - " + nbTest + " intro-curve x-gamma - 2 curves: " + (endTime - startTime) + " ms"); // Performance note: Cross-gamma intra-curve 2 curves: 07-Nov-12: On Mac Book Pro 2.6 GHz Intel Core i7: 1450 ms for 1000 sets. } }