Skip to content

Instantly share code, notes, and snippets.

@aresnick
Last active January 4, 2016 03:26
Show Gist options
  • Save aresnick/af342f19c3d2102ddeb1 to your computer and use it in GitHub Desktop.
Save aresnick/af342f19c3d2102ddeb1 to your computer and use it in GitHub Desktop.
var baseline_coc = 0.06; // What baseline investment should we compare this program to?
var annual_interest = 0.08; // What interest rate will we charge residents if they abandon their initiative?
var initial_loan = 50000.0; // Assume everyone begins with a $50K debt
var minimum_payment = { 'active': 500, 'inactive': 1000 } // If someone's initiative is active, offer a reduced minimum payment ($500/m) compared to $1000/m otherwise
var annual_deactivation_probability = 0.3; // How likely is it in any given year than an initiative shuts down?
var yearly_enrollment = [5, 10, 15, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20]; // Over the first 15 years, how many residents are enrolled per year?
// Variables of interest we'll be measuring over the course of runs
var total_paid = 0;
var lost_interest = 0;
var profit_over_baseline = 0;
var t = 0;
var Member = function() {
var self = this;
self.t_born = t;
self.t_dead = null;
self.age_at_death = null;
self.active = true;
self.balance = initial_loan;
self.minimum_annual_payment = self.active ? minimum_payment['active'] : minimum_payment['inactive'];
self.pay = function(amount) { // For a given Member, pay back `amount` of their loan
total_paid += amount;
self.balance -= amount;
};
self.grow_balance = function() { // Increment the balance each year
if (self.active) {
self.balance += 0;
lost_interest += annual_interest * self.balance;
} else {
self.balance *= (1 + annual_interest);
profit_over_baseline += (annual_interest - baseline_coc) * self.balance;
}
};
self.increment_year = function() { // Increment the year
if (self.active) {
if (Math.random() < annual_deactivation_probability) { // Simulate deactivation and record timeline if deactivating
self.active = false;
self.t_dead = t;
self.age_at_death = self.t_dead - self.t_born;
}
}
self.pay(self.minimum_annual_payment);
self.grow_balance();
};
self.get_age = function () {
return t - self.t_born;
}
};
var run = function() { // Simulate a run
t = 0;
total_paid = 0;
lost_interest = 0;
profit_over_baseline = 0;
var members = [];
// For each of the 15y of the program, simulate members' growth over time
yearly_enrollment.forEach(function(count) {
for (var i = 0; i < count; ++i) {
members.push(new Member());
};
members.forEach(function(member) {
member.increment_year();
});
t += 1;
});
// Log results
var results = {};
results["Total alumni"] = members.length;
var active_alumni = members.filter(function(m) {
return m.active;
});
results["Total active alumni"] = active_alumni.length;
var inactive_alumni = members.filter(function(m) { return !m.active; });
results["age_at_death"] = inactive_alumni.map(function(m) { return m.age_at_death; }).reduce(function(a,b) { return a + b; })/inactive_alumni.length;
results["Average living age"] = active_alumni.map(function(m) { return m.get_age(); }).reduce(function(a,b) { return a + b; })/active_alumni.length;
results["Invested principal"] = 50000 * members.length;
results["Outstanding balances"] = members.map(function(m) {
return m.balance;
}).reduce(function(a, b) {
return a + b;
});
results["Total paid"] = total_paid;
results["Lost interest"] = lost_interest;
results["Profit from inactive members"] = profit_over_baseline;
results["Net cost"] = profit_over_baseline - lost_interest;
return results;
};
// Simulate over num_runs (10K) runs
var num_runs = 10000;
var runs = [];
for (var i = 0; i < num_runs; ++i) {
runs.push(run());
};
// Average simulation results
var average = {};
Object.keys(runs[0]).forEach(function(key) {
average[key] = runs.map(function(r) {
return r[key];
}).reduce(function(a, b) {
return a + b;
}) / runs.length;
});
// Log out results
console.log(average);
///////////////////////////////////////////////////////////////////////////////
// Sample run results (10K)
//
// { 'Total alumni': 270,
// 'Total active alumni': 46.1633,
// age_at_death: 1.6657111417978643,
// 'Average living age': 3.213380739663558,
// 'Invested principal': 13500000,
// 'Outstanding balances': 20044032.82097633,
// 'Total paid': 985000,
// 'Lost interest': 2030810.98,
// 'Profit from inactive members': 2032838.8616636116,
// 'Net cost': 2027.8816636019956 }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment