-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsim.js
126 lines (101 loc) · 3.71 KB
/
sim.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const annualInflationRate = 0.02 // 2%
const annualInterestRate = 0.00 // 10%
const meanRetirementAge = 66 // 66 years
const meanStartingAge = 21 // 21 years
const jobToEarningsTimeline = require("./input/job-to-earnings-timeline.json")
const pretaxIncomeToPostTaxSavingData = require("./input/pretax-income-to-posttax-saving-portion.json")
function pretaxIncomeAmountToPostTaxSavingAmount(pretaxIncome) {
for (var j = 0; j < pretaxIncomeToPostTaxSavingData.quantileBounds.length; j++) {
if (pretaxIncome >= pretaxIncomeToPostTaxSavingData.quantileBounds[j][0] && pretaxIncome <= pretaxIncomeToPostTaxSavingData.quantileBounds[j][1]) {
break
}
}
// "quantileBounds": [
// [ 0, 24638 ],
// [ 24638, 47110 ],
// [ 47110, 77552 ],
// [ 77552, 126855 ],
// [ 126855, 1E10 ]
// ],
// "quantileData": {
// "0": {
// "totalIncome": 25525,
// "savingPortion": 0
// },
// "1": {
// "totalIncome": 37319,
// "savingPortion": 0
// },
// "2": {
// "totalIncome": 52431,
// "savingPortion": 0.055215426
// },
// "3": {
// "totalIncome": 86363,
// "savingPortion": 0.199796209
// },
// "4": {
// "totalIncome": 188102,
// "savingPortion": 0.265095533
// }
// }
// let slope = 0
// let offset = 0
// let dx = 0
// // special case on the left
// if (pretaxIncome < 24638) {
// slope = 0
// offset = 0
// dx = 0
// } else if (pretaxIncome < (24638 + 47110) / 2) {
// slope = 0
// offset = 24638
// dx = ((24638 + 47110) / 2) - pretaxIncome
// } else if (pretaxIncome < 47110) {
// slope = (0.055215426 / )
// } else if (pretaxIncome < (47110 + 0.5*(77552 - 47110))) {
// } else if (pretaxIncome < 77552) {
// } else if (pretaxIncome < 77552 + 0.5*(126855 - 77552)) {
// } else if (pretaxIncome < 126855) {
// } else {
// }
// return offset + (slope * dx)
return pretaxIncomeToPostTaxSavingData.quantileData[j].savingPortion * pretaxIncome
}
function getJobEarningsAtYear(jobName, yearsAfterInitialHire) {
const length = Object.keys(jobToEarningsTimeline[jobName]).length
return jobToEarningsTimeline[jobName][Math.min(yearsAfterInitialHire, length)]
// return (
// jobToEarningsTimeline[jobName][length - 1] +
// (
// jobToEarningsTimeline[jobName][length - 2] -
// jobToEarningsTimeline[jobName][length - 1]
// ) * (
// yearsAfterInitialHire - (length - 1)
// )
// )
}
const wealthTimelines = {}
for (var jobName in jobToEarningsTimeline) {
// console.log("Processing", jobName)
wealthTimelines[jobName] = [ getJobEarningsAtYear(jobName, 1) ]
for (var j = 2; j < meanRetirementAge - meanStartingAge; j++) {
wealthTimelines[jobName][j - 1] = (
(1 + annualInterestRate) * wealthTimelines[jobName][j - 2] +
pretaxIncomeAmountToPostTaxSavingAmount(getJobEarningsAtYear(jobName, j))
)
}
// console.log(jobName, "=>", wealthTimelines[jobName].length)
for (var j = 0; j < wealthTimelines[jobName].length; j++) {
wealthTimelines[jobName][j] *= Math.pow(1 - annualInflationRate, j)
}
}
let csv = `Year,${Object.keys(wealthTimelines).map(s => `"${s}"`).join(",")}\n`
for (var j = 0; j < meanRetirementAge - meanStartingAge - 1; ++j) {
csv += `${j}`
for (var jobName in wealthTimelines) {
csv += `,${wealthTimelines[jobName][j]}`
}
csv += `\n`
}
console.log(csv)