Making Better Investments with Math and JavaScript

January 18, 201912 min read

Last reviewed January 18, 2019

It is often said that one of the greatest physicists of the last century, Richard Feynman, endorsed that the best way of learning a subject is to refine a concept to be simple enough for a 5-year-old to understand. Well, I don’t expect to have any kids among my audience but I will try to explain how financial concepts NPV and IRR work using what you like (code and math).

This will set the foundations for building an online calculator and help us make better financial decisions in the future (disclaimer: don’t blame me if you go bankrupt).

Let’s start then with a simple but intriguing problem.

The Problem

Suppose that your friend Elon asks if you are interested on backing his new endeavour. He says that if you lend him $10,000 he expects to return $11,000 to you after one year. Should you accept the offer?

In other words: should you deposit $10,000 now in order to withdraw $11,000 in one year?

Of course I don’t intend to go into metaphysical questions about what you should do with your money neither to assess the risks of such transaction (as Elon’s predictions might not be true). The real goal here is to develop a tool where one can compare potential investments and then decide which one fits best given one’s condition.

Net Present Value

Now suppose the following: you know that you can easily allocate funds in government bonds that pay 5% per year. If your goal is to receive back the same amount your friend Elon is promising, how much should you invest?

Well, it’s easy to see that (1+0.05)x=11000(1 + 0.05)x = 11000, where xx is the initial investment in order to receive the same return Elon promised but with government bonds. This yields x10476x \cong 10476.

It means that, in today’s money, $11,000 equates to $10,476 if you decide to go with public bonds. But according to Elon all you need is $10,000 and hence we say that

NPV=1047610000=476NPV = 10476 - 10000 = 476

Which means that, in today’s money, you are expected to have a net profit of $476 in this transaction.

More generally, we can define NPV as:

NPV=t=0nCt(1+r)tNPV = \sum_{t=0}^n \frac{C_t}{(1 + r)^t}

Where CtC_t is the cash inflow or outflow in period tt and rr is the discount rate. Check that for C0=10000C_0 = -10000, C1=11000C_1 = 11000, n=1n = 1 and r=0.05r = 0.05 we achieve the same result.

Remember, in plain english (and according to investopedia):

NPV = (Today’s value of the expected cash flows) – (Today’s value of invested cash)

Writing a Function to Evaluate the NPV

Shall we write some code?

The goal here is to write a function that translates the above equation into bits. Thankfully with JavaScript we can write it in a single-line function:

const NPV = (cashflow, discountRate) => cashflow
  .reduce((acc, val, i) => acc + val / Math.pow((1 + discountRate), i), 0);

Beautiful, isn’t it?

If you are not familiar with arrow functions, I suggest you take some time and read this great article about it. You may also want to check .reduce reference in JavaScript.

Let’s walk through it:

First we assume that cashflow is an array of numbers, the one we want to reduce. The .reduce method takes two arguments, the first one being the reducer and the second one being an optional initial value.

const reducer = (acc, val, i) => acc + val / Math.pow((1 + discountRate), i);

On the other hand, reducer is a function which takes three args:

  • acc is the accumulator, the result of previous iterations.
  • val is the current value being evaluated.
  • i is the current index.

We are then calling the reducer for every entry in the array (here assuming the value of val), and evaluation the following:

acc + val / Math.pow((1 + discountRate), i)

Which basically is evaluating Ci(1+discountRate)i\frac{C_i}{(1 + discountRate)^i} and adding to the previously evaluated ii (remember that we initialize acc as 0).

You are now ready to test our function:

const NPV = (cashflow, discountRate) => cashflow
  .reduce((acc, val, i) => acc + val / Math.pow((1 + discountRate), i), 0);

const cashflow = [-10000, 11000];
const discountRate = 0.05;
console.log(NPV(cashflow, discountRate)); // 476.19047619047524

Great, now you know how to define NPV in english, in mathematics and in JavaScript. Tell me about being a polyglot!

Internal Rate of Return

NPV is great but still an absolute number. Is NPV=476NPV = 476 good or bad? Apart from the fact that this is a particular question (once risks are assessed differently by different people), it lacks information. For example, it is clear that this number is significantly better if the initial investment C0C_0 was $5,000, and definitely worse if t=10t = 10.

You then start looking for another metric. Instead of thinking about how much money you would make with such investment, you try to figure out what the discount rate is. You know that the government pays you 5%, but how much is Elon paying you given his predictions become true?

Again, it’s easy to see that (1+r)10000=11000(1 + r)10000 = 11000