QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
analytic_discr_geom_av_price.cpp
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) 2005 Gary Kennedy
6 Copyright (C) 2007 StatPro Italia srl
7
8 This file is part of QuantLib, a free-software/open-source library
9 for financial quantitative analysts and developers - http://quantlib.org/
10
11 QuantLib is free software: you can redistribute it and/or modify it
12 under the terms of the QuantLib license. You should have received a
13 copy of the license along with this program; if not, please email
14 <quantlib-dev@lists.sf.net>. The license is also available online at
15 <http://quantlib.org/license.shtml>.
16
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the license for more details.
20*/
21
22#include <ql/exercise.hpp>
23#include <ql/math/distributions/normaldistribution.hpp>
24#include <ql/pricingengines/asian/analytic_discr_geom_av_price.hpp>
25#include <ql/pricingengines/blackcalculator.hpp>
26#include <ql/pricingengines/greeks.hpp>
27#include <numeric>
28#include <utility>
29
30namespace QuantLib {
31
34 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
35 : process_(std::move(process)) {
37 }
38
40
41 /* this engine cannot really check for the averageType==Geometric
42 since it can be used as control variate for the Arithmetic version
43 QL_REQUIRE(arguments_.averageType == Average::Geometric,
44 "not a geometric average option");
45 */
46
47 QL_REQUIRE(arguments_.exercise->type() == Exercise::European,
48 "not an European Option");
49
50 Real runningLog;
51 Size pastFixings;
53 QL_REQUIRE(arguments_.runningAccumulator>0.0,
54 "positive running product required: "
55 << arguments_.runningAccumulator << " not allowed");
56 runningLog =
58 pastFixings = arguments_.pastFixings;
59 } else { // it is being used as control variate
60 runningLog = 1.0;
61 pastFixings = 0;
62 }
63
64 ext::shared_ptr<PlainVanillaPayoff> payoff =
65 ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
66 QL_REQUIRE(payoff, "non-plain payoff given");
67
68 Date referenceDate = process_->riskFreeRate()->referenceDate();
69 DayCounter rfdc = process_->riskFreeRate()->dayCounter();
70 DayCounter divdc = process_->dividendYield()->dayCounter();
71 DayCounter voldc = process_->blackVolatility()->dayCounter();
72 std::vector<Time> fixingTimes;
73 Size i;
74 for (i=0; i<arguments_.fixingDates.size(); i++) {
75 if (arguments_.fixingDates[i]>=referenceDate) {
76 Time t = voldc.yearFraction(referenceDate,
78 fixingTimes.push_back(t);
79 }
80 }
81
82 Size remainingFixings = fixingTimes.size();
83 Size numberOfFixings = pastFixings + remainingFixings;
84 Real N = static_cast<Real>(numberOfFixings);
85
86 Real pastWeight = pastFixings/N;
87 Real futureWeight = 1.0-pastWeight;
88
89 Time timeSum = std::accumulate(fixingTimes.begin(),
90 fixingTimes.end(), Real(0.0));
91
92 Volatility vola = process_->blackVolatility()->blackVol(
93 arguments_.exercise->lastDate(),
94 payoff->strike());
95 Real temp = 0.0;
96 for (i=pastFixings+1; i<numberOfFixings; i++)
97 temp += fixingTimes[i-pastFixings-1]*(N-i);
98 Real variance = vola*vola /N/N * (timeSum+ 2.0*temp);
99 Real dsigG_dsig = std::sqrt((timeSum + 2.0*temp))/N;
100 Real sigG = vola * dsigG_dsig;
101 Real dmuG_dsig = -(vola * timeSum)/N;
102
103 Date exDate = arguments_.exercise->lastDate();
104 Rate dividendRate = process_->dividendYield()->
105 zeroRate(exDate, divdc, Continuous, NoFrequency);
106 Rate riskFreeRate = process_->riskFreeRate()->
107 zeroRate(exDate, rfdc, Continuous, NoFrequency);
108 Rate nu = riskFreeRate - dividendRate - 0.5*vola*vola;
109
110 Real s = process_->stateVariable()->value();
111 QL_REQUIRE(s > 0.0, "positive underlying value required");
112
113 Size M = (pastFixings == 0 ? 1 : pastFixings);
114 Real muG = pastWeight * runningLog/M +
115 futureWeight * std::log(s) + nu*timeSum/N;
116 Real forwardPrice = std::exp(muG + variance / 2.0);
117
118 DiscountFactor riskFreeDiscount = process_->riskFreeRate()->discount(
119 arguments_.exercise->lastDate());
120
121 BlackCalculator black(payoff, forwardPrice, std::sqrt(variance),
122 riskFreeDiscount);
123
124 results_.value = black.value();
125 results_.delta = futureWeight*black.delta(forwardPrice)*forwardPrice/s;
126 results_.gamma = forwardPrice*futureWeight/(s*s)
127 *( black.gamma(forwardPrice)*futureWeight*forwardPrice
128 - pastWeight*black.delta(forwardPrice) );
129
130 Real Nx_1, nx_1;
133 if (sigG > QL_EPSILON) {
134 Real x_1 = (muG-std::log(payoff->strike())+variance)/sigG;
135 Nx_1 = CND(x_1);
136 nx_1 = ND(x_1);
137 } else {
138 Nx_1 = (muG > std::log(payoff->strike()) ? 1.0 : 0.0);
139 nx_1 = 0.0;
140 }
141 results_.vega = forwardPrice * riskFreeDiscount *
142 ( (dmuG_dsig + sigG * dsigG_dsig)*Nx_1 + nx_1*dsigG_dsig );
143
144 if (payoff->optionType() == Option::Put)
145 results_.vega -= riskFreeDiscount * forwardPrice *
146 (dmuG_dsig + sigG * dsigG_dsig);
147
148 Time tRho = rfdc.yearFraction(process_->riskFreeRate()->referenceDate(),
149 arguments_.exercise->lastDate());
150 results_.rho = black.rho(tRho)*timeSum/(N*tRho)
151 - (tRho-timeSum/N)*results_.value;
152
153 Time tDiv = divdc.yearFraction(
154 process_->dividendYield()->referenceDate(),
155 arguments_.exercise->lastDate());
156
157 results_.dividendRho = black.dividendRho(tDiv)*timeSum/(N*tDiv);
158
159 results_.strikeSensitivity = black.strikeSensitivity();
160
163 results_.delta,
164 results_.gamma);
165 }
166}
167
AnalyticDiscreteGeometricAveragePriceAsianEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process)
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
Black 1976 calculator class.
Real dividendRho(Time maturity) const
virtual Real delta(Real spot) const
virtual Real gamma(Real spot) const
Real rho(Time maturity) const
Cumulative normal distribution function.
Concrete date class.
Definition: date.hpp:125
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
Normal distribution function.
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
@ NoFrequency
null frequency
Definition: frequency.hpp:37
#define QL_EPSILON
Definition: qldefines.hpp:178
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
Real Volatility
volatility
Definition: types.hpp:78
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
Real blackScholesTheta(const ext::shared_ptr< GeneralizedBlackScholesProcess > &p, Real value, Real delta, Real gamma)
default theta calculation for Black-Scholes options
Definition: greeks.cpp:25
STL namespace.