Bankers Round (aka "half even up") is a rounding scheme very used in financial apps as it produces statistically less rounding issues than the most commonly extended "half up".

The problem is that Postgres' round function implements "half up". Read on to find out how to implement "half even up".

Python already defaults to bankers rounding, but to make it more explicit here's a function using the decimal module that implements a bround function that rounds to 2 decimal places using ROUND_HALF_EVEN:

>>> from decimal import ROUND_HALF_EVEN, Decimal
...
...
... def bround(val: Decimal) -> Decimal:
...     return val.quantize(Decimal("0.01"), ROUND_HALF_EVEN)
...
>>> bround(Decimal("2.125")), bround(Decimal("2.135"))
(Decimal('2.12'), Decimal('2.14'))

With Postgres' round the results are different:

localhost=> select round(2.125, 2), round(2.135, 2);
 round | round
-------+-------
  2.13 |  2.14
(1 row)

So now that the issue is clear, how do you create your own bround function in plpgsql?

create or replace function bround(value numeric, prec integer default 0)
returns numeric as $$
declare
    power_val numeric := power(10, prec)::numeric;
    scaled numeric := value * power_val;
    truncated numeric := trunc(scaled);
    result numeric;
begin
    result := case
        when abs(scaled - truncated) = 0.5 then
            case
                when truncated % 2 = 0 then truncated
                else truncated + sign(scaled)
            end
        else round(scaled)
    end;

    return round(result / power_val, prec);
end;
$$ language plpgsql strict immutable parallel safe;

This function now produces the expected output:

localhost=> select bround(2.125, 2), bround(2.135, 2);
 bround | bround
--------+--------
   2.12 |   2.14
(1 row)

The astute reader will have noticed that I have marked the function as strict immutable parallel safe. This basically tells the system that the function does not touch the database and it's safe to run in parallel. In my testing it makes it run 2.5x faster! See the docs for more information.