I concur.

There are significant differences in the implementation between gnc:get-exchange-totals and gnc:get-exchange-cost-totals that I believe are the root cause of the issue.  These differences appear to date back to May 3, 2019.    As a WAG, I modified gnc:get-exchange-cost-totals to match gnc:get-exchange-totals in the attached patch and the issue you've raised appears to be resolved.  I have not done any further testing,

Regards,

Sherlock


On 8/23/25 2:20 PM, Chang Wang wrote:
Thanks for the reminder. I'll post to the user list in the future.
However, in the above example, there is no gain or loss due to currency exchange as the exchange rates are set to 1 so no currency gain/loss needs to be booked. And the price source is set to be Last up through report date instead of average cost. Therefore, I think these are different issues.

On Sat, Aug 23, 2025 at 3:51 PM John Ralls <[email protected]> wrote:

    Oddly I just told somebody on IRC the same answer:
    https://bugs.gnucash.org/show_bug.cgi?id=797796

    Unless you’re willing to submit a PR, this is a user-list topic,
    so in the future please use gnucash-user instead of gnucash-devel.

    Regards,
    John Ralls

    > On Aug 23, 2025, at 1:43 PM, Chang Wang <[email protected]>
    wrote:
    >
    > Hi all,
    > I noticed an issue with the Trial Balance report when using
    stock trading and multiple currencies. Even when transactions are
    balanced, the Trial Balance report appears to break due to
    incorrect calculation of unrealized gains.
    >
    > I've attached an uncompressed minimal example to illustrate the
    problem.
    >
    > Steps to reproduce:
    > Open the attached book.
    > Generate a Trial Balance report with reporting currency set to
    USD, price source set to Last up through report date, and enable
    Show Foreign Currencies and Exchange Rates.
    >
    > Observed behavior:
    > The report shows an Unrealized Gain of $20,800, which is incorrect.
    >
    > Expected behavior:
    > The Unrealized Gain should be $200.
    >
    > Explanation:
    > The example contains three transactions:
    > 1) 08/02/2025 - Buy one stock for 10,200 JPY.
    > 2) 08/03/2025 - Exchange 100,000 JPY for 100,000 USD.
    > 3) 08/04/2025 - Buy one stock for 10,400 JPY.
    >
    > The JPY/USD rate is fixed at 1 on all days, so there should be
    no realized or unrealized currency gains. Stock prices are set at
    10X00 JPY on 08/0X/2025, where X = 1, 2, 3, 4.
    >
    > Therefore, in USD reporting currency, the Trial Balance should
    show unrealized gains as:
    > (10,400 * 2) - 10,200 - 10,400 = 200 JPY = 200 USD
    >
    > Notably, the Balance Sheet report does display the correct
    unrealized gain. And if transaction 3) or transaction 2) is
    removed, the Trial Balance turns out to be correct.
    >
    > I'm not familiar with Scheme, so I wasn't able to locate the
    problem in the source code. I also wasn't able to file a bug on
    Bugzilla, since the registration function appears to be broken.
    >
    > Thanks for your attention,
    > Chang
    > <tb.gnucash>_______________________________________________

_______________________________________________
gnucash-devel mailing list
[email protected]
https://lists.gnucash.org/mailman/listinfo/gnucash-devel
--- commodity-utilities.scm.orig        2025-08-23 19:49:25
+++ commodity-utilities.scm     2025-08-23 19:23:32
@@ -526,13 +526,6 @@
       (cond
        ((null? comm-splits)
         (gnc:resolve-unknown-comm sumlist report-commodity #:hide-warnings? 
hide-warnings?))
-
-       ;; However skip splits in trading accounts as these counterbalance
-       ;; the actual value and share amounts back to zero
-       ((eqv? (xaccAccountGetType (xaccSplitGetAccount (car comm-splits)))
-              ACCT-TYPE-TRADING)
-        (loop (cdr comm-splits)
-              sumlist))
 
        ;; Go through all splits and add up all value-amounts
        ;; and share-amounts
@@ -540,10 +533,15 @@
         (let* ((a (car comm-splits))
                (txn-comm (xaccTransGetCurrency (xaccSplitGetParent a)))
                (acc-comm (xaccAccountGetCommodity (xaccSplitGetAccount a)))
-               (share-amt (xaccSplitGetAmount a))
-               (value-amt (xaccSplitGetValue a)))
+               (share-amt (abs (xaccSplitGetAmount a)))
+               (value-amt (abs (xaccSplitGetValue a))))
 
           (cond
+           ;; Without shares this is not a buy or sell; ignore it.
+           ((zero? share-amt)
+            (loop (cdr comm-splits)
+                  sumlist))
+
            ((assoc txn-comm sumlist)
             => (lambda (comm-list)
                  (cond
@@ -571,16 +569,16 @@
                   ;; other commodity already exists in comm-list?
                   ((assoc txn-comm (cadr comm-list))
                    => (lambda (pair)
-                        ((caadr pair) 'add (- value-amt))
-                        ((cdadr pair) 'add (- share-amt))
+                        ((caadr pair) 'add value-amt)
+                        ((cdadr pair) 'add share-amt)
                         (loop (cdr comm-splits)
                               sumlist)))
                   (else
                    (let ((pair (list txn-comm (cons (gnc:make-value-collector)
                                                     
(gnc:make-value-collector)))))
                      ;; And add the balances to the comm-list entry.
-                     ((caadr pair) 'add (- value-amt))
-                     ((cdadr pair) 'add (- share-amt))
+                     ((caadr pair) 'add value-amt)
+                     ((cdadr pair) 'add share-amt)
                      (loop (cdr comm-splits)
                            (cons (list (car comm-list) (cons pair (cadr 
comm-list)))
                                  (alist-delete
_______________________________________________
gnucash-devel mailing list
[email protected]
https://lists.gnucash.org/mailman/listinfo/gnucash-devel

Reply via email to