1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2008 J. Erik Radmall
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include <ql/currencies/exchangeratemanager.hpp>
21#include <ql/experimental/commodities/commoditysettings.hpp>
22#include <ql/experimental/commodities/energycommodity.hpp>
23#include <ql/experimental/commodities/unitofmeasureconversionmanager.hpp>
24#include <iomanip>
25#include <utility>
26
27namespace QuantLib {
28
29 EnergyDailyPosition::EnergyDailyPosition(const Date& date,
30 Real payLegPrice,
31 Real receiveLegPrice,
32 bool unrealized)
33 : date(date), quantityAmount(0), payLegPrice(payLegPrice),
34 receiveLegPrice(receiveLegPrice), unrealized(unrealized) {}
35
36 std::ostream& operator<<(std::ostream& out,
37 const EnergyDailyPositions& dailyPositions) {
38 out << std::setw(12) << std::left << "positions"
39 << std::setw(12) << std::right << "pay"
40 << std::setw(12) << std::right << "receive"
41 << std::setw(10) << std::right << "qty"
42 << std::setw(14) << std::right << "delta"
43 << std::setw(10) << std::right << "open" << std::endl;
44
45 for (const auto& i : dailyPositions) {
46 const EnergyDailyPosition& dailyPosition = i.second;
47 out << std::setw(4) << io::iso_date(i.first) << " " << std::setw(12) << std::right
48 << std::fixed << std::setprecision(6) << dailyPosition.payLegPrice << std::setw(12)
49 << std::right << std::fixed << std::setprecision(6) << dailyPosition.receiveLegPrice
50 << std::setw(10) << std::right << std::fixed << std::setprecision(2)
51 << dailyPosition.quantityAmount << std::setw(14) << std::right << std::fixed
52 << std::setprecision(2) << dailyPosition.riskDelta << std::setw(10) << std::right
53 << std::fixed << std::setprecision(2)
54 << (dailyPosition.unrealized ? dailyPosition.quantityAmount : 0) << std::endl;
55 }
56
57 return out;
58 }
59
60
61
62
63
64 void EnergyCommodity::setupArguments(PricingEngine::arguments* args) const {
65 auto* arguments = dynamic_cast<EnergyCommodity::arguments*>(args);
66 QL_REQUIRE(arguments != nullptr, "wrong argument type");
67 //arguments->legs = legs_;
68 //arguments->payer = payer_;
69 }
70
71 void EnergyCommodity::fetchResults(const PricingEngine::results* r) const {
72 Instrument::fetchResults(r);
73 const auto* results = dynamic_cast<const EnergyCommodity::results*>(r);
74 QL_REQUIRE(results != nullptr, "wrong result type");
75 }
76
77 EnergyCommodity::EnergyCommodity(CommodityType commodityType,
78 const ext::shared_ptr<SecondaryCosts>& secondaryCosts)
79 : Commodity(secondaryCosts), commodityType_(std::move(commodityType)) {}
80
81 const CommodityType& EnergyCommodity::commodityType() const {
82 return commodityType_;
83 }
84
85
86 Real EnergyCommodity::calculateUomConversionFactor(
87 const CommodityType& commodityType,
88 const UnitOfMeasure& fromUnitOfMeasure,
89 const UnitOfMeasure& toUnitOfMeasure) {
90 if (toUnitOfMeasure != fromUnitOfMeasure) {
91 UnitOfMeasureConversion uomConv =
92 UnitOfMeasureConversionManager::instance().lookup(
93 commodityType, fromUnitOfMeasure, toUnitOfMeasure);
94 return uomConv.conversionFactor();
95 }
96
97 return 1;
98 }
99
100 Real EnergyCommodity::calculateFxConversionFactor(
101 const Currency& fromCurrency,
102 const Currency& toCurrency,
103 const Date& evaluationDate) {
104 if (fromCurrency != toCurrency) {
105 ExchangeRate exchRate = ExchangeRateManager::instance().lookup(
106 source: fromCurrency, target: toCurrency,
107 date: evaluationDate /*, ExchangeRate::Direct*/);
108 if (fromCurrency == exchRate.target())
109 return 1.0 / exchRate.rate();
110 return exchRate.rate();
111 }
112 return 1;
113 }
114
115 Real EnergyCommodity::calculateUnitCost(const CommodityType& commodityType,
116 const CommodityUnitCost& unitCost,
117 const Date& evaluationDate) const {
118 if (unitCost.amount().value() != 0) {
119 const Currency& baseCurrency =
120 CommoditySettings::instance().currency();
121 const UnitOfMeasure baseUnitOfMeasure =
122 CommoditySettings::instance().unitOfMeasure();
123 Real unitCostUomConversionFactor =
124 calculateUomConversionFactor(commodityType,
125 fromUnitOfMeasure: unitCost.unitOfMeasure(),
126 toUnitOfMeasure: baseUnitOfMeasure);
127 Real unitCostFxConversionFactor =
128 calculateFxConversionFactor(fromCurrency: unitCost.amount().currency(),
129 toCurrency: baseCurrency, evaluationDate);
130 return unitCost.amount().value() * unitCostUomConversionFactor
131 * unitCostFxConversionFactor;
132 }
133 return 0;
134 }
135
136 void EnergyCommodity::calculateSecondaryCostAmounts(
137 const CommodityType& commodityType,
138 Real totalQuantityValue,
139 const Date& evaluationDate) const {
140 secondaryCostAmounts_.clear();
141 if (secondaryCosts_ != nullptr) {
142 const Currency& baseCurrency =
143 CommoditySettings::instance().currency();
144 try {
145 for (SecondaryCosts::const_iterator i = secondaryCosts_->begin();
146 i != secondaryCosts_->end(); ++i) {
147 if (ext::any_cast<CommodityUnitCost>(operand: &i->second) != nullptr) {
148 Real value =
149 calculateUnitCost(
150 commodityType,
151 unitCost: ext::any_cast<CommodityUnitCost>(operand: i->second),
152 evaluationDate) * totalQuantityValue;
153 secondaryCostAmounts_[i->first] =
154 Money(baseCurrency, value);
155 } else if (ext::any_cast<Money>(operand: &i->second) != nullptr) {
156 const Money& amount = ext::any_cast<Money>(operand: i->second);
157 Real fxConversionFactor =
158 calculateFxConversionFactor(fromCurrency: amount.currency(),
159 toCurrency: baseCurrency,
160 evaluationDate);
161 secondaryCostAmounts_[i->first] =
162 Money(baseCurrency,
163 amount.value() * fxConversionFactor);
164 }
165 }
166 } catch (const std::exception& e) {
167 QL_FAIL("error calculating secondary costs: " << e.what());
168 }
169 }
170 }
171
172}
173
174

source code of quantlib/ql/experimental/commodities/energycommodity.cpp