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 <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/instruments/asianoption.hpp>
22#include <ql/time/date.hpp>
23#include <ql/settings.hpp>
24#include <algorithm>
25#include <utility>
26
27namespace QuantLib {
28
29 DiscreteAveragingAsianOption::DiscreteAveragingAsianOption(
30 Average::Type averageType,
31 Real runningAccumulator,
32 Size pastFixings,
33 std::vector<Date> fixingDates,
34 const ext::shared_ptr<StrikedTypePayoff>& payoff,
35 const ext::shared_ptr<Exercise>& exercise)
36 : OneAssetOption(payoff, exercise), averageType_(averageType),
37 runningAccumulator_(runningAccumulator), pastFixings_(pastFixings),
38 fixingDates_(std::move(fixingDates)), allPastFixingsProvided_(false) {
39 std::sort(first: fixingDates_.begin(), last: fixingDates_.end());
40
41 // Add a hard override to the runningAccumulator if pastFixings is 0
42 // (ie. the option is unseasoned)
43 if (pastFixings_ == 0) {
44 if (averageType == Average::Geometric) {
45 runningAccumulator_ = 1.0;
46 } else if (averageType == Average::Arithmetic) {
47 runningAccumulator_ = 0.0;
48 } else {
49 QL_FAIL("Unrecognised average type, must be Average::Arithmetic or Average::Geometric");
50 }
51 }
52 }
53
54 DiscreteAveragingAsianOption::DiscreteAveragingAsianOption(
55 Average::Type averageType,
56 std::vector<Date> fixingDates,
57 const ext::shared_ptr<StrikedTypePayoff>& payoff,
58 const ext::shared_ptr<Exercise>& exercise,
59 std::vector<Real> allPastFixings)
60 : OneAssetOption(payoff, exercise), averageType_(averageType), runningAccumulator_(0.0),
61 pastFixings_(0), fixingDates_(std::move(fixingDates)),
62 allPastFixingsProvided_(true), allPastFixings_(std::move(allPastFixings)) {}
63
64 void DiscreteAveragingAsianOption::setupArguments(
65 PricingEngine::arguments* args) const {
66
67 Real runningAccumulator = runningAccumulator_;
68 Size pastFixings = pastFixings_;
69 std::vector<Date> fixingDates = fixingDates_;
70
71 // If the option was initialised with a list of fixings, before pricing we
72 // compare the evaluation date to the fixing dates, and set up the pastFixings,
73 // fixingDates, and runningAccumulator accordingly
74 if (allPastFixingsProvided_) {
75 std::vector<Date> futureFixingDates = std::vector<Date>();
76 Date today = Settings::instance().evaluationDate();
77
78 pastFixings = 0;
79 for (auto fixingDate : fixingDates_) {
80 if (fixingDate < today) {
81 pastFixings += 1;
82 } else {
83 futureFixingDates.push_back(x: fixingDate);
84 }
85 }
86 fixingDates = futureFixingDates;
87
88 if (pastFixings > allPastFixings_.size())
89 QL_FAIL("Not enough past fixings have been provided for the required historical fixing dates");
90
91 if (averageType_ == Average::Geometric) {
92 runningAccumulator = 1.0;
93 for (Size i=0; i<pastFixings; i++)
94 runningAccumulator *= allPastFixings_[i];
95
96 } else if (averageType_ == Average::Arithmetic) {
97 runningAccumulator = 0.0;
98 for (Size i=0; i<pastFixings; i++)
99 runningAccumulator += allPastFixings_[i];
100
101 } else {
102 QL_FAIL("Unrecognised average type, must be Average::Arithmetic or Average::Geometric");
103 }
104
105 }
106
107 OneAssetOption::setupArguments(args);
108
109 auto* moreArgs = dynamic_cast<DiscreteAveragingAsianOption::arguments*>(args);
110 QL_REQUIRE(moreArgs != nullptr, "wrong argument type");
111 moreArgs->averageType = averageType_;
112 moreArgs->runningAccumulator = runningAccumulator;
113 moreArgs->pastFixings = pastFixings;
114 moreArgs->fixingDates = fixingDates;
115 }
116
117 void DiscreteAveragingAsianOption::arguments::validate() const {
118
119 OneAssetOption::arguments::validate();
120
121 QL_REQUIRE(Integer(averageType) != -1, "unspecified average type");
122 QL_REQUIRE(pastFixings != Null<Size>(), "null past-fixing number");
123 QL_REQUIRE(runningAccumulator != Null<Real>(), "null running product");
124 switch (averageType) {
125 case Average::Arithmetic:
126 QL_REQUIRE(runningAccumulator >= 0.0,
127 "non negative running sum required: "
128 << runningAccumulator << " not allowed");
129 break;
130 case Average::Geometric:
131 QL_REQUIRE(runningAccumulator > 0.0,
132 "positive running product required: "
133 << runningAccumulator << " not allowed");
134 break;
135 default:
136 QL_FAIL("invalid average type");
137 }
138
139 // check fixingTimes_ here
140 }
141
142
143
144
145 ContinuousAveragingAsianOption::ContinuousAveragingAsianOption(
146 Average::Type averageType,
147 const ext::shared_ptr<StrikedTypePayoff>& payoff,
148 const ext::shared_ptr<Exercise>& exercise)
149 : OneAssetOption(payoff, exercise),
150 averageType_(averageType) {}
151
152 void ContinuousAveragingAsianOption::setupArguments(
153 PricingEngine::arguments* args) const {
154
155 OneAssetOption::setupArguments(args);
156
157 auto* moreArgs = dynamic_cast<ContinuousAveragingAsianOption::arguments*>(args);
158 QL_REQUIRE(moreArgs != nullptr, "wrong argument type");
159 moreArgs->averageType = averageType_;
160 }
161
162 void ContinuousAveragingAsianOption::arguments::validate() const {
163
164 OneAssetOption::arguments::validate();
165
166 QL_REQUIRE(Integer(averageType) != -1, "unspecified average type");
167 }
168
169}
170
171

source code of quantlib/ql/instruments/asianoption.cpp

Morty Proxy This is a proxified and sanitized view of the page, visit original site.