To quantify Buffet's #1 rule of investing, "Don't lose money", I take the assumption that % returns of an investment follow a Normal distribution.

Now a high return high risk investment might follow N(mu=50%, sigma=70%) while low return low risk investment follow N(mu=20%, sigma=10%).

from operator import mul
from functools import reduce
from random import gauss
from statistics import median
from typing import List

def avg_cagr(percents: List[int]) -> float:
        '''Given (successive) % annual growth rates, returns average Compound Annual Growth Rate'''
        amount = reduce(mul, [1+p/100 for p in percents])
        amount = amount if amount > 0 else 0 # at worst, complete amount can be lost but can't go negative
        return (amount**(1/len(percents)) - 1)*100

def normal_returns(mu: float, sigma: float, years: int = 20, simulations: int = 1000) -> float:
    '''Returns net CAGR assuming annual percentage returns follow a Normal distribution'''
    return median(avg_cagr([gauss(mu=mu, sigma=sigma) for _ in range(years)]) for _ in range(simulations))

I have simulated normal_returns for various values of mu & sigma (for 20 consecutive years) and plotted a contour plot. We can see here that N(25, 20) handily beats N(60, 80). Plotting code

Contour plot of CAGR

My query is does this formulation of problem (beyond just the code) seem alright? Could I model/design it better? What are other approaches?

  • \$\begingroup\$ Since you're asking about the formulation of the problem beyond the code, this question may be better suited for the folks at Quant Stack Exchange. \$\endgroup\$ – wklock Dec 20 '18 at 18:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.