/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2002, 2003 Ferdinando Ametrano Copyright (C) 2003, 2004, 2005, 2006 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. */ /*! \file voltermstructure.hpp \brief Volatility term structures */ #ifndef quantlib_vol_term_structures_hpp #define quantlib_vol_term_structures_hpp #include #include namespace QuantLib { //! Black-volatility term structure /*! This abstract class defines the interface of concrete Black-volatility term structures which will be derived from this one. Volatilities are assumed to be expressed on an annual basis. */ class BlackVolTermStructure : public TermStructure { public: /*! \name Constructors See the TermStructure documentation for issues regarding constructors. */ //@{ //! default constructor /*! \warning term structures initialized by means of this constructor must manage their own reference date by overriding the referenceDate() method. */ BlackVolTermStructure(const DayCounter& dc = Actual365Fixed()); //! initialize with a fixed reference date BlackVolTermStructure(const Date& referenceDate, const Calendar& cal = Calendar(), const DayCounter& dc = Actual365Fixed()); //! calculate the reference date based on the global evaluation date BlackVolTermStructure(Natural settlementDays, const Calendar&, const DayCounter& dc = Actual365Fixed()); //@} virtual ~BlackVolTermStructure() {} //! \name Black Volatility //@{ //! present (a.k.a spot) volatility Volatility blackVol(const Date& maturity, Real strike, bool extrapolate = false) const; //! present (a.k.a spot) volatility Volatility blackVol(Time maturity, Real strike, bool extrapolate = false) const; //! present (a.k.a spot) variance Real blackVariance(const Date& maturity, Real strike, bool extrapolate = false) const; //! present (a.k.a spot) variance Real blackVariance(Time maturity, Real strike, bool extrapolate = false) const; //! future (a.k.a. forward) volatility Volatility blackForwardVol(const Date& date1, const Date& date2, Real strike, bool extrapolate = false) const; //! future (a.k.a. forward) volatility Volatility blackForwardVol(Time time1, Time time2, Real strike, bool extrapolate = false) const; //! future (a.k.a. forward) variance Real blackForwardVariance(const Date& date1, const Date& date2, Real strike, bool extrapolate = false) const; //! future (a.k.a. forward) variance Real blackForwardVariance(Time time1, Time time2, Real strike, bool extrapolate = false) const; //@} //! \name Limits //@{ //! the minimum strike for which the term structure can return vols virtual Real minStrike() const = 0; //! the maximum strike for which the term structure can return vols virtual Real maxStrike() const = 0; //@} //! \name Visitability //@{ virtual void accept(AcyclicVisitor&); //@} protected: /*! \name Calculations These methods must be implemented in derived classes to perform the actual volatility calculations. When they are called, range check has already been performed; therefore, they must assume that extrapolation is required. */ //@{ //! Black variance calculation virtual Real blackVarianceImpl(Time t, Real strike) const = 0; //! Black volatility calculation virtual Volatility blackVolImpl(Time t, Real strike) const = 0; //@} private: static const Time dT; void checkRange(Time, Real strike, bool extrapolate) const; }; //! Black-volatility term structure /*! This abstract class acts as an adapter to BlackVolTermStructure allowing the programmer to implement only the blackVolImpl(Time, Real, bool) method in derived classes. Volatility are assumed to be expressed on an annual basis. */ class BlackVolatilityTermStructure : public BlackVolTermStructure { public: /*! \name Constructors See the TermStructure documentation for issues regarding constructors. */ //@{ //! default constructor /*! \warning term structures initialized by means of this constructor must manage their own reference date by overriding the referenceDate() method. */ BlackVolatilityTermStructure(const DayCounter& dc = Actual365Fixed()); //! initialize with a fixed reference date BlackVolatilityTermStructure(const Date& referenceDate, const Calendar& cal = Calendar(), const DayCounter& dc = Actual365Fixed()); //! calculate the reference date based on the global evaluation date BlackVolatilityTermStructure(Natural settlementDays, const Calendar&, const DayCounter& dc = Actual365Fixed()); //@} //! \name Visitability //@{ virtual void accept(AcyclicVisitor&); //@} protected: /*! Returns the variance for the given strike and date calculating it from the volatility. */ Real blackVarianceImpl(Time maturity, Real strike) const; }; //! Black variance term structure /*! This abstract class acts as an adapter to VolTermStructure allowing the programmer to implement only the blackVarianceImpl(Time, Real, bool) method in derived classes. Volatility are assumed to be expressed on an annual basis. */ class BlackVarianceTermStructure : public BlackVolTermStructure { public: /*! \name Constructors See the TermStructure documentation for issues regarding constructors. */ //@{ //! default constructor /*! \warning term structures initialized by means of this constructor must manage their own reference date by overriding the referenceDate() method. */ BlackVarianceTermStructure(const DayCounter& dc = Actual365Fixed()); //! initialize with a fixed reference date BlackVarianceTermStructure(const Date& referenceDate, const Calendar& cal = Calendar(), const DayCounter& dc = Actual365Fixed()); //! calculate the reference date based on the global evaluation date BlackVarianceTermStructure(Natural settlementDays, const Calendar&, const DayCounter& dc = Actual365Fixed()); //@} //! \name Visitability //@{ virtual void accept(AcyclicVisitor&); //@} protected: /*! Returns the volatility for the given strike and date calculating it from the variance. */ Volatility blackVolImpl(Time maturity, Real strike) const; }; //! Local-volatility term structure /*! This abstract class defines the interface of concrete local-volatility term structures which will be derived from this one. Volatilities are assumed to be expressed on an annual basis. */ class LocalVolTermStructure : public TermStructure { public: /*! \name Constructors See the TermStructure documentation for issues regarding constructors. */ //@{ //! default constructor /*! \warning term structures initialized by means of this constructor must manage their own reference date by overriding the referenceDate() method. */ LocalVolTermStructure(const DayCounter& dc = Actual365Fixed()); //! initialize with a fixed reference date LocalVolTermStructure(const Date& referenceDate, const Calendar& cal = Calendar(), const DayCounter& dc = Actual365Fixed()); //! calculate the reference date based on the global evaluation date LocalVolTermStructure(Natural settlementDays, const Calendar&, const DayCounter& dc = Actual365Fixed()); //@} virtual ~LocalVolTermStructure() {} //! \name Local Volatility //@{ Volatility localVol(const Date& d, Real underlyingLevel, bool extrapolate = false) const; Volatility localVol(Time t, Real underlyingLevel, bool extrapolate = false) const; //@} //! \name Limits //@{ //! the minimum strike for which the term structure can return vols virtual Real minStrike() const = 0; //! the maximum strike for which the term structure can return vols virtual Real maxStrike() const = 0; //@} //! \name Visitability //@{ virtual void accept(AcyclicVisitor&); //@} protected: /*! \name Calculations These methods must be implemented in derived classes to perform the actual volatility calculations. When they are called, range check has already been performed; therefore, they must assume that extrapolation is required. */ //@{ //! local vol calculation virtual Volatility localVolImpl(Time t, Real strike) const = 0; //@} private: void checkRange(Time, Real strike, bool extrapolate) const; }; // inline definitions inline BlackVolTermStructure::BlackVolTermStructure(const DayCounter& dc) : TermStructure(dc) {} inline BlackVolTermStructure::BlackVolTermStructure(const Date& refDate, const Calendar& cal, const DayCounter& dc) : TermStructure(refDate, cal, dc) {} inline BlackVolTermStructure::BlackVolTermStructure(Natural settlDays, const Calendar& cal, const DayCounter& dc) : TermStructure(settlDays, cal, dc) {} inline Volatility BlackVolTermStructure::blackVol(const Date& maturity, Real strike, bool extrapolate) const { Time t = timeFromReference(maturity); checkRange(t,strike,extrapolate); return blackVolImpl(t, strike); } inline Volatility BlackVolTermStructure::blackVol(Time maturity, Real strike, bool extrapolate) const { checkRange(maturity,strike,extrapolate); return blackVolImpl(maturity, strike); } inline Real BlackVolTermStructure::blackVariance(const Date& maturity, Real strike, bool extrapolate) const { Time t = timeFromReference(maturity); checkRange(t,strike,extrapolate); return blackVarianceImpl(t, strike); } inline Real BlackVolTermStructure::blackVariance(Time maturity, Real strike, bool extrapolate) const { checkRange(maturity,strike,extrapolate); return blackVarianceImpl(maturity, strike); } inline void BlackVolTermStructure::accept(AcyclicVisitor& v) { Visitor* v1 = dynamic_cast*>(&v); if (v1 != 0) v1->visit(*this); else QL_FAIL("not a Black-volatility term structure visitor"); } inline void BlackVolTermStructure::checkRange(Time t, Real k, bool extrapolate) const { TermStructure::checkRange(t, extrapolate); QL_REQUIRE(extrapolate || allowsExtrapolation() || (k >= minStrike() && k <= maxStrike()), "strike (" << k << ") is outside the curve domain [" << minStrike() << "," << maxStrike()<< "]"); } inline BlackVolatilityTermStructure::BlackVolatilityTermStructure(const DayCounter& dc) : BlackVolTermStructure(dc) {} inline BlackVolatilityTermStructure::BlackVolatilityTermStructure( const Date& refDate, const Calendar& cal, const DayCounter& dc) : BlackVolTermStructure(refDate, cal, dc) {} inline BlackVolatilityTermStructure::BlackVolatilityTermStructure( Natural settlementDays, const Calendar& cal, const DayCounter& dc) : BlackVolTermStructure(settlementDays, cal, dc) {} inline Real BlackVolatilityTermStructure::blackVarianceImpl( Time maturity, Real strike) const { Volatility vol = blackVolImpl(maturity, strike); return vol*vol*maturity; } inline void BlackVolatilityTermStructure::accept(AcyclicVisitor& v) { Visitor* v1 = dynamic_cast*>(&v); if (v1 != 0) v1->visit(*this); else BlackVolTermStructure::accept(v); } inline BlackVarianceTermStructure::BlackVarianceTermStructure(const DayCounter& dc) : BlackVolTermStructure(dc) {} inline BlackVarianceTermStructure::BlackVarianceTermStructure( const Date& referenceDate, const Calendar& cal, const DayCounter& dc) : BlackVolTermStructure(referenceDate, cal, dc) {} inline BlackVarianceTermStructure::BlackVarianceTermStructure( Natural settlementDays, const Calendar& cal, const DayCounter& dc) : BlackVolTermStructure(settlementDays, cal, dc) {} inline Volatility BlackVarianceTermStructure ::blackVolImpl( Time maturity, Real strike) const { Time nonZeroMaturity = (maturity==0.0 ? 0.00001 : maturity); Real var = blackVarianceImpl(nonZeroMaturity, strike); return std::sqrt(var/nonZeroMaturity); } inline void BlackVarianceTermStructure::accept(AcyclicVisitor& v) { Visitor* v1 = dynamic_cast*>(&v); if (v1 != 0) v1->visit(*this); else BlackVolTermStructure::accept(v); } inline LocalVolTermStructure::LocalVolTermStructure(const DayCounter& dc) : TermStructure(dc) {} inline LocalVolTermStructure::LocalVolTermStructure( const Date& referenceDate, const Calendar& cal, const DayCounter& dc) : TermStructure(referenceDate, cal, dc) {} inline LocalVolTermStructure::LocalVolTermStructure( Natural settlementDays, const Calendar& cal, const DayCounter& dc) : TermStructure(settlementDays, cal, dc) {} inline Volatility LocalVolTermStructure::localVol(const Date& d, Real underlyingLevel, bool extrapolate) const { Time t = timeFromReference(d); checkRange(t,underlyingLevel,extrapolate); return localVolImpl(t, underlyingLevel); } inline Volatility LocalVolTermStructure::localVol(Time t, Real underlyingLevel, bool extrapolate) const { checkRange(t,underlyingLevel,extrapolate); return localVolImpl(t, underlyingLevel); } inline void LocalVolTermStructure::accept(AcyclicVisitor& v) { Visitor* v1 = dynamic_cast*>(&v); if (v1 != 0) v1->visit(*this); else QL_FAIL("not a local-volatility term structure visitor"); } inline void LocalVolTermStructure::checkRange(Time t, Real k, bool extrapolate) const { TermStructure::checkRange(t, extrapolate); QL_REQUIRE(extrapolate || allowsExtrapolation() || (k >= minStrike() && k <= maxStrike()), "strike (" << k << ") is outside the curve domain [" << minStrike() << "," << maxStrike() << "]"); } } #endif