/*
Copyright (C) 2011 Tim Blackler
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.
*/
/*
Copyright (C) 2006, 2008 Ferdinando Ametrano
Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
Copyright (C) 2003, 2004, 2005, 2006, 2007 StatPro Italia srl
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.
*/
package org.jquantlib.instruments;
import org.jquantlib.QL;
import org.jquantlib.cashflow.AverageBMALeg;
import org.jquantlib.cashflow.CashFlow;
import org.jquantlib.cashflow.IborLeg;
import org.jquantlib.cashflow.Leg;
import org.jquantlib.daycounters.DayCounter;
import org.jquantlib.indexes.BMAIndex;
import org.jquantlib.indexes.IborIndex;
import org.jquantlib.lang.annotation.Real;
import org.jquantlib.lang.exceptions.LibraryException;
import org.jquantlib.time.BusinessDayConvention;
import org.jquantlib.time.Schedule;
/**
* BMA Swap
*
* swap paying Libor against BMA coupons
*
* @category instruments
*
* @author Tim Blackler
*/
// TODO: code review :: license, class comments, comments for access modifiers, comments for @Override
public class BMASwap extends Swap {
static final /*@Spread*/ double basisPoint = 1.0e-4;
private final Type type;
private final /*@Real*/ double nominal;
private final /*@Rate*/ double liborFraction;
private final /*@Rate*/ double liborSpread;
public BMASwap(
final Type type,
final /*@Real*/ double nominal,
final Schedule liborSchedule,
final /*@Rate*/ double liborFraction,
final /*@Rate*/ double liborSpread,
final IborIndex liborIndex,
final DayCounter liborDayCount,
final Schedule bmaSchedule,
final BMAIndex bmaIndex,
final DayCounter bmaDayCount) {
super(2);
this.type = type;
this.nominal = nominal;
this.liborFraction = liborFraction;
this.liborSpread = liborSpread;
final BusinessDayConvention convention = liborSchedule.businessDayConvention();
final Leg iborLeg = new IborLeg(liborSchedule, liborIndex)
.withNotionals(nominal)
.withPaymentDayCounter(liborDayCount)
.withPaymentAdjustment(convention)
.withFixingDays(liborIndex.fixingDays())
.withGearings(liborFraction)
.withSpreads(liborSpread)
.Leg();
this.legs.add(iborLeg);
final Leg bmaLeg = new AverageBMALeg(bmaSchedule, bmaIndex)
.withNotionals(nominal)
.withPaymentDayCounter(bmaDayCount)
.withPaymentAdjustment(bmaSchedule.businessDayConvention())
.Leg();
this.legs.add(bmaLeg);
for (final Leg leg : this.legs) {
for (final CashFlow item : leg) {
item.addObserver(this);
}
}
switch (type) {
case Payer:
payer[0] = +1.0;
payer[1] = -1.0;
break;
case Receiver:
payer[0] = -1.0;
payer[1] = +1.0;
break;
default:
throw new LibraryException("Unknown BMA-swap type");
}
}
public /*@Rate*/ double liborFraction() /* @ReadOnly */ {
return liborFraction;
}
public /*@Spread*/ double liborSpread() /* @ReadOnly */ {
return liborSpread;
}
public /*@Real*/ double nominal() /* @ReadOnly */ {
return nominal;
}
public Type type() /* @ReadOnly */ {
return type;
}
public Leg liborLeg() /* @ReadOnly */ {
return legs.get(0);
}
public Leg bmaLeg() /* @ReadOnly */ {
return legs.get(1);
}
public /*@Real*/ double liborLegBPS() /* @ReadOnly */ {
calculate();
QL.require(!Double.isNaN(legBPS[0]) , "result not available");
return legBPS[0];
}
public /*@Real*/ double liborLegNPV() /* @ReadOnly */ {
calculate();
QL.require(!Double.isNaN(legNPV[0]) , "result not available");
return legNPV[0];
}
public /*@Real*/ double fairLiborFraction() /* @ReadOnly */ {
@Real
final double spreadNPV = (liborSpread/basisPoint)*liborLegBPS();
@Real
final double pureLiborNPV = liborLegNPV() - spreadNPV;
return -liborFraction * (bmaLegNPV() + spreadNPV) / pureLiborNPV;
}
public /*@Spread*/ double fairLiborSpread() /* @ReadOnly */ {
return liborSpread - NPV()/(liborLegBPS()/basisPoint);
}
public /*@Real*/ double bmaLegBPS() /* @ReadOnly */ {
calculate();
QL.require(!Double.isNaN(legBPS[1]) , "result not available");
return legBPS[1];
}
public /*@Real*/ double bmaLegNPV() /* @ReadOnly */ {
calculate();
QL.require(!Double.isNaN(legNPV[1]) , "result not available");
return legNPV[1];
}
//
// inner public enums
//
public static enum Type {
Receiver (-1),
Payer (1);
private final int enumValue;
private Type(final int frequency) {
this.enumValue = frequency;
}
static public Type valueOf(final int value) {
switch (value) {
case -1:
return Type.Receiver;
case 1:
return Type.Payer;
default:
throw new LibraryException("value must be one of -1, 1"); // TODO: message
}
}
public int toInteger() {
return this.enumValue;
}
}
}
Ads help maintain this website.