Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@jmillerinc
Created April 27, 2010 10:34
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jmillerinc/380603 to your computer and use it in GitHub Desktop.
Save jmillerinc/380603 to your computer and use it in GitHub Desktop.
Monte Carlo simulation of the payoffs to angel investing
#!/usr/bin/python
#
# Monte Carlo simulation of the payoffs to angel investing.
#
# Assume a pool of N different investors, each investing in D deals,
# with a fixed time horizon and a fixed distribution of payoffs.
# Randomly simulate each investor's total payoff, then compute the
# mean and std dev of all IRRs in the overall pool.
#
# This gives an individual angel an idea of what kind of payoff &
# variance to expect from investing in a certain # of deals.
#
# Written by Jeff Miller @jmillerinc.
#
# See: http://jmillerinc.com/2010/04/27/angel-investing-simulation
#
# Payoff distribution from http://www.gabrielweinberg.com/blog/2010/03/
# angel-investing-portfolio-scenario-planner-spreadsheet.html
import math
import optparse
import random
DEFAULT_NUM_INVESTORS = 10000
DEFAULT_NUM_DEALS = 20
NUM_YEARS = 5
PROBS = [.50, .20, .15, .13, .02]
PAYOFFS = [ 0, 1, 3, 10, 20]
def random_draw(cum_probs):
"""Randomly draw from a discrete distribution with the given
cumulative probabilities. Return the index of the probability
bucket that was drawn."""
z = random.random()
for i, p in enumerate(cum_probs):
if z <= p:
return i
raise Exception('Execution should never reach this point: ' +
'cumulative probabilities are invalid.')
def cumulative_probabilities(probs):
"""Given a discrete distribution as a list of probabilities,
return the list of cumulative probabilities."""
result = [sum(probs[0:i+1]) for i in range(len(probs))]
assert abs(result[-1] - 1.0) < 1e-6
return result
if __name__ == '__main__':
option_parser = optparse.OptionParser()
option_parser.add_option('-n', type='int', dest='num_investors', default=DEFAULT_NUM_INVESTORS,
metavar='N', help='Simulate N investors (default %d)' % DEFAULT_NUM_INVESTORS)
option_parser.add_option('-d', type='int', dest='num_deals', default=DEFAULT_NUM_DEALS,
metavar='D', help='Simulate D deals per investor (default %d)' % DEFAULT_NUM_DEALS)
options, args = option_parser.parse_args()
num_investors = options.num_investors
num_deals = options.num_deals
# Simulate N investors doing D deals each.
n = 0
summ = 0.0
summ2 = 0.0
cum_probs = cumulative_probabilities(PROBS)
deal_size = 1.0/float(num_deals)
for i in range(num_investors):
total_payoff = sum(deal_size * PAYOFFS[random_draw(cum_probs)] for j in range(num_deals))
irr = pow(total_payoff, 1.0/NUM_YEARS) - 1
summ += irr
summ2 += irr*irr
n += 1
mean_irr = summ/n
std_irr = math.sqrt((summ2 - summ*summ/n)/(n-1))
print 'N = %5d D = %3d mean_irr = %8.4f std_irr = %8.4f' % (num_investors, num_deals, mean_irr, std_irr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment