Coverage Report

Created: 2025-10-14 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/instruments/asianoption.cpp
Line
Count
Source
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
 <https://www.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
27
namespace 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
0
    : OneAssetOption(payoff, exercise), averageType_(averageType),
37
0
      runningAccumulator_(runningAccumulator), pastFixings_(pastFixings),
38
0
      fixingDates_(std::move(fixingDates)), allPastFixingsProvided_(false) {
39
0
        std::sort(fixingDates_.begin(), fixingDates_.end());
40
41
        // Add a hard override to the runningAccumulator if pastFixings is 0
42
        // (ie. the option is unseasoned)
43
0
        if (pastFixings_ == 0) {
44
0
            if (averageType == Average::Geometric) {
45
0
                runningAccumulator_ = 1.0;
46
0
            } else if (averageType == Average::Arithmetic) {
47
0
                runningAccumulator_ = 0.0;
48
0
            } else {
49
0
                QL_FAIL("Unrecognised average type, must be Average::Arithmetic or Average::Geometric");
50
0
            }
51
0
        }
52
0
    }
Unexecuted instantiation: QuantLib::DiscreteAveragingAsianOption::DiscreteAveragingAsianOption(QuantLib::Average::Type, double, unsigned long, std::__1::vector<QuantLib::Date, std::__1::allocator<QuantLib::Date> >, boost::shared_ptr<QuantLib::StrikedTypePayoff> const&, boost::shared_ptr<QuantLib::Exercise> const&)
Unexecuted instantiation: QuantLib::DiscreteAveragingAsianOption::DiscreteAveragingAsianOption(QuantLib::Average::Type, double, unsigned long, std::__1::vector<QuantLib::Date, std::__1::allocator<QuantLib::Date> >, boost::shared_ptr<QuantLib::StrikedTypePayoff> const&, boost::shared_ptr<QuantLib::Exercise> const&)
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
0
    : OneAssetOption(payoff, exercise), averageType_(averageType), runningAccumulator_(0.0),
61
0
      pastFixings_(0), fixingDates_(std::move(fixingDates)),
62
0
      allPastFixingsProvided_(true), allPastFixings_(std::move(allPastFixings)) {}
Unexecuted instantiation: QuantLib::DiscreteAveragingAsianOption::DiscreteAveragingAsianOption(QuantLib::Average::Type, std::__1::vector<QuantLib::Date, std::__1::allocator<QuantLib::Date> >, boost::shared_ptr<QuantLib::StrikedTypePayoff> const&, boost::shared_ptr<QuantLib::Exercise> const&, std::__1::vector<double, std::__1::allocator<double> >)
Unexecuted instantiation: QuantLib::DiscreteAveragingAsianOption::DiscreteAveragingAsianOption(QuantLib::Average::Type, std::__1::vector<QuantLib::Date, std::__1::allocator<QuantLib::Date> >, boost::shared_ptr<QuantLib::StrikedTypePayoff> const&, boost::shared_ptr<QuantLib::Exercise> const&, std::__1::vector<double, std::__1::allocator<double> >)
63
64
    void DiscreteAveragingAsianOption::setupArguments(
65
0
                                       PricingEngine::arguments* args) const {
66
67
0
        Real runningAccumulator = runningAccumulator_;
68
0
        Size pastFixings = pastFixings_;
69
0
        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
0
        if (allPastFixingsProvided_) {
75
0
            std::vector<Date> futureFixingDates = std::vector<Date>();
76
0
            Date today = Settings::instance().evaluationDate();
77
78
0
            pastFixings = 0;
79
0
            for (auto fixingDate : fixingDates_) {
80
0
                if (fixingDate < today) {
81
0
                    pastFixings += 1;
82
0
                } else {
83
0
                    futureFixingDates.push_back(fixingDate);
84
0
                }
85
0
            }
86
0
            fixingDates = futureFixingDates;
87
88
0
            if (pastFixings > allPastFixings_.size())
89
0
                QL_FAIL("Not enough past fixings have been provided for the required historical fixing dates");
90
91
0
            if (averageType_ == Average::Geometric) {
92
0
                runningAccumulator = 1.0;
93
0
                for (Size i=0; i<pastFixings; i++)
94
0
                    runningAccumulator *= allPastFixings_[i];
95
96
0
            } else if (averageType_ == Average::Arithmetic) {
97
0
                runningAccumulator = 0.0;
98
0
                for (Size i=0; i<pastFixings; i++)
99
0
                    runningAccumulator += allPastFixings_[i];
100
101
0
            } else {
102
0
                QL_FAIL("Unrecognised average type, must be Average::Arithmetic or Average::Geometric");
103
0
            }
104
105
0
        }
106
107
0
        OneAssetOption::setupArguments(args);
108
109
0
        auto* moreArgs = dynamic_cast<DiscreteAveragingAsianOption::arguments*>(args);
110
0
        QL_REQUIRE(moreArgs != nullptr, "wrong argument type");
111
0
        moreArgs->averageType = averageType_;
112
0
        moreArgs->runningAccumulator = runningAccumulator;
113
0
        moreArgs->pastFixings = pastFixings;
114
0
        moreArgs->fixingDates = fixingDates;
115
0
    }
116
117
0
    void DiscreteAveragingAsianOption::arguments::validate() const {
118
119
0
        OneAssetOption::arguments::validate();
120
121
0
        QL_REQUIRE(Integer(averageType) != -1, "unspecified average type");
122
0
        QL_REQUIRE(pastFixings != Null<Size>(), "null past-fixing number");
123
0
        QL_REQUIRE(runningAccumulator != Null<Real>(), "null running product");
124
0
        switch (averageType) {
125
0
            case Average::Arithmetic:
126
0
                QL_REQUIRE(runningAccumulator >= 0.0,
127
0
                           "non negative running sum required: "
128
0
                           << runningAccumulator << " not allowed");
129
0
                break;
130
0
            case Average::Geometric:
131
0
                QL_REQUIRE(runningAccumulator > 0.0,
132
0
                           "positive running product required: "
133
0
                           << runningAccumulator << " not allowed");
134
0
                break;
135
0
            default:
136
0
                QL_FAIL("invalid average type");
137
0
        }
138
139
        // check fixingTimes_ here
140
0
    }
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
0
    : OneAssetOption(payoff, exercise),
150
0
      averageType_(averageType) {}
Unexecuted instantiation: QuantLib::ContinuousAveragingAsianOption::ContinuousAveragingAsianOption(QuantLib::Average::Type, boost::shared_ptr<QuantLib::StrikedTypePayoff> const&, boost::shared_ptr<QuantLib::Exercise> const&)
Unexecuted instantiation: QuantLib::ContinuousAveragingAsianOption::ContinuousAveragingAsianOption(QuantLib::Average::Type, boost::shared_ptr<QuantLib::StrikedTypePayoff> const&, boost::shared_ptr<QuantLib::Exercise> const&)
151
152
    void ContinuousAveragingAsianOption::setupArguments(
153
0
                                       PricingEngine::arguments* args) const {
154
155
0
        OneAssetOption::setupArguments(args);
156
157
0
        auto* moreArgs = dynamic_cast<ContinuousAveragingAsianOption::arguments*>(args);
158
0
        QL_REQUIRE(moreArgs != nullptr, "wrong argument type");
159
0
        moreArgs->averageType = averageType_;
160
0
    }
161
162
0
    void ContinuousAveragingAsianOption::arguments::validate() const {
163
164
0
        OneAssetOption::arguments::validate();
165
166
        QL_REQUIRE(Integer(averageType) != -1, "unspecified average type");
167
0
    }
168
169
}
170