MarketForwardRateAgreement.java

/*
 * (c) Copyright Christian P. Fries, Germany. Contact: email@christian-fries.de.
 *
 * Created on 23.03.2014
 */
package net.finmath.marketdata.products;

import net.finmath.marketdata.model.AnalyticModel;
import net.finmath.marketdata.model.curves.DiscountCurve;
import net.finmath.marketdata.model.curves.ForwardCurve;

/**
 * Implements the valuation of a market forward rate agreement using curves
 * (discount curve, forward curve).
 *
 * The value of the forward rate agreement at its maturity time <i>t</i> is
 * <br>
 * <i>
 * (F(t)-K) / (1 + F(t) * dcf(periodStart,periodEnd))
 * </i>
 * where <i>F(t)</i> is the forward evaluated at maturity and
 * dcf(periodStart,periodEnd) is a given paymentOffset.
 *
 * The value of the forward rate agreement returned for an earlier time is
 * the above payoff multiplied with the corresponding discount factor curve.
 * Note that this valuation ignores a possible convexity adjustment between
 * the forward and the discount factors since the above formula is not a
 * linear function of <i>F</i>. Put differently, if this product is used
 * to calibrate a forward curve to a forward rate agreement, then the
 * calibrated forward curve will include the convexity adjustment.
 *
 * @author Christian Fries
 * @version 1.0
 */
public class MarketForwardRateAgreement extends AbstractAnalyticProduct implements AnalyticProduct {

	private final double						maturity;
	private final double						paymentOffset;
	private final String						forwardCurveName;
	private final double						spread;
	private final String						discountCurveName;

	/**
	 * Creates a market forward rate agreement.
	 *
	 * @param maturity Maturity, i.e., fixing on the forward curve.
	 * @param paymentOffset Payment offset.
	 * @param forwardCurveName Name of the forward curve, leave empty if this is a fix payment.
	 * @param spread Additional fixed payment (if any).
	 * @param discountCurveName Name of the discount curve for the forward.
	 */
	public MarketForwardRateAgreement(final double maturity, final double paymentOffset, final String forwardCurveName, final double spread, final String discountCurveName) {
		super();
		this.maturity = maturity;
		this.paymentOffset = paymentOffset;
		this.forwardCurveName = forwardCurveName;
		this.spread = spread;
		this.discountCurveName = discountCurveName;
	}

	@Override
	public double getValue(final double evaluationTime, final AnalyticModel model) {
		final ForwardCurve	forwardCurve	= model.getForwardCurve(forwardCurveName);
		final DiscountCurve	discountCurve	= model.getDiscountCurve(discountCurveName);

		DiscountCurve	discountCurveForForward = null;
		if(forwardCurve == null && forwardCurveName != null && forwardCurveName.length() > 0) {
			// User might like to get forward from discount curve.
			discountCurveForForward	= model.getDiscountCurve(forwardCurveName);

			if(discountCurveForForward == null) {
				// User specified a name for the forward curve, but no curve was found.
				throw new IllegalArgumentException("No curve of the name " + forwardCurveName + " was found in the model.");
			}
		}

		double forward		= -spread;
		if(forwardCurve != null) {
			forward			+= forwardCurve.getForward(model, maturity);
		}
		else if(discountCurveForForward != null) {
			forward			+= (discountCurveForForward.getDiscountFactor(maturity) / discountCurveForForward.getDiscountFactor(maturity+paymentOffset) - 1.0) / paymentOffset;
		}

		final double payoff = forward / (1 + forward * paymentOffset);

		final double discountFactor	= maturity > evaluationTime ? discountCurve.getDiscountFactor(model, maturity) : 0.0;

		return payoff * discountFactor / discountCurve.getDiscountFactor(model, evaluationTime);
	}
}