Logo Search packages:      
Sourcecode: quantlib version File versions

assetswap.cpp

/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
 Copyright (C) 2006 Chiara Fornarola

 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
 <quantlib-dev@lists.sf.net>. The license is also available online at
 <http://quantlib.org/reference/license.html>.

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

#include <ql/CashFlows/cashflowvectors.hpp>
#include <ql/CashFlows/fixedratecoupon.hpp>
#include <ql/CashFlows/floatingratecoupon.hpp>
#include <ql/CashFlows/simplecashflow.hpp>
#include <ql/Instruments/assetswap.hpp>

namespace QuantLib {

    AssetSwap::AssetSwap(
                  bool payFixedRate,
                  const boost::shared_ptr<Bond>& bond,
                  Real bondCleanPrice,
                  const Schedule& floatSchedule,
                  const boost::shared_ptr<Xibor>& index,
                  Spread spread,
                  const DayCounter& floatingDayCount,
                  const Handle<YieldTermStructure>& termStructure)
    : Swap(termStructure,
           std::vector<boost::shared_ptr<CashFlow> >(),
           std::vector<boost::shared_ptr<CashFlow> >()),
      payFixedRate_(payFixedRate), spread_(spread),
      bondCleanPrice_(bondCleanPrice) {

        // par asset swap
        nominal_ = bond->faceAmount();

        BusinessDayConvention convention =
            floatSchedule.businessDayConvention();

        std::vector<boost::shared_ptr<CashFlow> > floatingLeg =
            FloatingRateCouponVector(floatSchedule,
                                     convention,
                                     std::vector<Real>(1,nominal_),
                                     index->settlementDays(), index,
                                     std::vector<Real>(1,1.0),
                                     std::vector<Spread>(1,spread),
                                     floatingDayCount);
        std::vector<boost::shared_ptr<CashFlow> >::const_iterator i;

        for (i = floatingLeg.begin(); i < floatingLeg.end(); ++i)
            registerWith(*i);

        // upfront
        upfrontDate_ = floatSchedule.startDate();
        Real dirtyPrice = bondCleanPrice_ + bond->accruedAmount(upfrontDate_);
        Real upfront=(dirtyPrice-100.0)/100.0*nominal_;
        boost::shared_ptr<CashFlow> upfrontCashFlow (new
            SimpleCashFlow(upfront, upfrontDate_));
        floatingLeg.insert(floatingLeg.begin(), upfrontCashFlow);

        std::vector<boost::shared_ptr<CashFlow> > fixedLeg =
            bond->cashflows();
        // remove redemption
        fixedLeg.pop_back();
        for (i = fixedLeg.begin(); i < fixedLeg.end(); ++i)
            registerWith(*i);

        // handle when termination date is earlier than
        // bond maturity date


        legs_[0] = fixedLeg;
        legs_[1] = floatingLeg;
        if (payFixedRate_) {
            payer_[0]=-1.0;
            payer_[1]=+1.0;
        } else {
            payer_[0]=+1.0;
            payer_[1]=-1.0;
        }
    }

00092     void AssetSwap::setupArguments(Arguments* args) const {
        AssetSwap::arguments* arguments =
            dynamic_cast<AssetSwap::arguments*>(args);

        QL_REQUIRE(arguments != 0, "wrong argument type");

        arguments->payFixed = payFixedRate_;
        arguments->nominal = nominal_;
        // reset in case it's not set later
        arguments->currentFloatingCoupon = Null<Real>();

        Date settlement = termStructure_->referenceDate();
        DayCounter counter = termStructure_->dayCounter();
        Size i;

        const std::vector<boost::shared_ptr<CashFlow> >& fixedCoupons =
            bondLeg();

        arguments->fixedResetTimes = arguments->fixedPayTimes =
            std::vector<Time>(fixedCoupons.size());
        arguments->fixedCoupons = std::vector<Real>(fixedCoupons.size());

        for (i=0; i<fixedCoupons.size(); i++) {
            boost::shared_ptr<FixedRateCoupon> coupon =
                boost::dynamic_pointer_cast<FixedRateCoupon>(fixedCoupons[i]);

            Time time = counter.yearFraction(settlement, coupon->date());
            arguments->fixedPayTimes[i] = time;
            time = counter.yearFraction(settlement,
                                        coupon->accrualStartDate());
            arguments->fixedResetTimes[i] = time;
            arguments->fixedCoupons[i] = coupon->amount();
        }

        const std::vector<boost::shared_ptr<CashFlow> >& floatingCoupons =
            floatingLeg();

        arguments->floatingResetTimes = arguments->floatingPayTimes =
            arguments->floatingFixingTimes = arguments->floatingAccrualTimes =
            std::vector<Time>(floatingCoupons.size());
        arguments->floatingSpreads =
            std::vector<Spread>(floatingCoupons.size());

        for (i=0; i<floatingCoupons.size(); i++) {
            boost::shared_ptr<FloatingRateCoupon> coupon =
                boost::dynamic_pointer_cast<FloatingRateCoupon>(
                                                          floatingCoupons[i]);

            Date resetDate = coupon->accrualStartDate(); // already adjusted
            Time resetTime = counter.yearFraction(settlement, resetDate);
            arguments->floatingResetTimes[i] = resetTime;
            Time paymentTime =
                counter.yearFraction(settlement, coupon->date());
            arguments->floatingPayTimes[i] = paymentTime;
            Time floatingFixingTime =
                counter.yearFraction(settlement, coupon->fixingDate());
            arguments->floatingFixingTimes[i] = floatingFixingTime;
            arguments->floatingAccrualTimes[i] = coupon->accrualPeriod();
            arguments->floatingSpreads[i] = coupon->spread();
            if (resetTime < 0.0 && paymentTime >= 0.0)
                arguments->currentFloatingCoupon = coupon->amount();
        }
    }

    Spread AssetSwap::fairSpread() const {
        calculate();
        QL_REQUIRE(fairSpread_ != Null<Spread>(), "fairSpread not available");
        return fairSpread_;
    }

    Real AssetSwap::floatingLegBPS() const {
        calculate();
        QL_REQUIRE(legBPS_[1] != Null<Real>(), "floatingLegBPS not available");
        return legBPS_[1];
    }

    Real AssetSwap::fairPrice() const {
        calculate();
        QL_REQUIRE(fairPrice_ != Null<Real>(), "fairPrice not available");
        return fairPrice_;
    }
00173     void AssetSwap::setupExpired() const {
        Swap::setupExpired();
        legBPS_[0] = legBPS_[1] = 0.0;
        fairSpread_ = Null<Spread>();
        fairPrice_= Null<Real>();
    }

00180     void AssetSwap::performCalculations() const {
        if (engine_) {
            Instrument::performCalculations();
        } else {
            static const Spread basisPoint = 1.0e-4;
            Swap::performCalculations();
            fairSpread_ = spread_ - NPV_/(legBPS_[1]/basisPoint);

            // handle when upfrontDate_ is in the past
            if (upfrontDate_<termStructure_->referenceDate())
                fairPrice_ = Null<Real>();
            else
                fairPrice_= bondCleanPrice_ -
                    NPV_/(nominal_/100.0)/termStructure_->discount(
                                                            upfrontDate_);

        }
    }

00199     void AssetSwap::fetchResults(const Results* r) const {
        Instrument::fetchResults(r);
        const AssetSwap::results* results =
            dynamic_cast<const AssetSwap::results*>(r);
        fairSpread_ = results->fairSpread;
        fairPrice_= results->fairPrice;
    }

    void AssetSwap::arguments::validate() const {
        QL_REQUIRE(nominal != Null<Real>(),
                   "nominal null or not set");
        QL_REQUIRE(fixedResetTimes.size() == fixedPayTimes.size(),
                   "number of fixed start times different from "
                   "number of fixed payment times");
        QL_REQUIRE(fixedPayTimes.size() == fixedCoupons.size(),
                   "number of fixed payment times different from "
                   "number of fixed coupon amounts");
        QL_REQUIRE(floatingResetTimes.size() == floatingPayTimes.size(),
                   "number of floating start times different from "
                   "number of floating payment times");
        QL_REQUIRE(floatingFixingTimes.size() == floatingPayTimes.size(),
                   "number of floating fixing times different from "
                   "number of floating payment times");
        QL_REQUIRE(floatingAccrualTimes.size() == floatingPayTimes.size(),
                   "number of floating accrual times different from "
                   "number of floating payment times");
        QL_REQUIRE(floatingSpreads.size() == floatingPayTimes.size(),
                   "number of floating spreads different from "
                   "number of floating payment times");
        QL_REQUIRE(currentFloatingCoupon != Null<Real>() || // unless...
                   floatingResetTimes.empty() ||
                   floatingResetTimes[0] >= 0.0,
                   "current floating coupon null or not set");
    }


}

Generated by  Doxygen 1.6.0   Back to index