@calculator53295/backtest-engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -0
  3. package/dist/canonical/allocation.d.ts +64 -0
  4. package/dist/canonical/allocation.d.ts.map +1 -0
  5. package/dist/canonical/allocation.js +91 -0
  6. package/dist/canonical/allocation.js.map +1 -0
  7. package/dist/canonical/dates.d.ts +45 -0
  8. package/dist/canonical/dates.d.ts.map +1 -0
  9. package/dist/canonical/dates.js +86 -0
  10. package/dist/canonical/dates.js.map +1 -0
  11. package/dist/canonical/index.d.ts +12 -0
  12. package/dist/canonical/index.d.ts.map +1 -0
  13. package/dist/canonical/index.js +12 -0
  14. package/dist/canonical/index.js.map +1 -0
  15. package/dist/canonical/rebalance.d.ts +35 -0
  16. package/dist/canonical/rebalance.d.ts.map +1 -0
  17. package/dist/canonical/rebalance.js +56 -0
  18. package/dist/canonical/rebalance.js.map +1 -0
  19. package/dist/canonical/returns.d.ts +61 -0
  20. package/dist/canonical/returns.d.ts.map +1 -0
  21. package/dist/canonical/returns.js +65 -0
  22. package/dist/canonical/returns.js.map +1 -0
  23. package/dist/canonical/strategy.d.ts +62 -0
  24. package/dist/canonical/strategy.d.ts.map +1 -0
  25. package/dist/canonical/strategy.js +103 -0
  26. package/dist/canonical/strategy.js.map +1 -0
  27. package/dist/engine/align.d.ts +34 -0
  28. package/dist/engine/align.d.ts.map +1 -0
  29. package/dist/engine/align.js +97 -0
  30. package/dist/engine/align.js.map +1 -0
  31. package/dist/engine/backtest.d.ts +7 -0
  32. package/dist/engine/backtest.d.ts.map +1 -0
  33. package/dist/engine/backtest.js +95 -0
  34. package/dist/engine/backtest.js.map +1 -0
  35. package/dist/engine/frontier.d.ts +25 -0
  36. package/dist/engine/frontier.d.ts.map +1 -0
  37. package/dist/engine/frontier.js +40 -0
  38. package/dist/engine/frontier.js.map +1 -0
  39. package/dist/engine/index.d.ts +6 -0
  40. package/dist/engine/index.d.ts.map +1 -0
  41. package/dist/engine/index.js +5 -0
  42. package/dist/engine/index.js.map +1 -0
  43. package/dist/engine/metrics.d.ts +27 -0
  44. package/dist/engine/metrics.d.ts.map +1 -0
  45. package/dist/engine/metrics.js +202 -0
  46. package/dist/engine/metrics.js.map +1 -0
  47. package/dist/engine/types.d.ts +118 -0
  48. package/dist/engine/types.d.ts.map +1 -0
  49. package/dist/engine/types.js +2 -0
  50. package/dist/engine/types.js.map +1 -0
  51. package/dist/index.d.ts +25 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +25 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/montecarlo/data.d.ts +17 -0
  56. package/dist/montecarlo/data.d.ts.map +1 -0
  57. package/dist/montecarlo/data.js +38 -0
  58. package/dist/montecarlo/data.js.map +1 -0
  59. package/dist/montecarlo/simulate.d.ts +106 -0
  60. package/dist/montecarlo/simulate.d.ts.map +1 -0
  61. package/dist/montecarlo/simulate.js +264 -0
  62. package/dist/montecarlo/simulate.js.map +1 -0
  63. package/dist/retirement/bucketRules.d.ts +3 -0
  64. package/dist/retirement/bucketRules.d.ts.map +1 -0
  65. package/dist/retirement/bucketRules.js +37 -0
  66. package/dist/retirement/bucketRules.js.map +1 -0
  67. package/dist/retirement/engine.d.ts +7 -0
  68. package/dist/retirement/engine.d.ts.map +1 -0
  69. package/dist/retirement/engine.js +297 -0
  70. package/dist/retirement/engine.js.map +1 -0
  71. package/dist/retirement/index.d.ts +6 -0
  72. package/dist/retirement/index.d.ts.map +1 -0
  73. package/dist/retirement/index.js +6 -0
  74. package/dist/retirement/index.js.map +1 -0
  75. package/dist/retirement/runner.d.ts +15 -0
  76. package/dist/retirement/runner.d.ts.map +1 -0
  77. package/dist/retirement/runner.js +178 -0
  78. package/dist/retirement/runner.js.map +1 -0
  79. package/dist/retirement/strategies/index.d.ts +30 -0
  80. package/dist/retirement/strategies/index.d.ts.map +1 -0
  81. package/dist/retirement/strategies/index.js +270 -0
  82. package/dist/retirement/strategies/index.js.map +1 -0
  83. package/dist/retirement/types.d.ts +206 -0
  84. package/dist/retirement/types.d.ts.map +1 -0
  85. package/dist/retirement/types.js +2 -0
  86. package/dist/retirement/types.js.map +1 -0
  87. package/package.json +50 -0
@@ -0,0 +1,270 @@
1
+ // Convert annual real $ withdrawal to per-period amount given inflation + freq.
2
+ function perPeriod(annualNominal, periodsPerYear) {
3
+ return annualNominal / periodsPerYear;
4
+ }
5
+ // --------------------- constant-dollar ---------------------
6
+ const constantDollar = {
7
+ kind: 'constant-dollar',
8
+ defaults: { kind: 'constant-dollar', annualAmount: 40_000, inflationAdjusted: true, sourcing: 'proportional' },
9
+ decide(strategy, ctx) {
10
+ const s = strategy;
11
+ const factor = s.inflationAdjusted ? ctx.state.cpi / ctx.startCpi : 1;
12
+ return { amount: perPeriod(s.annualAmount * factor, ctx.periodsPerYear), sourcing: s.sourcing };
13
+ },
14
+ };
15
+ // --------------------- percent-of-portfolio ---------------------
16
+ const percentPortfolio = {
17
+ kind: 'percent-of-portfolio',
18
+ defaults: { kind: 'percent-of-portfolio', annualPct: 0.04, sourcing: 'proportional' },
19
+ decide(strategy, ctx) {
20
+ const s = strategy;
21
+ const b = ctx.state.balancesStart;
22
+ const total = b.stocks + b.bonds + b.cash;
23
+ const inflationFactor = ctx.state.cpi / ctx.startCpi;
24
+ let amountNominal = total * s.annualPct;
25
+ if (s.floorReal && s.floorReal > 0)
26
+ amountNominal = Math.max(amountNominal, s.floorReal * inflationFactor);
27
+ if (s.ceilingReal && s.ceilingReal > 0)
28
+ amountNominal = Math.min(amountNominal, s.ceilingReal * inflationFactor);
29
+ return { amount: perPeriod(amountNominal, ctx.periodsPerYear), sourcing: s.sourcing };
30
+ },
31
+ };
32
+ // --------------------- one-over-n ---------------------
33
+ const oneOverN = {
34
+ kind: 'one-over-n',
35
+ defaults: { kind: 'one-over-n', sourcing: 'proportional' },
36
+ decide(strategy, ctx) {
37
+ const s = strategy;
38
+ const b = ctx.state.balancesStart;
39
+ const total = b.stocks + b.bonds + b.cash;
40
+ const periodsLeft = Math.max(1, ctx.totalPeriods - ctx.state.index);
41
+ return { amount: total / periodsLeft, sourcing: s.sourcing };
42
+ },
43
+ };
44
+ // --------------------- VPW ---------------------
45
+ // Bogleheads-style: withdrawal rate rises with age. Simple closed-form (no lookup table dep).
46
+ // rate(age, horizon) ≈ 1 / annuityFactor(periodsLeft, realRate)
47
+ // We use a fixed real discount rate of 5% — close to the published table for 60/40.
48
+ const vpw = {
49
+ kind: 'vpw',
50
+ defaults: { kind: 'vpw', currentAge: 65, endAge: 100, sourcing: 'proportional' },
51
+ decide(strategy, ctx) {
52
+ const s = strategy;
53
+ const b = ctx.state.balancesStart;
54
+ const total = b.stocks + b.bonds + b.cash;
55
+ const yearsElapsed = Math.floor(ctx.state.index / ctx.periodsPerYear);
56
+ const age = s.currentAge + yearsElapsed;
57
+ const yearsLeft = Math.max(1, s.endAge - age);
58
+ const r = 0.05; // real discount rate
59
+ // Annuity-due-ish factor: (1 - (1+r)^-n) / r
60
+ const annuityFactor = (1 - Math.pow(1 + r, -yearsLeft)) / r;
61
+ const annualRate = 1 / annuityFactor;
62
+ return { amount: perPeriod(total * annualRate, ctx.periodsPerYear), sourcing: s.sourcing };
63
+ },
64
+ };
65
+ // --------------------- Guyton-Klinger ---------------------
66
+ // Implements the three rules in simplified form:
67
+ // - Withdrawal rule: inflation-adjust the prior real withdrawal each year.
68
+ // - Capital preservation: if current withdrawal rate > (1+guardrailCutPct) * initial, cut by cutAdjustPct.
69
+ // - Prosperity rule: if current rate < (1-guardrailRaisePct) * initial, raise by raiseAdjustPct.
70
+ // - Inflation rule: cap CPI growth (e.g. 6%) and skip the bump after a loss year if enabled.
71
+ const guytonKlinger = {
72
+ kind: 'guyton-klinger',
73
+ defaults: {
74
+ kind: 'guyton-klinger',
75
+ initialPct: 0.05,
76
+ guardrailRaisePct: 0.20,
77
+ guardrailCutPct: 0.20,
78
+ raiseAdjustPct: 0.10,
79
+ cutAdjustPct: 0.10,
80
+ inflationCap: 0.06,
81
+ skipInflationAfterLoss: true,
82
+ sourcing: 'proportional',
83
+ },
84
+ decide(strategy, ctx) {
85
+ const s = strategy;
86
+ const b = ctx.state.balancesStart;
87
+ const total = b.stocks + b.bonds + b.cash;
88
+ const inflationFactor = ctx.state.cpi / ctx.startCpi;
89
+ // initial real annual $ is initialPct of the starting portfolio (we re-derive each call —
90
+ // ctx doesn't carry it, but in real $ at startCpi that's effectively constant per cohort).
91
+ // We approximate "initial real $" as initialPct * total / (factor) at year 0; otherwise we
92
+ // use lastRealAnnualWithdrawal.
93
+ if (ctx.state.index === 0 || ctx.lastRealAnnualWithdrawal === undefined) {
94
+ const initialAnnual = total * s.initialPct;
95
+ return { amount: perPeriod(initialAnnual, ctx.periodsPerYear), sourcing: s.sourcing };
96
+ }
97
+ const prevRealAnnual = ctx.lastRealAnnualWithdrawal;
98
+ // Inflation rule: bump prior withdrawal by min(cpi-growth, cap). Skip if last period had a portfolio loss.
99
+ const prevCpi = ctx.prevState?.cpi ?? ctx.state.cpi;
100
+ const cpiGrowth = Math.min(s.inflationCap, Math.max(0, (ctx.state.cpi - prevCpi) / prevCpi));
101
+ let postLoss = false;
102
+ if (s.skipInflationAfterLoss && ctx.prevState) {
103
+ const prevReturns = ctx.prevState.returns;
104
+ const blended = prevReturns.stocks * 0.6 + prevReturns.bonds * 0.4;
105
+ postLoss = blended < 0;
106
+ }
107
+ let nextRealAnnual = prevRealAnnual * (1 + (postLoss ? 0 : cpiGrowth));
108
+ // Capital preservation / prosperity (apply on the nominal current rate vs initial rate).
109
+ const currentNominal = nextRealAnnual * inflationFactor;
110
+ const currentRate = currentNominal / total;
111
+ const upperGuardrail = s.initialPct * (1 + s.guardrailCutPct);
112
+ const lowerGuardrail = s.initialPct * (1 - s.guardrailRaisePct);
113
+ // Capital preservation only fires in the first ~15 years of horizon (per GK).
114
+ const yearsElapsed = ctx.state.index / ctx.periodsPerYear;
115
+ const yearsLeft = ctx.totalPeriods / ctx.periodsPerYear - yearsElapsed;
116
+ if (currentRate > upperGuardrail && yearsLeft > 15) {
117
+ nextRealAnnual *= (1 - s.cutAdjustPct);
118
+ }
119
+ else if (currentRate < lowerGuardrail) {
120
+ nextRealAnnual *= (1 + s.raiseAdjustPct);
121
+ }
122
+ const annualNominal = nextRealAnnual * inflationFactor;
123
+ return { amount: perPeriod(annualNominal, ctx.periodsPerYear), sourcing: s.sourcing };
124
+ },
125
+ };
126
+ // --------------------- CAPE-based ---------------------
127
+ // rate = multiplier + capeWeight / CAPE (Kitces).
128
+ const capeBased = {
129
+ kind: 'cape-based',
130
+ defaults: { kind: 'cape-based', multiplier: 0.0175, capeWeight: 0.50, floorPct: 0.025, ceilingPct: 0.08, sourcing: 'proportional' },
131
+ decide(strategy, ctx) {
132
+ const s = strategy;
133
+ const b = ctx.state.balancesStart;
134
+ const total = b.stocks + b.bonds + b.cash;
135
+ // CAPE not present? Fall back to multiplier alone — won't crash.
136
+ const cape = ctx.state.cape;
137
+ let rate = s.multiplier + (cape && cape > 0 ? s.capeWeight / cape : 0);
138
+ if (s.floorPct)
139
+ rate = Math.max(s.floorPct, rate);
140
+ if (s.ceilingPct)
141
+ rate = Math.min(s.ceilingPct, rate);
142
+ return { amount: perPeriod(total * rate, ctx.periodsPerYear), sourcing: s.sourcing };
143
+ },
144
+ };
145
+ // --------------------- 95% rule ---------------------
146
+ const ninetyFive = {
147
+ kind: '95-percent',
148
+ defaults: { kind: '95-percent', initialPct: 0.05, floorMultiplier: 0.95, sourcing: 'proportional' },
149
+ decide(strategy, ctx) {
150
+ const s = strategy;
151
+ const b = ctx.state.balancesStart;
152
+ const total = b.stocks + b.bonds + b.cash;
153
+ const inflationFactor = ctx.state.cpi / ctx.startCpi;
154
+ const pctAnnual = total * s.initialPct;
155
+ if (ctx.lastRealAnnualWithdrawal === undefined) {
156
+ return { amount: perPeriod(pctAnnual, ctx.periodsPerYear), sourcing: s.sourcing };
157
+ }
158
+ const floorAnnualNominal = ctx.lastRealAnnualWithdrawal * s.floorMultiplier * inflationFactor;
159
+ const annualNominal = Math.max(pctAnnual, floorAnnualNominal);
160
+ return { amount: perPeriod(annualNominal, ctx.periodsPerYear), sourcing: s.sourcing };
161
+ },
162
+ };
163
+ // --------------------- Endowment ---------------------
164
+ // withdrawal = alpha * (initialPct * total) + (1-alpha) * prior real withdrawal (inflation-adjusted).
165
+ const endowment = {
166
+ kind: 'endowment',
167
+ defaults: { kind: 'endowment', initialPct: 0.05, alpha: 0.30, sourcing: 'proportional' },
168
+ decide(strategy, ctx) {
169
+ const s = strategy;
170
+ const b = ctx.state.balancesStart;
171
+ const total = b.stocks + b.bonds + b.cash;
172
+ const inflationFactor = ctx.state.cpi / ctx.startCpi;
173
+ const pctAnnual = total * s.initialPct;
174
+ if (ctx.lastRealAnnualWithdrawal === undefined) {
175
+ return { amount: perPeriod(pctAnnual, ctx.periodsPerYear), sourcing: s.sourcing };
176
+ }
177
+ const priorAnnualNominal = ctx.lastRealAnnualWithdrawal * inflationFactor;
178
+ const annual = s.alpha * pctAnnual + (1 - s.alpha) * priorAnnualNominal;
179
+ return { amount: perPeriod(annual, ctx.periodsPerYear), sourcing: s.sourcing };
180
+ },
181
+ };
182
+ // --------------------- Vanguard Dynamic Spending ---------------------
183
+ // Bound the YoY change in real withdrawal to a ceiling/floor.
184
+ const vanguardDynamic = {
185
+ kind: 'vanguard-dynamic',
186
+ defaults: { kind: 'vanguard-dynamic', initialPct: 0.05, ceilingPct: 0.05, floorPct: 0.025, sourcing: 'proportional' },
187
+ decide(strategy, ctx) {
188
+ const s = strategy;
189
+ const b = ctx.state.balancesStart;
190
+ const total = b.stocks + b.bonds + b.cash;
191
+ const inflationFactor = ctx.state.cpi / ctx.startCpi;
192
+ const pctAnnual = total * s.initialPct;
193
+ if (ctx.lastRealAnnualWithdrawal === undefined) {
194
+ return { amount: perPeriod(pctAnnual, ctx.periodsPerYear), sourcing: s.sourcing };
195
+ }
196
+ // Compute real annual implied by pctAnnual:
197
+ const pctRealAnnual = pctAnnual / inflationFactor;
198
+ const maxReal = ctx.lastRealAnnualWithdrawal * (1 + s.ceilingPct);
199
+ const minReal = ctx.lastRealAnnualWithdrawal * (1 - s.floorPct);
200
+ const realAnnual = Math.max(minReal, Math.min(maxReal, pctRealAnnual));
201
+ return { amount: perPeriod(realAnnual * inflationFactor, ctx.periodsPerYear), sourcing: s.sourcing };
202
+ },
203
+ };
204
+ // --------------------- Legacy adapters ---------------------
205
+ const legacyFixedReal = {
206
+ kind: 'fixed-real',
207
+ defaults: { kind: 'fixed-real', annualAmount: 40_000, sourcing: 'proportional' },
208
+ decide(strategy, ctx) {
209
+ const s = strategy;
210
+ const inflation = ctx.state.cpi / ctx.startCpi;
211
+ return { amount: perPeriod(s.annualAmount * inflation, ctx.periodsPerYear), sourcing: s.sourcing };
212
+ },
213
+ };
214
+ const legacyFixedPct = {
215
+ kind: 'fixed-pct',
216
+ defaults: { kind: 'fixed-pct', annualPct: 0.04, sourcing: 'proportional' },
217
+ decide(strategy, ctx) {
218
+ const s = strategy;
219
+ const b = ctx.state.balancesStart;
220
+ const total = b.stocks + b.bonds + b.cash;
221
+ return { amount: perPeriod(total * s.annualPct, ctx.periodsPerYear), sourcing: s.sourcing };
222
+ },
223
+ };
224
+ const legacyGuardrails = {
225
+ kind: 'guardrails',
226
+ defaults: { kind: 'guardrails', initialPct: 0.04, sourcing: 'proportional' },
227
+ decide(strategy, ctx) {
228
+ const s = strategy;
229
+ const b = ctx.state.balancesStart;
230
+ const total = b.stocks + b.bonds + b.cash;
231
+ const inflation = ctx.state.cpi / ctx.startCpi;
232
+ return { amount: perPeriod(total * (s.initialPct * inflation), ctx.periodsPerYear), sourcing: s.sourcing };
233
+ },
234
+ };
235
+ const interactive = {
236
+ kind: 'interactive',
237
+ defaults: { kind: 'interactive' },
238
+ decide() {
239
+ throw new Error('Interactive strategy must be driven by Play Mode, not the engine.');
240
+ },
241
+ };
242
+ export const STRATEGY_REGISTRY = {
243
+ 'constant-dollar': constantDollar,
244
+ 'percent-of-portfolio': percentPortfolio,
245
+ 'one-over-n': oneOverN,
246
+ vpw,
247
+ 'guyton-klinger': guytonKlinger,
248
+ 'cape-based': capeBased,
249
+ '95-percent': ninetyFive,
250
+ endowment,
251
+ 'vanguard-dynamic': vanguardDynamic,
252
+ 'fixed-real': legacyFixedReal,
253
+ 'fixed-pct': legacyFixedPct,
254
+ guardrails: legacyGuardrails,
255
+ interactive,
256
+ };
257
+ export function getStrategyDef(kind) {
258
+ return STRATEGY_REGISTRY[kind];
259
+ }
260
+ export function strategyDecide(strategy, ctx) {
261
+ const def = STRATEGY_REGISTRY[strategy.kind];
262
+ return def.decide(strategy, ctx);
263
+ }
264
+ /** Helper to extract the sourcing field from any strategy that has one. */
265
+ export function getSourcing(strategy) {
266
+ if ('sourcing' in strategy)
267
+ return strategy.sourcing;
268
+ return 'proportional';
269
+ }
270
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/retirement/strategies/index.ts"],"names":[],"mappings":"AAyBA,gFAAgF;AAChF,SAAS,SAAS,CAAC,aAAqB,EAAE,cAAsB;IAC9D,OAAO,aAAa,GAAG,cAAc,CAAC;AACxC,CAAC;AAED,8DAA8D;AAC9D,MAAM,cAAc,GAAgB;IAClC,IAAI,EAAE,iBAAiB;IACvB,QAAQ,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE;IAC9G,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAAoE,CAAC;QAC/E,MAAM,MAAM,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,YAAY,GAAG,MAAM,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAClG,CAAC;CACF,CAAC;AAEF,mEAAmE;AACnE,MAAM,gBAAgB,GAAgB;IACpC,IAAI,EAAE,sBAAsB;IAC5B,QAAQ,EAAE,EAAE,IAAI,EAAE,sBAAsB,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE;IACrF,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAAyE,CAAC;QACpF,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,MAAM,eAAe,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;QACrD,IAAI,aAAa,GAAG,KAAK,GAAG,CAAC,CAAC,SAAS,CAAC;QACxC,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC;YAAE,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,SAAS,GAAG,eAAe,CAAC,CAAC;QAC3G,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC;YAAE,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,WAAW,GAAG,eAAe,CAAC,CAAC;QACjH,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,aAAa,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACxF,CAAC;CACF,CAAC;AAEF,yDAAyD;AACzD,MAAM,QAAQ,GAAgB;IAC5B,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE;IAC1D,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAA+D,CAAC;QAC1E,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpE,OAAO,EAAE,MAAM,EAAE,KAAK,GAAG,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC/D,CAAC;CACF,CAAC;AAEF,kDAAkD;AAClD,8FAA8F;AAC9F,gEAAgE;AAChE,oFAAoF;AACpF,MAAM,GAAG,GAAgB;IACvB,IAAI,EAAE,KAAK;IACX,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,EAAE;IAChF,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAAwD,CAAC;QACnE,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC;QACtE,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,GAAG,YAAY,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,qBAAqB;QACrC,6CAA6C;QAC7C,MAAM,aAAa,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,UAAU,GAAG,CAAC,GAAG,aAAa,CAAC;QACrC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,GAAG,UAAU,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC7F,CAAC;CACF,CAAC;AAEF,6DAA6D;AAC7D,iDAAiD;AACjD,6EAA6E;AAC7E,6GAA6G;AAC7G,mGAAmG;AACnG,+FAA+F;AAC/F,MAAM,aAAa,GAAgB;IACjC,IAAI,EAAE,gBAAgB;IACtB,QAAQ,EAAE;QACR,IAAI,EAAE,gBAAgB;QACtB,UAAU,EAAE,IAAI;QAChB,iBAAiB,EAAE,IAAI;QACvB,eAAe,EAAE,IAAI;QACrB,cAAc,EAAE,IAAI;QACpB,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;QAClB,sBAAsB,EAAE,IAAI;QAC5B,QAAQ,EAAE,cAAc;KACzB;IACD,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAAmE,CAAC;QAC9E,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,MAAM,eAAe,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;QACrD,0FAA0F;QAC1F,2FAA2F;QAC3F,2FAA2F;QAC3F,gCAAgC;QAChC,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC,wBAAwB,KAAK,SAAS,EAAE,CAAC;YACxE,MAAM,aAAa,GAAG,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC;YAC3C,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,aAAa,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxF,CAAC;QACD,MAAM,cAAc,GAAG,GAAG,CAAC,wBAAwB,CAAC;QACpD,2GAA2G;QAC3G,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,EAAE,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;QACpD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;QAC7F,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,CAAC,sBAAsB,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YAC9C,MAAM,WAAW,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC;YAC1C,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG,GAAG,WAAW,CAAC,KAAK,GAAG,GAAG,CAAC;YACnE,QAAQ,GAAG,OAAO,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,cAAc,GAAG,cAAc,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QACvE,yFAAyF;QACzF,MAAM,cAAc,GAAG,cAAc,GAAG,eAAe,CAAC;QACxD,MAAM,WAAW,GAAG,cAAc,GAAG,KAAK,CAAC;QAC3C,MAAM,cAAc,GAAG,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;QAC9D,MAAM,cAAc,GAAG,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC;QAChE,8EAA8E;QAC9E,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,cAAc,CAAC;QAC1D,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,cAAc,GAAG,YAAY,CAAC;QACvE,IAAI,WAAW,GAAG,cAAc,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC;YACnD,cAAc,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC;aAAM,IAAI,WAAW,GAAG,cAAc,EAAE,CAAC;YACxC,cAAc,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,aAAa,GAAG,cAAc,GAAG,eAAe,CAAC;QACvD,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,aAAa,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACxF,CAAC;CACF,CAAC;AAEF,yDAAyD;AACzD,kDAAkD;AAClD,MAAM,SAAS,GAAgB;IAC7B,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE;IACnI,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAA+D,CAAC;QAC1E,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,iEAAiE;QACjE,MAAM,IAAI,GAAI,GAAG,CAAC,KAAyC,CAAC,IAAI,CAAC;QACjE,IAAI,IAAI,GAAG,CAAC,CAAC,UAAU,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,CAAC,QAAQ;YAAE,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,CAAC,UAAU;YAAE,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACtD,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACvF,CAAC;CACF,CAAC;AAEF,uDAAuD;AACvD,MAAM,UAAU,GAAgB;IAC9B,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE;IACnG,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAA+D,CAAC;QAC1E,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,MAAM,eAAe,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;QACrD,MAAM,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC;QACvC,IAAI,GAAG,CAAC,wBAAwB,KAAK,SAAS,EAAE,CAAC;YAC/C,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACpF,CAAC;QACD,MAAM,kBAAkB,GAAG,GAAG,CAAC,wBAAwB,GAAG,CAAC,CAAC,eAAe,GAAG,eAAe,CAAC;QAC9F,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAC9D,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,aAAa,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACxF,CAAC;CACF,CAAC;AAEF,wDAAwD;AACxD,sGAAsG;AACtG,MAAM,SAAS,GAAgB;IAC7B,IAAI,EAAE,WAAW;IACjB,QAAQ,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE;IACxF,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAA8D,CAAC;QACzE,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,MAAM,eAAe,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;QACrD,MAAM,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC;QACvC,IAAI,GAAG,CAAC,wBAAwB,KAAK,SAAS,EAAE,CAAC;YAC/C,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACpF,CAAC;QACD,MAAM,kBAAkB,GAAG,GAAG,CAAC,wBAAwB,GAAG,eAAe,CAAC;QAC1E,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC;QACxE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjF,CAAC;CACF,CAAC;AAEF,wEAAwE;AACxE,8DAA8D;AAC9D,MAAM,eAAe,GAAgB;IACnC,IAAI,EAAE,kBAAkB;IACxB,QAAQ,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE;IACrH,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAAqE,CAAC;QAChF,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,MAAM,eAAe,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;QACrD,MAAM,SAAS,GAAG,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC;QACvC,IAAI,GAAG,CAAC,wBAAwB,KAAK,SAAS,EAAE,CAAC;YAC/C,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACpF,CAAC;QACD,4CAA4C;QAC5C,MAAM,aAAa,GAAG,SAAS,GAAG,eAAe,CAAC;QAClD,MAAM,OAAO,GAAG,GAAG,CAAC,wBAAwB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,GAAG,CAAC,wBAAwB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAChE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;QACvE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,UAAU,GAAG,eAAe,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACvG,CAAC;CACF,CAAC;AAEF,8DAA8D;AAC9D,MAAM,eAAe,GAAgB;IACnC,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE;IAChF,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAA+D,CAAC;QAC1E,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;QAC/C,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,YAAY,GAAG,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrG,CAAC;CACF,CAAC;AAEF,MAAM,cAAc,GAAgB;IAClC,IAAI,EAAE,WAAW;IACjB,QAAQ,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE;IAC1E,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAA8D,CAAC;QACzE,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC9F,CAAC;CACF,CAAC;AAEF,MAAM,gBAAgB,GAAgB;IACpC,IAAI,EAAE,YAAY;IAClB,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE;IAC5E,MAAM,CAAC,QAAQ,EAAE,GAAG;QAClB,MAAM,CAAC,GAAG,QAA+D,CAAC;QAC1E,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QAC1C,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;QAC/C,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,UAAU,GAAG,SAAS,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC7G,CAAC;CACF,CAAC;AAEF,MAAM,WAAW,GAAgB;IAC/B,IAAI,EAAE,aAAa;IACnB,QAAQ,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE;IACjC,MAAM;QACJ,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACvF,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAsC;IAClE,iBAAiB,EAAE,cAAc;IACjC,sBAAsB,EAAE,gBAAgB;IACxC,YAAY,EAAE,QAAQ;IACtB,GAAG;IACH,gBAAgB,EAAE,aAAa;IAC/B,YAAY,EAAE,SAAS;IACvB,YAAY,EAAE,UAAU;IACxB,SAAS;IACT,kBAAkB,EAAE,eAAe;IACnC,YAAY,EAAE,eAAe;IAC7B,WAAW,EAAE,cAAc;IAC3B,UAAU,EAAE,gBAAgB;IAC5B,WAAW;CACZ,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,IAAkB;IAC/C,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAA4B,EAAE,GAAoB;IAC/E,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,WAAW,CAAC,QAA4B;IACtD,IAAI,UAAU,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,QAAQ,CAAC;IACrD,OAAO,cAAc,CAAC;AACxB,CAAC"}
@@ -0,0 +1,206 @@
1
+ export type Buckets = {
2
+ stocks: number;
3
+ bonds: number;
4
+ cash: number;
5
+ };
6
+ export type Allocation = Buckets;
7
+ export type Returns = Buckets;
8
+ export type StepFreq = 'monthly' | 'annual';
9
+ export type RebalancePolicy = 'none' | 'yearly' | 'every-n-years' | 'on-withdrawal' | 'threshold';
10
+ export type RebalanceConfig = {
11
+ policy: RebalancePolicy;
12
+ everyN?: number;
13
+ bandPct?: number;
14
+ };
15
+ export type BucketSourcing = 'proportional' | 'cash-first' | 'stocks-first' | 'bonds-first' | 'best-performer';
16
+ export type LegacyConstantDollarStrategy = {
17
+ kind: 'fixed-real';
18
+ annualAmount: number;
19
+ sourcing: BucketSourcing;
20
+ };
21
+ export type LegacyPercentStrategy = {
22
+ kind: 'fixed-pct';
23
+ annualPct: number;
24
+ sourcing: BucketSourcing;
25
+ };
26
+ export type LegacyGuardrailsStrategy = {
27
+ kind: 'guardrails';
28
+ initialPct: number;
29
+ sourcing: BucketSourcing;
30
+ raiseThreshold?: number;
31
+ cutThreshold?: number;
32
+ };
33
+ export type InteractiveStrategy = {
34
+ kind: 'interactive';
35
+ };
36
+ export type ConstantDollarStrategy = {
37
+ kind: 'constant-dollar';
38
+ annualAmount: number;
39
+ inflationAdjusted: boolean;
40
+ sourcing: BucketSourcing;
41
+ };
42
+ export type PercentPortfolioStrategy = {
43
+ kind: 'percent-of-portfolio';
44
+ annualPct: number;
45
+ floorReal?: number;
46
+ ceilingReal?: number;
47
+ sourcing: BucketSourcing;
48
+ };
49
+ export type OneOverNStrategy = {
50
+ kind: 'one-over-n';
51
+ sourcing: BucketSourcing;
52
+ };
53
+ export type VpwStrategy = {
54
+ kind: 'vpw';
55
+ currentAge: number;
56
+ endAge: number;
57
+ sourcing: BucketSourcing;
58
+ };
59
+ export type GuytonKlingerStrategy = {
60
+ kind: 'guyton-klinger';
61
+ initialPct: number;
62
+ guardrailRaisePct: number;
63
+ guardrailCutPct: number;
64
+ raiseAdjustPct: number;
65
+ cutAdjustPct: number;
66
+ inflationCap: number;
67
+ skipInflationAfterLoss: boolean;
68
+ sourcing: BucketSourcing;
69
+ };
70
+ export type CapeBasedStrategy = {
71
+ kind: 'cape-based';
72
+ multiplier: number;
73
+ capeWeight: number;
74
+ floorPct?: number;
75
+ ceilingPct?: number;
76
+ sourcing: BucketSourcing;
77
+ };
78
+ export type NinetyFivePercentStrategy = {
79
+ kind: '95-percent';
80
+ initialPct: number;
81
+ floorMultiplier: number;
82
+ sourcing: BucketSourcing;
83
+ };
84
+ export type EndowmentStrategy = {
85
+ kind: 'endowment';
86
+ alpha: number;
87
+ initialPct: number;
88
+ sourcing: BucketSourcing;
89
+ };
90
+ export type VanguardDynamicStrategy = {
91
+ kind: 'vanguard-dynamic';
92
+ initialPct: number;
93
+ ceilingPct: number;
94
+ floorPct: number;
95
+ sourcing: BucketSourcing;
96
+ };
97
+ export type WithdrawalStrategy = LegacyConstantDollarStrategy | LegacyPercentStrategy | LegacyGuardrailsStrategy | InteractiveStrategy | ConstantDollarStrategy | PercentPortfolioStrategy | OneOverNStrategy | VpwStrategy | GuytonKlingerStrategy | CapeBasedStrategy | NinetyFivePercentStrategy | EndowmentStrategy | VanguardDynamicStrategy;
98
+ export type StrategyKind = WithdrawalStrategy['kind'];
99
+ export type CashflowStream = {
100
+ id: string;
101
+ name: string;
102
+ annualAmount: number;
103
+ startYear: number;
104
+ duration: number | 'forever';
105
+ inflationAdjusted: boolean;
106
+ inflationStartsImmediately: boolean;
107
+ enabled: boolean;
108
+ };
109
+ export type IncomeStream = CashflowStream;
110
+ export type ExtraWithdrawal = CashflowStream;
111
+ export type GlidePath = {
112
+ enabled: boolean;
113
+ finalAllocation: Allocation;
114
+ shape: 'linear' | 'quadratic-in' | 'quadratic-out';
115
+ };
116
+ export type FeeConfig = {
117
+ stocks: number;
118
+ bonds: number;
119
+ cash: number;
120
+ };
121
+ export type PeriodState = {
122
+ index: number;
123
+ date: string;
124
+ cpi: number;
125
+ returns: Returns;
126
+ balancesStart: Buckets;
127
+ withdrawal: Buckets;
128
+ balancesEnd: Buckets;
129
+ totalReal: number;
130
+ totalNominal: number;
131
+ grossWithdrawal?: number;
132
+ netWithdrawal?: number;
133
+ incomeReceived?: number;
134
+ feesPaid?: number;
135
+ };
136
+ export type SimConfig = {
137
+ startDate: string;
138
+ horizonYears: number;
139
+ stepFreq: StepFreq;
140
+ initialBalance: number;
141
+ initialAllocation: Allocation;
142
+ strategy: WithdrawalStrategy;
143
+ rebalance: RebalancePolicy;
144
+ rebalanceConfig?: RebalanceConfig;
145
+ fees?: FeeConfig;
146
+ glidePath?: GlidePath;
147
+ income?: IncomeStream[];
148
+ extraWithdrawals?: ExtraWithdrawal[];
149
+ };
150
+ export type TrialSummary = {
151
+ maxDrawdownReal: number;
152
+ maxDrawdownPeriod: number;
153
+ timeUnderwaterFraction: number;
154
+ worstYearReturn: number;
155
+ totalRealWithdrawn: number;
156
+ withdrawalCV: number;
157
+ };
158
+ export type TrialResult = {
159
+ config: SimConfig;
160
+ startDate: string;
161
+ periods: PeriodState[];
162
+ ranOutAtPeriod: number | null;
163
+ endBalanceReal: number;
164
+ endBalanceNominal: number;
165
+ summary?: TrialSummary;
166
+ };
167
+ export type Quantiles = {
168
+ p5: number;
169
+ p10: number;
170
+ p25: number;
171
+ p50: number;
172
+ p75: number;
173
+ p90: number;
174
+ p95: number;
175
+ };
176
+ export type RunSummary = {
177
+ count: number;
178
+ successRate: number;
179
+ endBalanceReal: Quantiles;
180
+ endBalanceNominal: Quantiles;
181
+ withdrawalRealByYear: Quantiles[];
182
+ balanceRealByYear: Quantiles[];
183
+ timeToRuin: number[];
184
+ medianMaxDrawdown: number;
185
+ meanMaxDrawdown: number;
186
+ medianTimeUnderwater: number;
187
+ worstCohortStart: string;
188
+ bestCohortStart: string;
189
+ sequenceRiskScore: number;
190
+ withdrawalVolatility: number;
191
+ startDates: string[];
192
+ };
193
+ export type RunResult = {
194
+ trials: TrialResult[];
195
+ summary: RunSummary;
196
+ configHash: string;
197
+ };
198
+ export type HistoricalRow = {
199
+ date: string;
200
+ spReturn: number;
201
+ bondReturn: number;
202
+ cashReturn: number;
203
+ cpi: number;
204
+ cape?: number;
205
+ };
206
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/retirement/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/retirement/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@calculator53295/backtest-engine",
3
+ "version": "0.1.0",
4
+ "description": "Pure TypeScript backtest and retirement-simulation engine with zero runtime dependencies: daily TWR/IRR backtesting, Monte Carlo retirement simulation, and a historical cohort engine with nine withdrawal strategies.",
5
+ "license": "MIT",
6
+ "author": "Calculator5329",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Calculator5329/finance-kit.git",
10
+ "directory": "packages/backtest-engine"
11
+ },
12
+ "homepage": "https://github.com/Calculator5329/finance-kit/tree/main/packages/backtest-engine#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/Calculator5329/finance-kit/issues"
15
+ },
16
+ "type": "module",
17
+ "sideEffects": false,
18
+ "main": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js"
24
+ },
25
+ "./retirement": {
26
+ "types": "./dist/retirement/index.d.ts",
27
+ "import": "./dist/retirement/index.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "scripts": {
37
+ "build": "tsc --build",
38
+ "typecheck": "tsc -p tsconfig.test.json"
39
+ },
40
+ "dependencies": {},
41
+ "keywords": [
42
+ "backtest",
43
+ "twr",
44
+ "irr",
45
+ "monte-carlo",
46
+ "retirement",
47
+ "withdrawal-strategies",
48
+ "portfolio"
49
+ ]
50
+ }