/*
* Created on 22.11.2009
*/
package net.finmath.montecarlo.interestrate.products.components;
import net.finmath.exception.CalculationException;
import net.finmath.montecarlo.RandomVariable;
import net.finmath.montecarlo.interestrate.LIBORModelMonteCarloSimulationInterface;
import net.finmath.stochastic.RandomVariableInterface;
/**
* A period. A period has references to the index (coupon) and the notional.
* It provides the fixing date for the index, the period length, and the payment date.
*
* @author Christian Fries
* @version 1.1
*/
public class Period extends AbstractPeriod {
private static final long serialVersionUID = -7107623461781510475L;
private final boolean couponFlow;
private final boolean notionalFlow;
private final boolean payer;
private final boolean isExcludeAccruedInterest;
/**
* Create a simple period with notional and index (coupon) flow.
*
* @param periodStart The period start.
* @param periodEnd The period end.
* @param fixingDate The fixing date (as double).
* @param paymentDate The payment date (as double).
* @param notional The notional object relevant for this period.
* @param index The index (used for coupon calculation) associated with this period.
* @param daycountFraction The daycount fraction (coupon = index(fixingDate) * daycountFraction).
* @param couponFlow If true, the coupon will be payed. Otherwise there will be not coupon flow.
* @param notionalFlow If true, there will be a positive notional flow at period start (but only if peirodStart > evaluationTime) and a negative notional flow at period end (but only if periodEnd > evaluationTime). Otherwise there will be no notional flows.
* @param payer If true, the period will be a payer period, i.e. notional and coupon at period end are payed (negative). Otherwise it is a receiver period.
* @param isExcludeAccruedInterest If the true, the valuation will exclude accrued interest, if any.
*/
public Period(double periodStart, double periodEnd, double fixingDate,
double paymentDate, AbstractNotional notional, AbstractProductComponent index, double daycountFraction,
boolean couponFlow, boolean notionalFlow, boolean payer, boolean isExcludeAccruedInterest) {
super(periodStart, periodEnd, fixingDate, paymentDate, notional, index, daycountFraction);
this.couponFlow = couponFlow;
this.notionalFlow = notionalFlow;
this.payer = payer;
this.isExcludeAccruedInterest = isExcludeAccruedInterest;
}
/**
* Create a simple period with notional and index (coupon) flow.
*
* The valuation does not exclude the accrued interest, i.e., the valuation reports a so called dirty price.
*
* @param periodStart The period start.
* @param periodEnd The period end.
* @param fixingDate The fixing date (as double).
* @param paymentDate The payment date (as double).
* @param notional The notional object relevant for this period.
* @param index The index (used for coupon calculation) associated with this period.
* @param daycountFraction The daycount fraction (coupon = index(fixingDate) * daycountFraction).
* @param couponFlow If true, the coupon will be payed. Otherwise there will be not coupon flow.
* @param notionalFlow If true, there will be a positive notional flow at period start (but only if peirodStart > evaluationTime) and a negative notional flow at period end (but only if periodEnd > evaluationTime). Otherwise there will be no notional flows.
* @param payer If true, the period will be a payer period, i.e. notional and coupon at period end are payed (negative). Otherwise it is a receiver period.
*/
public Period(double periodStart, double periodEnd, double fixingDate,
double paymentDate, AbstractNotional notional, AbstractProductComponent index, double daycountFraction,
boolean couponFlow, boolean notionalFlow, boolean payer) {
this(periodStart, periodEnd, fixingDate, paymentDate, notional, index, daycountFraction, couponFlow, notionalFlow, payer, false);
}
/**
* Create a simple period with notional and index (coupon) flow.
*
* The valuation does not exclude the accrued interest, i.e., the valuation reports a so called dirty price.
*
* @param periodStart The period start.
* @param periodEnd The period end.
* @param fixingDate The fixing date (as double).
* @param paymentDate The payment date (as double).
* @param notional The notional object relevant for this period.
* @param index The index (coupon) associated with this period.
* @param couponFlow If true, the coupon will be payed. Otherwise there will be not coupon flow.
* @param notionalFlow If true, there will be a positive notional flow at period start (but only if peirodStart > evaluationTime) and a negative notional flow at period end (but only if periodEnd > evaluationTime). Otherwise there will be no notional flows.
* @param payer If true, the period will be a payer period, i.e. notional and coupon at period end are payed (negative). Otherwise it is a receiver period.
*/
public Period(double periodStart, double periodEnd, double fixingDate,
double paymentDate, AbstractNotional notional, AbstractProductComponent index,
boolean couponFlow, boolean notionalFlow, boolean payer) {
this(periodStart, periodEnd, fixingDate, paymentDate, notional, index, periodEnd-periodStart, couponFlow, notionalFlow, payer);
}
/**
* This method returns the value random variable of the product within the specified model, evaluated at a given evalutationTime.
* Note: For a lattice this is often the value conditional to evalutationTime, for a Monte-Carlo simulation this is the (sum of) value discounted to evaluation time.
* Cashflows prior evaluationTime are not considered.
*
* @param evaluationTime The time on which this products value should be observed.
* @param model The model used to price the product.
* @return The random variable representing the value of the product discounted to evaluation time
* @throws net.finmath.exception.CalculationException Thrown if the valuation fails, specific cause may be available via the cause() method.
*/
@Override
public RandomVariableInterface getValue(double evaluationTime, LIBORModelMonteCarloSimulationInterface model) throws CalculationException {
if(evaluationTime >= this.getPaymentDate()) return new RandomVariable(0.0);
// Get random variables
RandomVariableInterface notionalAtPeriodStart = getNotional().getNotionalAtPeriodStart(this, model);
RandomVariableInterface numeraireAtEval = model.getNumeraire(evaluationTime);
RandomVariableInterface numeraire = model.getNumeraire(getPaymentDate());
// @TODO: Add support for weighted Monte-Carlo.
// RandomVariableInterface monteCarloProbabilities = model.getMonteCarloWeights(getPaymentDate());
RandomVariableInterface values;
// Calculate numeraire relative value of coupon flows
if(couponFlow) {
values = getCoupon(model);
values = values.mult(notionalAtPeriodStart);
values = values.div(numeraire);
if(isExcludeAccruedInterest && evaluationTime >= getPeriodStart() && evaluationTime < getPeriodEnd()) {
double nonAccruedInterestRatio = (getPeriodEnd() - evaluationTime) / (getPeriodEnd() - getPeriodStart());
values = values.mult(nonAccruedInterestRatio);
}
}
else {
values = new RandomVariable(0.0,0.0);
}
// Apply notional exchange
if(notionalFlow) {
RandomVariableInterface nationalAtPeriodEnd = getNotional().getNotionalAtPeriodEnd(this, model);
if(getPeriodStart() > evaluationTime) {
RandomVariableInterface numeraireAtPeriodStart = model.getNumeraire(getPeriodStart());
values = values.subRatio(notionalAtPeriodStart, numeraireAtPeriodStart);
}
if(getPeriodEnd() > evaluationTime) {
RandomVariableInterface numeraireAtPeriodEnd = model.getNumeraire(getPeriodEnd());
values = values.addRatio(nationalAtPeriodEnd, numeraireAtPeriodEnd);
}
}
if(payer) values = values.mult(-1.0);
values = values.mult(numeraireAtEval);
// Return values
return values;
}
@Override
public RandomVariableInterface getCoupon(LIBORModelMonteCarloSimulationInterface model) throws CalculationException {
// Calculate percentage value of coupon (not multiplied with notional, not discounted)
RandomVariableInterface values = getIndex().getValue(getFixingDate(), model);
// Apply daycount fraction
double periodDaycountFraction = getDaycountFraction();
values = values.mult(periodDaycountFraction);
return values;
}
@Override
public String toString() {
return "Period [couponFlow=" + couponFlow + ", notionalFlow="
+ notionalFlow + ", payer=" + payer + ", toString()="
+ super.toString() + "]";
}
}
Ads help maintain this website.