QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
analytic_discr_geom_av_strike.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2009 Master IMAFA - Polytech'Nice Sophia - Université de Nice Sophia Antipolis
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include <ql/exercise.hpp>
21#include <ql/math/distributions/normaldistribution.hpp>
22#include <ql/pricingengines/asian/analytic_discr_geom_av_strike.hpp>
23#include <utility>
24
25namespace QuantLib {
26
29 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
30 : process_(std::move(process)) {
32 }
33
35
37 "not a geometric average option");
38
39 QL_REQUIRE(arguments_.exercise->type() == Exercise::European,
40 "not an European option");
41
42 QL_REQUIRE(arguments_.runningAccumulator > 0.0,
43 "positive running product required: "
44 << arguments_.runningAccumulator << "not allowed");
45 Real runningLog = std::log(arguments_.runningAccumulator);
46 Size pastFixings = arguments_.pastFixings;
47 QL_REQUIRE(pastFixings == 0, "past fixings currently not managed");
48
49 ext::shared_ptr<PlainVanillaPayoff> payoff =
50 ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
51 QL_REQUIRE(payoff, "non-plain payoff given");
52
53 DayCounter rfdc = process_->riskFreeRate()->dayCounter();
54 DayCounter divdc = process_->dividendYield()->dayCounter();
55 DayCounter voldc = process_->blackVolatility()->dayCounter();
56
57 std::vector<Time> fixingTimes;
58 for (auto& fixingDate : arguments_.fixingDates) {
59 if (fixingDate >= arguments_.fixingDates[0]) {
60 Time t = voldc.yearFraction(arguments_.fixingDates[0], fixingDate);
61 fixingTimes.push_back(t);
62 }
63 }
64
65 Size remainingFixings = fixingTimes.size();
66 Size numberOfFixings = pastFixings + remainingFixings;
67 Real N = static_cast<Real>(numberOfFixings);
68
69 Real pastWeight = pastFixings/N;
70 Real futureWeight = 1.0-pastWeight;
71
72 Time timeSum = std::accumulate(fixingTimes.begin(),
73 fixingTimes.end(), Real(0.0));
74
75 Time residualTime = rfdc.yearFraction(arguments_.fixingDates[pastFixings],
76 arguments_.exercise->lastDate());
77
78
79 Real underlying = process_->stateVariable()->value();
80 QL_REQUIRE(underlying > 0.0, "positive underlying value required");
81
82 Volatility volatility = process_->blackVolatility()->blackVol(
83 arguments_.exercise->lastDate(),
84 underlying);
85
86 Date exDate = arguments_.exercise->lastDate();
87 Rate dividendRate = process_->dividendYield()->
88 zeroRate(exDate, divdc, Continuous, NoFrequency);
89
90 Rate riskFreeRate = process_->riskFreeRate()->
91 zeroRate(exDate, rfdc, Continuous, NoFrequency);
92
93 Rate nu = riskFreeRate - dividendRate - 0.5*volatility*volatility;
94
95 Real temp = 0.0;
96 for (Size i=pastFixings+1; i<numberOfFixings; i++)
97 temp += fixingTimes[i-pastFixings-1]*(N-i);
98 Real variance = volatility*volatility /N/N * (timeSum + 2.0*temp);
99 Real covarianceTerm = volatility*volatility/N * timeSum;
100 Real sigmaSum_2 = variance + volatility*volatility*residualTime -
101 2.0*covarianceTerm;
102
103 Size M = (pastFixings == 0 ? 1 : pastFixings);
104 Real runningLogAverage = runningLog/M;
105
106 Real muG = pastWeight * runningLogAverage +
107 futureWeight * std::log(underlying) +
108 nu*timeSum/N;
109
111
112 Real y1 = (std::log(underlying)+
113 (riskFreeRate-dividendRate)*residualTime-
114 muG - variance/2.0 + sigmaSum_2/2.0)
115 /std::sqrt(sigmaSum_2);
116 Real y2 = y1-std::sqrt(sigmaSum_2);
117
118 switch (payoff->optionType()) {
119 case Option::Call:
120 results_.value = underlying*std::exp(-dividendRate*residualTime)
121 *f(y1)-
122 std::exp(muG + variance/2.0 - riskFreeRate*residualTime)
123 *f(y2);
124 break;
125 case Option::Put:
126 results_.value = -underlying*std::exp(-dividendRate*residualTime)
127 *f(-y1)+
128 std::exp(muG + variance/2.0 - riskFreeRate*residualTime)
129 *f(-y2);
130 break;
131 default:
132 QL_FAIL("invalid option type");
133 }
134 }
135
136}
137
AnalyticDiscreteGeometricAverageStrikeAsianEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process)
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
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
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
@ NoFrequency
null frequency
Definition: frequency.hpp:37
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
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
STL namespace.