/*
Copyright (C) 2009 Ueli Hofstetter
Copyright (C) 2009 John Martin
This source code is release under the BSD License.
This file is part of JQuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://jquantlib.org/
JQuantLib is free software: you can redistribute it and/or modify it
under the terms of the JQuantLib license. You should have received a
copy of the license along with this program; if not, please email
. The license is also available online at
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
JQuantLib is based on QuantLib. http://quantlib.org/
When applicable, the original copyright notice follows this notice.
*/
package org.jquantlib.cashflow;
import org.jquantlib.QL;
import org.jquantlib.math.Constants;
import org.jquantlib.util.PolymorphicVisitor;
import org.jquantlib.util.Visitor;
/**
* Capped and/or floored floating-rate coupon
*
* The payoff {@latex$ P } of a capped floating-rate coupon is:
* {@latex[ P = N \times T \times \min(a L + b, C) }
*
* The payoff of a floored floating-rate coupon is:
* {@latex[ P = N \times T \times \max(a L + b, F) }
*
* The payoff of a collared floating-rate coupon is:
* {@latex[ P = N \times T \times \min(\max(a L + b, F), C) } where
*
* {@latex$ N } is the notional, {@latex$ T }is the accrual time, {@latex$ L } is the floating rate, {@latex$ a } is its gearing,
* {@latex$ b } is the spread, and {@latex$ C } and {@latex$ F } are the strikes.
*
* They can be decomposed in the following manner. Decomposition of a capped floating rate coupon:
* {@latex[ R = \min(a L + b, C) = (a L + b) + \min(C - b - \xi |a| L, 0) } where
* {@latex$ \xi = sgn(a) }. Then:
* {@latex[ R = (a L + b) + |a| \min(\frac{C - b}{|a|} - \xi L, 0) }
*
* @author Ueli Hofstetter
* @author John Martin
*/
/*
Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
Copyright (C) 2003, 2004 StatPro Italia srl
Copyright (C) 2003 Nicolas Di C�sar�
Copyright (C) 2006, 2007 Cristina Duminuco
Copyright (C) 2006 Ferdinando Ametrano
Copyright (C) 2007 Giorgio Facchinetti
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
. The license is also available online at
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
/**
* Coupon paying a variable index-based rate
*
* @author Ueli Hofstetter
* @author John Martin
*/
// TODO: code review :: license, class comments, comments for access modifiers, comments for @Override
// TODO: code review :: please verify against QL/C++ code
public class CappedFlooredCoupon extends FloatingRateCoupon {
protected FloatingRateCoupon underlying_;
protected boolean isCapped_, isFloored_;
protected /* @Rate */ double cap_, floor_;
//
// public constructors
//
public CappedFlooredCoupon(final FloatingRateCoupon underlying) {
this(underlying, Constants.NULL_REAL, Constants.NULL_REAL);
}
public CappedFlooredCoupon(final FloatingRateCoupon underlying, final double cap, final double floor) {
super(underlying.date(), underlying.nominal,
underlying.accrualStartDate(), underlying.accrualEndDate(),
underlying.fixingDays(), underlying.index(), underlying.gearing(), underlying.spread(),
underlying.referencePeriodStart(), underlying.referencePeriodEnd(),
underlying.dayCounter(), underlying.isInArrears());
this.underlying_ = underlying;
isCapped_ = false;
isFloored_ = false;
if (gearing_ > 0) {
if (!Double.isNaN(cap)) {
isCapped_ = true;
cap_ = cap;
}
if (!Double.isNaN(floor)) {
floor_ = floor;
isFloored_ = true;
}
}
// FIXME :: this comment does not belong to C++ code :: evaluate and eventually remove
//
// note subtle difference, caps become floors and floors become caps
// if gearing is < 0.
// It maybe WRONG to do this, note how we access the floor() and cap()
// functions defined below. if we swap the caps and floors at construction, for
// a negative gearing, we will undo this change when we access the negative
// gearing again through the floor and cap functions.
else {
if (!Double.isNaN(cap)) {
floor_ = cap;
isFloored_ = true;
}
if (!Double.isNaN(floor)) {
isCapped_ = true;
cap_ = floor;
}
}
if (isCapped_ && isFloored_) {
QL.require(cap >= floor , "cap level less than floor level"); // TODO: message
}
this.underlying_.addObserver(this);
//XXX:registerWith
// registerWith(underlying);
}
@Override
public void setPricer(final FloatingRateCouponPricer pricer) {
if (this.pricer_ != null) {
this.pricer_.deleteObserver (this);
}
this.pricer_ = pricer;
if (this.pricer_ != null) {
this.pricer_.addObserver (this);
}
update();
underlying_.setPricer (pricer);
}
@Override
public /*@Rate*/ double rate() /* @ReadOnly */ {
QL.require (underlying_.pricer_ != null, "pricer not set");
final double swapletRate = underlying_.rate();
double floorRate = 0.0;
double capRate = 0.0;
if (isFloored_) {
floorRate = underlying_.pricer_.floorletRate(effectiveFloor());
}
if (isCapped_) {
capRate = underlying_.pricer_.capletRate (effectiveCap());
}
return swapletRate + floorRate - capRate;
}
@Override
public /*@Rate*/ double convexityAdjustment() /* @ReadOnly */ {
return underlying_.convexityAdjustment();
}
public boolean isCapped() /* @ReadOnly */{
return isCapped_;
}
public boolean isFloored() /* @ReadOnly */{
return isFloored_;
}
public /*@Rate*/ double cap() /* @ReadOnly */ {
if (gearing_ > 0 && isCapped_) {
return cap_;
}
if (gearing_ < 0 && isFloored_) {
return floor_;
}
return Constants.NULL_REAL;
}
public /*@Rate*/ double floor() /* @ReadOnly */ {
if (gearing_ > 0 && isFloored_) {
return floor_;
}
if (gearing_ < 0 && isCapped_) {
return cap_;
}
return Constants.NULL_REAL;
}
private /*@Rate*/ double effectiveCap() /* @ReadOnly */ {
return (cap_ - spread()) / gearing();
}
private /*@Rate*/ double effectiveFloor() /* @ReadOnly */ {
return (floor_ - spread()) / gearing();
}
//
// implements Observer
//
@Override
public void update() {
notifyObservers();
}
//
// implements PolymorphicVisitable
//
@Override
public void accept(final PolymorphicVisitor pv) {
final Visitor v = (pv!=null) ? pv.visitor(this.getClass()) : null;
if (v != null) {
v.visit(this);
} else {
super.accept(pv);
}
}
}
Ads help maintain this website.