Support for commodities / units / currencies
hrj opened this issue · 7 comments
I stumbled to Unit library written in scala Squants. It seems to be doing lot of stuff which would be handy with units / currencies.
In any case, it would be good to be able support at least following use cases:
-
"units" where there is constant conversion between units e.g.:
- centimeters to inches
- liters to gallons
- centimeters to meters or kilometers
- seconds to hours, and to days
- special case: what to do with leap seconds? Is time actually "currency" with exchange rate to hours and days?
-
currencies which are possible to convert between each other, but exchange rate varies, and typically exchance rate is not know at the time of transaction. Probably these should be handled via currency accounts, where exchange rate can be recorded as it happened, and day-to-day value of currency account could be "exchanged" based on current rates.
- Are stocks and other financial instruments "currencies" e.g. can they be handled via same mechanism, or do they need own category/type?
-
Commodities which doesn't have conversion nor value. These are plain values, as Abandon values are at the moment.
Agreed @jaa127
My design notes:
- Currencies / units / commodities can be implemented as normal accounts with a special name. For example, USD income could be represented by
Income:_USD
. The underscore at the front of the name indicates that it's a currency / unit / commodity. - Any account with an underscore prefixed before it is "strongly typed". You can only transfer amounts if the names match. For example, you can only transfer between two
_USD
accounts. - When transferring amounts between two different types, say between
_USD
and_INR
, a conversion has to be made. The conversion can be either implicit or explicit.- explicit conversion: for example,
Income:_INR 100 @ 50 \n Assets:Bank:_USD
would convert 100 INR to 2 USD (at the rate of 50 INR per USD). - implicit conversion: If explicit rate is not specified and there is a function named
INR_to_USD
in the current scope, it is used to automatically convert fromINR
toUSD
.
- explicit conversion: for example,
Optional
- Syntax sugar for specifying the unit. For example
Income INR 50
would be shorthand forIncome:_INR 50
. - Constraint: Prefixed accounts can't have children; they have to be leaf nodes (this constraint is not necessary and can be relaxed later).
How about if there is formal account definition at the begin of parsing process (e.g. begin of ledger file or provided by config-file). This would allow to assing all kind of metadata to accounts (e.g. #108, #60), and define default unit / commodity per account.
It would also be handy, if you could mix commodities inside account. For example you could have cash in multiple currencies, and to have multiple cash accounts to be able handle multiple currencies is kind of inconvenient. It should also be desided how mixed commodities (tree) balances are handled in case of different commodities.
How about if there is formal account definition at the begin of parsing process (e.g. begin of ledger file or provided by config-file). This would allow to assing all kind of metadata to accounts (e.g. #108, #60), and define default unit / commodity per account.
Agreed; though I think we can build this later, once the core support for currencies is in place.
It would also be handy, if you could mix commodities inside account. For example you could have cash in multiple currencies, and to have multiple cash accounts to be able handle multiple currencies is kind of inconvenient. It should also be desided how mixed commodities (tree) balances are handled in case of different commodities.
I think all this is handled by my idea of using special account names. Basically, we already have a tree structure, and currencies can be just represented as children. It seems simpler from both user's and developer's point of view. It avoids the need to create a separate structure inside every account. I am not sure why you think it would be inconvenient. If you can give an example in a .ledger
format, it would be useful to me.
I am not sure why you think it would be inconvenient. If you can give an example in a .ledger format, it would be useful to me.
The main reason is that there is need to maintain multiple separate accounts just for commodities.
Real example: There is car trip from Finland to Norway via Sweden. Finland is Euro (EUR), Sweden is Krona (SEK) and Norway is Krone (NOK). In each country I byu fuel and some other car related stuff.
If this is done without commodities as leaf accounts, then it could be something like this:
2017-02-01 car stuff in finland
e:car 1 EUR ; general purpose car stuff
e:car:fuel 20 EUR ; fuel
a:cash
2017-02-01 car stuff in sweden
e:car 10 SEK ; general purpose car stuff
e:car:fuel 200 SEK ; fuel
a:cash
2017-02-01 car stuff in norway
e:car 10 NOK ; general purpose car stuff
e:car:fuel 200 NOK ; fuel
a:cash
If commodities are leaf accounts, then this gets really messy. Especially if I didn't know that I will visit Norway and Sweden by car, when Chart of Accounts was established....
Chart of Accounts is a good point. Out of curiosity, how do you define it in abandon currently? Or is it a concern for the future? Perhaps we can make currency accounts exempt from Chart of Account?
Hmm, from your example, I have another doubt:
2017-02-01 car stuff in sweden
e:car 10 SEK ; general purpose car stuff
e:car:fuel 200 SEK ; fuel
a:cash
What if a:cash
has a balance of 100 SEK? Should abandon
- deduct 100 SEK from
a:cash
and try to deduct the remaining 110 SEK by converting from another currency? - Or should it just allow the amount of
a:cash
to get negative? - Or should it flag an error?
With the currency-as-leaf-account design the answer is 2
. If there is an always-positive constraint set for a:cash
it would result in 3
.
Answering my own doubt:
If 1
is desired, then the transaction entry can be:
2017-02-01 car stuff in sweden
e:car 10 SEK ; general purpose car stuff
e:car:fuel 200 SEK ; fuel
a:cash -100 SEK
a:cash:_EUR
(balance adjustment would be done from EUR currency).
This will work with any design (leaf-currency-account or otherwise).