Thoughts, ideas and solutions from a few EPM consultants.

Rounding in FDM vs FDMEE (Visual Basic to Jython)

FDM to FDMEE conversions have been very popular in the past year or so for obvious reasons. While users can choose to keep using visual basic for their logic some have chosen to use Jython. As a person who started his career writing database driven websites with ASP (VBScript) and Cold Fusion. I am happy to be slowly saying goodbye to VB (The last holdout now appears to be Microsoft Office) and hello to Python (Jython.)

Unfortunately VB doesn't always work like you would expect it to. When most people think of rounding they expect the following:

ValueRounded
100.00100
100.50101
101.00101
101.50102
102.00102
102.50103



Unfortunately VB doesn't round like this. When it was designed VB used round to even where it was expected that odd numbers rounded up at .5 and even numbers are rounded down at .5. This would result in the following:

ValueRounded
100.00100
100.50100
101.00101
101.50102
102.00102
102.50102



In a ideal world this is one of those things where you might say, well Python makes more sense so lets go with that, but the world of finance is far from ideal. In the past couple of years I have learned some things can't be "fixed". Sometimes you just have to make it match.

Below is a Python implementation of Visual Basic's Round Even.

Updated 06/22/2016:
Well I stand corrected, the VB rounding functionality makes more sense than first thought. Justin pointed me to this article which refers to this type of rounding as bank rounding and from a finance point of view this makes a ton of sense.

It also occurred to me shortly after the post that I should have added the ability to round to a particular place in the number. Using the function below a positive number in the ndigits parameter will round the fractional part of the number to that number of decimal places. A negative number will round in the integer part (before the decimal).

Example:
bank_round(120500, -3) = 120000
bank_round(121500, -3) = 122000
bank_round(101.125, 2) = 101.12
bank_round(101.135, 2) = 101.14

Updated 06/30/2016:
While trying to increase write performance (Java StringBuilder seems to be good) I ran across this post.

TL;DR Python 3 uses bankers rounding. So if Jython ever gets compatibility with Python 3 (Jython is currently Python 2.x) and Oracle decideds to upgrade FDMEE off this old version of Jython (2.5). Bankers rounding might be the default meaning this script would not be necessary.