Many fixes to --market and --exchange

Also, --exchange now accepted multiple, comma-separated commodities.
This commit is contained in:
John Wiegley 2009-02-22 22:22:07 -04:00
parent ea418c7fbc
commit de6de07bac
8 changed files with 324 additions and 151 deletions

View file

@ -515,12 +515,25 @@ amount_t::value(const bool primary_only,
const optional<commodity_t&>& in_terms_of) const
{
if (quantity) {
#if defined(DEBUG_ON)
DEBUG("commodity.prices.find",
"amount_t::value of " << commodity().symbol());
if (moment)
DEBUG("commodity.prices.find",
"amount_t::value: moment = " << *moment);
if (in_terms_of)
DEBUG("commodity.prices.find",
"amount_t::value: in_terms_of = " << in_terms_of->symbol());
#endif
if (has_commodity() &&
(! primary_only || commodity().has_flags(COMMODITY_PRIMARY)) &&
(! in_terms_of || commodity() != *in_terms_of)) {
optional<price_point_t> point(commodity().find_price(in_terms_of, moment));
if (point)
(! primary_only || ! commodity().has_flags(COMMODITY_PRIMARY))) {
if (in_terms_of && commodity() == *in_terms_of) {
return *this;
}
else if (optional<price_point_t> point =
commodity().find_price(in_terms_of, moment)) {
return (point->price * number()).rounded();
}
}
} else {
throw_(amount_error, "Cannot determine value of an uninitialized amount");
@ -996,7 +1009,7 @@ void amount_t::print(std::ostream& _out) const
if (comm.annotated) {
annotated_commodity_t& ann(static_cast<annotated_commodity_t&>(comm));
assert(&*ann.details.price != this);
assert(! ann.details.price || &*ann.details.price != this);
ann.write_annotations(out);
}

View file

@ -38,8 +38,9 @@ void commodity_t::base_t::history_t::add_price(commodity_t& source,
const amount_t& price,
const bool reflexive)
{
DEBUG("commodity.prices",
"add_price to " << source << " : " << date << ", " << price);
DEBUG("commodity.prices.add", "add_price to " << source
<< (reflexive ? " (secondary)" : " (primary)")
<< " : " << date << ", " << price);
history_map::iterator i = prices.find(date);
if (i != prices.end()) {
@ -51,18 +52,19 @@ void commodity_t::base_t::history_t::add_price(commodity_t& source,
}
if (reflexive) {
if (! price.commodity().has_flags(COMMODITY_NOMARKET)) {
amount_t inverse = price.inverted();
inverse.set_commodity(const_cast<commodity_t&>(source));
price.commodity().add_price(date, inverse, false);
}
amount_t inverse = price.inverted();
inverse.set_commodity(const_cast<commodity_t&>(source));
price.commodity().add_price(date, inverse, false);
} else {
DEBUG("commodity.prices.add",
"marking commodity " << source.symbol() << " as primary");
source.add_flags(COMMODITY_PRIMARY);
}
}
bool commodity_t::base_t::history_t::remove_price(const datetime_t& date)
{
DEBUG("commodity.prices", "remove_price: " << date);
DEBUG("commodity.prices.add", "remove_price: " << date);
history_map::size_type n = prices.erase(date);
if (n > 0)
@ -93,7 +95,7 @@ void commodity_t::base_t::varied_history_t::
bool commodity_t::base_t::varied_history_t::remove_price(const datetime_t& date,
commodity_t& comm)
{
DEBUG("commodity.prices", "varied_remove_price: " << date << ", " << comm);
DEBUG("commodity.prices.add", "varied_remove_price: " << date << ", " << comm);
if (optional<history_t&> hist = history(comm))
return hist->remove_price(date);
@ -120,22 +122,22 @@ optional<price_point_t>
} while (false)
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG_INDENT("commodity.prices.find", indent);
if (moment)
DEBUG("commodity.prices", "find price nearest before or on: " << *moment);
DEBUG("commodity.prices.find", "find price nearest before or on: " << *moment);
else
DEBUG("commodity.prices", "find any price");
DEBUG("commodity.prices.find", "find any price");
if (oldest) {
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " but no older than: " << *oldest);
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " but no older than: " << *oldest);
}
#endif
if (prices.size() == 0) {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " there are no prices in this history");
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " there are no prices in this history");
#endif
return none;
}
@ -146,8 +148,8 @@ optional<price_point_t>
point.price = (*r).second;
found = true;
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " using most recent price");
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " using most recent price");
#endif
} else {
history_map::const_iterator i = prices.lower_bound(*moment);
@ -157,8 +159,8 @@ optional<price_point_t>
point.price = (*r).second;
found = true;
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " using last price");
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " using last price");
#endif
} else {
point.when = (*i).first;
@ -174,8 +176,8 @@ optional<price_point_t>
found = true;
}
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " using found price");
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " using found price");
#endif
}
}
@ -192,29 +194,29 @@ optional<price_point_t>
if (! found) {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " could not find a price");
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " could not find a price");
#endif
return none;
}
else if (moment && point.when > *moment) {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " price is too young ");
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " price is too young ");
#endif
return none;
}
else if (oldest && point.when < *oldest) {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " price is too old ");
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " price is too old ");
#endif
return none;
}
else {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices",
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find",
" returning price: " << point.when << ", " << point.price);
#endif
return point;
@ -238,23 +240,23 @@ optional<price_point_t>
assert(! commodity || source != *commodity);
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", "varied_find_price for: " << source);
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", "varied_find_price for: " << source);
DEBUG_INDENT("commodity.prices", indent);
DEBUG_INDENT("commodity.prices.find", indent);
if (commodity)
DEBUG("commodity.prices", " looking for: commodity '" << *commodity << "'");
DEBUG("commodity.prices.find", " looking for: commodity '" << *commodity << "'");
else
DEBUG("commodity.prices", " looking for: any commodity");
DEBUG("commodity.prices.find", " looking for: any commodity");
if (moment) {
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " time index: " << *moment);
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " time index: " << *moment);
}
if (oldest) {
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices", " only consider prices younger than: " << *oldest);
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find", " only consider prices younger than: " << *oldest);
}
#endif
@ -271,8 +273,8 @@ optional<price_point_t>
continue;
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent + 1);
DEBUG("commodity.prices",
DEBUG_INDENT("commodity.prices.find", indent + 1);
DEBUG("commodity.prices.find",
" searching for price via commodity '" << comm << "'");
#endif
@ -288,8 +290,8 @@ optional<price_point_t>
if (commodity && comm != *commodity) {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent + 1);
DEBUG("commodity.prices", " looking for translation price");
DEBUG_INDENT("commodity.prices.find", indent + 1);
DEBUG("commodity.prices.find", " looking for translation price");
#endif
xlat = comm.find_price(commodity, moment, limit
@ -299,8 +301,8 @@ optional<price_point_t>
);
if (xlat) {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent + 1);
DEBUG("commodity.prices", " found translated price "
DEBUG_INDENT("commodity.prices.find", indent + 1);
DEBUG("commodity.prices.find", " found translated price "
<< xlat->price << " from " << xlat->when);
#endif
@ -308,15 +310,15 @@ optional<price_point_t>
if (xlat->when < point->when) {
point->when = xlat->when;
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent + 1);
DEBUG("commodity.prices",
DEBUG_INDENT("commodity.prices.find", indent + 1);
DEBUG("commodity.prices.find",
" adjusting date of result back to " << point->when);
#endif
}
} else {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent + 1);
DEBUG("commodity.prices", " saw no translated price there");
DEBUG_INDENT("commodity.prices.find", indent + 1);
DEBUG("commodity.prices.find", " saw no translated price there");
#endif
continue;
}
@ -324,8 +326,8 @@ optional<price_point_t>
assert(! commodity || point->price.commodity() == *commodity);
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent + 1);
DEBUG("commodity.prices",
DEBUG_INDENT("commodity.prices.find", indent + 1);
DEBUG("commodity.prices.find",
" saw a price there: " << point->price << " from " << point->when);
#endif
if (! limit || point->when > *limit) {
@ -335,16 +337,16 @@ optional<price_point_t>
}
} else {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent + 1);
DEBUG("commodity.prices", " saw no price there");
DEBUG_INDENT("commodity.prices.find", indent + 1);
DEBUG("commodity.prices.find", " saw no price there");
#endif
}
}
if (found) {
#if defined(DEBUG_ON)
DEBUG_INDENT("commodity.prices", indent);
DEBUG("commodity.prices",
DEBUG_INDENT("commodity.prices.find", indent);
DEBUG("commodity.prices.find",
" found price " << best.price << " from " << best.when);
#endif
return best;
@ -381,16 +383,14 @@ void commodity_t::exchange(commodity_t& commodity,
const amount_t& per_unit_cost,
const datetime_t& moment)
{
if (! commodity.has_flags(COMMODITY_NOMARKET)) {
DEBUG("commodity.prices", "exchanging commodity " << commodity
<< " at per unit cost " << per_unit_cost << " on " << moment);
DEBUG("commodity.prices.add", "exchanging commodity " << commodity
<< " at per unit cost " << per_unit_cost << " on " << moment);
commodity_t& base_commodity
(commodity.annotated ?
as_annotated_commodity(commodity).referent() : commodity);
commodity_t& base_commodity
(commodity.annotated ?
as_annotated_commodity(commodity).referent() : commodity);
base_commodity.add_price(moment, per_unit_cost);
}
base_commodity.add_price(moment, per_unit_cost);
}
commodity_t::cost_breakdown_t
@ -400,17 +400,12 @@ commodity_t::exchange(const amount_t& amount,
const optional<datetime_t>& moment,
const optional<string>& tag)
{
// (let* ((commodity (amount-commodity amount))
// (current-annotation
// (and (annotated-commodity-p commodity)
// (commodity-annotation commodity)))
// (base-commodity (if (annotated-commodity-p commodity)
// (get-referent commodity)
// commodity))
// (per-unit-cost (or per-unit-cost
// (divide total-cost amount)))
// (total-cost (or total-cost
// (multiply per-unit-cost amount))))
DEBUG("commodity.prices.add", "exchange: " << amount << " for " << cost);
DEBUG("commodity.prices.add", "exchange: is-per-unit = " << is_per_unit);
if (moment)
DEBUG("commodity.prices.add", "exchange: moment = " << *moment);
if (tag)
DEBUG("commodity.prices.add", "exchange: tag = " << *tag);
commodity_t& commodity(amount.commodity());
@ -418,44 +413,33 @@ commodity_t::exchange(const amount_t& amount,
if (commodity.annotated)
current_annotation = &as_annotated_commodity(commodity).details;
commodity_t& base_commodity
(current_annotation ?
as_annotated_commodity(commodity).referent() : commodity);
amount_t per_unit_cost(is_per_unit ? cost : (cost / amount).unrounded());
amount_t per_unit_cost(is_per_unit ? cost : cost / amount);
DEBUG("commodity.prices.add", "exchange: per-unit-cost = " << per_unit_cost);
exchange(commodity, per_unit_cost, moment ? *moment : CURRENT_TIME());
cost_breakdown_t breakdown;
breakdown.final_cost = ! is_per_unit ? cost : cost * amount;
breakdown.final_cost = ! is_per_unit ? cost : (cost * amount).unrounded();
// Add a price history entry for this conversion if we know when it took
// place
// (if (and moment (not (commodity-no-market-price-p base-commodity)))
// (add-price base-commodity per-unit-cost moment))
if (moment && ! commodity.has_flags(COMMODITY_NOMARKET))
base_commodity.add_price(*moment, per_unit_cost);
// ;; returns: ANNOTATED-AMOUNT TOTAL-COST BASIS-COST
// (values (annotate-commodity
// amount
// (make-commodity-annotation :price per-unit-cost
// :date moment
// :tag tag))
// total-cost
// (if current-annotation
// (multiply (annotation-price current-annotation) amount)
// total-cost))))
DEBUG("commodity.prices.add",
"exchange: final-cost = " << breakdown.final_cost);
if (current_annotation && current_annotation->price)
breakdown.basis_cost = *current_annotation->price * amount;
breakdown.basis_cost = (*current_annotation->price * amount).unrounded();
else
breakdown.basis_cost = breakdown.final_cost;
DEBUG("commodity.prices.add",
"exchange: basis-cost = " << breakdown.basis_cost);
breakdown.amount =
amount_t(amount, annotation_t(per_unit_cost, moment ?
moment->date() : optional<date_t>(), tag));
DEBUG("commodity.prices.add",
"exchange: amount = " << breakdown.amount);
return breakdown;
}
@ -755,7 +739,7 @@ void annotated_commodity_t::write_annotations(std::ostream& out,
out << " {" << *info.price << '}';
if (info.date)
out << " [" << format_date(*info.date) << ']';
out << " [" << format_date(*info.date, string("%Y/%m/%d")) << ']';
if (info.tag)
out << " (" << *info.tag << ')';

View file

@ -85,9 +85,6 @@ bool entry_base_t::finalize()
// for auto-calculating the value of entries with no cost, and the per-unit
// price of unpriced commodities.
// (let ((balance 0)
// null-xact)
value_t balance;
xact_t * null_xact = NULL;
@ -119,8 +116,8 @@ bool entry_base_t::finalize()
DEBUG("entry.finalize", "initial balance = " << balance);
// If there is only one xact, balance against the default account if
// one has been set.
// If there is only one xact, balance against the default account if one has
// been set.
if (journal && journal->basket && xacts.size() == 1 && ! balance.is_null()) {
// jww (2008-07-24): Need to make the rest of the code aware of what to do
@ -131,9 +128,9 @@ bool entry_base_t::finalize()
}
if (null_xact != NULL) {
// If one xact has no value at all, its value will become the
// inverse of the rest. If multiple commodities are involved, multiple
// xacts are generated to balance them all.
// If one xact has no value at all, its value will become the inverse of
// the rest. If multiple commodities are involved, multiple xacts are
// generated to balance them all.
if (balance.is_balance()) {
bool first = true;
@ -161,41 +158,88 @@ bool entry_base_t::finalize()
else if (balance.is_balance() &&
balance.as_balance().amounts.size() == 2) {
// When an entry involves two different commodities (regardless of how
// many xacts there are) determine the conversion ratio by dividing
// the total value of one commodity by the total value of the other. This
// establishes the per-unit cost for this xact for both
// commodities.
// many xacts there are) determine the conversion ratio by dividing the
// total value of one commodity by the total value of the other. This
// establishes the per-unit cost for this xact for both commodities.
const balance_t& bal(balance.as_balance());
DEBUG("entry.finalize", "there were exactly two commodities");
balance_t::amounts_map::const_iterator a = bal.amounts.begin();
bool saw_cost = false;
xact_t * top_xact = NULL;
const amount_t& x((*a++).second);
const amount_t& y((*a++).second);
foreach (xact_t * xact, xacts) {
if (! xact->amount.is_null())
if (xact->amount.is_annotated())
top_xact = xact;
else if (! top_xact)
top_xact = xact;
if (! y.is_realzero()) {
amount_t per_unit_cost = (x / y).abs();
if (xact->cost) {
saw_cost = true;
break;
}
}
commodity_t& comm(x.commodity());
if (! saw_cost && top_xact) {
const balance_t& bal(balance.as_balance());
DEBUG("entry.finalize", "there were no costs, and a valid top_xact");
balance_t::amounts_map::const_iterator a = bal.amounts.begin();
const amount_t * x = &(*a++).second;
const amount_t * y = &(*a++).second;
if (x->commodity() != top_xact->amount.commodity()) {
const amount_t * t = x;
x = y;
y = t;
}
DEBUG("entry.finalize", "primary amount = " << *y);
DEBUG("entry.finalize", "secondary amount = " << *x);
commodity_t& comm(x->commodity());
amount_t per_unit_cost;
amount_t total_cost;
foreach (xact_t * xact, xacts) {
if (xact != top_xact && xact->must_balance() &&
! xact->amount.is_null() &&
xact->amount.is_annotated() &&
xact->amount.annotation().price) {
amount_t temp = *xact->amount.annotation().price * xact->amount;
if (total_cost.is_null()) {
total_cost = temp;
y = &total_cost;
} else {
total_cost += temp;
}
DEBUG("entry.finalize", "total_cost = " << total_cost);
}
}
per_unit_cost = (*y / *x).abs();
DEBUG("entry.finalize", "per_unit_cost = " << per_unit_cost);
foreach (xact_t * xact, xacts) {
const amount_t& amt(xact->amount);
if (! (xact->cost || ! xact->must_balance() ||
amt.commodity() == comm)) {
if (xact->must_balance() && amt.commodity() == comm) {
balance -= amt;
xact->cost = per_unit_cost * amt;
balance += *xact->cost;
}
DEBUG("entry.finalize", "set xact->cost to = " << *xact->cost);
}
}
}
DEBUG("entry.finalize", "resolved balance = " << balance);
}
// Now that the xact list has its final form, calculate the balance
// once more in terms of total cost, accounting for any possible gain/loss
// Now that the xact list has its final form, calculate the balance once
// more in terms of total cost, accounting for any possible gain/loss
// amounts.
foreach (xact_t * xact, xacts) {
@ -204,9 +248,12 @@ bool entry_base_t::finalize()
throw_(balance_error, "Transaction's cost must be of a different commodity");
commodity_t::cost_breakdown_t breakdown =
commodity_t::exchange(xact->amount, *xact->cost);
commodity_t::exchange(xact->amount, *xact->cost, false,
datetime_t(date(), time_duration(0, 0, 0, 0)));
if (xact->amount.is_annotated())
if (xact->amount.is_annotated() &&
breakdown.basis_cost.commodity() ==
breakdown.final_cost.commodity())
add_or_set_value(balance, (breakdown.basis_cost -
breakdown.final_cost).rounded());
else
@ -231,8 +278,8 @@ bool entry_base_t::finalize()
if (! xact->amount.is_null()) {
all_null = false;
// jww (2008-08-09): For now, this feature only works for
// non-specific commodities.
// jww (2008-08-09): For now, this feature only works for non-specific
// commodities.
add_or_set_value(xact->account->xdata().value, xact->amount);
DEBUG("entry.finalize.totals",

View file

@ -128,26 +128,22 @@ value_t report_t::fn_market_value(call_scope_t& scope)
scoped_array<char> buf(new char[args.get<string>(2).length() + 1]);
std::strcpy(buf.get(), args.get<string>(2).c_str());
bool primary_only = false;
for (char * p = std::strtok(buf.get(), ",");
p;
p = std::strtok(NULL, ",")) {
if (commodity_t * commodity = amount_t::current_pool->find(trim_ws(p))) {
value_t result =
args.value_at(0).value(primary_only, args.has(1) ?
args.value_at(0).value(false, args.has(1) ?
args.get<datetime_t>(1) :
optional<datetime_t>(), *commodity);
if (! result.is_null())
return result;
}
// For subsequent, secondary commodities, don't convert primaries
primary_only = true;
}
} else {
value_t result =
args.value_at(0).value(! args.has(2), args.has(1) ?
args.get<datetime_t>(1) :
optional<datetime_t>());
args.value_at(0).value(true, args.has(1) ?
args.get<datetime_t>(1) : optional<datetime_t>());
if (! result.is_null())
return result;
}

View file

@ -411,9 +411,9 @@ public:
OPTION_(report_t, market, DO() { // -V
parent->HANDLER(revalued).on_only();
parent->HANDLER(display_amount_)
.set_expr("market(amount_expr, now, exchange)");
.set_expr("market(amount_expr, date, exchange)");
parent->HANDLER(display_total_)
.set_expr("market(total_expr, now, exchange)");
.set_expr("market(total_expr, date, exchange)");
});
OPTION_(report_t, monthly, DO() { // -M

View file

@ -492,7 +492,7 @@ void instance_t::price_entry_directive(char * line)
if (commodity_t * commodity =
amount_t::current_pool->find_or_create(symbol)) {
commodity->add_price(datetime, price);
commodity->add_price(datetime, price, true);
commodity->add_flags(COMMODITY_KNOWN);
} else {
assert(false);
@ -895,19 +895,11 @@ xact_t * instance_t::parse_xact(char * line,
if (xact->cost->sign() < 0)
throw parse_error("A transaction's cost may not be negative");
amount_t per_unit_cost(*xact->cost);
if (per_unit)
*xact->cost *= xact->amount;
else
per_unit_cost /= xact->amount;
commodity_t::exchange(xact->amount.commodity(),
per_unit_cost, datetime_t(xact->date()));
DEBUG("textual.parse", "line " << linenum << ": "
<< "Total cost is " << *xact->cost);
DEBUG("textual.parse", "line " << linenum << ": "
<< "Per-unit cost is " << per_unit_cost);
DEBUG("textual.parse", "line " << linenum << ": "
<< "Annotated amount is " << xact->amount);

View file

@ -0,0 +1,81 @@
reg --exchange=' C, A '
<<<
2009/01/01 January 1st, 2009 (1)
Assets:Brokerage 100 A
Assets:Brokerage -200 B
2009/01/01 January 1st, 2009 (2)
Assets:Brokerage 100 A
Assets:Brokerage -300 B
2009/01/01 January 1st, 2009 (3)
Assets:Brokerage 100 A
Assets:Brokerage -400 B
2009/01/02 January 2nd, 2009
Assets:Brokerage 250 B
Assets:Brokerage -500 C
2009/01/03 January 3rd, 2009
Assets:Brokerage 600 C
Assets:Brokerage -1000 D
2009/01/04 January 4th, 2009
Assets:Brokerage 300 A
Assets:Brokerage -15000 F
2009/01/05 January 5th, 2009
Assets:Brokerage 2000 E
Assets:Brokerage -8000 F
2009/01/06 January 6th, 2009
Assets:Brokerage 155 A @ 2 D
Assets:Brokerage
2009/01/07 January 7th, 2009
Assets:Brokerage 155 A @@ 200 C
Assets:Brokerage
2009/01/08 January 8th, 2009
Assets:Brokerage 155 A (A123) @@ 500 F
Assets:Brokerage
2009/01/09 January 9th, 2009
Assets:Brokerage 1000.00 E
Assets:Brokerage -155 A {2 D}
2009/01/10 January 10th, 2009
Assets:Brokerage $2,000.00
Assets:Brokerage -155 A [2009/01/06]
>>>1
09-Jan-01 January 1st, 2009 (1) Assets:Brokerage 100 A 100 A
Assets:Brokerage -50 A 100 A
-200 B
09-Jan-01 January 1st, 2009 (2) Assets:Brokerage 100 A 200 A
-200 B
Assets:Brokerage -75 A 200 A
-500 B
09-Jan-01 January 1st, 2009 (3) Assets:Brokerage 100 A 300 A
-500 B
Assets:Brokerage -100 A 300 A
-900 B
09-Jan-02 January 2nd, 2009 Assets:Brokerage 500 C 1100 C
Assets:Brokerage -500 C 600 C
09-Jan-03 January 3rd, 2009 Assets:Brokerage 600 C 1200 C
Assets:Brokerage -600 C 600 C
09-Jan-04 January 4th, 2009 Assets:Brokerage 2400 C 3000 C
Assets:Brokerage -2400 C 600 C
09-Jan-05 January 5th, 2009 Assets:Brokerage 1280 C 1880 C
Assets:Brokerage -1280 C 600 C
09-Jan-06 January 6th, 2009 Assets:Brokerage 186 C -1254 C
Assets:Brokerage -186 C -1440 C
09-Jan-07 January 7th, 2009 Assets:Brokerage 200 C -1258 C
Assets:Brokerage -200 C -1458 C
09-Jan-08 January 8th, 2009 Assets:Brokerage 200 C -6871 C
Assets:Brokerage -200 C -7071 C
09-Jan-09 January 9th, 2009 Assets:Brokerage 200 C -9671 C
Assets:Brokerage -200 C -9871 C
09-Jan-10 January 10th, 2009 Assets:Brokerage 200 C -9671 C
Assets:Brokerage -200 C -9871 C
>>>2
=== 0

View file

@ -0,0 +1,60 @@
reg --market stocks
<<<
2009/01/01 Sample 1a
Assets:Brokerage:Stocks 100 S
Assets:Brokerage:Cash -100 P
P 2009/01/01 00:00:00 S 2 P
2009/02/01 Sample 2a
Assets:Brokerage:Stocks 100 S @ 1 P
Assets:Brokerage:Cash
P 2009/02/01 00:00:00 S 4 P
2009/03/01 Sample 3a
Assets:Brokerage:Stocks 100 S @@ 100 P
Assets:Brokerage:Cash
P 2009/03/01 00:00:00 S 8 P
2009/04/01 Sample 4a
Assets:Brokerage:Cash 100 P
Assets:Brokerage:Stocks -100 S {1 P}
P 2009/04/01 00:00:00 S 16 P
; In this usage case, the top amount is always secondary
; 2010/01/01 Sample 1b
; Assets:Brokerage:Cash -100 P
; Assets:Brokerage:Stocks 100 S
;
; P 2010/01/01 00:00:00 S 2 P
2010/02/01 Sample 2b
Assets:Brokerage:Cash
Assets:Brokerage:Stocks 100 S @ 1 P
P 2010/02/01 00:00:00 S 4 P
2010/03/01 Sample 3b
Assets:Brokerage:Cash
Assets:Brokerage:Stocks 100 S @@ 100 P
P 2010/03/01 00:00:00 S 8 P
2010/04/01 Sample 4b
Assets:Brokerage:Stocks -100 S {1 P}
Assets:Brokerage:Cash 100 P
P 2010/04/01 00:00:00 S 16 P
>>>1
09-Jan-01 Sample 1a As:Brokerage:Stocks 200 P 200 P
09-Feb-01 Sample 2a As:Brokerage:Stocks 400 P 800 P
09-Mar-01 Sample 3a As:Brokerage:Stocks 800 P 2400 P
09-Apr-01 Sample 4a As:Brokerage:Stocks -1600 P 3200 P
10-Feb-01 Sample 2b As:Brokerage:Stocks 400 P 1200 P
10-Mar-01 Sample 3b As:Brokerage:Stocks 800 P 3200 P
10-Apr-01 Sample 4b As:Brokerage:Stocks -1600 P 4800 P
>>>2
=== 0