ForwardRateAgreement.java
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;
import net.finmath.time.Schedule;
/**
* Implements the valuation of a FRA in multi-curve setting.
*
* According to Ametrano/Bianchetti (2013) p.22, the size of the convexity adjustment
* between market FRA and textbook FRA is neglegible. This class can thus be used for the valuation of the market FRA.
*
* market conventions (see Ametrano/Bianchetti (2013), p.22):
* spot offset: 2BD
* day count convention: act/360
* fixing date offset: 2BD
*
* @author Rebecca Declara
* @author Christian Fries
* @version 1.0
*/
public class ForwardRateAgreement extends AbstractAnalyticProduct implements AnalyticProduct {
private final Schedule schedule;
private final String forwardCurveName;
private final double spread;
private final String discountCurveName;
private final boolean isPayer;
/**
* Creates a FRA. The FRA has a unit notional of 1.
*
* @param schedule The schedule (provides fixing and periods length).
* @param spread The market FRA rate
* @param forwardCurveName Name of the forward curve
* @param discountCurveName Name of the discount curve (possibly multi curve setting).
* @param isPayer If true, the fra pays fix, i.e., the payoff is forward - spread. Otherwise it is spread - forward.
*/
public ForwardRateAgreement(final Schedule schedule, final double spread, final String forwardCurveName, final String discountCurveName, final boolean isPayer) {
super();
this.schedule = schedule;
this.forwardCurveName = forwardCurveName;
this.spread = spread;
this.discountCurveName = discountCurveName;
this.isPayer = isPayer;
// Check schedule
if(schedule.getNumberOfPeriods() > 1) {
throw new IllegalArgumentException("Number of periods has to be 1: Change frequency to 'tenor'!");
}
}
/**
* Creates a payer FRA. The FRA has a unit notional of 1.
*
* @param schedule The schedule (provides fixing and periods length).
* @param spread The market FRA rate
* @param forwardCurveName Name of the forward curve
* @param discountCurveName Name of the discount curve (possibly multi curve setting).
*/
public ForwardRateAgreement(final Schedule schedule, final double spread, final String forwardCurveName, final String discountCurveName) {
this(schedule, spread, forwardCurveName, discountCurveName, true /* isPayer */);
}
@Override
public double getValue(final double evaluationTime, final AnalyticModel model) {
if(model==null) {
throw new IllegalArgumentException("model==null");
}
final DiscountCurve discountCurve = model.getDiscountCurve(discountCurveName);
if(discountCurve==null) {
throw new IllegalArgumentException("No discount curve with name '" + discountCurveName + "' was found in the model:\n" + model.toString());
}
final ForwardCurve forwardCurve = model.getForwardCurve(forwardCurveName);
if(forwardCurve==null && forwardCurveName!=null && forwardCurveName.length()>0) {
throw new IllegalArgumentException("No forward curve with name '" + forwardCurveName + "' was found in the model:\n" + model.toString());
}
final double fixingDate = schedule.getFixing(0);
final double paymentDate = schedule.getPayment(0);
final double periodLength = schedule.getPeriodLength(0);
double forward = 0.0;
if(forwardCurve != null) {
forward += forwardCurve.getForward(model, fixingDate, paymentDate-fixingDate);
}
// Valuation of the market FRA for payer and receiver direction, neglecting convexity adjustment
final double notional = isPayer ? 1.0 : -1.0;
final double discountFactorFixingDate = fixingDate > evaluationTime ? discountCurve.getDiscountFactor(model, fixingDate) : 0.0;
return notional * (forward - spread) / (1.0 + forward * periodLength) * discountFactorFixingDate * periodLength;
}
/**
* Return the par FRA rate for a given curve.
*
* @param model A given model.
* @return The par FRA rate.
*/
public double getRate(final AnalyticModel model) {
if(model==null) {
throw new IllegalArgumentException("model==null");
}
final ForwardCurve forwardCurve = model.getForwardCurve(forwardCurveName);
if(forwardCurve==null) {
throw new IllegalArgumentException("No forward curve of name '" + forwardCurveName + "' found in given model:\n" + model.toString());
}
final double fixingDate = schedule.getFixing(0);
return forwardCurve.getForward(model,fixingDate);
}
}