#167 jGnash 1.x: "Market value" can disagree with "Portfolio Rpt"

closed
Engine (46)
5
2010-07-07
2010-06-21
Tom Edelson
No

It can occasionally happen, in the current code for jGnash 1.x, that the "market value" of an investment account, as shown in the investment register, will not agree with the total market value as shown in the Portfolio Report.

The attached file,

security-value-rounding-problem.jgnash.xml

demonstrates this problem. It is a variant on the standard test file, "mini.jgnash.xml", as stored in the repository (and last updated in the commit which created revision 2134, which was part of the implementation of Feature Request number 3,005,411, 'Add support for retrieving "share balance" from a script').

In the new "security-value-rounding-problem" test data file, there is one investment account, whose name is "brokerage account". It has a "Cash Balance" of zero, so its "Market Value" should be equal to its "Balance" (both as shown at the top of the investment register; the "Balance" shown there is actually the total value of the account).

And these two figures in the investment register are indeed equal, at $23,212.30. This is also, as expected, the value of the account as shown in the jGnash "Account list", when "Accounts" is selected in the jGnash main window.

But if you run a Portfolio on this same account, the figure shown as "Value", under "Summary", is one cent less: $23,212.29.

I have a real-life data file in which, one month, there was the same discrepancy (for one investment account) between the value as shown in the register, and in the "Account list", on the one hand, and that shown in the Portfolio Report, on the other hand. The value shown in the Portfolio Report was the one which agreed with my brokerage statement for that month. In practical terms, I think this means that this should be called the "correct" value: the value shown in the investment register, and in the "Account list", should be the same.

jGnash uses BigDecimal objects as internal representations of amounts of money, so its calculations with such amounts should be exact: we can't blame this small discrepancy on the inherent rounding errors seen with floating-point numbers.

I have not yet dived into the code in order to track down the cause of the discrepancy. However, the results are at least consistent with the following hypothesis:

1. When you do an exact multiplication of the current "quantity" (number of shares held) for a security in an account, and the latest price of that security, the result will often be a number with extra decimal places: not an integral number of dollars and cents, or whatever is the standard representation for the applicable currency.

2. You get the result shown in the investment register, and in the "Account list", if you do an exact additions of all these multiplication results, and *only then* round the total to the nearest cent.

3. You get the result shown in the Portfolio Report, and in the broker's statement, if you first round the result of each multiplication to the nearest penny, and then add up these rounded results.

So the hypothesis is that this is the difference between what the two calculations are actually doing.

If this is correct, then, in my opinion, the calculation of the "Market Value", as shown in the investment register, should be changed so as to be consistent with the calculation done in preparing the Portfolio Report.

Discussion

  • Tom Edelson

    Tom Edelson - 2010-07-07

    I was essentially correct about the reason for the discrepancy. In the code for the Portfolio Report, the value of each security holding, within the investment account, was being rounded to two decimal places, before those values were added to produce the market value of the account as a whole.

    The bug report mentions three places within the UI in which the market value of an investment account is shown: in the Portfolio Report, in the register for an investment account, and in the Account List.

    In the latter two places, but not the first, the market value is obtained by calling (directly or indirectly) method

    getMarketValue (Date start, Date end)

    of the InvestmentAccount class. Prior to this fix, that method was not doing any rounding on the values of individual security holdings, before adding them up.

    Those findings led to two commits:

    In revision 2201, I changed a number of classes, but these changes weren't (and aren't) expected to make any change in the user-visible behavior of the program: they were for readability only. (In particular, making at least some of them was helpful in confirming where various parts of the program get their idea of a "market value".) The classes changed, in addition to "jgnash.engine.InvestmentAccount", were

    jgnash.ui.MainFrame

    gnash.ui.list.AccountListTreeTablePane

    jgnash.ui.register.invest.InvestmentRegisterPanel

    In revision 2202, the only Java class changed was "jgnash.engine.InvestmentAccount", and the only functional change was to the above-mentioned flavor of its "getMarketValue" method: to round the value of each security holding to two decimal places, as the code in

    jgnash.report.compiled.PortfolioReportTableModel

    does.

    At that point, I thought that the fix was complete. But then it occurred to me: about this rounding, should the number of decimal places really be hard-wired to two? This is correct if the "reporting currency" of the particular investment account is the US dollar, or any of a number of currencies in which values are normally stated to two decimal places. But jGnash allows you to specify the reporting currency of an account, and also to specify the "scale" of a currency, meaning the number of decimal places to which values in that currency are to be reported. So these settings should be respected in reporting the market value of a security holding, or that of an investment account as a whole.

    This led to two more commits (the last two which will be ascribed to this bug). Again, the first commit. revision 2203, was for readability only: changes which I made in the processing of figuring out, or confirming, how to do the "real" fix. This time, only one class was changed:

    jgnash.text.CommodityFormat

    Finally, in revision 2212, the only Java class changed was, again,

    jgnash.engine.InvestmentAccount

    , method

    getMarketValue (Date start, Date end)

    , and it caused the interim rounding, as described above, to be done to a variable number of decimal places, dependent on the "reporting currency" of the InvestmentAccount in question.

    That completes the description of what I did, in fixing this bug. I have three concluding "notes".

    Note 1: it is clear, I assume, that there shouldn't be a discrepancy between the market value, as reported in different places in the program. But one might wonder why I am assuming that (prior to the fix) the "correct" value is the one shown in the Portfolio Report, and not the one shown in the other two places. After all, there really is no precise definition of the "market value" of a security holding, until it is sold.

    I chose the value as shown in the Portfolio Report, essentially, because it was the one which agreed with my broker's statement ... and thus, the one which would save trouble when "reconciling" that statement with what jGnash says. I didn't actually investigate whether all brokers follow the same practice as mine, but I think it stands to reason that they would. This is based on the assumption that they report the "market values" of individual security holdings, as well as the total for the account; and on the further assumption that a broker's statement, like a "portfolio report", is expected to follow accounting conventions, in which individual values are expected to add up exactly to the total as shown.

    Note 2: Ideally, the Portfolio Report shouldn't just be using the same algorithm to get market values; it should be using the same code. At one stage in the work on this bug, I thought that, with the fix, it would now at least be using the same algorithm; using the same code was desirable, but could be postponed for later.

    However, the Portfolio Report still has a hard-wired value, two, for the number of decimal places to which values should be rounded. So -- after the final version of this fix -- we are back to a situation where it isn't even using the same algorithm as is used elsewhere. The difference is that now, when the results are different, it is the version in the register and the Account List, not the version in the Portfolio Report, that I regard as "correct".

    This strengthens my view that the market value, as shown anywhere in the program, should be calculated using the same code. However, I am not going to make that happen at this time. Nor am I going to create a formal bug report to reflect this new type of discrepancy ... only because I am not entirely sure whether the Portfolio Report code was ever intended to be general enough to produce exactly "correct" results, regardless of reporting currency.

    Note 3: I haven't done any actual testing with jGnash 2, but a quick look at the code suggests to me that a basically similar problem *may* [still] exist in the jGnash 2.x releases. The code looked at was (class, then method):

    jgnash.engine.InvestmentAccountProxy:

    getMarketValue (final Date start, final Date end)

    jgnash.engine.InvestmentTransaction:

    getMarketValue (final BigDecimal sharePrice)

     
  • Tom Edelson

    Tom Edelson - 2010-07-07
    • labels: 332159 --> Engine
    • status: open --> closed
     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks