It is said that
Being consistent in percentage annual returns leads to larger amount over time.
That is for any given principal, getting 20% successively for 2 years is better than 30% for first year and 10% for second year even though both percentages add to 40. First case yields 44% while the later one yields 43%.
I have tried to simulate this for arbitrary number of years and arbitrary percentages using Python 3. The obvious added constraint is that sum of percentages is constant (otherwise, inconsistent arbitrarily high percentages will obviously beat consistent low percentages).
from operator import mul
from functools import reduce
import numpy as np
from collections import namedtuple
from typing import List, Tuple
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])
return (amount**(1/len(percents)) - 1)*100
def dirichlet(n: int = 5, amount: float = 100) -> List[float]:
'''Returns n random numbers which sum to "amount"'''
random_returns = np.random.dirichlet(alpha=np.ones(n), size=1)[0]*amount
return random_returns
def simulate_returns(n: int = 5, amount: float = 100, iterations: int = 40) -> List[Tuple[float, float]]:
'''Generate bunch of random percentages that sum to a constant and compare average CAGR with their deviation'''
net_returns = namedtuple('net_returns', 'deviation CAGR')
results = []
for _ in range(iterations):
random_returns = dirichlet(n, amount)
avg_returns = avg_cagr(random_returns)
deviation = np.std(random_returns)
results.append(net_returns(deviation, avg_returns))
return sorted(results, key=lambda x: x.CAGR, reverse=True)
if __name__ == '__main__':
results = simulate_returns()
print('\n'.join(('dev=' + str(round(result.deviation, 2)) + ', ' + 'CAGR=' + str(round(result.CAGR, 2))) for result in results))
Key Ideas in the code:
- Dirichlet distribution is used to generate bunch of random numbers that sum to a constant
- Standard deviation is used to illustrate consistency
Result: Simulation agrees with maxim.