/*
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.
 */

/*
 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 java.util.ArrayList;
import java.util.List;

import org.jquantlib.QL;
import org.jquantlib.cashflow.CashFlow;
import org.jquantlib.cashflow.FixedRateCoupon;
import org.jquantlib.cashflow.FixedRateLeg;
import org.jquantlib.cashflow.IborCoupon;
import org.jquantlib.cashflow.IborLeg;
import org.jquantlib.cashflow.Leg;
import org.jquantlib.daycounters.DayCounter;
import org.jquantlib.indexes.IborIndex;
import org.jquantlib.lang.exceptions.LibraryException;
import org.jquantlib.math.Constants;
import org.jquantlib.pricingengines.PricingEngine;
import org.jquantlib.time.BusinessDayConvention;
import org.jquantlib.time.Date;
import org.jquantlib.time.Schedule;

/**
 * Plain-vanilla swap
 *
 * @note if you define TodaysPayments like this
 * 
 * new Settings().setTodaysPayments(true);
 * 
* payments occurring at the settlement date of * the swap are included in the NPV, and therefore * affect the fair-rate and fair-spread * calculation. This might not be what you want. * * @category instruments * * @author Richard Gomes */ // TODO: code review :: license, class comments, comments for access modifiers, comments for @Override public class VanillaSwap extends Swap { static final /*@Spread*/ double basisPoint = 1.0e-4; private final Type type; private final /*@Real*/ double nominal; private final Schedule fixedSchedule; private final /*@Rate*/ double fixedRate; private final DayCounter fixedDayCount; private final Schedule floatingSchedule; private final IborIndex iborIndex; private final /*@Spread*/ double spread; private final DayCounter floatingDayCount; private final BusinessDayConvention paymentConvention; // private final Array fixingDays; // results private /*@Rate*/ double fairRate; private /*@Spread*/ double fairSpread; public VanillaSwap( final Type type, final /*@Real*/ double nominal, final Schedule fixedSchedule, final /*@Rate*/ double fixedRate, final DayCounter fixedDayCount, final Schedule floatSchedule, final IborIndex iborIndex, final /*@Spread*/ double spread, final DayCounter floatingDayCount) { this(type, nominal, fixedSchedule, fixedRate, fixedDayCount, floatSchedule, iborIndex, spread, floatingDayCount, BusinessDayConvention.Following); } //FIXME: remove parameter "fixingDays" public VanillaSwap( final Type type, final /*@Real*/ double nominal, final Schedule fixedSchedule, final /*@Rate*/ double fixedRate, final DayCounter fixedDayCount, final Schedule floatSchedule, final IborIndex iborIndex, final /*@Spread*/ double spread, final DayCounter floatingDayCount, final BusinessDayConvention paymentConvention /*, final Array fixingDays*/) { super(2); this.type = type; this.nominal = nominal; this.fixedSchedule = fixedSchedule; this.fixedRate = fixedRate; this.fixedDayCount = fixedDayCount; this.floatingSchedule = floatSchedule; this.iborIndex = iborIndex; this.spread = spread; this.floatingDayCount = floatingDayCount; this.paymentConvention = paymentConvention; //FIXME this.fixingDays = fixingDays; final Leg fixedLeg = new FixedRateLeg(fixedSchedule, fixedDayCount) .withNotionals(nominal) .withCouponRates(fixedRate) .withPaymentAdjustment(paymentConvention) .Leg(); // JM where are gearings set they cannot be null for the floating leg. final Leg floatingLeg = new IborLeg(floatingSchedule, iborIndex) .withNotionals(nominal) .withPaymentDayCounter(floatingDayCount) .withPaymentAdjustment(paymentConvention) //FIXME:: .withFixingDays (fixingDays) // FIXME: slight deviation from quantlib, need to expose fixing days up the stack .withSpreads(spread) // FIXME: JM quantlib does not assign this, it is currently required for construction // .withGearings(1.0) .Leg(); for (final CashFlow item : floatingLeg) { item.addObserver(this); } super.legs.add(fixedLeg); super.legs.add(floatingLeg); if (type==Type.Payer) { super.payer[0] = -1.0; super.payer[1] = +1.0; } else { super.payer[0] = +1.0; super.payer[1] = -1.0; } } public /*@Rate*/ double fairRate() /* @ReadOnly */ { calculate(); QL.require(!Double.isNaN(fairRate) , "result not available"); // TODO: message return fairRate; } public /*@Spread*/ double fairSpread() /* @ReadOnly */ { calculate(); QL.require(!Double.isNaN(fairSpread) , "result not available"); // TODO: message return fairSpread; } public final Leg fixedLeg() /* @ReadOnly */ { return legs.get(0); } public final Leg floatingLeg() /* @ReadOnly */ { return legs.get(1); } public /*@Real*/ double fixedLegBPS() /* @ReadOnly */ { calculate(); QL.require(!Double.isNaN(legBPS[0]) , "result not available"); // TODO: message return legBPS[0]; } public /*@Real*/ double floatingLegBPS() /* @ReadOnly */ { calculate(); QL.require(!Double.isNaN(legBPS[1]) , "result not available"); return legBPS[1]; } public /*@Real*/ double fixedLegNPV() /* @ReadOnly */ { calculate(); QL.require(!Double.isNaN(legNPV[0]) , "result not available"); // TODO: message return legNPV[0]; } public /*@Real*/ double floatingLegNPV() /* @ReadOnly */ { calculate(); QL.require(!Double.isNaN(legNPV[1]) , "result not available"); // TODO: message return legNPV[1]; } @Override public void setupExpired() /* @ReadOnly */ { super.setupExpired(); legBPS[0] = 0.0; legBPS[1] = 0.0; fairRate = Constants.NULL_REAL; fairSpread = Constants.NULL_REAL; } @Override public void setupArguments(final PricingEngine.Arguments arguments) /* @ReadOnly */ { super.setupArguments(arguments); if (arguments.getClass().isAssignableFrom(VanillaSwap.Arguments.class)) { final VanillaSwap.ArgumentsImpl a = (VanillaSwap.ArgumentsImpl) arguments; a.type = type; a.nominal = nominal; final Leg fixedCoupons = fixedLeg(); a.fixedResetDates = new ArrayList(fixedCoupons.size()); a.fixedPayDates = new ArrayList(fixedCoupons.size()); a.fixedCoupons = new ArrayList(fixedCoupons.size()); for (int i=0; i(floatingCoupons.size()); a.floatingPayDates = new ArrayList(floatingCoupons.size()); a.floatingFixingDates = new ArrayList(floatingCoupons.size()); a.floatingAccrualTimes = new ArrayList(floatingCoupons.size()); a.floatingSpreads = new ArrayList(floatingCoupons.size()); a.floatingCoupons = new ArrayList(floatingCoupons.size()); for (int i=0; i fixedResetDates; public List fixedPayDates; public List floatingAccrualTimes; public List floatingResetDates; public List floatingFixingDates; public List floatingPayDates; public List fixedCoupons; public List floatingSpreads; public List floatingCoupons; @Override public void validate() /* @ReadOnly */ { super.validate(); QL.require(!Double.isNaN(nominal) , "nominal null or not set"); // TODO: message QL.require(fixedResetDates.size() == fixedPayDates.size() , "number of fixed start dates different from number of fixed payment dates"); QL.require(fixedPayDates.size() == fixedCoupons.size() , "number of fixed payment dates different from number of fixed coupon amounts"); QL.require(floatingResetDates.size() == floatingPayDates.size() , "number of floating start dates different from number of floating payment dates"); QL.require(floatingFixingDates.size() == floatingPayDates.size() , "number of floating fixing dates different from number of floating payment dates"); QL.require(floatingAccrualTimes.size() == floatingPayDates.size() , "number of floating accrual Times different from number of floating payment dates"); QL.require(floatingSpreads.size() == floatingPayDates.size() , "number of floating spreads different from number of floating payment dates"); QL.require(floatingPayDates.size() == floatingCoupons.size() , "number of floating payment dates different from number of floating coupon amounts"); } } /** * Results from simple swap calculation * * @author Richard Gomes */ // TODO: code review :: object model needs to be validated and eventually refactored public class ResultsImpl extends Swap.ResultsImpl implements VanillaSwap.Results { public /*@Rate*/ double fairRate; public /*@Spread*/ double fairSpread; @Override public void reset() { super.reset(); fairRate = Constants.NULL_REAL; fairSpread = Constants.NULL_REAL; } } }

Ads help maintain this website.