20#include <ql/exercise.hpp>
21#include <ql/math/distributions/normaldistribution.hpp>
22#include <ql/pricingengines/asian/analytic_discr_geom_av_strike.hpp>
29 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
30 : process_(
std::move(process)) {
37 "not a geometric average option");
40 "not an European option");
43 "positive running product required: "
47 QL_REQUIRE(pastFixings == 0,
"past fixings currently not managed");
49 ext::shared_ptr<PlainVanillaPayoff> payoff =
50 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
arguments_.payoff);
51 QL_REQUIRE(payoff,
"non-plain payoff given");
57 std::vector<Time> fixingTimes;
61 fixingTimes.push_back(t);
65 Size remainingFixings = fixingTimes.size();
66 Size numberOfFixings = pastFixings + remainingFixings;
67 Real N =
static_cast<Real>(numberOfFixings);
69 Real pastWeight = pastFixings/N;
70 Real futureWeight = 1.0-pastWeight;
72 Time timeSum = std::accumulate(fixingTimes.begin(),
73 fixingTimes.end(),
Real(0.0));
80 QL_REQUIRE(underlying > 0.0,
"positive underlying value required");
93 Rate nu = riskFreeRate - dividendRate - 0.5*volatility*volatility;
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 -
103 Size M = (pastFixings == 0 ? 1 : pastFixings);
104 Real runningLogAverage = runningLog/M;
106 Real muG = pastWeight * runningLogAverage +
107 futureWeight * std::log(underlying) +
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);
118 switch (payoff->optionType()) {
120 results_.
value = underlying*std::exp(-dividendRate*residualTime)
122 std::exp(muG + variance/2.0 - riskFreeRate*residualTime)
126 results_.
value = -underlying*std::exp(-dividendRate*residualTime)
128 std::exp(muG + variance/2.0 - riskFreeRate*residualTime)
132 QL_FAIL(
"invalid option type");
AnalyticDiscreteGeometricAverageStrikeAsianEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process)
void calculate() const override
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
Cumulative normal distribution function.
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.
Average::Type averageType
std::vector< Date > fixingDates
DiscreteAveragingAsianOption::results results_
DiscreteAveragingAsianOption::arguments arguments_
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
@ NoFrequency
null frequency
Real Time
continuous quantity with 1-year units
Real Volatility
volatility
std::size_t Size
size of a container