Hi guys,
the Black-Scholes implied volatlity sigma=sigma(t,K,T) , starting at t, is the number which, when put in the Black-Scholes formula for a european option with strike K and maturity T quoted at t, reproduces the fair price on the market. The existence of such a surface indicates that the Black-Scholes assumption that assets have a constant volatility should be relaxed. The simplest extension is to assume that assets still follow a one-dimensional ito diffusion process but with a local volatility function that depends on the forward and the time. A local volatility surface class ql/termstructures/volatility/equityfx/localvolsurface.hpp already exists in QuantLib. This class takes an implied vol surface as an input and use the dupire equation to calculate the local volatility. A drawback of this equation is that it uses the first and second derivatives of the european option price. The produced local volatility surface is not able to match the european options. I suggest to replace the dupire equation with an algorithm to calibrate the local volatility by fitting the prices of a set of vanilla european options. Several steps need to be done for this purpose. (i) A localvol class needs to be implemented that just takes as an input a matrix, vector of dates and srtikes that do the interpolation. See attached file. (ii) A dupire process needs to be implemented that just takes the local vol class and returns the drift and diffusion according to time and forward. See attached file again. (iii) A pricing engine for european options needs to be implemented that calculates the market value according a given dupire process. This pricing engine will be used as part of the calibration procedure. This part is almost finished using finite element. (iv) A pricing engine for european options based on monte carlo simulation needs to be implemented. This pricing engine will then be used to validate that the other pricing engine is really working. ( Writing test cases) (v) A minization procedure to choose the correct surface among a family of surfaces. (vi) Exporting the implemented classes to QuantLibXL and building excel sheets to provide examples. Step (iii) is almost finished. In my calculation procedure i wite codes like vvec=(M+.5*t* (L+r*M ) ).applyTo(uvec); //modifying L uvec=(M-.5*t* (L+r*M ) ).solveFor(vvec); Here M is the mass matrix and L the stiffness matrix and are from type TridiagonalOperator. Such writing is of course really bad because this will result in eight times allocating and deallocating a TridiagonalOperator. A speedup with the help of template expression using Boost.proto should avoid the creation of temporary TridiagonalOperator. This needs to be implemented. I hope that i can get help for step (iv) and (vi). If someone is interested just drop me an email. With kind regards, Kim Tang /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2009 Kim Kuen Tang 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 <[hidden email]>. 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. */ #include "dupireprocess.hpp" namespace QuantLib { DupireProcess::DupireProcess( const Handle<Quote>& x0, const Handle<YieldTermStructure>& dividendTS, const Handle<YieldTermStructure>& riskFreeTS, const Handle<LocalVol>& localvol, const boost::shared_ptr<discretization>& disc) : StochasticProcess1D(disc), x0_(x0), riskFreeRate_(riskFreeTS), dividendYield_(dividendTS), localvol_(localvol) { registerWith(x0_); registerWith(riskFreeRate_); registerWith(dividendYield_); } Real DupireProcess::x0() const { return x0_->value(); } Real DupireProcess::drift(Time t, Real x) const { // we could be more anticipatory if we know the right dt // for which the drift will be used Time t1 = t + 0.0001; return (riskFreeRate_->forwardRate(t,t1,Continuous,NoFrequency,true) - dividendYield_->forwardRate(t,t1,Continuous,NoFrequency,true) ) *x; } Real DupireProcess::diffusion(Time t, Real x) const { return localvol_->localVol(t, x, true)*x; } Real DupireProcess::apply(Real x0, Real dx) const { return x0 * std::exp(dx); } Time DupireProcess::time(const Date& d) const { return riskFreeRate_->dayCounter().yearFraction( riskFreeRate_->referenceDate(), d); } void DupireProcess::update() { StochasticProcess1D::update(); } const Handle<Quote>& DupireProcess::stateVariable() const { return x0_; } const Handle<YieldTermStructure>& DupireProcess::dividendYield() const { return dividendYield_; } const Handle<YieldTermStructure>& DupireProcess::riskFreeRate() const { return riskFreeRate_; } const Handle<LocalVol>& DupireProcess::localVolatility() const { return localvol_; } } /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2009 Kim Kuen Tang 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 <[hidden email]>. 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. */ # ifndef QUANTLIB_DUPIREPROCESS_HPP_KKT_250609 # define QUANTLIB_DUPIREPROCESS_HPP_KKT_250609 # include <ql/stochasticprocess.hpp> # include <ql/processes/eulerdiscretization.hpp> # include <ql/termstructures/yieldtermstructure.hpp> # include <ql/quote.hpp> # include "localvol.hpp" namespace QuantLib { //! dupire process /*! This class describes the stochastic process governed by \f[ dS(t) /S = (r(t)-q(t) ) dt + \sigma(t,S) dW_t \f] \ingroup processes */ class DupireProcess : public StochasticProcess1D { public: DupireProcess( const Handle<Quote>& x0, const Handle<YieldTermStructure>& dividendTS, const Handle<YieldTermStructure>& riskFreeTS, const Handle<LocalVol>& localvol, const boost::shared_ptr<discretization>& d = boost::shared_ptr<discretization>(new EulerDiscretization)); //! \name StochasticProcess1D interface //@{ Real x0() const; /*! \todo revise extrapolation */ Real drift(Time t, Real x) const; /*! \todo revise extrapolation */ Real diffusion(Time t, Real x) const; Real apply(Real x0, Real dx) const; //@} Time time(const Date&) const; //! \name Observer interface //@{ void update(); //@} //! \name Inspectors //@{ const Handle<Quote>& stateVariable() const; const Handle<YieldTermStructure>& dividendYield() const; const Handle<YieldTermStructure>& riskFreeRate() const; const Handle<LocalVol>& localVolatility() const; //@} private: Handle<Quote> x0_; Handle<YieldTermStructure> riskFreeRate_, dividendYield_; Handle<LocalVol> localvol_; }; } //QuantLib # endif /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2009 Kim Kuen Tang 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 <[hidden email]>. 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. */ # include "localvol.hpp" # include <ql/termstructures/volatility/equityfx/blackvoltermstructure.hpp> # include <ql/termstructures/yieldtermstructure.hpp> # include <ql/quotes/simplequote.hpp> # include <ql/math/interpolations/bilinearinterpolation.hpp> namespace QuantLib { Real LocalVol::maxVol() const { return *std::max_element(volMatrix_.begin(), volMatrix_.end()); } const Date& LocalVol::referenceDate() const { return this->referenceDate_; } DayCounter LocalVol::dayCounter() const { return dayCounter_; } Date LocalVol::maxDate() const { return maxDate_; } Real LocalVol::minStrike() const { return strikes_.back(); } Real LocalVol::maxStrike() const { return strikes_.front(); } LocalVol::LocalVol(const Date& referenceDate, const Calendar& cal, const std::vector<Date>& dates, const std::vector<Real>& strikes, const Matrix& volMatrix, const DayCounter& dayCounter, Extrapolation lowerEx, Extrapolation upperEx ) : LocalVolTermStructure(referenceDate,cal,Following,dayCounter), referenceDate_(referenceDate), dayCounter_(dayCounter), maxDate_(dates.back()), strikes_(strikes), lowerExtrapolation_(lowerEx), upperExtrapolation_(upperEx),volMatrix_(volMatrix) { QL_REQUIRE(dates.size()==volMatrix.columns(), "mismatch between date vector and vol matrix colums"); QL_REQUIRE(strikes_.size()==volMatrix.rows(), "mismatch between money-strike vector and vol matrix rows"); QL_REQUIRE(dates[0]>=referenceDate, "cannot have dates[0] <= referenceDate"); times_.resize(dates.size()); std::vector<Time>::iterator t=times_.begin(); for(std::vector<Date>::const_iterator it=dates.begin(), end=dates.end(); it!=end;++it, ++t) *t=timeFromReference(*it); for(std::vector<Time>::const_iterator it=times_.begin()+1, end=times_.end(); it!=end;++it) QL_REQUIRE(it[0]-it[-1] > 0.0, "dates are not sorted"); // default: bilinear interpolation setInterpolation<Bilinear>(); } void LocalVol::accept(AcyclicVisitor& v) { Visitor<LocalVol>* v1 = dynamic_cast<Visitor<LocalVol>*>(&v); if (v1 != 0) v1->visit(*this); else LocalVolTermStructure::accept(v); } Volatility LocalVol::localVolImpl(Time t, Real underlyingLevel) const { return varianceSurface_(t,underlyingLevel,true); } } # ifndef LOCALVOL_HPP_KTT_260709 # define LOCALVOL_HPP_KTT_260709 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2009 Kim Kuen Tang 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 <[hidden email]>. 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. */ /*! \file localvol.hpp \brief Local volatility surface */ # include <ql/termstructures/volatility/equityfx/localvoltermstructure.hpp> # include <ql/math/matrix.hpp> # include <ql/math/interpolations/interpolation2d.hpp> namespace QuantLib { class LocalVol : public LocalVolTermStructure { public: enum Extrapolation { ConstantExtrapolation, InterpolatorDefaultExtrapolation }; LocalVol(const Date& referenceDate, const Calendar& cal, const std::vector<Date>& dates, const std::vector<Real>& strikes, const Matrix& volMatrix, const DayCounter& dayCounter, Extrapolation lowerExtrapolation = InterpolatorDefaultExtrapolation, Extrapolation upperExtrapolation = InterpolatorDefaultExtrapolation); //! \name TermStructure interface //@{ const Date& referenceDate() const; DayCounter dayCounter() const; Date maxDate() const; //@} //! \name VolatilityTermStructure interface //@{ Real minStrike() const; Real maxStrike() const; Real maxVol() const; template <class Interpolator> void setInterpolation(const Interpolator& i = Interpolator()) { varianceSurface_ = i.interpolate(times_.begin(), times_.end(), strikes_.begin(), strikes_.end(), volMatrix_); notifyObservers(); } //@} //! \name Visitability //@{ virtual void accept(AcyclicVisitor&); //@} protected: Volatility localVolImpl(Time, Real) const; private: DayCounter dayCounter_; Date maxDate_; Date referenceDate_; std::vector<Real> strikes_; std::vector<Time> times_; Matrix volMatrix_; Interpolation2D varianceSurface_; Extrapolation lowerExtrapolation_, upperExtrapolation_; }; } #endif ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Hi Kim
On Tuesday 04 August 2009 22:15:23 Kim Kuen Tang wrote: > (iii) A pricing engine for european options needs to be implemented that > calculates the market value according a given dupire process. This > pricing engine will be used as part of the calibration procedure. This > part is almost finished using finite element. The performance of the finite difference pricing engine might (will) be too slow for calibration purposes if you are using the backwards equation to price option by option. The forward equation of the problem (s. Fokker-Planck equation) allows you to price all calibration options at once and will give you a real performance boost. cheers Klaus ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Klaus Spanderen schrieb: Hi Klaus, > The performance of the finite difference pricing engine might (will) be too > slow for calibration purposes if you are using the backwards equation to > price option by option. The forward equation of the problem (s. Fokker-Planck > equation) allows you to price all calibration options at once and will give > you a real performance boost. > > thanks for the advice. Using Fokker-Planck equation saves a lot of work for evaluating the cost function and the gradient of the cost function. I will integrate this in the calibration procedure. In the meantime a clever target function needs to be chosen to ensure stability of the calibration. For example small change of the input implied volatility surface shouldnt have big impact on the local volatility surface. And it shouldnt produce values near to zero or negative. Do you have some advice? Best regards, Kim Tang > cheers > Klaus > > > ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Kim Tang scribed: > Using Fokker-Planck equation saves a lot of work for evaluating the cost > function and the gradient of the cost function. > I will integrate this in the calibration procedure. In the meantime a > clever target function needs to be chosen to ensure stability of the > calibration. Hi, Kim. In fact, what you want to do was already done in the article "The equity option volatility smile: an implicit finite-difference approach", B. G. Andersen and Rupert Brotherton-Ratcliffe, so try to find it. Regarding your topic i have some questions: - what is essential of volMatrix in your LocalVol class? I guess, that it should be local vol matrix, moreover varianceSurface_ should be replaced by localVolSurface_; - what do you mean by 5th step, cause maybe it's a topic i'm really interested in? When you have some market data (ie option vols/variances) you should choose good extrapolation technique for the tails, cause you need wide range (strikes) of local vols during implementation of MC or PDE, and this data have big impact on the LV calibration. I use simple bicubic interpolation, which is enough for LV calculation, but good extrapolation is still mystery for me. PS i'm not really familiar with MC framework, but you could implement your engine via PDE in QL |
Free forum by Nabble | Edit this page |