Posted by
nabbleuser2008 on
Sep 22, 2008; 12:04pm
URL: http://quantlib.414.s1.nabble.com/AnaliticHestonEngine-SV-or-SVJ-tp6640p6650.html
Dear Klaus,
Thank you very much for all your help.
Took me a little while to compare the prices from all the methods, including the one with adjusted maturity. May be for the reasons you're mentioning below, I'm not getting a perfect fit with any of the models, even though some or most model prices are very good.
Thanks again for all your help and advice.
Cheers,
C
<quote author="Klaus Spanderen-2">
Hi
sorry for the late answer.
On Monday 01 September 2008 17:57:02 nabbleuser2008 wrote:
> I also wanted to try what you're saying below, but I was not
> able to understand how to do what you were saying
I've attached a version of the LongstaffSchwartzPathPricer, which calculates
the average life time 'til exercise of an option instead of the price. (There
are better ways to do this but this was easy to implement). Just replace the
original file by the attached one and ran e.g. eamples like
MCLongstaffSchwartzEngineTest::testAmericanOption. The npv is the average
life time. Now (hopefully;-) the implied vols of calls and puts quoted in
terms of the average life time will be closer together than the implied vols
quoted in terms of the option maturity. Calibrate on "synth" european options
with maturity = avg. life time of the american options.
> I've used the FDDividendAmericanEngine to calculate the implied
> volatilities ( Even though I noticed the comment in the source file that
> impliedVolatility may not be accurate. I still used it as I couldn't find a
> better alternative in the QL librarary for my needs, as I'm interested in
> americans with discrete dividend payments.)
>
Be aware that the Heston model is using a dividend yield and that the
volatilities for a discrete dividend Black-Scholes models and dividend yield
BS-model aren't the same. See e.g.
Bos, R. et al. (2003) Dealing with discrete dividends, Risk Magazine, 16, pp.
109–112.
to transfer volatility surfaces between both dividend models. The Heston
calibration helper assumes a dividend yield BS volatility. May be for the
time being you are better off using the FDAmericanEngine and a dividend
yield.
cheers
Klaus
--
Klaus Spanderen
Ludwig Erhard Str. 12
48734 Reken (Germany)
EMail: klaus@NOSPAMspanderen.de (remove NOSPAM from the address)
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2006 Klaus Spanderen
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.
*/
/*! \file longstaffschwartzpathpricer.hpp
\brief Longstaff-Schwarz path pricer for early exercise options
*/
#ifndef quantlib_longstaff_schwartz_path_pricer_hpp
#define quantlib_longstaff_schwartz_path_pricer_hpp
#include <ql/termstructures/yieldtermstructure.hpp>
#include <ql/math/functional.hpp>
#include <ql/math/linearleastsquaresregression.hpp>
#include <ql/methods/montecarlo/pathpricer.hpp>
#include <ql/methods/montecarlo/earlyexercisepathpricer.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
namespace QuantLib {
//! Longstaff-Schwarz path pricer for early exercise options
/*! References:
Francis Longstaff, Eduardo Schwartz, 2001. Valuing American Options
by Simulation: A Simple Least-Squares Approach, The Review of
Financial Studies, Volume 14, No. 1, 113-147
\ingroup mcarlo
\test the correctness of the returned value is tested by
reproducing results available in web/literature
*/
template <class PathType>
class LongstaffSchwartzPathPricer : public PathPricer<PathType> {
public:
typedef typename EarlyExerciseTraits<PathType>::StateType StateType;
LongstaffSchwartzPathPricer(
const TimeGrid& times,
const boost::shared_ptr<EarlyExercisePathPricer<PathType> >& ,
const boost::shared_ptr<YieldTermStructure>& termStructure);
Real operator()(const PathType& path) const;
virtual void calibrate();
protected:
bool calibrationPhase_;
const boost::shared_ptr<EarlyExercisePathPricer<PathType> >
pathPricer_;
boost::scoped_array<Array> coeff_;
boost::scoped_array<DiscountFactor> dF_;
mutable std::vector<PathType> paths_;
const std::vector<boost::function1<Real, StateType> > v_;
const TimeGrid times_;
};
template <class PathType> inline
LongstaffSchwartzPathPricer<PathType>::LongstaffSchwartzPathPricer(
const TimeGrid& times,
const boost::shared_ptr<EarlyExercisePathPricer<PathType> >&
pathPricer,
const boost::shared_ptr<YieldTermStructure>& termStructure)
: calibrationPhase_(true),
pathPricer_(pathPricer),
coeff_ (new Array[times.size()-1]),
dF_ (new DiscountFactor[times.size()-1]),
v_ (pathPricer_->basisSystem()),
times_ (times) {
for (Size i=0; i<times.size()-1; ++i) {
dF_[i] = termStructure->discount(times[i+1])
/ termStructure->discount(times[i]);
}
}
template <class PathType> inline
Real LongstaffSchwartzPathPricer<PathType>::operator()(
const PathType& path) const {
if (calibrationPhase_) {
// store paths for the calibration
paths_.push_back(path);
// result doesn't matter
return 0.0;
}
const Size len = EarlyExerciseTraits<PathType>::pathLength(path);
Real price = times_[len-1];
for (Size i=len-2; i>0; --i) {
const Real exercise = (*pathPricer_)(path, i);
if (exercise > 0.0) {
const StateType regValue = pathPricer_->state(path, i);
Real continuationValue = 0.0;
for (Size l=0; l<v_.size(); ++l) {
continuationValue += coeff_[i][l] * v_[l](regValue);
}
if (continuationValue < exercise) {
price = times_[i];
}
}
}
return price;
}
template <class PathType> inline
void LongstaffSchwartzPathPricer<PathType>::calibrate() {
const Size n = paths_.size();
Array prices(n), exercise(n);
const Size len = EarlyExerciseTraits<PathType>::pathLength(paths_[0]);
std::transform(paths_.begin(), paths_.end(), prices.begin(),
boost::bind(&EarlyExercisePathPricer<PathType>
::operator(),
pathPricer_.get(), _1, len-1));
for (Size i=len-2; i>0; --i) {
std::vector<Real> y;
std::vector<StateType> x;
//roll back step
for (Size j=0; j<n; ++j) {
exercise[j]=(*pathPricer_)(paths_[j], i);
if (exercise[j]>0.0) {
x.push_back(pathPricer_->state(paths_[j], i));
y.push_back(dF_[i]*prices[j]);
}
}
if (v_.size() <= x.size()) {
coeff_[i]
= LinearLeastSquaresRegression<StateType>(x, y, v_).a();
}
else {
// if number of itm paths is smaller then the number of
// calibration functions -> no early exercise
coeff_[i] = Array(v_.size(), 0.0);
}
for (Size j=0, k=0; j<n; ++j) {
prices[j]*=dF_[i];
if (exercise[j]>0.0) {
Real continuationValue = 0.0;
for (Size l=0; l<v_.size(); ++l) {
continuationValue += coeff_[i][l] * v_[l](x[k]);
}
if (continuationValue < exercise[j]) {
prices[j] = exercise[j];
}
++k;
}
}
}
// remove calibration paths
paths_.clear();
// entering the calculation phase
calibrationPhase_ = false;
}
}
#endif
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/_______________________________________________
QuantLib-users mailing list
QuantLib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/quantlib-users</quote>