A further simplification of -V and -X
With -X COMM, all values are computed in terms of COMM, regardless. With -V, only secondary commodities will ever be computed, never primaries. Further, if a secondary commodities has an associated price, the valuation is done in terms of that price's commodity.
This commit is contained in:
parent
ae8ab81062
commit
be6cef93c4
14 changed files with 64 additions and 68 deletions
|
|
@ -724,8 +724,7 @@ void amount_t::in_place_unreduce()
|
|||
}
|
||||
|
||||
optional<amount_t>
|
||||
amount_t::value(const bool primary_only,
|
||||
const optional<datetime_t>& moment,
|
||||
amount_t::value(const optional<datetime_t>& moment,
|
||||
const optional<commodity_t&>& in_terms_of) const
|
||||
{
|
||||
if (quantity) {
|
||||
|
|
@ -740,28 +739,33 @@ amount_t::value(const bool primary_only,
|
|||
"amount_t::value: in_terms_of = " << in_terms_of->symbol());
|
||||
#endif
|
||||
if (has_commodity() &&
|
||||
(! primary_only || ! commodity().has_flags(COMMODITY_PRIMARY))) {
|
||||
if (in_terms_of &&
|
||||
commodity().referent() == in_terms_of->referent()) {
|
||||
(in_terms_of || ! commodity().has_flags(COMMODITY_PRIMARY))) {
|
||||
optional<price_point_t> point;
|
||||
optional<commodity_t&> comm(in_terms_of);
|
||||
|
||||
if (comm && commodity().referent() == comm->referent()) {
|
||||
return *this;
|
||||
}
|
||||
else if (has_annotation() && annotation().price &&
|
||||
annotation().has_flags(ANNOTATION_PRICE_FIXATED)) {
|
||||
amount_t price(*annotation().price);
|
||||
price.multiply(*this, true);
|
||||
price.in_place_round();
|
||||
return price;
|
||||
else if (has_annotation() && annotation().price) {
|
||||
if (annotation().has_flags(ANNOTATION_PRICE_FIXATED)) {
|
||||
point = price_point_t();
|
||||
point->price = *annotation().price;
|
||||
}
|
||||
else if (! in_terms_of) {
|
||||
comm = annotation().price->commodity();
|
||||
}
|
||||
}
|
||||
|
||||
if (! point) {
|
||||
point = commodity().find_price(comm, moment);
|
||||
// Whether a price was found or not, check whether we should attempt
|
||||
// to download a price from the Internet. This is done if (a) no
|
||||
// price was found, or (b) the price is "stale" according to the
|
||||
// setting of --price-exp.
|
||||
if (point)
|
||||
point = commodity().check_for_updated_price(point, moment, comm);
|
||||
}
|
||||
else {
|
||||
optional<price_point_t> point =
|
||||
commodity().find_price(in_terms_of, moment);
|
||||
|
||||
// Whether a price was found or not, check whether we should
|
||||
// attempt to download a price from the Internet. This is done
|
||||
// if (a) no price was found, or (b) the price is "stale"
|
||||
// according to the setting of --price-exp.
|
||||
point = commodity().check_for_updated_price(point, moment,
|
||||
in_terms_of);
|
||||
if (point) {
|
||||
amount_t price(point->price);
|
||||
price.multiply(*this, true);
|
||||
|
|
@ -769,7 +773,6 @@ amount_t::value(const bool primary_only,
|
|||
return price;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw_(amount_error,
|
||||
_("Cannot determine value of an uninitialized amount"));
|
||||
|
|
|
|||
|
|
@ -399,8 +399,7 @@ public:
|
|||
$100.00.
|
||||
*/
|
||||
optional<amount_t>
|
||||
value(const bool primary_only = true,
|
||||
const optional<datetime_t>& moment = none,
|
||||
value(const optional<datetime_t>& moment = none,
|
||||
const optional<commodity_t&>& in_terms_of = none) const;
|
||||
|
||||
amount_t price() const;
|
||||
|
|
|
|||
|
|
@ -185,16 +185,14 @@ balance_t& balance_t::operator/=(const amount_t& amt)
|
|||
}
|
||||
|
||||
optional<balance_t>
|
||||
balance_t::value(const bool primary_only,
|
||||
const optional<datetime_t>& moment,
|
||||
balance_t::value(const optional<datetime_t>& moment,
|
||||
const optional<commodity_t&>& in_terms_of) const
|
||||
{
|
||||
balance_t temp;
|
||||
bool resolved = false;
|
||||
|
||||
foreach (const amounts_map::value_type& pair, amounts) {
|
||||
if (optional<amount_t> val = pair.second.value(primary_only, moment,
|
||||
in_terms_of)) {
|
||||
if (optional<amount_t> val = pair.second.value(moment, in_terms_of)) {
|
||||
temp += *val;
|
||||
resolved = true;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -384,8 +384,7 @@ public:
|
|||
}
|
||||
|
||||
optional<balance_t>
|
||||
value(const bool primary_only = false,
|
||||
const optional<datetime_t>& moment = none,
|
||||
value(const optional<datetime_t>& moment = none,
|
||||
const optional<commodity_t&>& in_terms_of = none) const;
|
||||
|
||||
balance_t price() const;
|
||||
|
|
|
|||
|
|
@ -264,10 +264,6 @@ commodity_t::varied_history_t::find_price(const commodity_t& source,
|
|||
if (comm == source)
|
||||
continue;
|
||||
|
||||
// Only value secondary commodities in terms of primary ones
|
||||
if (! commodity && ! comm.has_flags(COMMODITY_PRIMARY))
|
||||
continue;
|
||||
|
||||
DEBUG_INDENT("commodity.prices.find", indent + 1);
|
||||
DEBUG("commodity.prices.find",
|
||||
"searching for price via commodity '" << comm << "'");
|
||||
|
|
@ -370,8 +366,7 @@ commodity_t::find_price(const optional<commodity_t&>& commodity,
|
|||
#endif
|
||||
) const
|
||||
{
|
||||
if (! has_flags(COMMODITY_WALKED) && base->varied_history &&
|
||||
(commodity || ! has_flags(COMMODITY_PRIMARY))) {
|
||||
if (! has_flags(COMMODITY_WALKED) && base->varied_history) {
|
||||
optional<base_t::time_and_commodity_t> pair;
|
||||
#if defined(VERIFY_ON)
|
||||
optional<price_point_t> checkpoint;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ struct price_point_t
|
|||
datetime_t when;
|
||||
amount_t price;
|
||||
|
||||
price_point_t() {}
|
||||
price_point_t(datetime_t _when, amount_t _price)
|
||||
: when(_when), price(_price) {}
|
||||
|
||||
bool operator==(const price_point_t& other) const {
|
||||
return when == other.when && price == other.price;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,16 +45,16 @@ using namespace boost::python;
|
|||
namespace {
|
||||
|
||||
boost::optional<amount_t> py_value_0(const amount_t& amount) {
|
||||
return amount.value(false, CURRENT_TIME());
|
||||
return amount.value(CURRENT_TIME());
|
||||
}
|
||||
boost::optional<amount_t> py_value_1(const amount_t& amount,
|
||||
commodity_t& in_terms_of) {
|
||||
return amount.value(false, CURRENT_TIME(), in_terms_of);
|
||||
return amount.value(CURRENT_TIME(), in_terms_of);
|
||||
}
|
||||
boost::optional<amount_t> py_value_2(const amount_t& amount,
|
||||
commodity_t& in_terms_of,
|
||||
datetime_t& moment) {
|
||||
return amount.value(false, moment, in_terms_of);
|
||||
return amount.value(moment, in_terms_of);
|
||||
}
|
||||
|
||||
void py_parse_2(amount_t& amount, object in, unsigned char flags) {
|
||||
|
|
|
|||
|
|
@ -45,16 +45,16 @@ using namespace boost::python;
|
|||
namespace {
|
||||
|
||||
boost::optional<balance_t> py_value_0(const balance_t& balance) {
|
||||
return balance.value(false, CURRENT_TIME());
|
||||
return balance.value(CURRENT_TIME());
|
||||
}
|
||||
boost::optional<balance_t> py_value_1(const balance_t& balance,
|
||||
commodity_t& in_terms_of) {
|
||||
return balance.value(false, CURRENT_TIME(), in_terms_of);
|
||||
return balance.value(CURRENT_TIME(), in_terms_of);
|
||||
}
|
||||
boost::optional<balance_t> py_value_2(const balance_t& balance,
|
||||
commodity_t& in_terms_of,
|
||||
datetime_t& moment) {
|
||||
return balance.value(false, moment, in_terms_of);
|
||||
return balance.value(moment, in_terms_of);
|
||||
}
|
||||
|
||||
boost::optional<amount_t>
|
||||
|
|
|
|||
|
|
@ -48,16 +48,16 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(set_string_overloads, set_string, 0, 2)
|
|||
namespace {
|
||||
|
||||
boost::optional<value_t> py_value_0(const value_t& value) {
|
||||
return value.value(false, CURRENT_TIME());
|
||||
return value.value(CURRENT_TIME());
|
||||
}
|
||||
boost::optional<value_t> py_value_1(const value_t& value,
|
||||
commodity_t& in_terms_of) {
|
||||
return value.value(false, CURRENT_TIME(), in_terms_of);
|
||||
return value.value(CURRENT_TIME(), in_terms_of);
|
||||
}
|
||||
boost::optional<value_t> py_value_2(const value_t& value,
|
||||
commodity_t& in_terms_of,
|
||||
datetime_t& moment) {
|
||||
return value.value(false, moment, in_terms_of);
|
||||
return value.value(moment, in_terms_of);
|
||||
}
|
||||
|
||||
PyObject * py_base_type(value_t& value)
|
||||
|
|
|
|||
|
|
@ -466,7 +466,7 @@ value_t report_t::fn_market(call_scope_t& scope)
|
|||
/* add_prices= */ false,
|
||||
moment);
|
||||
else
|
||||
result = args.value_at(0).value(true, moment);
|
||||
result = args.value_at(0).value(moment);
|
||||
|
||||
if (! result.is_null())
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -1401,8 +1401,7 @@ bool value_t::is_zero() const
|
|||
return false;
|
||||
}
|
||||
|
||||
value_t value_t::value(const bool primary_only,
|
||||
const optional<datetime_t>& moment,
|
||||
value_t value_t::value(const optional<datetime_t>& moment,
|
||||
const optional<commodity_t&>& in_terms_of) const
|
||||
{
|
||||
switch (type()) {
|
||||
|
|
@ -1411,13 +1410,13 @@ value_t value_t::value(const bool primary_only,
|
|||
|
||||
case AMOUNT:
|
||||
if (optional<amount_t> val =
|
||||
as_amount().value(primary_only, moment, in_terms_of))
|
||||
as_amount().value(moment, in_terms_of))
|
||||
return *val;
|
||||
return NULL_VALUE;
|
||||
|
||||
case BALANCE:
|
||||
if (optional<balance_t> bal =
|
||||
as_balance().value(primary_only, moment, in_terms_of))
|
||||
as_balance().value(moment, in_terms_of))
|
||||
return *bal;
|
||||
return NULL_VALUE;
|
||||
|
||||
|
|
@ -1455,7 +1454,7 @@ value_t value_t::exchange_commodities(const std::string& commodities,
|
|||
if (commodity_t * commodity =
|
||||
commodity_pool_t::current_pool->parse_price_expression(p, add_prices,
|
||||
moment)) {
|
||||
value_t result = value(false, moment, *commodity);
|
||||
value_t result = value(moment, *commodity);
|
||||
if (! result.is_null())
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -476,8 +476,7 @@ public:
|
|||
void in_place_unreduce(); // exists for efficiency's sake
|
||||
|
||||
// Return the "market value" of a given value at a specific time.
|
||||
value_t value(const bool primary_only = false,
|
||||
const optional<datetime_t>& moment = none,
|
||||
value_t value(const optional<datetime_t>& moment = none,
|
||||
const optional<commodity_t&>& in_terms_of = none) const;
|
||||
|
||||
value_t price() const;
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@
|
|||
>>>2
|
||||
While parsing file "$sourcepath/src/amount.h", line 66:
|
||||
Error: No quantity specified for amount
|
||||
While parsing file "$sourcepath/src/amount.h", line 726:
|
||||
While parsing file "$sourcepath/src/amount.h", line 725:
|
||||
Error: Invalid date/time: line amount_t amoun
|
||||
While parsing file "$sourcepath/src/amount.h", line 732:
|
||||
While parsing file "$sourcepath/src/amount.h", line 731:
|
||||
Error: Invalid date/time: line string amount_
|
||||
While parsing file "$sourcepath/src/amount.h", line 738:
|
||||
While parsing file "$sourcepath/src/amount.h", line 737:
|
||||
Error: Invalid date/time: line string amount_
|
||||
While parsing file "$sourcepath/src/amount.h", line 744:
|
||||
While parsing file "$sourcepath/src/amount.h", line 743:
|
||||
Error: Invalid date/time: line string amount_
|
||||
While parsing file "$sourcepath/src/amount.h", line 750:
|
||||
While parsing file "$sourcepath/src/amount.h", line 749:
|
||||
Error: Invalid date/time: line std::ostream&
|
||||
While parsing file "$sourcepath/src/amount.h", line 757:
|
||||
While parsing file "$sourcepath/src/amount.h", line 756:
|
||||
Error: Invalid date/time: line std::istream&
|
||||
=== 7
|
||||
|
|
|
|||
|
|
@ -73,11 +73,11 @@ void CommodityTestCase::testPriceHistory()
|
|||
cad.add_price(jan17_06, amount_t("$1.11"));
|
||||
|
||||
#ifndef NOT_FOR_PYTHON
|
||||
optional<amount_t> amt = x1.value(false, feb28_07sbm);
|
||||
optional<amount_t> amt = x1.value(feb28_07sbm);
|
||||
assertTrue(amt);
|
||||
assertEqual(amount_t("$1831.83"), *amt);
|
||||
|
||||
amt = x1.value(false, CURRENT_TIME());
|
||||
amt = x1.value(CURRENT_TIME());
|
||||
assertTrue(amt);
|
||||
assertEqual(string("$2124.12"), amt->to_string());
|
||||
#ifdef INTEGER_MATH
|
||||
|
|
@ -86,18 +86,18 @@ void CommodityTestCase::testPriceHistory()
|
|||
assertEqual(string("$2124.122"), amt->to_fullstring());
|
||||
#endif
|
||||
|
||||
amt = x1.value(false, CURRENT_TIME(), euro);
|
||||
amt = x1.value(CURRENT_TIME(), euro);
|
||||
assertTrue(amt);
|
||||
assertEqual(string("EUR 1366.87"), amt->rounded().to_string());
|
||||
|
||||
// Add a newer Euro pricing
|
||||
aapl.add_price(jan17_07, amount_t("EUR 23.00"));
|
||||
|
||||
amt = x1.value(false, CURRENT_TIME(), euro);
|
||||
amt = x1.value(CURRENT_TIME(), euro);
|
||||
assertTrue(amt);
|
||||
assertEqual(string("EUR 2302.30"), amt->to_string());
|
||||
|
||||
amt = x1.value(false, CURRENT_TIME(), cad);
|
||||
amt = x1.value(CURRENT_TIME(), cad);
|
||||
assertTrue(amt);
|
||||
assertEqual(string("CAD 3223.22"), amt->to_string());
|
||||
#endif // NOT_FOR_PYTHON
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue