Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
compositeindex.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
20
24#include <ql/time/calendars/jointcalendar.hpp>
25
26namespace QuantExt {
27
28CompositeIndex::CompositeIndex(const std::string& name, const std::vector<QuantLib::ext::shared_ptr<QuantLib::Index>>& indices,
29 const std::vector<Real>& weights,
30 const std::vector<QuantLib::ext::shared_ptr<FxIndex>>& fxConversion)
31 : name_(name), indices_(indices), weights_(weights), fxConversion_(fxConversion) {
32 QL_REQUIRE(indices_.size() == weights_.size(), "CompositeIndex: indices size (" << indices_.size()
33 << ") must match weights size ("
34 << weights_.size() << ")");
35 QL_REQUIRE(fxConversion_.empty() || fxConversion_.size() == indices_.size(),
36 "CompositeIndex: fx conversion size (" << fxConversion_.size() << ") must match indices size ("
37 << indices_.size() << ")");
38
39 for (auto const& f : fxConversion) {
40 registerWith(f);
41 }
42
43 std::vector<Calendar> cals;
44 for (auto const& i : indices) {
45 registerWith(i);
46 cals.push_back(i->fixingCalendar());
47 }
48
49 fixingCalendar_ = JointCalendar(cals);
50}
51
52std::string CompositeIndex::name() const { return name_; }
53
55
56bool CompositeIndex::isValidFixingDate(const Date& fixingDate) const {
57 return fixingCalendar_.isBusinessDay(fixingDate);
58}
59
60Real CompositeIndex::fixing(const Date& fixingDate, bool forecastTodaysFixing) const {
61 Real result = 0.0;
62 for (Size i = 0; i < indices_.size(); ++i) {
63 Real indexFixing;
64 try {
65 indexFixing = indices_[i]->fixing(fixingDate, forecastTodaysFixing);
66 } catch (const std::exception&) {
67 auto gi = QuantLib::ext::dynamic_pointer_cast<QuantExt::GenericIndex>(indices_[i]);
68 if (gi && gi->expiry() != Date() && fixingDate >= gi->expiry())
69 indexFixing = 0.0;
70 else
71 throw;
72 }
73
74 // if the fixing date is not a valid fx fixing date, adjust the latter to the preceding valid date
75 result += indexFixing * weights_[i] *
76 (fxConversion_.empty() || fxConversion_[i] == nullptr
77 ? 1.0
78 : fxConversion_[i]->fixing(fxConversion_[i]->fixingCalendar().adjust(fixingDate, Preceding),
79 forecastTodaysFixing));
80 }
81 return result;
82}
83
84Real CompositeIndex::dividendsBetweenDates(const Date& startDate, const Date& endDate) const {
85 const Date& today = Settings::instance().evaluationDate();
86 Real dividends = 0.0;
87 for (Size i = 0; i < indices_.size(); ++i) {
88 if (auto ei = QuantLib::ext::dynamic_pointer_cast<EquityIndex2>(indices_[i])) {
89 for (auto const& d : ei->dividendFixings()) {
90 if (d.exDate >= startDate && d.exDate <= std::min(endDate, today)) {
91 // if the fixing date is not a valid fx fixing date, adjust the latter to the preceding valid date
92 dividends +=
93 d.rate * weights_[i] *
94 (fxConversion_.empty() || fxConversion_[i] == nullptr
95 ? 1.0
96 : fxConversion_[i]->fixing(fxConversion_[i]->fixingCalendar().adjust(d.exDate, Preceding)));
97 }
98 }
99 }
100 }
101 return dividends;
102}
103
104std::vector<std::pair<QuantLib::Date, std::string>> CompositeIndex::dividendFixingDates(const Date& startDate,
105 const Date& endDate) {
106
107 std::vector<std::pair<QuantLib::Date, std::string>> fixings;
108 const Date& eDate = endDate == Date() ? Settings::instance().evaluationDate() : endDate;
109 for (Size i = 0; i < indices_.size(); ++i) {
110 if (QuantLib::ext::dynamic_pointer_cast<EquityIndex2>(indices_[i]) && !fxConversion_.empty() && fxConversion_[i]) {
111 Date d = fxConversion_[i]->fixingCalendar().adjust(startDate, Preceding);
112 while (d <= eDate) {
113 fixings.push_back(std::make_pair<Date, std::string>(
114 fxConversion_[i]->fixingCalendar().adjust(d, Preceding), fxConversion_[i]->name()));
115 d = fxConversion_[i]->fixingCalendar().advance(d, 1, Days);
116 }
117 }
118 }
119 return fixings;
120 }
121
122} // namespace QuantExt
bond index class representing historical and forward bond prices
const std::vector< QuantLib::ext::shared_ptr< QuantLib::Index > > & indices() const
Inspectors.
std::vector< QuantLib::ext::shared_ptr< QuantLib::Index > > indices_
std::vector< QuantLib::ext::shared_ptr< FxIndex > > fxConversion_
std::vector< std::pair< QuantLib::Date, std::string > > dividendFixingDates(const Date &startDate, const Date &endDate=Date::maxDate())
Calendar fixingCalendar() const override
const std::vector< QuantLib::ext::shared_ptr< FxIndex > > & fxConversion() const
std::string name() const override
Index interface.
std::vector< Real > weights_
Real dividendsBetweenDates(const Date &startDate, const Date &endDate=Date::maxDate()) const
CompositeIndex(const std::string &name, const std::vector< QuantLib::ext::shared_ptr< QuantLib::Index > > &indices, const std::vector< Real > &weights, const std::vector< QuantLib::ext::shared_ptr< FxIndex > > &fxConversion={})
bool isValidFixingDate(const Date &fixingDate) const override
Real fixing(const Date &fixingDate, bool forecastTodaysFixing=false) const override
index representing a weighted sum of underlying indices
equity index class for holding equity fixing histories and forwarding.
generic index class for storing price histories