Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
valuationcalculator.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 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
19/*! \file engine/valuationcalculator.hpp
20 \brief The cube valuation calculator interface
21 \ingroup simulation
22*/
23
27
28namespace ore {
29namespace analytics {
30
31void NPVCalculator::init(const QuantLib::ext::shared_ptr<Portfolio>& portfolio, const QuantLib::ext::shared_ptr<SimMarket>& simMarket) {
32 DLOG("init NPVCalculator");
33 tradeCcyIndex_.resize(portfolio->size());
34 std::set<std::string> ccys;
35 for (auto const& [tradeId, trade] : portfolio->trades())
36 ccys.insert(trade->npvCurrency());
37
38 size_t i = 0;
39 for (auto const& [tradeId, trade] : portfolio->trades()) {
40 tradeCcyIndex_[i] = std::distance(ccys.begin(), ccys.find(trade->npvCurrency()));
41 i++;
42 }
43
44 ccyQuotes_.resize(ccys.size());
45 for (Size i = 0; i < ccys.size(); ++i)
46 ccyQuotes_[i] = (simMarket->fxRate(*std::next(ccys.begin(), i) + baseCcyCode_));
47 fxRates_.resize(ccys.size());
48}
49
51 for (Size i = 0; i < ccyQuotes_.size(); ++i)
52 fxRates_[i] = ccyQuotes_[i]->value();
53}
54
55void NPVCalculator::calculate(const QuantLib::ext::shared_ptr<Trade>& trade, Size tradeIndex,
56 const QuantLib::ext::shared_ptr<SimMarket>& simMarket, QuantLib::ext::shared_ptr<NPVCube>& outputCube,
57 QuantLib::ext::shared_ptr<NPVCube>& outputCubeNettingSet, const Date& date, Size dateIndex,
58 Size sample, bool isCloseOut) {
59 if (!isCloseOut)
60 outputCube->set(npv(tradeIndex, trade, simMarket), tradeIndex, dateIndex, sample, index_);
61}
62
63void NPVCalculator::calculateT0(const QuantLib::ext::shared_ptr<Trade>& trade, Size tradeIndex,
64 const QuantLib::ext::shared_ptr<SimMarket>& simMarket, QuantLib::ext::shared_ptr<NPVCube>& outputCube,
65 QuantLib::ext::shared_ptr<NPVCube>& outputCubeNettingSet) {
66 outputCube->setT0(npv(tradeIndex, trade, simMarket), tradeIndex, index_);
67}
68
69Real NPVCalculator::npv(Size tradeIndex, const QuantLib::ext::shared_ptr<Trade>& trade,
70 const QuantLib::ext::shared_ptr<SimMarket>& simMarket) {
71 Real npv = trade->instrument()->NPV();
72 if (close_enough(npv, 0.0))
73 return npv;
74 Real fx = fxRates_[tradeCcyIndex_[tradeIndex]];
75 Real numeraire = simMarket->numeraire();
76 return npv * fx / numeraire;
77}
78
79void CashflowCalculator::init(const QuantLib::ext::shared_ptr<Portfolio>& portfolio,
80 const QuantLib::ext::shared_ptr<SimMarket>& simMarket) {
81 DLOG("init CashflowCalculator");
83 std::set<std::string> ccys;
84 for (auto const& [tradeId,trade] : portfolio->trades()) {
85 tradeAndLegCcyIndex_.push_back(std::vector<Size>(trade->legs().size()));
86 for (auto const& l : trade->legCurrencies()) {
87 ccys.insert(l);
88 }
89 }
90 size_t i = 0;
91 for (const auto& [tradeId, trade] : portfolio->trades()) {
92 for (Size j = 0; j < trade->legs().size(); ++j) {
94 std::distance(ccys.begin(), ccys.find(trade->legCurrencies()[j]));
95 }
96 i++;
97 }
98 ccyQuotes_.resize(ccys.size());
99 for (Size i = 0; i < ccys.size(); ++i)
100 ccyQuotes_[i] = (simMarket->fxRate(*std::next(ccys.begin(), i) + baseCcyCode_));
101 fxRates_.resize(ccys.size());
102}
103
105 for (Size i = 0; i < ccyQuotes_.size(); ++i)
106 fxRates_[i] = ccyQuotes_[i]->value();
107}
108
109void CashflowCalculator::calculate(const QuantLib::ext::shared_ptr<Trade>& trade, Size tradeIndex,
110 const QuantLib::ext::shared_ptr<SimMarket>& simMarket,
111 QuantLib::ext::shared_ptr<NPVCube>& outputCube,
112 QuantLib::ext::shared_ptr<NPVCube>& outputCubeNettingSet, const Date& date, Size dateIndex,
113 Size sample, bool isCloseOut) {
114 if (isCloseOut)
115 return;
116
117 Real netPositiveFlow = 0;
118 Real netNegativeFlow = 0;
119
120 QL_REQUIRE(dateGrid_->valuationDates()[dateIndex] == date, "Date mixup, date is " << date << " but grid index is "
121 << dateIndex << ", grid(dateIndex) is "
122 << dateGrid_->dates()[dateIndex]);
123 // Date startDate = dateIndex == 0 ? t0Date_ : dateGrid_->dates()[dateIndex - 1];
124 Date startDate = date;
125 Date endDate = date == dateGrid_->dates().back() ? date : dateGrid_->dates()[dateIndex + 1];
126
127 bool isOption = trade->instrument()->isOption();
128 bool isExercised = false;
129 bool isPhysical = false;
130 Real longShort = 1.0;
131 if (isOption) {
132 QuantLib::ext::shared_ptr<data::OptionWrapper> wrapper =
133 QuantLib::ext::dynamic_pointer_cast<data::OptionWrapper>(trade->instrument());
134 isExercised = wrapper->isExercised();
135 longShort = wrapper->isLong() ? 1.0 : -1.0;
136 isPhysical = wrapper->isPhysicalDelivery();
137 }
138
139 try {
140 if (!isOption || (isExercised && isPhysical)) {
141 for (Size i = 0; i < trade->legs().size(); i++) {
142 const Leg& leg = trade->legs()[i];
143 Real legFlow = 0;
144 for (auto flow : leg) {
145 // Take flows in (t, t+1]
146 if (startDate < flow->date() && flow->date() <= endDate)
147 legFlow += flow->amount();
148 }
149 if (legFlow != 0) {
150 // Do FX conversion and add to netFlow
151 Real fx = fxRates_[tradeAndLegCcyIndex_[tradeIndex][i]];
152 Real direction = trade->legPayers()[i] ? -1.0 : 1.0;
153 legFlow *= direction * longShort * fx;
154 if (legFlow > 0)
155 netPositiveFlow += legFlow;
156 else
157 netNegativeFlow += legFlow;
158 }
159 }
160 }
161 } catch (std::exception& e) {
162 ALOG("Failed to calculate cashflows for trade " << trade->id() << " : " << e.what());
163 netPositiveFlow = 0;
164 netNegativeFlow = 0;
165 } catch (...) {
166 ALOG("Failed to calculate cashflows for trade " << trade->id() << " : Unhandled Exception");
167 netPositiveFlow = 0;
168 netNegativeFlow = 0;
169 }
170
171 Real numeraire = simMarket->numeraire();
172
173 outputCube->set(netPositiveFlow / numeraire, tradeIndex, dateIndex, sample, index_);
174 outputCube->set(netNegativeFlow / numeraire, tradeIndex, dateIndex, sample, index_+1);
175}
176
177void NPVCalculatorFXT0::init(const QuantLib::ext::shared_ptr<Portfolio>& portfolio,
178 const QuantLib::ext::shared_ptr<SimMarket>& simMarket) {
179 DLOG("init NPVCalculatorFXT0");
180 tradeCcyIndex_.resize(portfolio->size());
181 std::set<std::string> ccys;
182 for (auto const& [tradeId, trade]: portfolio->trades())
183 ccys.insert(trade->npvCurrency());
184 size_t i = 0;
185 for (auto const& [tradeId, trade] : portfolio->trades()){
186 tradeCcyIndex_[i] = std::distance(ccys.begin(), ccys.find(trade->npvCurrency()));
187 i++;
188 }
189 fxRates_.resize(ccys.size());
190 for (Size i = 0; i < ccys.size(); ++i)
191 fxRates_[i] = t0Market_->fxRate(*std::next(ccys.begin(), i) + baseCcyCode_)->value();
192}
193
194void NPVCalculatorFXT0::calculate(const QuantLib::ext::shared_ptr<Trade>& trade, Size tradeIndex,
195 const QuantLib::ext::shared_ptr<SimMarket>& simMarket, QuantLib::ext::shared_ptr<NPVCube>& outputCube,
196 QuantLib::ext::shared_ptr<NPVCube>& outputCubeNettingSet, const Date& date, Size dateIndex,
197 Size sample, bool isCloseOut) {
198 if (!isCloseOut)
199 outputCube->set(npv(tradeIndex, trade, simMarket), tradeIndex, dateIndex, sample, index_);
200}
201
202void NPVCalculatorFXT0::calculateT0(const QuantLib::ext::shared_ptr<Trade>& trade, Size tradeIndex,
203 const QuantLib::ext::shared_ptr<SimMarket>& simMarket,
204 QuantLib::ext::shared_ptr<NPVCube>& outputCube,
205 QuantLib::ext::shared_ptr<NPVCube>& outputCubeNettingSet) {
206 outputCube->setT0(npv(tradeIndex, trade, simMarket), tradeIndex, index_);
207}
208
209Real NPVCalculatorFXT0::npv(Size tradeIndex, const QuantLib::ext::shared_ptr<Trade>& trade,
210 const QuantLib::ext::shared_ptr<SimMarket>& simMarket) {
211 Real npv = trade->instrument()->NPV();
212 if (close_enough(npv, 0.0))
213 return npv;
214 Real fx = fxRates_[tradeCcyIndex_[tradeIndex]];
215 Real numeraire = simMarket->numeraire();
216 return npv * fx / numeraire;
217}
218
219} // namespace analytics
220} // namespace ore
void init(const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< SimMarket > &simMarket) override
virtual void calculate(const QuantLib::ext::shared_ptr< Trade > &trade, Size tradeIndex, const QuantLib::ext::shared_ptr< SimMarket > &simMarket, QuantLib::ext::shared_ptr< NPVCube > &outputCube, QuantLib::ext::shared_ptr< NPVCube > &outputCubeNettingSet, const Date &date, Size dateIndex, Size sample, bool isCloseOut=false) override
std::vector< std::vector< Size > > tradeAndLegCcyIndex_
QuantLib::ext::shared_ptr< DateGrid > dateGrid_
std::vector< Handle< Quote > > ccyQuotes_
virtual void calculateT0(const QuantLib::ext::shared_ptr< Trade > &trade, Size tradeIndex, const QuantLib::ext::shared_ptr< SimMarket > &simMarket, QuantLib::ext::shared_ptr< NPVCube > &outputCube, QuantLib::ext::shared_ptr< NPVCube > &outputCubeNettingSet) override
QuantLib::ext::shared_ptr< Market > t0Market_
Real npv(Size tradeIndex, const QuantLib::ext::shared_ptr< Trade > &trade, const QuantLib::ext::shared_ptr< SimMarket > &simMarket)
void init(const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< SimMarket > &simMarket) override
virtual void calculate(const QuantLib::ext::shared_ptr< Trade > &trade, Size tradeIndex, const QuantLib::ext::shared_ptr< SimMarket > &simMarket, QuantLib::ext::shared_ptr< NPVCube > &outputCube, QuantLib::ext::shared_ptr< NPVCube > &outputCubeNettingSet, const Date &date, Size dateIndex, Size sample, bool isCloseOut=false) override
virtual void calculateT0(const QuantLib::ext::shared_ptr< Trade > &trade, Size tradeIndex, const QuantLib::ext::shared_ptr< SimMarket > &simMarket, QuantLib::ext::shared_ptr< NPVCube > &outputCube, QuantLib::ext::shared_ptr< NPVCube > &outputCubeNettingSet) override
virtual Real npv(Size tradeIndex, const QuantLib::ext::shared_ptr< Trade > &trade, const QuantLib::ext::shared_ptr< SimMarket > &simMarket)
void init(const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< SimMarket > &simMarket) override
virtual void calculate(const QuantLib::ext::shared_ptr< Trade > &trade, Size tradeIndex, const QuantLib::ext::shared_ptr< SimMarket > &simMarket, QuantLib::ext::shared_ptr< NPVCube > &outputCube, QuantLib::ext::shared_ptr< NPVCube > &outputCubeNettingSet, const Date &date, Size dateIndex, Size sample, bool isCloseOut=false) override
std::vector< Handle< Quote > > ccyQuotes_
SafeStack< ValueType > value
#define DLOG(text)
#define ALOG(text)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Size size(const ValueType &v)
The counterparty cube calculator interface.