1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2003 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#include <ql/exercise.hpp>
22#include <ql/pricingengines/blackcalculator.hpp>
23#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
24#include <utility>
25
26namespace QuantLib {
27
28 AnalyticEuropeanEngine::AnalyticEuropeanEngine(
29 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
30 : process_(std::move(process)) {
31 registerWith(h: process_);
32 }
33
34 AnalyticEuropeanEngine::AnalyticEuropeanEngine(
35 ext::shared_ptr<GeneralizedBlackScholesProcess> process,
36 Handle<YieldTermStructure> discountCurve)
37 : process_(std::move(process)), discountCurve_(std::move(discountCurve)) {
38 registerWith(h: process_);
39 registerWith(h: discountCurve_);
40 }
41
42 void AnalyticEuropeanEngine::calculate() const {
43
44 // if the discount curve is not specified, we default to the
45 // risk free rate curve embedded within the GBM process
46 ext::shared_ptr<YieldTermStructure> discountPtr =
47 discountCurve_.empty() ?
48 process_->riskFreeRate().currentLink() :
49 discountCurve_.currentLink();
50
51 QL_REQUIRE(arguments_.exercise->type() == Exercise::European,
52 "not an European option");
53
54 ext::shared_ptr<StrikedTypePayoff> payoff =
55 ext::dynamic_pointer_cast<StrikedTypePayoff>(r: arguments_.payoff);
56 QL_REQUIRE(payoff, "non-striked payoff given");
57
58 Real variance =
59 process_->blackVolatility()->blackVariance(
60 d: arguments_.exercise->lastDate(),
61 strike: payoff->strike());
62 DiscountFactor dividendDiscount =
63 process_->dividendYield()->discount(
64 d: arguments_.exercise->lastDate());
65 DiscountFactor df = discountPtr->discount(d: arguments_.exercise->lastDate());
66 DiscountFactor riskFreeDiscountForFwdEstimation =
67 process_->riskFreeRate()->discount(d: arguments_.exercise->lastDate());
68 Real spot = process_->stateVariable()->value();
69 QL_REQUIRE(spot > 0.0, "negative or null underlying given");
70 Real forwardPrice = spot * dividendDiscount / riskFreeDiscountForFwdEstimation;
71
72 BlackCalculator black(payoff, forwardPrice, std::sqrt(x: variance),df);
73
74
75 results_.value = black.value();
76 results_.delta = black.delta(spot);
77 results_.deltaForward = black.deltaForward();
78 results_.elasticity = black.elasticity(spot);
79 results_.gamma = black.gamma(spot);
80
81 DayCounter rfdc = discountPtr->dayCounter();
82 DayCounter divdc = process_->dividendYield()->dayCounter();
83 DayCounter voldc = process_->blackVolatility()->dayCounter();
84 Time t = rfdc.yearFraction(d1: process_->riskFreeRate()->referenceDate(),
85 d2: arguments_.exercise->lastDate());
86 results_.rho = black.rho(maturity: t);
87
88 t = divdc.yearFraction(d1: process_->dividendYield()->referenceDate(),
89 d2: arguments_.exercise->lastDate());
90 results_.dividendRho = black.dividendRho(maturity: t);
91
92 t = voldc.yearFraction(d1: process_->blackVolatility()->referenceDate(),
93 d2: arguments_.exercise->lastDate());
94 results_.vega = black.vega(maturity: t);
95 try {
96 results_.theta = black.theta(spot, maturity: t);
97 results_.thetaPerDay =
98 black.thetaPerDay(spot, maturity: t);
99 } catch (Error&) {
100 results_.theta = Null<Real>();
101 results_.thetaPerDay = Null<Real>();
102 }
103
104 results_.strikeSensitivity = black.strikeSensitivity();
105 results_.itmCashProbability = black.itmCashProbability();
106
107 Real tte = process_->blackVolatility()->timeFromReference(d: arguments_.exercise->lastDate());
108 results_.additionalResults["spot"] = spot;
109 results_.additionalResults["dividendDiscount"] = dividendDiscount;
110 results_.additionalResults["riskFreeDiscount"] = riskFreeDiscountForFwdEstimation;
111 results_.additionalResults["forward"] = forwardPrice;
112 results_.additionalResults["strike"] = payoff->strike();
113 results_.additionalResults["volatility"] = Real(std::sqrt(x: variance / tte));
114 results_.additionalResults["timeToExpiry"] = tte;
115 }
116
117}
118
119

source code of quantlib/ql/pricingengines/vanilla/analyticeuropeanengine.cpp