Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
averageoffpeakpowerhelper.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#include <ql/utilities/null_deleter.hpp>
21
22using QuantLib::AcyclicVisitor;
23using QuantLib::Calendar;
24using QuantLib::Date;
25using QuantLib::Handle;
26using QuantLib::Natural;
27using QuantLib::Quote;
28using QuantLib::Real;
29using QuantLib::Visitor;
30using std::max;
31using std::min;
32
33namespace QuantExt {
34
36 const QuantLib::ext::shared_ptr<CommodityIndex>& index,
37 const Date& start,
38 const Date& end,
39 const QuantLib::ext::shared_ptr<FutureExpiryCalculator>& calc,
40 const QuantLib::ext::shared_ptr<CommodityIndex>& peakIndex,
41 const Calendar& peakCalendar,
42 Natural peakHoursPerDay)
43 : PriceHelper(price) {
44 init(index, start, end, calc, peakIndex, peakCalendar, peakHoursPerDay);
45}
46
47AverageOffPeakPowerHelper::AverageOffPeakPowerHelper(Real price,
48 const QuantLib::ext::shared_ptr<CommodityIndex>& index,
49 const Date& start,
50 const Date& end,
51 const QuantLib::ext::shared_ptr<FutureExpiryCalculator>& calc,
52 const QuantLib::ext::shared_ptr<CommodityIndex>& peakIndex,
53 const Calendar& peakCalendar,
54 Natural peakHoursPerDay)
55 : PriceHelper(price) {
56 init(index, start, end, calc, peakIndex, peakCalendar, peakHoursPerDay);
57}
58
59void AverageOffPeakPowerHelper::init(const QuantLib::ext::shared_ptr<CommodityIndex>& index,
60 const Date& start, const Date& end, const QuantLib::ext::shared_ptr<FutureExpiryCalculator>& calc,
61 const QuantLib::ext::shared_ptr<CommodityIndex>& peakIndex, const Calendar& peakCalendar,
62 Natural peakHoursPerDay) {
63
64 QL_REQUIRE(peakHoursPerDay <= 24, "AverageOffPeakPowerHelper: peak hours per day should not be greater than 24.");
65 Natural ophpd = 24 - peakHoursPerDay;
66
67 // Make a copy of the commodity index linked to this price helper's price term structure handle,
68 // termStructureHandle_.
69 auto indexClone = index->clone(Date(), termStructureHandle_);
70
71 // While bootstrapping is happening, this price helper's price term structure handle, termStructureHandle_, will
72 // be updated multiple times. We don't want the index notified each time.
73 indexClone->unregisterWith(termStructureHandle_);
74 registerWith(indexClone);
75
76 // Create the business day off-peak portion of the cashflow.
77 bool useBusinessDays = true;
78 businessOffPeak_ = QuantLib::ext::make_shared<CommodityIndexedAverageCashFlow>(1.0, start, end, end, indexClone,
79 peakCalendar, 0.0, 1.0, true, 0, 0, calc, true, false, useBusinessDays);
80 peakDays_ = businessOffPeak_->indices().size();
81
82 // Create the holiday off-peak portion of the cashflow.
83 useBusinessDays = false;
84 holidayOffPeak_ = QuantLib::ext::make_shared<CommodityIndexedAverageCashFlow>(ophpd / 24.0, start, end, end, indexClone,
85 peakCalendar, 0.0, 1.0, true, 0, 0, calc, true, false, useBusinessDays);
86 nonPeakDays_ = holidayOffPeak_->indices().size();
87
88 // Create the holiday peak portion of the cashflow.
89 holidayPeak_ = QuantLib::ext::make_shared<CommodityIndexedAverageCashFlow>(peakHoursPerDay / 24.0, start, end, end,
90 peakIndex, peakCalendar, 0.0, 1.0, true, 0, 0, calc, true, false, useBusinessDays);
91
92 // Get the date index pairs involved in the averaging. The earliest date is the expiry date of the future contract
93 // referenced in the first element and the latest date is the expiry date of the future contract referenced in
94 // the last element. We must look at both off peak cashflows here.
95 const auto& mpBop = businessOffPeak_->indices();
96 const auto& mpHop = holidayOffPeak_->indices();
97 earliestDate_ = min(mpBop.begin()->second->expiryDate(), mpHop.begin()->second->expiryDate());
98 pillarDate_ = max(mpBop.rbegin()->second->expiryDate(), mpHop.rbegin()->second->expiryDate());
99}
100
101Real AverageOffPeakPowerHelper::impliedQuote() const {
102 QL_REQUIRE(termStructure_, "AverageFuturePriceHelper term structure not set.");
103 businessOffPeak_->update();
104 holidayOffPeak_->update();
105 holidayPeak_->update();
106 return (peakDays_ * businessOffPeak_->amount() + nonPeakDays_ * (holidayOffPeak_->amount()
107 + holidayPeak_->amount())) / (peakDays_ + nonPeakDays_);
108}
109
110void AverageOffPeakPowerHelper::setTermStructure(PriceTermStructure* ts) {
111 QuantLib::ext::shared_ptr<PriceTermStructure> temp(ts, null_deleter());
112 // Do not set the relinkable handle as an observer i.e. registerAsObserver is false here.
113 termStructureHandle_.linkTo(temp, false);
114 PriceHelper::setTermStructure(ts);
115}
116
117void AverageOffPeakPowerHelper::accept(AcyclicVisitor& v) {
118 if (auto vis = dynamic_cast<Visitor<AverageOffPeakPowerHelper>*>(&v))
119 vis->visit(*this);
120 else
121 PriceHelper::accept(v);
122}
123
124void AverageOffPeakPowerHelper::deepUpdate() {
125 if (businessOffPeak_)
126 businessOffPeak_->update();
127 if (holidayOffPeak_)
128 holidayOffPeak_->update();
129 if (holidayPeak_)
130 holidayPeak_->update();
131}
132
133} // namespace QuantExt
Price helper for average of off-peak electricity prices over a period.
AverageOffPeakPowerHelper(const QuantLib::Handle< QuantLib::Quote > &price, const QuantLib::ext::shared_ptr< CommodityIndex > &index, const QuantLib::Date &start, const QuantLib::Date &end, const ext::shared_ptr< FutureExpiryCalculator > &calc, const QuantLib::ext::shared_ptr< CommodityIndex > &peakIndex, const QuantLib::Calendar &peakCalendar, QuantLib::Natural peakHoursPerDay=16)
CompiledFormula min(CompiledFormula x, const CompiledFormula &y)
CompiledFormula max(CompiledFormula x, const CompiledFormula &y)