/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.capletstripping; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.commons.lang.ArrayUtils; import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolator; import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolatorFactory; import com.opengamma.analytics.math.interpolation.GridInterpolator2D; import com.opengamma.analytics.math.interpolation.Interpolator1DFactory; import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.tuple.DoublesPair; /** * Combine the results of different strippings. This is normally used to combine multiple single strike results. */ public class CombinedCapletStrippingResults { private final CapletStrippingResult[] _results; /** * combine the results * @param results individual results */ public CombinedCapletStrippingResults(CapletStrippingResult[] results) { ArgumentChecker.noNulls(results, "results"); _results = results; } /** * get the sorted array of unique caplet expiry times from the set of caps in each set of results * @return caplet expiry times */ protected double[] getCapletExpiries() { int nRes = _results.length; double[][] t = new double[nRes][]; for (int i = 0; i < nRes; i++) { t[i] = _results[i].getPricer().getCapletExpiries(); } return toUnique(t); } /** * get the sorted array of unique caplet strikes from the set of caps in each set of results * @return caplet strikes */ protected double[] getStrikes() { int nRes = _results.length; double[][] k = new double[nRes][]; for (int i = 0; i < nRes; i++) { k[i] = _results[i].getPricer().getStrikes(); } return toUnique(k); } private double[] toUnique(double[][] from) { int n = from.length; double[] base = from[0]; List<Double> list = Arrays.asList(ArrayUtils.toObject(base)); Set<Double> set = new TreeSet<>(list); for (int i = 1; i < n; i++) { double[] temp = from[i]; if (!Arrays.equals(base, temp)) { int m = temp.length; for (int j = 0; j < m; j++) { set.add(temp[j]); } } } list = new ArrayList<>(set); double[] res = ArrayUtils.toPrimitive(list.toArray(new Double[0])); Arrays.sort(res); return res; } /** * Dump out the caplet volatility surface n a tab separated format (this allows easy pasting * into Excel). We store the (calibrated) caplet volatilities, rather than a continuous surface, so we create * a surface using a 2D linear grid interpolator ({@link GridInterpolator2D}. * @param out an output stream * @param nExpPoints number of sample points in the expiry direction * @param nStrikePoints number of sample points in the strike direction */ public void printSurface(PrintStream out, int nExpPoints, int nStrikePoints) { double[] t = getCapletExpiries(); double[] k = getStrikes(); double timeRange = t[t.length - 1] - t[0]; double strikeRange = k[k.length - 1] - k[0]; int nRes = _results.length; Map<DoublesPair, Double> map = new HashMap<>(); for (int i = 0; i < nRes; i++) { CapletStrippingResult result = _results[i]; DoublesPair[] expStrikes = result.getPricer().getExpiryStrikeArray(); DoubleMatrix1D vols = result.getCapletVols(); int n = expStrikes.length; for (int j = 0; j < n; j++) { map.put(expStrikes[j], vols.getEntry(j)); } } CombinedInterpolatorExtrapolator interpolator = CombinedInterpolatorExtrapolatorFactory.getInterpolator( Interpolator1DFactory.LINEAR, Interpolator1DFactory.LINEAR_EXTRAPOLATOR); GridInterpolator2D interpolator2D = new GridInterpolator2D(interpolator, interpolator); Map<Double, Interpolator1DDataBundle> db = interpolator2D.getDataBundle(map); double[] times = new double[nExpPoints]; double[] strikes = new double[nStrikePoints]; for (int i = 0; i < nStrikePoints; i++) { strikes[i] = k[0] + strikeRange * i / (nStrikePoints - 1.0); } out.println(); for (int j = 0; j < nExpPoints; j++) { times[j] = t[0] + timeRange * j / (nExpPoints - 1.0); out.print("\t" + times[j]); } for (int i = 0; i < nStrikePoints; i++) { out.print("\n" + strikes[i]); for (int j = 0; j < nExpPoints; j++) { Double vol = interpolator2D.interpolate(db, DoublesPair.of(times[j], strikes[i])); out.print("\t" + vol); } } out.println(); } }