All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opengamma.strata.pricer.capfloor.VerticalSpreadVolatilityIborCapletFloorletBinaryPeriodPricer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2022 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.strata.pricer.capfloor;

import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.collect.ArgChecker;
import com.opengamma.strata.collect.tuple.Pair;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.product.capfloor.IborCapletFloorletBinaryPeriod;
import com.opengamma.strata.product.capfloor.IborCapletFloorletPeriod;
import com.opengamma.strata.product.capfloor.IborCapletFloorletPeriod.Builder;
import com.opengamma.strata.product.common.PutCall;

/**
 * Pricer for binary caplet/floorlet based on volatilities.
 * 

* The pricing methodologies is based on 'call spread' approach. *

* The value of the caplet/floorlet after expiry is a fixed payoff amount. The value is zero if valuation date is * after payment date of the caplet/floorlet. */ public class VerticalSpreadVolatilityIborCapletFloorletBinaryPeriodPricer { /** The default spread between the approximating options strikes. */ private static final double DEFAULT_SPREAD = 1.0e-4; /** * Default implementation. */ public static final VerticalSpreadVolatilityIborCapletFloorletBinaryPeriodPricer DEFAULT = new VerticalSpreadVolatilityIborCapletFloorletBinaryPeriodPricer( VolatilityIborCapletFloorletPeriodPricer.DEFAULT, DEFAULT_SPREAD); /** Vanilla option pricer for approximating vanilla options. */ private final VolatilityIborCapletFloorletPeriodPricer capletPricer; /** The spread between the approximating options. */ private final double spread; /** * Creates an instance. * * @param capletPricer the pricer for {@link IborCapletFloorletPeriod} * @param spread the spread between the approximating options strikes */ public VerticalSpreadVolatilityIborCapletFloorletBinaryPeriodPricer( VolatilityIborCapletFloorletPeriodPricer capletPricer, double spread) { this.capletPricer = ArgChecker.notNull(capletPricer, "capletPricer"); this.spread = ArgChecker.notNegativeOrZero(spread, "spread"); } //------------------------------------------------------------------------- /** * Returns the pricer used to price the approximating vanilla caplet/floorlet pricer. * * @return the pricer */ VolatilityIborCapletFloorletPeriodPricer getVanillaOptionProductPricer() { return capletPricer; } /** * Returns the spread between the approximating FX vanilla options. * * @return the spread */ double getSpread() { return spread; } /** * Calculates the present value of the binary caplet/floorlet period. * * @param period the Ibor caplet/floorlet period * @param ratesProvider the rates provider * @param volatilities the volatilities * @return the present value */ public CurrencyAmount presentValue( IborCapletFloorletBinaryPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { double expiry = volatilities.relativeTime(period.getFixingDateTime()); Currency currency = period.getCurrency(); if (expiry < 0d) { // Option has expired already return CurrencyAmount.of(currency, 0d); } Pair callSpread = vanillaOptionVerticalSpreadPair(period); CurrencyAmount firstOptionPv = capletPricer.presentValue(callSpread.getFirst(), ratesProvider, volatilities); CurrencyAmount secondOptionPv = capletPricer.presentValue(callSpread.getSecond(), ratesProvider, volatilities); return firstOptionPv.plus(secondOptionPv).multipliedBy(Math.signum(period.getAmount())); } //------------------------------------------------------------------------- /** * Calculates the present value rates sensitivity of the binary caplet/floorlet period. *

* The present value rates sensitivity of the caplet/floorlet is the sensitivity * of the present value to the underlying curves. * * @param period the Ibor caplet/floorlet period * @param ratesProvider the rates provider * @param volatilities the volatilities * @return the present value curve sensitivity */ public PointSensitivityBuilder presentValueSensitivityRatesStickyStrike( IborCapletFloorletBinaryPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { double expiry = volatilities.relativeTime(period.getFixingDateTime()); if (expiry < 0d) { // Option has expired already return PointSensitivityBuilder.none(); } Pair callSpread = vanillaOptionVerticalSpreadPair(period); PointSensitivityBuilder firstOptionPts = capletPricer.presentValueSensitivityRates(callSpread.getFirst(), ratesProvider, volatilities); PointSensitivityBuilder secondOptionPts = capletPricer.presentValueSensitivityRates(callSpread.getSecond(), ratesProvider, volatilities); return (firstOptionPts.combinedWith(secondOptionPts)).multipliedBy(Math.signum(period.getAmount())); } /** * Calculates the present value sensitivity to model parameters of the binary caplet/floorlet period. *

* The present value rates sensitivity of the caplet/floorlet is the sensitivity * of the present value to the underlying curves. * * @param period the Ibor caplet/floorlet period * @param ratesProvider the rates provider * @param volatilities the volatilities * @return the present value curve sensitivity */ public PointSensitivityBuilder presentValueSensitivityModelParamsVolatility( IborCapletFloorletBinaryPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities) { double expiry = volatilities.relativeTime(period.getFixingDateTime()); if (expiry < 0d) { // Option has expired already return PointSensitivityBuilder.none(); } Pair callSpread = vanillaOptionVerticalSpreadPair(period); PointSensitivityBuilder firstOptionPts = capletPricer.presentValueSensitivityModelParamsVolatility(callSpread.getFirst(), ratesProvider, volatilities); PointSensitivityBuilder secondOptionPts = capletPricer.presentValueSensitivityModelParamsVolatility(callSpread.getSecond(), ratesProvider, volatilities); return (firstOptionPts.combinedWith(secondOptionPts)).multipliedBy(Math.signum(period.getAmount())); } //------------------------------------------------------------------------- /** * Creates pair of vanilla caplet for binary caplet/floorlet pricing by call spread. * * @param binary the binary caplet/floorlet * @return the call spread */ public Pair vanillaOptionVerticalSpreadPair(IborCapletFloorletBinaryPeriod binary) { double capFloorInd = (binary.getPutCall().equals(PutCall.CALL) ? 1d : -1d); double adjStrikeLow = binary.getStrike() - spread; double adjStrikeHigh = binary.getStrike() + spread; double amount = Math.abs(binary.getAmount()); double rescaledNotional = amount / (2.0d * spread) * capFloorInd; // To obtain the amount over the strike length 2 * spread Builder optionLong = IborCapletFloorletPeriod.builder() .currency(binary.getCurrency()) .notional(rescaledNotional) .startDate(binary.getStartDate()) .endDate(binary.getEndDate()) .yearFraction(binary.getYearFraction()) .paymentDate(binary.getPaymentDate()) .iborRate(binary.getIborRate()); Builder optionShort = IborCapletFloorletPeriod.builder() .currency(binary.getCurrency()) .notional(-rescaledNotional) .startDate(binary.getStartDate()) .endDate(binary.getEndDate()) .yearFraction(binary.getYearFraction()) .paymentDate(binary.getPaymentDate()) .iborRate(binary.getIborRate()); if (binary.getPutCall().equals(PutCall.CALL)) { // Cap return Pair.of(optionLong.caplet(adjStrikeLow).build(), optionShort.caplet(adjStrikeHigh).build()); } // Floor return Pair.of(optionLong.floorlet(adjStrikeLow).build(), optionShort.floorlet(adjStrikeHigh).build()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy