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

net.finmath.singleswaprate.products.CashSettledReceiverSwaption Maven / Gradle / Ivy

package net.finmath.singleswaprate.products;

import net.finmath.singleswaprate.annuitymapping.AnnuityMapping;
import net.finmath.singleswaprate.annuitymapping.AnnuityMapping.AnnuityMappingType;
import net.finmath.singleswaprate.annuitymapping.AnnuityMappingFactory;
import net.finmath.singleswaprate.model.VolatilityCubeModel;
import net.finmath.time.Schedule;

/**
 * A European cash settled receiver swaption.
 *
 * @author Christian Fries
 * @author Roland Bachl
 *
 */
public class CashSettledReceiverSwaption extends AbstractSingleSwapRateProduct {

	private final double strike;
	private final AnnuityMappingType annuityMappingType;

	/**
	 * Create the product.
	 *
	 * @param fixSchedule The fix schedule of the swap.
	 * @param floatSchedule The float schedule of the swap.
	 * @param strike The strike of the option.
	 * @param discountCurveName The name of the discount curve.
	 * @param forwardCurveName The name of the forward curve.
	 * @param volatilityCubeName The name of the volatility cube.
	 * @param annuityMappingType The type of annuity mapping to be used for evaluation.
	 */
	public CashSettledReceiverSwaption(Schedule fixSchedule, Schedule floatSchedule, double strike, String discountCurveName, String forwardCurveName,
			String volatilityCubeName, AnnuityMappingType annuityMappingType) {
		super(fixSchedule, floatSchedule, discountCurveName, forwardCurveName, volatilityCubeName);
		this.strike = strike;
		this.annuityMappingType = annuityMappingType;
	}

	/**
	 * Create the product with custom replication settings.
	 *
	 * @param fixSchedule The fix schedule of the swap.
	 * @param floatSchedule The float schedule of the swap.
	 * @param strike The strike of the option.
	 * @param discountCurveName The name of the discount curve.
	 * @param forwardCurveName The name of the forward curve.
	 * @param volatilityCubeName The name of the volatility cube.
	 * @param annuityMappingType The type of annuity mapping to be used for evaluation.
	 * @param replicationLowerBound The lowest strike the replication may use.
	 * @param replicationUpperBound The largest strike the replication may use.
	 * @param replicationNumberOfEvaluationPoints The number of points the replication may evaluate.
	 */
	public CashSettledReceiverSwaption(Schedule fixSchedule, Schedule floatSchedule, double strike, String discountCurveName,
			String forwardCurveName, String volatilityCubeName, AnnuityMappingType annuityMappingType,
			double replicationLowerBound, double replicationUpperBound, int replicationNumberOfEvaluationPoints) {
		super(fixSchedule, floatSchedule, discountCurveName, forwardCurveName, volatilityCubeName);
		this.strike = strike;
		this.annuityMappingType = annuityMappingType;

		setIntegrationParameters(replicationLowerBound, replicationUpperBound, replicationNumberOfEvaluationPoints);
	}

	@Override
	protected double payoffFunction(double swapRate, AnnuityMapping annuityMapping, VolatilityCubeModel model) {
		double value = Math.max(strike -swapRate, 0.0);
		value *= annuityMapping.getValue(swapRate) *cashFunction(swapRate);
		return value;
	}

	//Not full integrand; singular part is being split of to be added after integration
	@Override
	protected double hedgeWeight(double swapRate, AnnuityMapping annuityMapping, VolatilityCubeModel model) {

		if(!(swapRate < strike)) {
			return 0;
		}

		double value = annuityMapping.getSecondDerivative(swapRate) * cashFunction(swapRate);
		value += 2 *annuityMapping.getFirstDerivative(swapRate) *cashFunctionFirstDerivative(swapRate);
		value += annuityMapping.getValue(swapRate) *cashFunctionSecondDerivative(swapRate);
		value *= strike -swapRate;

		value -= (annuityMapping.getFirstDerivative(swapRate) *cashFunction(swapRate) +annuityMapping.getValue(swapRate)
		*cashFunctionFirstDerivative(swapRate)) *2;
		return value;
	}

	//added to the integral over the hedge weight
	@Override
	protected double singularAddon(double swapRate, AnnuityMapping annuityMapping, VolatilityCubeModel model) {
		double value = annuityMapping.getValue(swapRate) * cashFunction(swapRate);
		if(swapRate < strike) {
			value *= valueCall(strike, model, swapRate);
		} else {
			value *= valuePut(strike, model, swapRate);
		}
		return value;
	}

	@Override
	protected AnnuityMapping buildAnnuityMapping( VolatilityCubeModel model) {

		AnnuityMappingFactory factory = new AnnuityMappingFactory(getFixSchedule(), getFloatSchedule(), getDiscountCurveName(), getForwardCurveName(), getVolatilityCubeName(),
				strike, getIntegrationLowerBound(), getIntegrationUpperBound(), getIntegrationNumberOfEvaluationPoints());
		return factory.build(annuityMappingType, model);
	}

	/**
	 * The annuity cash function for equidistant tenors. This replaces the annuity compared to the physically settled swaption.
	 *
	 * @param swapRate The swap rate.
	 * @return The value of the annuity cash function.
	 */
	private double cashFunction(double swapRate) {

		int numberOfPeriods = getFixSchedule().getNumberOfPeriods();
		double periodLength = 0.0;
		for(int index = 0; index < numberOfPeriods; index++) {
			periodLength += getFixSchedule().getPeriodLength(index);
		}
		periodLength /= getFixSchedule().getNumberOfPeriods();

		if(swapRate == 0.0) {
			return numberOfPeriods * periodLength;
		} else {
			return (1 - Math.pow(1 + periodLength * swapRate, - numberOfPeriods)) / swapRate;
		}
	}

	/**
	 * The first derivative of the annuity cash function.
	 *
	 * @param swapRate The swap rate.
	 * @return The first derivative of the annuity cash function.
	 */
	private double cashFunctionFirstDerivative(double swapRate){

		int numberOfPeriods = getFixSchedule().getNumberOfPeriods();
		double periodLength = 0.0;
		for(int index = 0; index < getFixSchedule().getNumberOfPeriods(); index++) {
			periodLength += getFixSchedule().getPeriodLength(index);
		}
		periodLength /= getFixSchedule().getNumberOfPeriods();

		if(swapRate == 0.0) {
			return - (numberOfPeriods +1) *numberOfPeriods /2 /periodLength /periodLength;
		} else {
			double value = Math.pow(periodLength * swapRate + 1, - numberOfPeriods - 1);
			value *= numberOfPeriods * periodLength / swapRate;
			value -= cashFunction(swapRate) /swapRate;
			return value;
		}
	}

	/**
	 * The second derivative of the annuity cash function.
	 *
	 * @param swapRate The swap rate.
	 * @return The second derivative of the annuity cash function.
	 */
	private double cashFunctionSecondDerivative(double swapRate) {

		int numberOfPeriods = getFixSchedule().getNumberOfPeriods();
		double periodLength = 0.0;
		for(int index = 0; index < numberOfPeriods; index++) {
			periodLength += getFixSchedule().getPeriodLength(index);
		}
		periodLength /= numberOfPeriods;

		double value;
		if(swapRate == 0.0) {
			value  = numberOfPeriods * (numberOfPeriods +1) * (numberOfPeriods +2);
			value *= periodLength * periodLength * periodLength /3;
		} else {
			value  = Math.pow(periodLength * swapRate + 1, - numberOfPeriods - 2);
			value *= - (numberOfPeriods +1) * numberOfPeriods * periodLength * periodLength / swapRate;
			value -= cashFunctionFirstDerivative(swapRate) *2 /swapRate;
		}
		return value;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy