Translated from the Spanish original. Where they differ, the Spanish one holds.
- App: Horalis Growth (and Horalis Cost of Living, phase B3) · Reviewed: 9 October 2026 (phase A4 of the Horalis plan)
- Engine (A4):
packages/seed-kit/src/withdrawal-rate.ts(maxRate,safeRate,steadyRate,withEarlyCrash) and its testpackages/seed-kit/test/withdrawal-rate.test.ts; in Growth,src/lib/safe-rate.ts(safeRateFor,planWithdrawalRate,similarAsset,worstFall) andsrc/components/money/pay-details.tsx; the one-line sentence, inpackages/seed-kit/src/words/(withdrawal.why). - Code (in
projects/wealth-lens/):src/lib/monte-carlo.ts(survives,successRates,yearsLasting),src/lib/withdrawal.ts(the slider's steps and zones),src/lib/success-table.ts(precalculated rates),src/lib/finance.ts(monthlyWithdrawal,requiredCapital),src/lib/mix.ts(mixSuccessRates)
The question it answers
"When I finish saving, how much could I take out each month, and how long would it last?" It is "Could pay you each month", the slider from 2 % to 7 %, "lasted 30 years in N of 100 futures" and its zone (prudent, risky, very risky). The same rate decides which countries and monthly goals are "enough".
The rate the data back (phase A4)
Question: "How much could I take out each year without it running out, according to what has already happened?" Before, the starting rate was a fixed 4 % for everything. Now it is, for each investment, the highest yearly rate, fixed after the rise in prices, that would have lasted 30 years starting in any year of its data, the worst included (Bengen's method, 1994).
In plain words: starting the withdrawal in each year of history is tried (1928, 1929, 1930…). For each start, the highest rate with which the money manages to pay the 30 years is searched for. The investment's rate is the lowest of all of those: that of the worst start.
Exact, for a start with real returns r₁…r_N (a withdrawal at the start of each year, then the rest grows):
- N withdrawals of w last if
w × (1 + 1/(1+r₁) + 1/((1+r₁)(1+r₂)) + … + 1/((1+r₁)…(1+r_{N−1}))) ≤ 1; - the highest rate of that start is 1 divided by that sum (
maxRate); as the sum only grows, every balance in between stays above zero; - the investment's rate is the minimum over every start with N whole years (
safeRate), and which year was the worst and how many starts ("periods") lie behind it are kept.
Each investment:
| Investment | Years of data | 30-year rate | Worst start | Periods |
|---|---|---|---|---|
| US shares (Shiller) | 1928–2022 | 3.78 % | 1929 | 66 |
| German bonds | 1988–2024 | 5.56 % | 1994 | 8 (few) |
| Gold (World Bank) | 1988–2024 | 2.22 % | 1988 | 8 (few) |
| 60/40 mix of shares and bonds, reweighted each year | 1988–2022 | 7.58 % | 1990 | 6 (few) |
| Savings account (1.5 % − 2 % inflation) | grows the same each year | 3.10 % | — | — |
- All the years of each asset are used, not only the common ones (1988–2022): when looking for the worst start, more years can only find a worse one. That is why US shares include 1929 and 1966.
- Few periods. With fewer than 10 starts (
FEW_PERIODS), with data of less than twice the years (fewer than two periods that do not overlap: ten periods of 30 years that share 21 are still a single era, and this rule does not switch itself off by adding a year at each update), or if the data have fewer years than asked (then all their years are used: a single period), the page says so in the same sentence as the rate: "Only 8 periods of German bonds: a rough guide. 5.56 %, € … a month." (and, if needed, "The data only have N years, not 30"). - Rounding. The rate the app uses is rounded down to the hundredth of a point (
floorRate): the exact one empties the money just with the last withdrawal, and a rounding error could leave it a cent short of lasting (the screen said both "lasts 30 years" and "runs out at 29"). - Words. "The most that lasted 30 years", "held", and always "What held in the past is not a promise" (inform, do not advise, rules 5 and 8). The brief's sentence says "safe rate": it is kept because it is the owner's, who must decide whether it becomes "the rate that held". The bonds and the 60/40 mix come out high precisely because of that: their data only cover one period of falling interest rates.
- A mix uses the years all its parts have, at each part's weight each year (even if the plan lets the weights drift: it is an approximation).
- Savings, or growth without ups and downs: it grows the same each year, so there is a single answer (
steadyRate). - "My %" (own growth): it has no history. The rate is chosen by the person; the starting one is that of the most similar asset (the one with the closest swing; on a tie, the one with the closest growth), never above that of the asset with the longest history (US shares, 66 periods), and the page says whose it is ("It starts at the rate of US shares: 3.78 %…"; with few periods, the warning). The page shows what would happen with a fall like that asset's worst year at the start and then its own growth each year (
withEarlyCrash): "First, a fall like the worst year of US stocks (−38%, 1931). €100,000 would become €62,000. Then 5 %, € … a month, runs out after 17 years" (with an own growth of 5 %): the fall, with its money. - Below, always, the one-line sentence (reusable by any tool): "More return usually brings sharper falls. A fall at the start of the withdrawal forces selling cheap. That is why the safe rate does not rise as much." (The brief's, split into three short sentences by the 12-word rule.)
- The plan's rate:
withdrawalRate: nullmeans "the data's", and it follows the investment if it changes. The slider offers from 2 % to 7 % every 0.5 % plus the data's rate, wherever it is; any other step is the person's choice ("You chose 5 %" and "Use the data's rate"). A "What if…?" changes the view, not the data's rate. - Files: version 13. Before, every plan started at 4 %, which cannot be told apart from a choice: a 4 % from an earlier file moves to the data's rate; any other rate is kept.
Edge cases (tests)
- No growth: 1 ÷ years (25 years → 4 %); a single year → 100 %.
- Fixed growth: the exact annuity due.
- The rate found lasts when played year by year, and 0.1 % more no longer does.
- The same series with the fall at the start gives less than with the fall at the end.
- Everything lost before the end → 0; lost in the last year → the earlier withdrawals were paid.
- Data shorter than the term → all of it is used, one period, and it says so.
- 6 periods → "few"; 10 → not.
- More years → a lower rate.
- Broken inputs (no years, gaps, non-whole years) → an error.
- A fall at the start: it lasts with a low rate; it runs out earlier than without the fall; after running out it pays no more.
Sources
- Bengen, W. P. (1994), "Determining Withdrawal Rates Using Historical Data", Journal of Financial Planning 7(4): the highest fixed real rate that lasted some 30 years from each start of 1926–1976 in the US, about 4 %, for portfolios of 50–75 % in shares and the rest in Treasury bonds (SBBI data). The app gives 3.78 % for 100 % in US shares with Shiller's data (1928–2022; worst start, 1929): the difference comes from the portfolio and the data, not from the years.
- Cooley, Hubbard and Walz (1998), "Retirement Savings: Choosing a Withdrawal Rate That Is Sustainable", AAII Journal 20(2) (the Trinity study): overlapping US periods of 1926–1995; with 50 % or more in shares, 4 % lasted 30 years in 95 % or more of the periods.
- Pfau (2010), outside the US: 4 % often failed. That is why the rate comes from each asset's data and never from a fixed rule.
The second question: "How much does it give me a month today?" (phase B2)
Since B2, My money first asks what the person wants to know. The second question uses this same rate without years or future:
- Input: only what they have and where it is invested (fields 1 and 3 of the plan, shared with the first question).
- Answer: capital × the data's rate for that investment ÷ 12, in today's money (it rises with prices each year). One sentence: "You could take out 3.8 % a year: the most that lasted 30 years in the data of US shares." (with few periods, the warning in front, in the same sentence). Below, from which years to which, the worst start, the periods and "What held in the past is not a promise".
- Always the data's rate, not the slider's: the rate chosen in the first question belongs to that plan. So the answer does not depend on a setting the person may not see.
- Own growth: the starting rate (that of the most similar asset, at most that of US shares) and that its growth has no history.
- Why 30 years: a line on screen, "30 years: a long retirement (Bengen, 1994; the Trinity study, 1998)".
- Code:
src/lib/income.ts(incomeAnswer),src/components/money/income-answer.tsx. Tests:src/lib/income.test.ts(€100,000 in US shares: 3.78 %, €315 a month),entry.test.tsande2e/money.test.mts("the two questions").
The formula, in plain words
Each year you take out the same money (in today's euros): a percentage of what you had at the start. Each month, a twelfth of it. To know whether it lasts, 5,000 sequences of 30 years drawn at random from the real years are tried: if in one of them the money runs out before the end, that counts as a failure.
Exact:
- Each month: total × rate / 12, with the total at the end of the plan's years.
- Capital that pays a monthly spending G: 12·G / rate.
- Test of a sequence: balance = 1; each year, balance ← balance − rate (at the start of the year); if balance ≤ 0, it fails; if not, balance ← balance·(1 + r). It lasts if it gets there with money after the last withdrawal.
- 5,000 sequences of 30 years, an i.i.d. bootstrap of the asset's real years (seed 20260929). A mix, with its joint draw (1,000 paths). Without swings (savings, or one's own with a swing of 0): it lasts or it does not, and the app says when it runs out.
- Zones: prudent if it lasted in 90 or more of every 100; risky if in 75 or more; very risky below that.
What the data give (lasted 30 years in N of every 100, by rate):
| Asset | 2 % | 4 % | 7 % |
|---|---|---|---|
| US shares (S&P 500) | 99.6 | 92.9 | 62.1 |
| German bonds | 99.7 | 74.5 | 1.3 |
| Gold | 91.5 | 44.3 | 4.9 |
| Starting plan (5 %, the swing of US shares) | 98.6 | 81.8 | 36.2 |
With the starting plan, 4 % fell in "risky"; since A4 it starts at 3.78 % (the rate of US shares), which lasts in 84.8 of every 100 futures: still "risky".
Assumptions
- Fixed withdrawals in real terms, never adjusted to how the market goes.
- 30 years of withdrawal, whenever it starts.
- All the money stays invested in the same thing as during the saving.
- No taxes or fees.
- Each year is independent (as in the simulated futures).
Sources (dated)
- The yearly data from 1988 to 2022 of growth.
- The "4 % rule": Bengen, W. P. (1994), "Determining Withdrawal Rates Using Historical Data", Journal of Financial Planning 7(4); Cooley, Hubbard and Walz (1998), "Retirement Savings: Choosing a Withdrawal Rate That Is Sustainable", AAII Journal 20(2) (the Trinity study).
- Outside the US: Pfau, W. D. (2010), "An International Perspective on Safe Withdrawal Rates: The Demise of the 4 Percent Rule?", Journal of Financial Planning 23(12).
- Flexible withdrawals: Guyton and Klinger (2006), "Decision Rules and Maximum Initial Withdrawal Rates", Journal of Financial Planning 19(3).
Validation (tests)
src/lib/monte-carlo.test.ts(17): 100 % success with a fixed 7 % and withdrawals of 4 %; 0 % with withdrawals of 15 %; high but not certain at 4 % with history; it falls as the rate rises; reproducible; several rates at once give the same as one by one; years it lasts without swings (1 ÷ rate with no growth).src/lib/success-table.test.ts(2): recalculates the 66 precalculated rates and fails if the data change.src/lib/withdrawal.test.ts(3): the slider's 11 steps, fitting any rate to a step and the three zones.src/lib/calculator.test.ts: what it pays each month and the countries it is enough for.e2e/money.test.mtsande2e/colours.test.mts: the slider, its zones with an icon and a word, and that they can be told apart with colour blindness.
Limits
- It says how many times it lasted in the model, not the probability that it lasts.
- It does not say how much is left: a path that ends with €1 and another with twice the start count the same.
- For someone who stops working young, 30 years may be too few.
What is debatable (A4)
- Two different answers to two questions. The data's rate looks at the real starts (1928–2022 for shares); the zone (prudent, risky) looks at 5,000 futures with the years of 1988–2022 in random order. With US shares they agree (3.78 %: it lasted from any real year and lasts in 94 of every 100 futures, "prudent"). With few periods they do not: bonds at 5.56 % last in 20 of every 100 futures and the 60/40 mix at 7.58 % in 35 ("very risky"). Both are true; the page shows them together.
- Few periods give high rates. Bonds (5.56 %) and the 60/40 mix (7.58 %) come from 6–8 starts in years of falling rates. The page says "a rough guide" and the zone usually says "very risky". Another option would be never to give more than the rate of shares with a long history; it is not done because it would mix assets. Cost: little.
- 30 years for everyone. Bengen's and Trinity's term is kept; B2 explains the value beside the result.
What is debatable
- It depends a lot on the period. With 1988–2022, the S&P 500 gives 92.9 % at 4 %; world shares (MSCI World, withdrawn in phase A2) gave 76.6 %. The Trinity study (US, 1926–1995) gives 95 % or more for 30 years at 4 % with half or more in shares; Pfau (2010) shows that outside the US 4 % often failed. The app's figures are consistent with that, but very sensitive to the asset and the years. Cost: it goes with the period decision of growth.
- A fixed 30 years. A withdrawal at 45 may last 45 years. Cost: a control for the length and precalculating more tables.
- Binary success. It does not tell failing in year 10 from failing in year 29, nor how much is left over. Cost: also show what is left in the typical case and in the bad one.
- Rigid withdrawals. Whoever cuts back in bad years (Guyton–Klinger rules) can start with more. The app does not model it. Cost: a "flexible" variant, with its sheet.
- "Prudent", "risky". They are labels of the data (90 and 75 of every 100, conventional thresholds, not a standard), but they sound like a judgement on the person. See inform, do not advise: the phrase must always come with its figure ("lasted in 79 of every 100"). Cost: review the wording with the legal sheet.
- The withdrawal starts with the final total. The sequence risk right at retirement (a fall in the first year) is in the 30-year test, but "Could pay you each month" is calculated on the typical total, not on the bad one. Cost: show the payment with "if it goes badly".
- Outdated comments in the code (corrected in this change, without touching the calculation):
monte-carlo.tssaid "100 % shares" (it is the plan's asset) andsimulation.tsspoke of the precalculated rates 3, 4 and 5 % (there are 11, from 2 % to 7 %).
History
- 2026-10-10 (A4, after the independent review): a few-periods rule that does not switch itself off; the warning in the rate's sentence; rounding down to the hundredth; "My %" never starts above the rate of US shares and says whose it is; the fall with its money; "what held in the past is not a promise"; Bengen corrected; the data's rate goes into the precalculated table.
- 2026-10-09 (phase A4): the starting rate stops being a fixed 4 %: it is the one each investment's data back (see above), with the worst start, the periods and the warning if they are few; "My %" shows a fall like that of the most similar asset. Data file version 13.
- 2026-10-03: first sheet (no change to the calculation; two code comments aligned with what it does).
- 2026-10-09 (phase A2): without world shares or the Nasdaq-100 (their data are not open). The starting plan now moves with the swing of US shares (16.4 % instead of 17.8 %): at 4 % it lasts in 81.8 of every 100 (before, 79.5), still "risky". Gold comes from the World Bank's Pink Sheet (December averages): 44.3 at 4 % (before, 44.6). The precalculated table was recalculated (
src/lib/success-table.ts, testsuccess-table.test.ts). - 2026-10-14 (phase B2): the rate also answers the second question ("How much does it give me a month today?"); the 30 years carry their why on screen. The calculation does not change.