com.opengamma.financial.analytics.model.VegaMatrixUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.financial.analytics.model.VegaMatrixUtils.java

Source

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

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.ArrayUtils;
import org.threeten.bp.Period;

import com.opengamma.analytics.financial.forex.method.PresentValueForexBlackVolatilityNodeSensitivityDataBundle;
import com.opengamma.analytics.financial.forex.method.PresentValueForexBlackVolatilityQuoteSensitivityDataBundle;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.financial.analytics.DoubleLabelledMatrix2D;
import com.opengamma.financial.analytics.DoubleLabelledMatrix3D;
import com.opengamma.financial.analytics.volatility.surface.VolatilitySurfaceDefinition;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.time.Tenor;
import com.opengamma.util.tuple.Pair;

/**
 * Contains utility methods that vega output from the analytics libraries into objects that
 * can be transported and displayed by the engine.
 */
public class VegaMatrixUtils {
    private static final DecimalFormat FX_OPTION_FORMATTER = new DecimalFormat("##");
    private static final DecimalFormat IR_FUTURE_OPTION_FORMATTER = new DecimalFormat("##.###");
    private static final DecimalFormat DELTA_FORMATTER = new DecimalFormat("##");

    /**
     * Returns a bucketed FX option vega matrix with delta / expiry axes.
     * @param vegas The vegas, not null
     * @return A labelled vega matrix.
     */
    public static DoubleLabelledMatrix2D getVegaFXMatrix(
            final PresentValueForexBlackVolatilityNodeSensitivityDataBundle vegas) {
        ArgumentChecker.notNull(vegas, "vegas");
        final double[] expiries = vegas.getExpiries().getData();
        final double[] delta = vegas.getDelta().getData();
        final double[][] vega = vegas.getVega().getData();
        final int nDelta = delta.length;
        final int nExpiries = expiries.length;
        final Double[] rowValues = new Double[nExpiries];
        final String[] rowLabels = new String[nExpiries];
        final Double[] columnValues = new Double[nDelta];
        final String[] columnLabels = new String[nDelta];
        final double[][] values = new double[nDelta][nExpiries];
        for (int i = 0; i < nDelta; i++) {
            columnValues[i] = delta[i];
            columnLabels[i] = "P" + DELTA_FORMATTER.format(delta[i] * 100) + " "
                    + vegas.getCurrencyPair().getFirst() + "/" + vegas.getCurrencyPair().getSecond();
            for (int j = 0; j < nExpiries; j++) {
                if (i == 0) {
                    rowValues[j] = expiries[j];
                    rowLabels[j] = VegaMatrixUtils.getFXVolatilityFormattedExpiry(expiries[j]);
                }
                values[i][j] = vega[j][i];
            }
        }
        return new DoubleLabelledMatrix2D(rowValues, rowLabels, columnValues, columnLabels, values);
    }

    /**
     * Returns a bucketed FX option vega matrix with the same axes as the volatility quotes (i.e. ATM, risk-reversal and butterfly quotes)
     * @param vegas The vegas, not null
     * @return A labelled vega matrix
     */
    public static DoubleLabelledMatrix2D getVegaFXQuoteMatrix(
            final PresentValueForexBlackVolatilityQuoteSensitivityDataBundle vegas) {
        ArgumentChecker.notNull(vegas, "vegas");
        final double[] expiries = vegas.getExpiries();
        final double[] delta = vegas.getDelta();
        final double[][] vega = vegas.getVega();
        final int nDelta = delta.length;
        final int nExpiries = expiries.length;
        final Double[] rowValues = new Double[nExpiries];
        final String[] rowLabels = new String[nExpiries];
        final Double[] columnValues = new Double[nDelta];
        final String[] columnLabels = new String[nDelta];
        final double[][] values = new double[nDelta][nExpiries];
        columnLabels[0] = "ATM " + " " + vegas.getCurrencyPair().getFirst() + "/"
                + vegas.getCurrencyPair().getSecond();
        columnValues[0] = 0.;
        final int n = (nDelta - 1) / 2;
        for (int i = 0; i < n; i++) {
            columnLabels[1 + i] = "RR " + FX_OPTION_FORMATTER.format(delta[i] * 100) + " "
                    + vegas.getCurrencyPair().getFirst() + "/" + vegas.getCurrencyPair().getSecond();
            columnValues[1 + i] = 1. + i;
            columnLabels[n + 1 + i] = "B " + FX_OPTION_FORMATTER.format(delta[i] * 100) + " "
                    + vegas.getCurrencyPair().getFirst() + "/" + vegas.getCurrencyPair().getSecond();
            columnValues[n + 1 + i] = n + 1. + i;
        }
        for (int j = 0; j < nExpiries; j++) {
            rowValues[j] = expiries[j];
            rowLabels[j] = getFXVolatilityFormattedExpiry(expiries[j]);
        }
        for (int i = 0; i < nDelta; i++) {
            for (int j = 0; j < nExpiries; j++) {
                values[i][j] = vega[j][i];
            }
        }
        return new DoubleLabelledMatrix2D(rowValues, rowLabels, columnValues, columnLabels, values);
    }

    /**
     * Returns a bucketed interest rate future option vega matrix with strike / expiry axes.
     * @param definition The volatility surface, not null
     * @param matrix The vega matrix, not null
     * @param expiryValues The expiries, not null
     * @return A labelled vega matrix.
     */
    public static DoubleLabelledMatrix2D getVegaIRFutureOptionQuoteMatrix(
            final VolatilitySurfaceDefinition<?, ?> definition, final DoubleMatrix2D matrix,
            final double[] expiryValues) {
        ArgumentChecker.notNull(definition, "definition");
        ArgumentChecker.notNull(matrix, "matrix");
        ArgumentChecker.notNull(expiryValues, "expiry values");
        final int columns = matrix.getNumberOfRows();
        ArgumentChecker.isTrue(columns == expiryValues.length, "Did not have same number of columns as expiries");
        final int rows = matrix.getNumberOfColumns();
        final Double[] rowValues = new Double[rows];
        final Double[] columnValues = new Double[columns];
        final Object[] rowLabels = new Object[rows];
        final Object[] columnLabels = new Object[columns];
        final double[][] values = new double[rows][columns];
        final Object[] strikes = definition.getYs();
        final Object[] nFutureOption = definition.getXs();
        for (int i = 0; i < rows; i++) {
            final double strike = ((Number) strikes[i]).doubleValue();
            rowValues[i] = strike;
            rowLabels[i] = IR_FUTURE_OPTION_FORMATTER.format(strike);
            for (int j = 0; j < columns; j++) {
                if (i == 0) {
                    final int n = ((Number) nFutureOption[j]).intValue();
                    columnValues[j] = Double.valueOf(n);
                    columnLabels[j] = n;
                }
                values[i][j] = matrix.getEntry(j, i);
            }
        }
        return new DoubleLabelledMatrix2D(columnValues, columnLabels, rowValues, rowLabels, values);
    }

    /**
     * Returns a bucketed swaption vega cube with swaption expiry / swap maturity / distance from ATM axes.
     * @param fittedPoints The points in the swaption volatility cube, not null
     * @param matrices a map from swaption expiry to vega matrix, not null
     * @return A labelled vega cube
     */
    public static DoubleLabelledMatrix3D getVegaSwaptionCubeQuoteMatrix(
            final Map<Pair<Tenor, Tenor>, Double[]> fittedPoints, final Map<Double, DoubleMatrix2D> matrices) {
        ArgumentChecker.notNull(fittedPoints, "fitted points");
        ArgumentChecker.notNull(matrices, "matrices");
        final List<Double> xKeysList = new ArrayList<>();
        final List<Double> xLabelsList = new ArrayList<>();
        final List<Double> yKeysList = new ArrayList<>();
        final List<Tenor> yLabelsList = new ArrayList<>();
        final List<Double> zKeysList = new ArrayList<>();
        final List<Tenor> zLabelsList = new ArrayList<>();
        for (final Entry<Pair<Tenor, Tenor>, Double[]> entry : fittedPoints.entrySet()) {
            final double swapMaturity = getTime(entry.getKey().getFirst());
            if (!zKeysList.contains(swapMaturity)) {
                zKeysList.add(swapMaturity);
                zLabelsList.add(entry.getKey().getFirst());
            }
            final double swaptionExpiry = getTime(entry.getKey().getSecond());
            if (!yKeysList.contains(swaptionExpiry)) {
                yKeysList.add(swaptionExpiry);
                yLabelsList.add(entry.getKey().getSecond());
            }
            if (xKeysList.size() == 0) {
                final Double[] relativeStrikesArray = entry.getValue();
                for (final Double relativeStrike : relativeStrikesArray) {
                    xKeysList.add(relativeStrike);
                    xLabelsList.add(relativeStrike);
                }
            }
        }
        final Double[] xKeys = xKeysList.toArray(ArrayUtils.EMPTY_DOUBLE_OBJECT_ARRAY);
        final Double[] xLabels = xLabelsList.toArray(ArrayUtils.EMPTY_DOUBLE_OBJECT_ARRAY);
        final Double[] yKeys = yKeysList.toArray(ArrayUtils.EMPTY_DOUBLE_OBJECT_ARRAY);
        final Tenor[] yLabels = yLabelsList.toArray(new Tenor[yLabelsList.size()]);
        final Double[] zKeys = zKeysList.toArray(ArrayUtils.EMPTY_DOUBLE_OBJECT_ARRAY);
        final Tenor[] zLabels = zLabelsList.toArray(new Tenor[zLabelsList.size()]);
        final double[][][] values = new double[zKeys.length][xKeys.length][yKeys.length];
        for (int i = 0; i < zKeys.length; i++) {
            values[i] = matrices.get(zKeys[i]).toArray();
        }
        return new DoubleLabelledMatrix3D(xKeys, xLabels, yKeys, yLabels, zKeys, zLabels, values);
    }

    public static String getFXVolatilityFormattedExpiry(final double expiry) {
        if (expiry < 1. / 54) {
            final int days = (int) Math.ceil((365 * expiry));
            return days + "D";
        }
        if (expiry < 1. / 13) {
            final int weeks = (int) Math.ceil((52 * expiry));
            return weeks + "W";
        }
        if (expiry < 0.95) {
            final int months = (int) Math.ceil((12 * expiry));
            return months + "M";
        }
        return ((int) Math.ceil(expiry)) + "Y";
    }

    private static double getTime(final Tenor tenor) { //TODO this should be moved into a utils class
        final Period period = tenor.getPeriod();
        final double months = period.toTotalMonths();
        return months / 12.;
    }
}