Currency conversion

Here are various ways of recording a conversion from one currency or commodity to another.

Implicit conversion

For simplicity, let's assume we are just exchanging cash with a friend:

2021-07-27 give dollars, get euros
    assets:cash      USD -10.00
    assets:cash      EUR   8.50

hledger understands that 10 dollars were converted to 8.50 euros. A conversion rate is inferred automatically so as to make the transaction balance. (This can be seen with hledger print -x.)

This is easy to write and to understand; it's fine for getting started. However it is not a fully correct double-entry-bookkeeping journal entry, since USD has magically transformed into EUR "in flight". It is also somewhat error prone, since a typo in either amount may not be detected. For example, we might forget the decimal point and write USD -1000. Also, it is easy to create such entries accidentally. For example, in one posting within a transaction we might mistype or omit the currency symbol.

hledger accepts these implicit conversions by default, for convenience and compatibility. But you can disallow them by using strict mode or by running the check command (eg: hledger check balancednoautoconversion).

Declared conversion rate

We can declare the conversion rate, which adds redundancy allowing hledger to catch errors, and also makes the rate more explicit to human readers. We can write the total amount with @@ (convenient when entries are complex):

2021-07-27 give dollars, get euros
    assets:cash      USD -10.00 @@ EUR 8.50
    assets:cash      EUR   8.50

or the per-unit amount with @ (makes the exchange rate, or an investment's cost basis, clearer):

2021-07-27 give dollars, get euros
    assets:cash      USD -10.00 @ EUR 0.85
    assets:cash      EUR   8.50

hledger calls these "transaction prices". They can also be used generate market prices for value reports.

This is probably the most frequently used style among hledger users.

Fully balanced conversion

A fully correct double-entry-bookkeeping journal entry avoids the PTA-specific @/@@ notation, and is balanced in each commodity, using equity. Eg:

2021-07-27 give dollars, get euros
    assets:cash        USD -10.00
    equity:conversion  USD  10.00
    assets:cash        EUR   8.50
    equity:conversion  EUR  -8.50

or, letting hledger infer the above:

2021-07-27 give dollars, get euros
    assets:cash        USD -10.00
    assets:cash        EUR   8.50
    equity:conversion

This is discussed more here.

Two entries

This comes up eg when converting Paypal CSV, which provides two records for a currency conversion, one for each side. For example, given some paypal CSV rules like:

account1 assets:paypal
...
if %type (T0200|General Currency Conversion)
 description %type for %referencetxnid %itemtitle
 account2 equity:conversion

we might see journal entries like:

2020-05-16 * Liberapay donation to simonmichael (team darcs-hub)
    assets:online:paypal                     C$24.56 =* C$24.56
    revenues:foss donations:darcshub        C$-26.00
    expenses:banking:paypal                   C$1.44

2020-05-16 * General Currency Conversion for 8Y4N723T948333034 Liberapay donation to simonmichael (team darcs-hub)
    assets:online:paypal                    C$-24.56 =* C$0.00
    equity:conversion                        C$24.56

2020-05-16 * General Currency Conversion for 8Y4N723T948333034 Liberapay donation to simonmichael (team darcs-hub)
    assets:online:paypal                      $16.88 =* $17.55
    equity:conversion                        $-16.88

Ie: some canadian dollars received, followed by two transactions converting that balance to US dollars. This is equivalent to the "Fully balanced conversion" above, just with the conversion entry split into two.

Balancing the books

If you are a fan of the accounting equation and like to check it by seeing a zero total in the balancesheetequity report, you will need to do something with these equity:conversion balances. Such as, converting them to retained revenues/expenses in your local currency. This can perhaps be done at transaction time, or at the end of each accounting period, or with report options. Best practice is not yet clear, suggestions welcome.