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

com.opengamma.strata.pricer.impl.cms.DiscountingCmsPeriodPricer Maven / Gradle / Ivy

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

import java.time.LocalDate;
import java.util.OptionalDouble;

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.Messages;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.ZeroRateSensitivity;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.pricer.swap.DiscountingSwapProductPricer;
import com.opengamma.strata.product.cms.CmsPeriod;
import com.opengamma.strata.product.cms.CmsPeriodType;
import com.opengamma.strata.product.swap.ResolvedSwap;

/**
 *  Computes the price of a CMS coupon by simple forward estimation.
 *  

* This is an overly simplistic approach to CMS coupon pricer. It is provided only for testing and comparison * purposes. It is not recommended to use this for valuation or risk management purposes. */ public class DiscountingCmsPeriodPricer { /** * Default implementation. */ public static final DiscountingCmsPeriodPricer DEFAULT = new DiscountingCmsPeriodPricer( DiscountingSwapProductPricer.DEFAULT); /** * Pricer for the underlying swap. */ private final DiscountingSwapProductPricer swapPricer; /** * Creates an instance. * * @param swapPricer the pricer for {@link ResolvedSwap} */ public DiscountingCmsPeriodPricer( DiscountingSwapProductPricer swapPricer) { this.swapPricer = ArgChecker.notNull(swapPricer, "legPricer"); } //------------------------------------------------------------------------- /** * Computes the present value of CMS coupon by simple forward rate estimation. * * @param cmsPeriod the CMS * @param provider the rates provider * @return the present value */ public CurrencyAmount presentValue( CmsPeriod cmsPeriod, RatesProvider provider) { Currency ccy = cmsPeriod.getCurrency(); LocalDate valuationDate = provider.getValuationDate(); if (valuationDate.isAfter(cmsPeriod.getPaymentDate())) { return CurrencyAmount.zero(ccy); } LocalDate fixingDate = cmsPeriod.getFixingDate(); double dfPayment = provider.discountFactor(ccy, cmsPeriod.getPaymentDate()); if (!fixingDate.isAfter(valuationDate)) { // Using fixing OptionalDouble fixedRate = provider.timeSeries(cmsPeriod.getIndex()).get(fixingDate); if (fixedRate.isPresent()) { double payoff = 0d; switch (cmsPeriod.getCmsPeriodType()) { case CAPLET: payoff = Math.max(fixedRate.getAsDouble() - cmsPeriod.getStrike(), 0d); break; case FLOORLET: payoff = Math.max(cmsPeriod.getStrike() - fixedRate.getAsDouble(), 0d); break; case COUPON: payoff = fixedRate.getAsDouble(); break; default: throw new IllegalArgumentException("unsupported CMS type"); } return CurrencyAmount.of(ccy, payoff * dfPayment * cmsPeriod.getNotional() * cmsPeriod.getYearFraction()); } else if (fixingDate.isBefore(valuationDate)) { throw new IllegalArgumentException(Messages.format( "Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.getIndex(), fixingDate)); } } if (!cmsPeriod.getCmsPeriodType().equals(CmsPeriodType.COUPON)) { throw new IllegalArgumentException("Unable to price cap or floor in this pricer"); } // Using forward ResolvedSwap swap = cmsPeriod.getUnderlyingSwap(); double forward = swapPricer.parRate(swap, provider); return CurrencyAmount.of(ccy, forward * dfPayment * cmsPeriod.getNotional() * cmsPeriod.getYearFraction()); } /** * Computes the forward rate associated to the swap underlying the CMS period. *

* Returns a value only if the period has not fixed yet. If the fixing date is on or before the valuation date, * an {@link IllegalArgumentException} is thrown. * * @param cmsPeriod the CMS * @param provider the rates provider * @return the forward rate */ public double forwardRate( CmsPeriod cmsPeriod, RatesProvider provider) { LocalDate fixingDate = cmsPeriod.getFixingDate(); LocalDate valuationDate = provider.getValuationDate(); if (!fixingDate.isAfter(valuationDate)) { // Using fixing throw new IllegalArgumentException("Forward rate is availaible only for valuation date after the fixing date"); } ResolvedSwap swap = cmsPeriod.getUnderlyingSwap(); return swapPricer.parRate(swap, provider); } //------------------------------------------------------------------------- /** * Computes the present value curve sensitivity by simple forward rate estimation. * * @param cmsPeriod the CMS * @param provider the rates provider * @return the present value sensitivity */ public PointSensitivityBuilder presentValueSensitivity( CmsPeriod cmsPeriod, RatesProvider provider) { Currency ccy = cmsPeriod.getCurrency(); LocalDate valuationDate = provider.getValuationDate(); if (valuationDate.isAfter(cmsPeriod.getPaymentDate())) { return PointSensitivityBuilder.none(); } LocalDate fixingDate = cmsPeriod.getFixingDate(); double dfPayment = provider.discountFactor(ccy, cmsPeriod.getPaymentDate()); if (!fixingDate.isAfter(valuationDate)) { // Using fixing OptionalDouble fixedRate = provider.timeSeries(cmsPeriod.getIndex()).get(fixingDate); if (fixedRate.isPresent()) { double payoff = 0d; switch (cmsPeriod.getCmsPeriodType()) { case CAPLET: payoff = Math.max(fixedRate.getAsDouble() - cmsPeriod.getStrike(), 0d); break; case FLOORLET: payoff = Math.max(cmsPeriod.getStrike() - fixedRate.getAsDouble(), 0d); break; case COUPON: payoff = fixedRate.getAsDouble(); break; default: throw new IllegalArgumentException("unsupported CMS type"); } return provider.discountFactors(ccy).zeroRatePointSensitivity( cmsPeriod.getPaymentDate()).multipliedBy(payoff * cmsPeriod.getNotional() * cmsPeriod.getYearFraction()); } else if (fixingDate.isBefore(valuationDate)) { throw new IllegalArgumentException(Messages.format( "Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.getIndex(), fixingDate)); } } if (!cmsPeriod.getCmsPeriodType().equals(CmsPeriodType.COUPON)) { throw new IllegalArgumentException("Unable to price cap or floor in this pricer"); } // Using forward ResolvedSwap swap = cmsPeriod.getUnderlyingSwap(); ZeroRateSensitivity dfPaymentdr = provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.getPaymentDate()); double forward = swapPricer.parRate(swap, provider); PointSensitivityBuilder forwardSensi = swapPricer.parRateSensitivity(swap, provider); return forwardSensi.multipliedBy(dfPayment).combinedWith(dfPaymentdr.multipliedBy(forward)) .multipliedBy(cmsPeriod.getNotional() * cmsPeriod.getYearFraction()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy