Package org.jquantlib.instruments

Source Code of org.jquantlib.instruments.CapFloor

/*
Copyright (C) 2007 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
<jquant-devel@lists.sourceforge.net>. The license is also available online at
<http://www.jquantlib.org/index.php/LICENSE.TXT>.

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) 2001, 2002, 2003 Sadruddin Rejeb
Copyright (C) 2006 Ferdinando Ametrano
Copyright (C) 2006 Fran�ois du Vignaud
Copyright (C) 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
<quantlib-dev@lists.sf.net>. The license is also available online at
<http://quantlib.org/license.shtml>.

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.List;

import org.jquantlib.QL;
import org.jquantlib.Settings;
import org.jquantlib.cashflow.CashFlow;
import org.jquantlib.cashflow.CashFlows;
import org.jquantlib.cashflow.FloatingRateCoupon;
import org.jquantlib.cashflow.Leg;
import org.jquantlib.lang.exceptions.LibraryException;
import org.jquantlib.pricingengines.PricingEngine;
import org.jquantlib.quotes.Handle;
import org.jquantlib.termstructures.YieldTermStructure;
import org.jquantlib.time.Date;

/**
* Base class for cap-like instruments
*
* @category instruments
*
* @author Ueli Hofstetter
*/
public class CapFloor extends Instrument {

    public enum Type { Cap, Floor, Collar };

    private final Type type_;
    private final Leg floatingLeg_;
    private List</*@Rate*/ Double> capRates_;
    private List</*@Rate*/ Double> floorRates_;
    private final Handle<YieldTermStructure> termStructure_;

    public CapFloor(
            final CapFloor.Type type,
            final Leg floatingLeg,
            final List</*@Rate*/ Double> capRates,
            final List</*@Rate*/ Double> floorRates,
            final Handle<YieldTermStructure> termStructure,
            final PricingEngine engine){

        if (System.getProperty("EXPERIMENTAL") == null)
            throw new UnsupportedOperationException("Work in progress");

        this.type_ = type;
        this.floatingLeg_ = floatingLeg;
        this.capRates_ = capRates;
        this.floorRates_ = floorRates;
        this.termStructure_ = termStructure;

        setPricingEngine(engine);



        if (type_ == Type.Cap || type_ == Type.Collar) {
            QL.require(capRates_.size()>0 , "no cap rates given"); // QA:[RG]::verified // TODO: message
            // capRates_.reserve(floatingLeg_.size());
            while (capRates_.size() < floatingLeg_.size()) {
                // this looks kind of suspicious...
                capRates_.add(capRates_.get(capRates_.size() - 1));
            }
        }

        if (type_ == Type.Floor || type_ == Type.Collar) {
            QL.require(floorRates_.size()>0 , "no floor rates given"); // QA:[RG]::verified // TODO: message
            // floorRates_.reserve(floatingLeg_.size());
            while (floorRates_.size() < floatingLeg_.size()) {
                floorRates_.add(floorRates_.get(floorRates_.size() - 1));
            }
        }

        final Date evaluationDate = new Settings().evaluationDate();
        for (final CashFlow cashFlow : floatingLeg_) {
            cashFlow.addObserver(this);
        }

        // TODO: code review :: please verify against QL/C++ code
        // seems like we should have this.evaluationDate

        this.termStructure_.addObserver(this);
        evaluationDate.addObserver(this);
    }

    public CapFloor(
            final Type type,
            final Leg floatingLeg,
            final List</*@Rate*/ Double> strikes,
            final Handle<YieldTermStructure> termStructure,
            final PricingEngine engine){

        if (System.getProperty("EXPERIMENTAL") == null)
            throw new UnsupportedOperationException("Work in progress");

        this.type_ = type;
        this.floatingLeg_ = floatingLeg;
        this.termStructure_ = termStructure;

        setPricingEngine(engine);

        QL.require(strikes.size()>0 , "no strikes given"); // QA:[RG]::verified // TODO: message
        if (type_ == Type.Cap) {
            capRates_ = strikes;
            //capRates_.reserve(floatingLeg_.size());
            while (capRates_.size() < floatingLeg_.size()) {
                capRates_.add(capRates_.get(capRates_.size()-1));
            }
        } else if (type_ == Type.Floor) {
            floorRates_ = strikes;
            //floorRates_.reserve(floatingLeg_.size());
            while (floorRates_.size() < floatingLeg_.size()) {
                floorRates_.add(floorRates_.get(floorRates_.size()-1));
            }
        } else
            throw new LibraryException("only Cap/Floor types allowed in this constructor"); // QA:[RG]::verified // TODO: message

        final Date evaluationDate = new Settings().evaluationDate();
        for (final CashFlow cashFlow : floatingLeg_) {
            cashFlow.addObserver(this);
        }

        // TODO: code review :: please verify against QL/C++ code
        // Seems like we should have this.evaluationDate

        this.termStructure_.addObserver(this);
        evaluationDate.addObserver(this);
    }

    public /*@Rate*/double atmRate(){
        return CashFlows.getInstance().atmRate(floatingLeg_, termStructure_);
    }

    @Override
    public boolean isExpired(){
        Date lastPaymentDate = Date.minDate();
        for (int i=0; i<floatingLeg_.size(); i++) {
            //FIXME: kind of ugly... intention: get the last date of all dates in the floatingdate c++ max syntax.
            lastPaymentDate = lastPaymentDate.le(floatingLeg_.get(i).date())?floatingLeg_.get(i).date():lastPaymentDate;
        }
        return lastPaymentDate.le(termStructure_.currentLink().referenceDate());
    }

    public Date startDate(){
        return CashFlows.getInstance().startDate(floatingLeg_);
    }

    public Date maturityDate() {
        return CashFlows.getInstance().maturityDate(floatingLeg_);
    }

    public Date lastFixingDate() {
        final CashFlow lastCoupon = floatingLeg_.get(floatingLeg_.size() - 1); // no linkedlist :-(
        final FloatingRateCoupon lastFloatingCoupon = (FloatingRateCoupon) lastCoupon;
        return lastFloatingCoupon.fixingDate();
    }

    //    public void setupArguments
    //TODO: inner class arguments
    //void void setupArguments(/*PricingEngine.arguments* args*/Arguments args)  {
    //   CapFloor::arguments* arguments =
    //       dynamic_cast<CapFloor::arguments*>(args);
    //   QL_REQUIRE(arguments != 0, "wrong argument type");
    //
    //   Size n = floatingLeg_.size();
    //
    //   arguments->startTimes.clear();
    //   arguments->startTimes.reserve(n);
    //
    //   arguments->fixingDates.clear();
    //   arguments->fixingDates.reserve(n);
    //
    //   arguments->fixingTimes.clear();
    //   arguments->fixingTimes.reserve(n);
    //
    //   arguments->endTimes.clear();
    //   arguments->endTimes.reserve(n);
    //
    //   arguments->accrualTimes.clear();
    //   arguments->accrualTimes.reserve(n);
    //
    //   arguments->forwards.clear();
    //
    //   arguments->discounts.clear();
    //
    //   arguments->nominals.clear();
    //   arguments->nominals.reserve(n);
    //
    //   arguments->gearings.clear();
    //   arguments->gearings.reserve(n);
    //
    //   arguments->capRates.clear();
    //
    //   arguments->floorRates.clear();
    //
    //   arguments->type = type_;
    //
    //   Date today = Settings::instance().evaluationDate();
    //   Date settlement = termStructure_->referenceDate();
    //   DayCounter counter = termStructure_->dayCounter();
    //
    //   for (Size i=0; i<n; i++) {
    //       boost::shared_ptr<FloatingRateCoupon> coupon =
    //           boost::dynamic_pointer_cast<FloatingRateCoupon>(floatingLeg_[i]);
    //       QL_REQUIRE(coupon, "non-iborCoupon given");
    //       Date beginDate = coupon->accrualStartDate();
    //       Time time = counter.yearFraction(settlement, beginDate);
    //       arguments->startTimes.push_back(time);
    //       Date fixingDate = coupon->fixingDate();
    //       arguments->fixingDates.push_back(fixingDate);
    //       time = counter.yearFraction(today, fixingDate);
    //       arguments->fixingTimes.push_back(time);
    //       time = counter.yearFraction(settlement, coupon->date());
    //       arguments->endTimes.push_back(time);
    //       // this is passed explicitly for precision
    //       arguments->accrualTimes.push_back(coupon->accrualPeriod());
    //       // this is passed explicitly for precision
    //       if (arguments->endTimes.back() >= 0.0) { // but only if needed
    //           arguments->forwards.push_back(coupon->adjustedFixing());
    //           arguments->discounts.push_back(
    //                             termStructure_->discount(coupon->date()));
    //       } else {
    //           arguments->forwards.push_back(Null<Rate>());
    //           arguments->discounts.push_back(Null<DiscountFactor>());
    //       }
    //       arguments->nominals.push_back(coupon->nominal());
    //       Spread spread = coupon->spread();
    //       Real gearing = coupon->gearing();
    //       QL_REQUIRE(gearing > 0.0, "positive gearing required");
    //       arguments->gearings.push_back(gearing);
    //       arguments->spreads.push_back(spread);
    //       if (type_ == Cap || type_ == Collar)
    //           arguments->capRates.push_back((capRates_[i]-spread)/gearing);
    //       if (type_ == Floor || type_ == Collar)
    //           arguments->floorRates.push_back(
    //                                        (floorRates_[i]-spread)/gearing);
    //   }
    //}

    //void CapFloor::arguments::validate() const {
    //   QL_REQUIRE(endTimes.size() == startTimes.size(),
    //              "number of start times (" << startTimes.size()
    //              << ") different from that of end times ("
    //              << endTimes.size() << ")");
    //   QL_REQUIRE(accrualTimes.size() == startTimes.size(),
    //              "number of start times (" << startTimes.size()
    //              << ") different from that of accrual times ("
    //              << accrualTimes.size() << ")");
    //   QL_REQUIRE(type == CapFloor::Floor ||
    //              capRates.size() == startTimes.size(),
    //              "number of start times (" << startTimes.size()
    //              << ") different from that of cap rates ("
    //              << capRates.size() << ")");
    //   QL_REQUIRE(type == CapFloor::Cap ||
    //              floorRates.size() == startTimes.size(),
    //              "number of start times (" << startTimes.size()
    //              << ") different from that of floor rates ("
    //              << floorRates.size() << ")");
    //   QL_REQUIRE(gearings.size() == startTimes.size(),
    //              "number of start times (" << startTimes.size()
    //              << ") different from that of gearings ("
    //              << floorRates.size() << ")");
    //   QL_REQUIRE(nominals.size() == startTimes.size(),
    //              "number of start times (" << startTimes.size()
    //              << ") different from that of nominals ("
    //              << nominals.size() << ")");
    //}
    //
    //Volatility CapFloor::impliedVolatility(Real targetValue,
    //                                      Real accuracy,
    //                                      Size maxEvaluations,
    //                                      Volatility minVol,
    //                                      Volatility maxVol) const {
    //   calculate();
    //   QL_REQUIRE(!isExpired(), "instrument expired");
    //
    //   Volatility guess = 0.10;   // no way we can get a more accurate one
    //
    //   ImpliedVolHelper f(*this, termStructure_, targetValue);
    //   Brent solver;
    //   //NewtonSafe solver;
    //   solver.setMaxEvaluations(maxEvaluations);
    //   return solver.solve(f, accuracy, guess, minVol, maxVol);
    //}
    //
    //
    //CapFloor::ImpliedVolHelper::ImpliedVolHelper(
    //                         const CapFloor& cap,
    //                         const Handle<YieldTermStructure>& termStructure,
    //                         Real targetValue)
    //: termStructure_(termStructure), targetValue_(targetValue) {
    //
    //   vol_ = boost::shared_ptr<SimpleQuote>(new SimpleQuote(0.0));
    //   Handle<Quote> h(vol_);
    //   engine_ = boost::shared_ptr<PricingEngine>(new BlackCapFloorEngine(h));
    //   cap.setupArguments(engine_->getArguments());
    //
    //   results_ =
    //       dynamic_cast<const Instrument::results*>(engine_->getResults());
    //}
    //
    //Real CapFloor::ImpliedVolHelper::operator()(Volatility x) const {
    //   vol_->setValue(x);
    //   engine_->calculate();
    //   return results_->value-targetValue_;
    //}
    //
    //Real CapFloor::ImpliedVolHelper::derivative(Volatility x) const {
    //   vol_->setValue(x);
    //   engine_->calculate();
    //   return 0.0;
    //   //return results_->vega;
    //}
    //
    //std::ostream& operator<<(std::ostream& out, CapFloor::Type t) {
    //   switch (t) {
    //     case CapFloor::Cap:
    //       return out << "Cap";
    //     case CapFloor::Floor:
    //       return out << "Floor";
    //     case CapFloor::Collar:
    //       return out << "Collar";
    //     default:
    //       QL_FAIL("unknown CapFloor::Type (" << Integer(t) << ")");
    //   }
    //}







    @Override
    protected void performCalculations() throws ArithmeticException {
        // TODO Auto-generated method stub

    }
    @Override
    protected void setupArguments(final PricingEngine.Arguments arguments) {
        // TODO Auto-generated method stub

    }




    //    */
    //    class CapFloor : public Instrument {
    //      public:
    //        enum Type { Cap, Floor, Collar };
    //        class arguments;
    //        class engine;
    //        CapFloor(Type type,
    //                 const Leg& floatingLeg,
    //                 const std::vector<Rate>& capRates,
    //                 const std::vector<Rate>& floorRates,
    //                 const Handle<YieldTermStructure>& termStructure,
    //                 const boost::shared_ptr<PricingEngine>& engine);
    //        CapFloor(Type type,
    //                 const Leg& floatingLeg,
    //                 const std::vector<Rate>& strikes,
    //                 const Handle<YieldTermStructure>& termStructure,
    //                 const boost::shared_ptr<PricingEngine>& engine);
    //        //! \name Instrument interface
    //        //@{
    //        bool isExpired() const;
    //        void setupArguments(PricingEngine::arguments*) const;
    //        //@}
    //        //! \name Inspectors
    //        //@{
    //        Type type() const { return type_; }
    //        const Leg& leg() const {
    //            return floatingLeg_;
    //        }
    //        const std::vector<Rate>& capRates() const {
    //            return capRates_;
    //        }
    //        const std::vector<Rate>& floorRates() const {
    //            return floorRates_;
    //        }
    //        const Leg& floatingLeg() const {
    //            return floatingLeg_;
    //        }
    //        Rate atmRate() const;
    //        Date startDate() const;
    //        Date maturityDate() const;
    //        Date lastFixingDate() const;
    //        //@}
    //        //! implied term volatility
    //        Volatility impliedVolatility(Real price,
    //                                     Real accuracy = 1.0e-4,
    //                                     Size maxEvaluations = 100,
    //                                     Volatility minVol = 1.0e-7,
    //                                     Volatility maxVol = 4.0) const;
    //      private:
    //        Type type_;
    //        Leg floatingLeg_;
    //        std::vector<Rate> capRates_;
    //        std::vector<Rate> floorRates_;
    //        Handle<YieldTermStructure> termStructure_;
    //        // helper class for implied USE_INDEXEDvolatility calculation
    //        class ImpliedVolHelper {
    //          public:
    //            ImpliedVolHelper(const CapFloor&,
    //                             const Handle<YieldTermStructure>&,
    //                             Real targetValue);
    //            Real operator()(Volatility x) const;
    //            Real derivative(Volatility x) const;
    //          private:
    //            boost::shared_ptr<PricingEngine> engine_;
    //            Handle<YieldTermStructure> termStructure_;
    //            Real targetValue_;
    //            boost::shared_ptr<SimpleQuote> vol_;
    //            const Instrument::results* results_;
    //        };
    //    };
    //
    //    //! Concrete cap class
    //    /*! \ingroup instruments */
    //    class Cap : public CapFloor {
    //      public:
    //        Cap(const Leg& floatingLeg,
    //            const std::vector<Rate>& exerciseRates,
    //            const Handle<YieldTermStructure>& termStructure,
    //            const boost::shared_ptr<PricingEngine>& engine)
    //        : CapFloor(CapFloor::Cap, floatingLeg,
    //                   exerciseRates, std::vector<Rate>(),
    //                   termStructure, engine) {}
    //    };
    //
    //    //! Concrete floor class
    //    /*! \ingroup instruments */
    //    class Floor : public CapFloor {
    //      public:
    //        Floor(const Leg& floatingLeg,
    //              const std::vector<Rate>& exerciseRates,
    //              const Handle<YieldTermStructure>& termStructure,
    //              const boost::shared_ptr<PricingEngine>& engine)
    //        : CapFloor(CapFloor::Floor, floatingLeg,
    //                   std::vector<Rate>(), exerciseRates,
    //                   termStructure, engine) {}
    //    };
    //
    //    //! Concrete collar class
    //    /*! \ingroup instruments */
    //    class Collar : public CapFloor {
    //      public:
    //        Collar(const Leg& floatingLeg,
    //               const std::vector<Rate>& capRates,
    //               const std::vector<Rate>& floorRates,
    //               const Handle<YieldTermStructure>& termStructure,
    //               const boost::shared_ptr<PricingEngine>& engine)
    //        : CapFloor(CapFloor::Collar, floatingLeg, capRates, floorRates,
    //                   termStructure, engine) {}
    //    };
    //
    //
    //    //! %Arguments for cap/floor calculation
    //    class CapFloor::arguments : public virtual PricingEngine::arguments {
    //      public:
    //        arguments() : type(CapFloor::Type(-1)) {}
    //        CapFloor::Type type;
    //        std::vector<Time> startTimes;
    //        std::vector<Date> fixingDates;
    //        std::vector<Time> fixingTimes;
    //        std::vector<Time> endTimes;
    //        std::vector<Time> accrualTimes;
    //        std::vector<Rate> capRates;
    //        std::vector<Rate> floorRates;
    //        std::vector<Rate> forwards;
    //        std::vector<Real> gearings;
    //        std::vector<Real> spreads;
    //        std::vector<DiscountFactor> discounts;
    //        std::vector<Real> nominals;
    //        void validate() const;
    //    };
    //
    //    //! base class for cap/floor engines
    //    class CapFloor::engine
    //        : public GenericEngine<CapFloor::arguments, CapFloor::results> {};
    //
    //    std::ostream& operator<<(std::ostream&, CapFloor::Type);

}
TOP

Related Classes of org.jquantlib.instruments.CapFloor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.