/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.capletstripping; import com.opengamma.analytics.financial.model.volatility.BlackFormulaRepository; import com.opengamma.analytics.financial.model.volatility.SimpleOptionData; import com.opengamma.analytics.financial.model.volatility.VolatilityModel1D; import com.opengamma.analytics.financial.model.volatility.surface.VolatilitySurface; import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface; import com.opengamma.util.ArgumentChecker; /** * */ public class CapFloorPricer { private final SimpleOptionData[] _caplets; private final int _n; /** * Decomposes a cap (floor) down to relevant information about its caplets (floorlets), i.e. the forward (ibor) values, * the fixing times and the discount factors. Each caplet (floorlet), and hence the whole cap (floor) can then be priced by suppling a VolatilityModel1D * (which gives a Black vol for a particular forward/strike/expiry) or a VolatilityTermStructure (which gives the vol simply as a function of expiry) * @param cap a cap or floor * @param curves The relevant curves */ public CapFloorPricer(final CapFloor cap, final MulticurveProviderInterface curves) { _caplets = CapFloorDecomposer.toOptions(cap, curves); _n = _caplets.length; } /** * price a cap given its volatility * @param vol The cap volatility * @return cap price */ public double price(final double vol) { double sum = 0; for (int i = 0; i < _n; i++) { sum += BlackFormulaRepository.price(_caplets[i], vol); } return sum; } /** * Price a cap (floor) with a VolatilityModel1D. This allows the same cap to be prices with different models (different models include different * parameters for the same model), with repeating calculations (e.g. as part of a caplet stripping routine) * @param volModel VolatilityModel1D which gives a Black vol for a particular forward/strike/expiry * @return The cap (floor) price * @deprecated discourage use of {@link VolatilityModel1D} */ @Deprecated public double price(final VolatilityModel1D volModel) { double sum = 0; for (int i = 0; i < _n; i++) { final double vol = volModel.getVolatility(_caplets[i]); sum += BlackFormulaRepository.price(_caplets[i], vol); } return sum; } /** * Price the cap using a (caplet) volatility surface. This will give a (Black) volatility dependent on the * strike and expiry of each caplet. The cap price is of course the sum of the prices of each of the constituent caplets. * @param volSurface the (Black) volatility surface of the underlying caplets * @return The cap/floor price */ public double price(final VolatilitySurface volSurface) { double sum = 0; for (int i = 0; i < _n; i++) { final SimpleOptionData caplet = _caplets[i]; final double vol = volSurface.getVolatility(caplet.getTimeToExpiry(), caplet.getStrike()); sum += BlackFormulaRepository.price(_caplets[i], vol); } return sum; } /** * Price the cap from the volatilities of its caplets. * @param capletVols The (Black) volatility of caplets. These <b>must</b> be order by (ascending) order of fixing time. * @return The cap price */ public double price(final double[] capletVols) { ArgumentChecker.isTrue(capletVols.length == _n, "number of caplets is not equal to number of vols"); double sum = 0; for (int i = 0; i < _n; i++) { final double vol = capletVols[i]; sum += BlackFormulaRepository.price(_caplets[i], vol); } return sum; } /** * The implied volatility of a cap. * @param capPrice The cap price * @return The cap implied volatility */ public double impliedVol(final double capPrice) { return BlackFormulaRepository.impliedVolatility(_caplets, capPrice); } /** * * @param capletVolModel model of caplet volatility * @return the implied volatility * @deprecated discourage use of {@link VolatilityModel1D} */ @Deprecated public double impliedVol(final VolatilityModel1D capletVolModel) { final double price = price(capletVolModel); return impliedVol(price); } /** * get the implied volatility of a cap from a (caplet) volatility surface - this will give a (Black) volatility dependent on the * strike and expiry of each caplet. * @param volSurface The (caplet) volatility surface * @return The cap implied volatility */ public double impliedVol(final VolatilitySurface volSurface) { final double price = price(volSurface); return impliedVol(price); } /** * get the implied volatility of a cap from the volatilities of the underlying caplets. * @param capletVols The (Black) volatility of caplets. These <b>must</b> be order by (ascending) order of fixing time. * @return The cap implied volatility */ public double impliedVol(final double[] capletVols) { final double price = price(capletVols); return impliedVol(price); } /** * get the cap vega; the sensitivity of its price to its volatility * @param capVolatility The cap volatility * @return The cap vega */ public double vega(final double capVolatility) { double sum = 0; for (int i = 0; i < _n; i++) { sum += BlackFormulaRepository.vega(_caplets[i], capVolatility); } return sum; } /** * * @param capletVolModel model of caplet volatility * @return the vega * @deprecated discourage use of {@link VolatilityModel1D} */ @Deprecated public double vega(final VolatilityModel1D capletVolModel) { final double vol = impliedVol(capletVolModel); return vega(vol); } /** * get the cap vega; the sensitivity of its price to its volatility * @param volSurface The (caplet) volatility surface * @return the cap vega */ public double vega(final VolatilitySurface volSurface) { final double vol = impliedVol(volSurface); return vega(vol); } /** * get the cap vega; the sensitivity of its price to its volatility * @param capletVols The (Black) volatility of caplets. These <b>must</b> be order by (ascending) order of fixing time. * @return the cap vega */ public double vega(final double[] capletVols) { final double vol = impliedVol(capletVols); return vega(vol); } /** * Get the forward rates for the period covered by the caplets. * @return the forward rates - these are order by (caplet) fixing time */ public double[] getCapletForwardRates() { final double[] fwds = new double[_n]; for (int i = 0; i < _n; i++) { fwds[i] = _caplets[i].getForward(); } return fwds; } /** * get the cap forward. This is the swap rate for the same period (on the same index). * @return The cap forward */ protected double getCapForward() { double sum1 = 0; double sum2 = 0; final double[] df = getDiscountFactors(); final double[] fwds = getCapletForwardRates(); // COMMENT - the discount factor includes the accrual fraction for (int i = 0; i < _n; i++) { sum1 += df[i] * fwds[i]; sum2 += df[i]; } return sum1 / sum2; } /** * Gets the caplet expiries. * @return the caplet expiries */ public double[] getCapletExpiries() { final double[] t = new double[_n]; for (int i = 0; i < _n; i++) { t[i] = _caplets[i].getTimeToExpiry(); } return t; } /** * Gets the discount factors. <b>Note</b> this is purely the number to multiple the result of Black's formula * ({@link BlackFormulaRepository}) by; this is the discount factor from the end of the period (when payment is * made) multiplied by the year fraction. * @return the discount factors */ protected double[] getDiscountFactors() { final double[] df = new double[_n]; for (int i = 0; i < _n; i++) { df[i] = _caplets[i].getDiscountFactor(); } return df; } /** * Gets the strike * @return the strike */ protected double getStrike() { return _caplets[0].getStrike(); } /** * Gets the number of caplets * @return the number of caplets */ public int getNumberCaplets() { return _n; } /** * get the underlying caplets (order by fixing time) as an array of {@link SimpleOptionData} * @return array of {@link SimpleOptionData} */ public SimpleOptionData[] getCapletAsOptionData() { return _caplets; } }