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:
John Wiegley 2010-06-07 09:49:17 -04:00
parent ae8ab81062
commit be6cef93c4
14 changed files with 64 additions and 68 deletions

View file

@ -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"));

View file

@ -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;

View file

@ -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 {

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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) {

View file

@ -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>

View file

@ -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)

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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

View file

@ -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