Structure of a KMyMoney XML File

KMyMoney so far is the best GUI application for personal accounting that I've tried to use. It is not perfect, but using it in conjunction with beancount and hledger addresses my needs in financial report generation. In order to export transactions stored in KMyMoney's XML file to hledger/beancount journal file, one needs to know its XML structure.

A typical KMyMoney file is a gzip-compressed XML file with *.kmy extension. Firstly, we need to decompress it:

Elements

The resulting file contains the following elements:

If we don't need any extra information, we can only print the elements:

Accounts

Accounts represents assets, liabilities and equities and also expense and income categories. Accounts may be formatted in two ways. The full format looks like this:

Note that '/<ACCOUNT.*id="A000003"/,/<\/ACCOUNT>/' is a range pattern in AWK, meaning "print" every line starting with a match '/<ACCOUNT.*id="A000003"/' and ending with a line matching '/<\/ACCOUNT>/'.

The short format looks like this:

A single AWK scripts which will retrieve both formats:

Or using getline function inside AWK to get the same output as in the previous command:

Payees

A payee is a person or organization to whom money is paid in exchange for a certain good or a service. It can some general description like "Groceries", "Supermarket" or "Restaurant" or specific product you bought, e.g. "Wireless router Linksys".

Payees can be retrieved using the following command:

A unique payee ID start with letter "P" followed by digits, for example "P000004". To search for a specific payee, execute:

Similarly, IDs for transactions, accounts and splits follow the same naming convention: T000000000000000005, A000015, S0001. Payees, transactions and accounts have global IDs, whereas splits have IDs which are unique only inside a transaction.

Transactions

Transactions represent money flow from accounts to accounts when goods and services are bought or sold or when money is transferred from one account to another.

Exactly the same ouput can be obtained using a range pattern:

This transaction's commodity is EUR, which means that all accounts in this transaction have also commodity EUR. There are no multi-currency accounts in KMyMoney! This is very important, since other plain text accounting  software do support multi-currency accounts.

The transaction above corresponds to the following Beancount's ledger transaction:

KMyMoney uses fractions instead of decimal numbers. The tea (Earl Grey) costs "7/4" EUR (1.75 EUR), it is not a number yet, it needs to be interpreted (evaluated) to be represented in floating point or decimal format. This method of representing numbers has an advantage: rounding errors can be mitigated, e.g. if you buy 3 units of commodity "A" for 10 units of commodity "B", then the price of one unit of commodity "A" will be equal to "10/3" and not 3.3333 units of commodity "B".

The amount transferred to/from an account is called "value" and it is defined as:

value = shares * price

All values in a transaction have to sum up to zero as in any double-entry bookkeeping system. So if we check: -19/4 + 3/2 + 2/1 + 7/4 - 1/2 = 0. Indeed, they do.

The first split S0001 usually corresponds to the source account, in which transaction was recorded. The currency of this account will be set to the commodity of the transaction.

Currency Conversion

Now if you have an account in foreign currency, let's say USD, and all your expense categories are in the main currency (EUR), then KMyMoney will translate amounts in USD to amounts in EUR, because expense accounts do not have multi-currency mode. For example, let's say you bought groceries with USD:

Groceriesthey will be displayed in USD in the interface, but recorded in EUR for the expense categories using the conversion rate you provide in the pop-up window. This transaction will be recorded as:

The corresponding Beancount transaction is given below:

Account A000014 (Expenses:Food:Bread) will be augmented by the amount of "shares" Euros (1.55 EUR) and not by "value". However, account A000013 (Assets:Cash-USD) will be decreased by the amount of "value" US Dollars (-3.3 USD).

So in total, the balance of A000014 (Expenses:Food:Bread) will be +3.05 EUR = 1.50 EUR (from transaction T000000000000000004) + 1.55 EUR (from transaction T000000000000000005). This is the amount of money we've spent on bread in two transactions.

If you want the transaction to be recorded in USD as is, then you need to create a new account for every expense category and use it instead, e.g. "Expenses:Food:Bread-USD". Obviously, this approach is impractical. Report generation involving financial flow, income and expenses can be handled using Beancount or hledger. I wrote a custom kmymoney2hledgers converter to handle multi-currency problem. The beforementioned transaction can be changed to:

where unnecessary conversion from USD to EUR is omitted. Beancount and hledger are able to perform this conversion using implicit conversion rates (if main currency is EUR, then these USDs were exchanged for some amount of EUR, and hence the conversion rate is known) or rates specified explicitly.

KMyMoney may stay as a user-friendly GUI application for entering transactions. Auto-completion for payees, ability to easily change the account hierarchy and move transactions from one account to another are the advantages of KMyMoney.