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/instruments/forwardvanillaoption.hpp>
29 #include <ql/instruments/vanillaoption.hpp>
30 #include <ql/processes/blackscholesprocess.hpp>
31 #include <ql/termstructures/volatility/equityfx/impliedvoltermstructure.hpp>
32 #include <ql/termstructures/yield/impliedtermstructure.hpp>
33 #include <ql/instruments/payoffs.hpp>
34 #include <ql/exercise.hpp>
35 
36 namespace QuantLib {
37 
38     //! %Forward engine for vanilla options
39     /*! \ingroup forwardengines
40 
41         \test
42         - the correctness of the returned value is tested by
43           reproducing results available in literature.
44         - the correctness of the returned greeks is tested by
45           reproducing numerical derivatives.
46     */
47     template <class Engine>
48     class ForwardVanillaEngine
49         : public GenericEngine<ForwardOptionArguments<VanillaOption::arguments>,
50                                VanillaOption::results> {
51       public:
52         ForwardVanillaEngine(
53                     const ext::shared_ptr<GeneralizedBlackScholesProcess>&);
54         void calculate() const;
55       protected:
56         void setup() const;
57         void getOriginalResults() const;
58         ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
59         mutable ext::shared_ptr<Engine> originalEngine_;
60         mutable VanillaOption::arguments* originalArguments_;
61         mutable const VanillaOption::results* originalResults_;
62     };
63 
64 
65     // template definitions
66 
67     template <class Engine>
ForwardVanillaEngine(const ext::shared_ptr<GeneralizedBlackScholesProcess> & process)68     ForwardVanillaEngine<Engine>::ForwardVanillaEngine(
69         const ext::shared_ptr<GeneralizedBlackScholesProcess>& process)
70     : process_(process) {
71         registerWith(process_);
72     }
73 
74 
75     template <class Engine>
setup() const76     void ForwardVanillaEngine<Engine>::setup() const {
77 
78         ext::shared_ptr<StrikedTypePayoff> argumentsPayoff =
79             ext::dynamic_pointer_cast<StrikedTypePayoff>(
80                 this->arguments_.payoff);
81         QL_REQUIRE(argumentsPayoff, "wrong payoff given");
82 
83         ext::shared_ptr<StrikedTypePayoff> payoff(
84                    new PlainVanillaPayoff(argumentsPayoff->optionType(),
85                                           this->arguments_.moneyness *
86                                           process_->x0()));
87 
88         // maybe the forward value is "better", in some fashion
89         // the right level is needed in order to interpolate
90         // the vol
91         Handle<Quote> spot = process_->stateVariable();
92         QL_REQUIRE(spot->value() >= 0.0, "negative or null underlting given");
93         Handle<YieldTermStructure> dividendYield(
94             ext::shared_ptr<YieldTermStructure>(
95                new ImpliedTermStructure(process_->dividendYield(),
96                                         this->arguments_.resetDate)));
97         Handle<YieldTermStructure> riskFreeRate(
98             ext::shared_ptr<YieldTermStructure>(
99                new ImpliedTermStructure(process_->riskFreeRate(),
100                                         this->arguments_.resetDate)));
101         // The following approach is ok if the vol is at most
102         // time dependant. It is plain wrong if it is asset dependant.
103         // In the latter case the right solution would be stochastic
104         // volatility or at least local volatility (which unfortunately
105         // implies an unrealistic time-decreasing smile)
106         Handle<BlackVolTermStructure> blackVolatility(
107             ext::shared_ptr<BlackVolTermStructure>(
108                 new ImpliedVolTermStructure(process_->blackVolatility(),
109                                             this->arguments_.resetDate)));
110 
111         ext::shared_ptr<GeneralizedBlackScholesProcess> fwdProcess(
112                        new GeneralizedBlackScholesProcess(spot, dividendYield,
113                                                           riskFreeRate,
114                                                           blackVolatility));
115 
116         originalEngine_ = ext::shared_ptr<Engine>(new Engine(fwdProcess));
117         originalEngine_->reset();
118 
119         originalArguments_ =
120             dynamic_cast<VanillaOption::arguments*>(
121                                              originalEngine_->getArguments());
122         QL_REQUIRE(originalArguments_, "wrong engine type");
123         originalResults_ =
124             dynamic_cast<const VanillaOption::results*>(
125                                                originalEngine_->getResults());
126         QL_REQUIRE(originalResults_, "wrong engine type");
127 
128         originalArguments_->payoff = payoff;
129         originalArguments_->exercise = this->arguments_.exercise;
130 
131         originalArguments_->validate();
132     }
133 
134     template <class Engine>
calculate() const135     void ForwardVanillaEngine<Engine>::calculate() const {
136         setup();
137         originalEngine_->calculate();
138         getOriginalResults();
139     }
140 
141     template <class Engine>
getOriginalResults() const142     void ForwardVanillaEngine<Engine>::getOriginalResults() const {
143 
144         DayCounter rfdc = process_->riskFreeRate()->dayCounter();
145         DayCounter divdc = process_->dividendYield()->dayCounter();
146         Time resetTime = rfdc.yearFraction(
147                                      process_->riskFreeRate()->referenceDate(),
148                                      this->arguments_.resetDate);
149         DiscountFactor discQ = process_->dividendYield()->discount(
150                                                   this->arguments_.resetDate);
151 
152         this->results_.value = discQ * originalResults_->value;
153         // I need the strike derivative here ...
154         if (originalResults_->delta != Null<Real>() &&
155             originalResults_->strikeSensitivity != Null<Real>()) {
156             this->results_.delta = discQ * (originalResults_->delta +
157                   this->arguments_.moneyness *
158                         originalResults_->strikeSensitivity);
159         }
160         this->results_.gamma = 0.0;
161         this->results_.theta = process_->dividendYield()->
162             zeroRate(this->arguments_.resetDate, divdc, Continuous, NoFrequency)
163             * this->results_.value;
164         if (originalResults_->vega != Null<Real>())
165             this->results_.vega  = discQ * originalResults_->vega;
166         if (originalResults_->rho != Null<Real>())
167             this->results_.rho   = discQ *  originalResults_->rho;
168         if (originalResults_->dividendRho != Null<Real>()) {
169             this->results_.dividendRho = - resetTime * this->results_.value
170                + discQ * originalResults_->dividendRho;
171         }
172     }
173 
174 }
175 
176 
177 #endif
178