1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2004 Decillion Pty(Ltd)
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 <http://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/money.hpp>
22#include <ql/currencies/exchangeratemanager.hpp>
23#include <ql/math/comparison.hpp>
24
25#include <boost/format.hpp>
26
27namespace QuantLib {
28
29 namespace {
30
31 void convertTo(Money& m, const Currency& target) {
32 if (m.currency() != target) {
33 ExchangeRate rate =
34 ExchangeRateManager::instance().lookup(source: m.currency(),
35 target);
36 m = rate.exchange(amount: m).rounded();
37 }
38 }
39
40 void convertToBase(Money& m) {
41 const auto & base_currency =
42 Money::Settings::instance().baseCurrency();
43 QL_REQUIRE(!base_currency.empty(), "no base currency set");
44 convertTo(m, target: base_currency);
45 }
46
47 }
48
49 Money& Money::operator+=(const Money& m) {
50 const auto & conversion_type = Settings::instance().conversionType();
51 if (currency_ == m.currency_) {
52 value_ += m.value_;
53 } else if (conversion_type == Money::BaseCurrencyConversion) {
54 convertToBase(m&: *this);
55 Money tmp = m;
56 convertToBase(m&: tmp);
57 *this += tmp;
58 } else if (conversion_type == Money::AutomatedConversion) {
59 Money tmp = m;
60 convertTo(m&: tmp, target: currency_);
61 *this += tmp;
62 } else {
63 QL_FAIL("currency mismatch and no conversion specified");
64 }
65 return *this;
66 }
67
68 Money& Money::operator-=(const Money& m) {
69 const auto & conversion_type = Settings::instance().conversionType();
70 if (currency_ == m.currency_) {
71 value_ -= m.value_;
72 } else if (conversion_type == Money::BaseCurrencyConversion) {
73 convertToBase(m&: *this);
74 Money tmp = m;
75 convertToBase(m&: tmp);
76 *this -= tmp;
77 } else if (conversion_type == Money::AutomatedConversion) {
78 Money tmp = m;
79 convertTo(m&: tmp, target: currency_);
80 *this -= tmp;
81 } else {
82 QL_FAIL("currency mismatch and no conversion specified");
83 }
84 return *this;
85 }
86
87 Decimal operator/(const Money& m1, const Money& m2) {
88 const auto & conversion_type =
89 Money::Settings::instance().conversionType();
90 if (m1.currency() == m2.currency()) {
91 return m1.value()/m2.value();
92 } else if (conversion_type == Money::BaseCurrencyConversion) {
93 Money tmp1 = m1;
94 convertToBase(m&: tmp1);
95 Money tmp2 = m2;
96 convertToBase(m&: tmp2);
97 return tmp1/tmp2;
98 } else if (conversion_type == Money::AutomatedConversion) {
99 Money tmp = m2;
100 convertTo(m&: tmp, target: m1.currency());
101 return m1/tmp;
102 } else {
103 QL_FAIL("currency mismatch and no conversion specified");
104 }
105 }
106
107 bool operator==(const Money& m1, const Money& m2) {
108 const auto & conversion_type =
109 Money::Settings::instance().conversionType();
110 if (m1.currency() == m2.currency()) {
111 return m1.value() == m2.value();
112 } else if (conversion_type == Money::BaseCurrencyConversion) {
113 Money tmp1 = m1;
114 convertToBase(m&: tmp1);
115 Money tmp2 = m2;
116 convertToBase(m&: tmp2);
117 return tmp1 == tmp2;
118 } else if (conversion_type == Money::AutomatedConversion) {
119 Money tmp = m2;
120 convertTo(m&: tmp, target: m1.currency());
121 return m1 == tmp;
122 } else {
123 QL_FAIL("currency mismatch and no conversion specified");
124 }
125 }
126
127 bool operator<(const Money& m1, const Money& m2) {
128 const auto & conversion_type =
129 Money::Settings::instance().conversionType();
130 if (m1.currency() == m2.currency()) {
131 return m1.value() < m2.value();
132 } else if (conversion_type == Money::BaseCurrencyConversion) {
133 Money tmp1 = m1;
134 convertToBase(m&: tmp1);
135 Money tmp2 = m2;
136 convertToBase(m&: tmp2);
137 return tmp1 < tmp2;
138 } else if (conversion_type == Money::AutomatedConversion) {
139 Money tmp = m2;
140 convertTo(m&: tmp, target: m1.currency());
141 return m1 < tmp;
142 } else {
143 QL_FAIL("currency mismatch and no conversion specified");
144 }
145 }
146
147 bool operator<=(const Money& m1, const Money& m2) {
148 const auto & conversion_type =
149 Money::Settings::instance().conversionType();
150 if (m1.currency() == m2.currency()) {
151 return m1.value() <= m2.value();
152 } else if (conversion_type == Money::BaseCurrencyConversion) {
153 Money tmp1 = m1;
154 convertToBase(m&: tmp1);
155 Money tmp2 = m2;
156 convertToBase(m&: tmp2);
157 return tmp1 <= tmp2;
158 } else if (conversion_type == Money::AutomatedConversion) {
159 Money tmp = m2;
160 convertTo(m&: tmp, target: m1.currency());
161 return m1 <= tmp;
162 } else {
163 QL_FAIL("currency mismatch and no conversion specified");
164 }
165 }
166
167 bool close(const Money& m1, const Money& m2, Size n) {
168 const auto & conversion_type =
169 Money::Settings::instance().conversionType();
170 if (m1.currency() == m2.currency()) {
171 return close(x: m1.value(),y: m2.value(),n);
172 } else if (conversion_type == Money::BaseCurrencyConversion) {
173 Money tmp1 = m1;
174 convertToBase(m&: tmp1);
175 Money tmp2 = m2;
176 convertToBase(m&: tmp2);
177 return close(m1: tmp1,m2: tmp2,n);
178 } else if (conversion_type == Money::AutomatedConversion) {
179 Money tmp = m2;
180 convertTo(m&: tmp, target: m1.currency());
181 return close(m1,m2: tmp,n);
182 } else {
183 QL_FAIL("currency mismatch and no conversion specified");
184 }
185 }
186
187 bool close_enough(const Money& m1, const Money& m2, Size n) {
188 const auto & conversion_type =
189 Money::Settings::instance().conversionType();
190 if (m1.currency() == m2.currency()) {
191 return close_enough(x: m1.value(),y: m2.value(),n);
192 } else if (conversion_type == Money::BaseCurrencyConversion) {
193 Money tmp1 = m1;
194 convertToBase(m&: tmp1);
195 Money tmp2 = m2;
196 convertToBase(m&: tmp2);
197 return close_enough(m1: tmp1,m2: tmp2,n);
198 } else if (conversion_type == Money::AutomatedConversion) {
199 Money tmp = m2;
200 convertTo(m&: tmp, target: m1.currency());
201 return close_enough(m1,m2: tmp,n);
202 } else {
203 QL_FAIL("currency mismatch and no conversion specified");
204 }
205 }
206
207
208 std::ostream& operator<<(std::ostream& out, const Money& m) {
209 boost::format fmt(m.currency().format());
210 fmt.exceptions(newexcept: boost::io::all_error_bits ^
211 boost::io::too_many_args_bit);
212 return out << fmt % m.rounded().value()
213 % m.currency().code()
214 % m.currency().symbol();
215 }
216
217
218 const Money::ConversionType & Money::Settings::conversionType() const
219 {
220 return conversionType_;
221 }
222
223 Money::ConversionType & Money::Settings::conversionType()
224 {
225 return conversionType_;
226 }
227
228 const Currency & Money::Settings::baseCurrency() const
229 {
230 return baseCurrency_;
231 }
232
233 Currency & Money::Settings::baseCurrency()
234 {
235 return baseCurrency_;
236 }
237
238 Money::BaseCurrencyProxy& Money::BaseCurrencyProxy::operator=(const Currency& c) {
239 Money::Settings::instance().baseCurrency() = c;
240 return *this;
241 }
242
243 Money::BaseCurrencyProxy::operator Currency() const {
244 return Money::Settings::instance().baseCurrency();
245 }
246
247 Money::ConversionTypeProxy& Money::ConversionTypeProxy::operator=(ConversionType t) {
248 Money::Settings::instance().conversionType() = t;
249 return *this;
250 }
251
252 Money::ConversionTypeProxy::operator Money::ConversionType() const {
253 return Money::Settings::instance().conversionType();
254 }
255
256}
257

source code of quantlib/ql/money.cpp

Morty Proxy This is a proxified and sanitized view of the page, visit original site.