/src/quantlib/ql/pricingengines/vanilla/integralengine.cpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 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 | | <https://www.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 | | #include <ql/exercise.hpp> |
22 | | #include <ql/math/integrals/segmentintegral.hpp> |
23 | | #include <ql/pricingengines/vanilla/integralengine.hpp> |
24 | | #include <utility> |
25 | | |
26 | | namespace QuantLib { |
27 | | |
28 | | namespace { |
29 | | |
30 | | class Integrand { |
31 | | public: |
32 | | Integrand(ext::shared_ptr<Payoff> payoff, Real s0, Rate drift, Real variance) |
33 | 0 | : payoff_(std::move(payoff)), s0_(s0), drift_(drift), variance_(variance) {} |
34 | 0 | Real operator()(Real x) const { |
35 | 0 | Real temp = s0_ * std::exp(x); |
36 | 0 | Real result = (*payoff_)(temp); |
37 | 0 | return result * |
38 | 0 | std::exp(-(x - drift_)*(x -drift_)/(2.0*variance_)) ; |
39 | 0 | } |
40 | | private: |
41 | | ext::shared_ptr<Payoff> payoff_; |
42 | | Real s0_; |
43 | | Rate drift_; |
44 | | Real variance_; |
45 | | }; |
46 | | } |
47 | | |
48 | | IntegralEngine::IntegralEngine(ext::shared_ptr<GeneralizedBlackScholesProcess> process) |
49 | 0 | : process_(std::move(process)) { |
50 | 0 | registerWith(process_); |
51 | 0 | } |
52 | | |
53 | 0 | void IntegralEngine::calculate() const { |
54 | |
|
55 | 0 | QL_REQUIRE(arguments_.exercise->type() == Exercise::European, |
56 | 0 | "not an European Option"); |
57 | | |
58 | 0 | ext::shared_ptr<StrikedTypePayoff> payoff = |
59 | 0 | ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); |
60 | 0 | QL_REQUIRE(payoff, "non-striked payoff given"); |
61 | | |
62 | 0 | Real variance = |
63 | 0 | process_->blackVolatility()->blackVariance( |
64 | 0 | arguments_.exercise->lastDate(), payoff->strike()); |
65 | |
|
66 | 0 | DiscountFactor dividendDiscount = |
67 | 0 | process_->dividendYield()->discount( |
68 | 0 | arguments_.exercise->lastDate()); |
69 | 0 | DiscountFactor riskFreeDiscount = |
70 | 0 | process_->riskFreeRate()->discount(arguments_.exercise->lastDate()); |
71 | 0 | Rate drift = std::log(dividendDiscount/riskFreeDiscount)-0.5*variance; |
72 | |
|
73 | 0 | Integrand f(arguments_.payoff, |
74 | 0 | process_->stateVariable()->value(), |
75 | 0 | drift, variance); |
76 | 0 | SegmentIntegral integrator(5000); |
77 | |
|
78 | 0 | Real infinity = 10.0*std::sqrt(variance); |
79 | 0 | results_.value = |
80 | 0 | process_->riskFreeRate()->discount( |
81 | 0 | arguments_.exercise->lastDate()) / |
82 | | std::sqrt(2.0*M_PI*variance) * |
83 | 0 | integrator(f, drift-infinity, drift+infinity); |
84 | 0 | } |
85 | | |
86 | | } |
87 | | |