QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
forwardengine.hpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2002, 2003, 2004 Ferdinando Ametrano
5 Copyright (C) 2007 StatPro Italia srl
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21/*! \file forwardengine.hpp
22 \brief Forward (strike-resetting) vanilla-option engine
23*/
24
25#ifndef quantlib_forward_engine_hpp
26#define quantlib_forward_engine_hpp
27
28#include <ql/exercise.hpp>
35#include <utility>
36
37namespace QuantLib {
38
39 //! %Forward engine for vanilla options
40 /*! \ingroup forwardengines
41
42 \test
43 - the correctness of the returned value is tested by
44 reproducing results available in literature.
45 - the correctness of the returned greeks is tested by
46 reproducing numerical derivatives.
47 */
48 template <class Engine>
50 : public GenericEngine<ForwardOptionArguments<VanillaOption::arguments>,
51 VanillaOption::results> {
52 public:
53 ForwardVanillaEngine(ext::shared_ptr<GeneralizedBlackScholesProcess>);
54 void calculate() const override;
55
56 protected:
57 void setup() const;
58 void getOriginalResults() const;
59 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
60 mutable ext::shared_ptr<Engine> originalEngine_;
63 };
64
65
66 // template definitions
67
68 template <class Engine>
70 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
71 : process_(std::move(process)) {
73 }
74
75
76 template <class Engine>
78
79 ext::shared_ptr<StrikedTypePayoff> argumentsPayoff =
80 ext::dynamic_pointer_cast<StrikedTypePayoff>(
81 this->arguments_.payoff);
82 QL_REQUIRE(argumentsPayoff, "wrong payoff given");
83
84 ext::shared_ptr<StrikedTypePayoff> payoff(
85 new PlainVanillaPayoff(argumentsPayoff->optionType(),
86 this->arguments_.moneyness *
87 process_->x0()));
88
89 // maybe the forward value is "better", in some fashion
90 // the right level is needed in order to interpolate
91 // the vol
92 Handle<Quote> spot = process_->stateVariable();
93 QL_REQUIRE(spot->value() > 0.0, "negative or null underlying given");
94 Handle<YieldTermStructure> dividendYield(
95 ext::shared_ptr<YieldTermStructure>(
96 new ImpliedTermStructure(process_->dividendYield(),
97 this->arguments_.resetDate)));
98 Handle<YieldTermStructure> riskFreeRate(
99 ext::shared_ptr<YieldTermStructure>(
100 new ImpliedTermStructure(process_->riskFreeRate(),
101 this->arguments_.resetDate)));
102 // The following approach is ok if the vol is at most
103 // time dependant. It is plain wrong if it is asset dependant.
104 // In the latter case the right solution would be stochastic
105 // volatility or at least local volatility (which unfortunately
106 // implies an unrealistic time-decreasing smile)
107 Handle<BlackVolTermStructure> blackVolatility(
108 ext::shared_ptr<BlackVolTermStructure>(
109 new ImpliedVolTermStructure(process_->blackVolatility(),
110 this->arguments_.resetDate)));
111
112 ext::shared_ptr<GeneralizedBlackScholesProcess> fwdProcess(
113 new GeneralizedBlackScholesProcess(spot, dividendYield,
114 riskFreeRate,
115 blackVolatility));
116
117 originalEngine_ = ext::shared_ptr<Engine>(new Engine(fwdProcess));
118 originalEngine_->reset();
119
120 originalArguments_ =
121 dynamic_cast<VanillaOption::arguments*>(
122 originalEngine_->getArguments());
123 QL_REQUIRE(originalArguments_, "wrong engine type");
124 originalResults_ =
125 dynamic_cast<const VanillaOption::results*>(
126 originalEngine_->getResults());
127 QL_REQUIRE(originalResults_, "wrong engine type");
128
129 originalArguments_->payoff = payoff;
130 originalArguments_->exercise = this->arguments_.exercise;
131
132 originalArguments_->validate();
133 }
134
135 template <class Engine>
137 setup();
138 originalEngine_->calculate();
139 getOriginalResults();
140 }
141
142 template <class Engine>
144
145 DayCounter rfdc = process_->riskFreeRate()->dayCounter();
146 DayCounter divdc = process_->dividendYield()->dayCounter();
147 Time resetTime = rfdc.yearFraction(
148 process_->riskFreeRate()->referenceDate(),
149 this->arguments_.resetDate);
150 DiscountFactor discQ = process_->dividendYield()->discount(
151 this->arguments_.resetDate);
152
153 this->results_.value = discQ * originalResults_->value;
154 // I need the strike derivative here ...
155 if (originalResults_->delta != Null<Real>() &&
156 originalResults_->strikeSensitivity != Null<Real>()) {
157 this->results_.delta = discQ * (originalResults_->delta +
158 this->arguments_.moneyness *
159 originalResults_->strikeSensitivity);
160 }
161 this->results_.gamma = 0.0;
162 this->results_.theta = process_->dividendYield()->
163 zeroRate(this->arguments_.resetDate, divdc, Continuous, NoFrequency)
164 * this->results_.value;
165 if (originalResults_->vega != Null<Real>())
166 this->results_.vega = discQ * originalResults_->vega;
167 if (originalResults_->rho != Null<Real>())
168 this->results_.rho = discQ * originalResults_->rho;
169 if (originalResults_->dividendRho != Null<Real>()) {
170 this->results_.dividendRho = - resetTime * this->results_.value
171 + discQ * originalResults_->dividendRho;
172 }
173 }
174
175}
176
177
178#endif
Black-Scholes processes.
const Instrument::results * results_
Definition: cdsoption.cpp:63
day counter class
Definition: daycounter.hpp:44
Time yearFraction(const Date &, const Date &, const Date &refPeriodStart=Date(), const Date &refPeriodEnd=Date()) const
Returns the period between two dates as a fraction of year.
Definition: daycounter.hpp:128
Forward engine for vanilla options
ext::shared_ptr< Engine > originalEngine_
void calculate() const override
VanillaOption::arguments * originalArguments_
const VanillaOption::results * originalResults_
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
ForwardVanillaEngine(ext::shared_ptr< GeneralizedBlackScholesProcess >)
Generalized Black-Scholes stochastic process.
template base class for option pricing engines
Shared handle to an observable.
Definition: handle.hpp:41
Implied term structure at a given date in the future.
Implied vol term structure at a given date in the future.
template class providing a null value for a given type.
Definition: null.hpp:76
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
basic option arguments
Definition: option.hpp:57
Plain-vanilla payoff.
Definition: payoffs.hpp:105
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
Option exercise classes and payoff function.
Forward version of a vanilla option.
@ NoFrequency
null frequency
Definition: frequency.hpp:37
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
Implied term structure.
Implied Black Vol Term Structure.
ext::shared_ptr< QuantLib::Payoff > payoff
Definition: any.hpp:35
STL namespace.
Payoffs for various options.
Vanilla option on a single asset.