008 -Pure, Functional, Financial Python Katas

The previous kata explained that there are very few mathematical concepts used in finance.

This series of katas has so far only used one concept in Python, which is the lambda.

Unfortunately while Python's lambdas can represent the missing concept - the 'Taylor Series' - it sometimes cannot actually compute the representation.

Usually if we want to find answers to problems of unknown complexity, we can reduce the complexity step by step by using recursion.

An example is calculating a factorial of a number, e.g.

FACTORIAL = lambda n, a=1: a if n == 0 else FACTORIAL(n - 1, a * n)  

We can call FACTORIAL(3) and get 6 (1 * 2 * 3) back and so on.

The FACTORIAL function recursively calls itself until the problem is reduced to a simple answer.

However large the problem is, we can use recursion to remove each layer of the onion and find a solution.

Without being able to gauge exactly what is required to solve a problem beforehand, recursion is a useful tool.

The problem is, Python is a stateful language. It keeps track of state in a 'stack' in case something goes wrong.

Which means recursive calls of about 1,000 and more will crash our script. E.g. FACTORIAL(1000) will error, because Python has to store too much state.

Tracking state is useful if you use statements, but our lambdas are stateless, they are not statements at all but expressions! Unfortunately Python does not cater for us in the lambda-underground-movement, so we have to use something which Python does not keep track of.

We use an ugly while loop within a 'trampoline',

def _trampoline(bouncer):  
    while callable(bouncer):
        bouncer = bouncer()
    return bouncer


THUNK = lambda name, *args: lambda: name(*args)

TRAMPOLINE = lambda f: lambda *args: _trampoline(f(*args))

IDENTITY = lambda x: x

_FACTORIAL = lambda n, c=IDENTITY: c(1) if n == 0 else THUNK(  
    _FACTORIAL, n - 1, lambda result: THUNK(c, n * result))

FACTORIAL = TRAMPOLINE(_FACTORIAL)  

Find a little more explanation here.

This is uglier (understatement!) but within Python this is unfortunately necessary for us to achieve a couple of targets.

1) although we add our while loop and a lot of junk, our new factorial function has the same essential logic of our original

3) our logic is free of imperative commands

3) we can reuse this trampoline for other recursive use cases

4) our scripts won't crash due to too much recursion

~

Now to today's kata!

The Taylor theorem helps us understand how functions and therefore mathematical representations of financial products work when things change.

In our case we are going to looking at how a savings account changes over time.

From the previous kata,

B(t) = B(0) * exp(r * t)

We assume the interest rate has been fixed.

Now we need to calculate,

B(t+dt)

where 'dt' is our change in time.

We can do this using a Taylor series.

From Wikipedia, we see,

Let's ignore the last 'h' term for the time being, this represents the remainder or error in our numerical approximation.

'x' is equal to our 't+dt'. 'a' is 't', which means 'x-a' is 'dt'.

The remainder term can also be estimated by,

The middle term is what we are interested in.

'M' is the maximum value of our bank account between 't' and 't+dt', which in our case will by found by plugging 't+dt' into our bank account exponent (assuming 'dt' is positive!).

The kata is then to use the Taylor expansion to give a numerical estimate of a bank account.

Try it recursively without and with trampolines.

And stop making recursive calls when the remainder is less than $0.0001 dollars.

Now we have perhaps the final tool in both our programming and mathematical toolboxes, we are ready to tackle bigger problems!