/*
Copyright (C) 2009 Ueli Hofstetter
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.Settings;
import org.jquantlib.indexes.InterestRateIndex;
import org.jquantlib.instruments.Option;
import org.jquantlib.pricingengines.BlackFormula;
import org.jquantlib.quotes.Handle;
import org.jquantlib.termstructures.YieldTermStructure;
import org.jquantlib.termstructures.volatilities.optionlet.OptionletVolatilityStructure;
import org.jquantlib.time.Date;
/*
* DONE!
*/
public class BlackIborCouponPricer extends IborCouponPricer {
private final static String missing_caplet_volatility = "missing caplet volatility";
public BlackIborCouponPricer(final Handle capletVol) {
super(capletVol);
}
private IborCoupon coupon_;
private double discount_;
private double gearing_;
private double spread_;
private double spreadLegValue_;
@Override
public void initialize( final FloatingRateCoupon coupon) {
coupon_ = (IborCoupon)coupon;
gearing_ = coupon_.gearing();
spread_ = coupon_.spread();
final Date paymentDate = coupon_.date();
final InterestRateIndex index = coupon_.index();
final Handle rateCurve = index.termStructure();
final Date today = new Settings().evaluationDate();
if(paymentDate.gt(today))
discount_ = rateCurve.currentLink().discount(paymentDate);
else
discount_ = 1.0;
spreadLegValue_ = spread_ * coupon_.accrualPeriod()* discount_;
}
@Override
public double swapletPrice() {
// past or future fixing is managed in InterestRateIndex::fixing()
final double swapletPrice = adjustedFixing()* coupon_.accrualPeriod()* discount_;
return gearing_ * swapletPrice + spreadLegValue_;
}
@Override
public double swapletRate() {
return swapletPrice()/(coupon_.accrualPeriod()*discount_);
}
@Override
public double capletPrice(final double effectiveCap) {
final double capletPrice = optionletPrice(Option.Type.Call, effectiveCap);
return gearing_ * capletPrice;
}
@Override
public double capletRate(final double effectiveCap) {
return capletPrice(effectiveCap)/(coupon_.accrualPeriod()*discount_);
}
@Override
public double floorletPrice(final double effectiveFloor) {
final double floorletPrice = optionletPrice(Option.Type.Put, effectiveFloor);
return gearing_ * floorletPrice;
}
@Override
public double floorletRate(final double effectiveFloor) {
return floorletPrice(effectiveFloor)/
(coupon_.accrualPeriod()*discount_);
}
public double optionletPrice(final Option.Type optionType, final double effStrike) {
final Date fixingDate = coupon_.fixingDate();
if (fixingDate.le(new Settings().evaluationDate())) {
// the amount is determined
double a, b;
if (optionType==Option.Type.Call) {
a = coupon_.indexFixing();
b = effStrike;
} else {
a = effStrike;
b = coupon_.indexFixing();
}
return Math.max(a - b, 0.0)* coupon_.accrualPeriod()*discount_;
} else {
QL.require(capletVolatility()!=null , missing_caplet_volatility); // TODO: message
// not yet determined, use Black model
final double fixing =
BlackFormula.blackFormula(
optionType,
effStrike,
adjustedFixing(),
Math.sqrt(capletVolatility().currentLink().blackVariance(fixingDate,
effStrike)));
return fixing * coupon_.accrualPeriod()*discount_;
}
}
public double adjustedFixing() {
double adjustement = 0.0;
final double fixing = coupon_.indexFixing();
if (!coupon_.isInArrears())
adjustement = 0.0;
else {
// see Hull, 4th ed., page 550
QL.require(capletVolatility() != null , missing_caplet_volatility); // TODO: message
final Date d1 = coupon_.fixingDate();
final Date referenceDate = capletVolatility().currentLink().referenceDate();
if (d1.le(referenceDate))
adjustement = 0.0;
else {
final Date d2 = coupon_.index().maturityDate(d1);
final double tau = coupon_.index().dayCounter().yearFraction(d1, d2);
final double variance = capletVolatility().currentLink().blackVariance(d1, fixing);
adjustement = fixing*fixing*variance*tau/(1.0+fixing*tau);
}
}
return fixing + adjustement;
}
}
Ads help maintain this website.