Rounding currency

I’m wondering why by default we use ROUND_HALF_EVEN?
I know it can be customized by country, but I’m not sure about this default half even when most of the references I can found it’s mentioning to round up:

If the application of the conversion rate gives a result which is exactly half-way, the sum is rounded up.

https://eur-lex.europa.eu/summary/EN/legissum:l25025
Spain for example it’s not determined by law, but the Tax Base FAQ solves the question.

Also I have found some inconsistency in the rounding, which for now I can not understand:

Currency = pool.get('currency.currency')
eur, = Currency.search([('code', '=', 'EUR')])
from decimal import Decimal
>>> eur.round(Decimal('3.5650'))
Decimal('3.56')
>>> eur.round(Decimal('60.2550'))
Decimal('60.26')

FTR the issue1147 is where the rounding was introduced.

It’s the way rounding with ROUND_HALF_EVEN works: when the last significant number is a five you round towards the even number (so sometimes up, sometimes down).

This choice has been made because it’s the most “fair” way to round numbers because 50% of the time you go up and 50% of the time you go down.

This was only for the switch to euro period/

Indeed it does not solve because their definition is incomplete.

This just shows that most country laws can not write clear specifications. But as @nicoe said we choose the fairest way of rounding. But as often the best option is unknown from common people.

Which is incomplete for you?

The following is clear for me:

En caso de que el importe previo al redondeo esté expresado con tres decimales y el tercer decimal sea exactamente la mitad de un céntimo, el redondeo se efectuará por exceso al céntimo superior más próximo.

Which translates to:

In case of the amount previous to rounding have 3 decimal and third decimal is exactly half on 1 cent, the rounding will be done to the upper cent.

Indeed but if is a FAQ not a law. There should be no problem as long as the same tax rounding rule is always used.

One point that may need a change of this behavior is the need to be compliant with a 3rdparty software if the data is exported. Most of the ones i know do not use ROUND_HALF_EVEN but ROUND_HALF_UP as the FAQ is recommending it.

If you need to export not raw data but source data that should be computed the same way in different software, you will have much more problem than just that.

I do not see why we should change our good default because other software are bad.

I the eyes of any accountant this default is not a good default. But yes, tryton is a framework and it is written for developers. So in the end the developer is responsible to make the framework suitable for the enduser.

Because we choseen a “fair” rounding but maybe our users prefer to have a more predictable one like HALF_UP. I’m not sure about it but something to be checked.

I will like to have @albert opinion here as I see they set the HALF_UP rounding as default value for Spanish companies back in 2015.

ROUND_HALF_EVEN is as much predictable as any rounding method.

What is easly understood for somebody is not easly understood for the everyone.

It seems it is not predictable for somebody that studied Business Administration and Managment as @acaubet did:

So that makes me think that account module users that will have diferent toughts.

I stop discussing here because any way this will never change in standard because it would break all the existing accounting.

I think we could provide a configuration value and store the value in ir.configuration like we do with the default language. This would make it easy to keep the default value for existing databases and to provide a solution to choose another value for new databases.

I guess everything has been said already. HALF_UP is easier to understand for users and we’d rather spend our time discussing more important things for the company than trying to convince them that the way HALF_EVEN is more fair. Let alone spend time repeating it every now and then because they forgot about it.

Of course there are ways to do some sort of “migration” to support switching the rounding option. But making it a configuration makes it appears like it can be changed when in reality you should not (or at least not during a fiscal year). And what happens when something spans across multiple fiscal years? There are probably ways around that too but it seems to be too much code for so little gain.

But I understand that this behaviour is not the one that 99% of the people expect. People are taught ROUND_HALF_UP in primary / middle school and stick to that up until the end sometimes (I learned about ROUND_HALF_EVEN when having to deal with scientific measurements).

For me this issue is mainly managing the expectations of your users (and sometimes you have to use ROUND_HALF_UP because you can not convince them or whatever) and in that case, it’s just a matter of overriding the default value of round(): nothing too complicated.

Nothing so complicated for the ones that are used to Tryton development and that want to have a custom module for it. But sincerly if you are a system administrator without programing knowledge having to override a method is someway scary.

OK I agree but then maybe stick to the default value.

We have to take into account the past and making code to be backward compatible + adding an option seems like a waste of resource and also useless.

Not sure if you understand. Are you proposing that everybody sticks to ROUND_HALF_EVEN?

I understand that we should not allow to modify the rounding once the database has been intialized. But this sounds like the same behaviour as we currently have with main language. Once it is set it can not be changed

I do not think we need to make it backward comptabile.

So what other options we have?

What I mean is that if you’re not comfortable creating a module for that then maybe you should stick to the default value. This rounding might be unusual for you but it’s not false.

Backward compatible as in : making previous database created without the option behave like they did previously. This is required.

Some code will be written to support this. Yes it’s some simple code but its added value is almost 0.