[ { "name": "£1,000 drawn at £300 a year with no growth: three full years and a £100 fourth", "args": [ { "minor": 100000, "currency": "GBP" }, { "minor": 30000, "currency": "GBP" }, 0, 0, 10 ], "expect": { "fullYears": 3, "exhausted": true, "totalWithdrawn": { "minor": 100000, "currency": "GBP" }, "closingBalance": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 100000, "currency": "GBP" }, "withdrawal": { "minor": 30000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 70000, "currency": "GBP" } }, { "year": 2, "opening": { "minor": 70000, "currency": "GBP" }, "withdrawal": { "minor": 30000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 40000, "currency": "GBP" } }, { "year": 3, "opening": { "minor": 40000, "currency": "GBP" }, "withdrawal": { "minor": 30000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 10000, "currency": "GBP" } }, { "year": 4, "opening": { "minor": 10000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "withdrawal first, then 10% growth on what is left (not growth first)", "args": [ { "minor": 100000, "currency": "GBP" }, { "minor": 10000, "currency": "GBP" }, 1000, 0, 3 ], "expect": { "fullYears": 3, "exhausted": false, "totalWithdrawn": { "minor": 30000, "currency": "GBP" }, "closingBalance": { "minor": 96690, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 100000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 9000, "currency": "GBP" }, "closing": { "minor": 99000, "currency": "GBP" } }, { "year": 2, "opening": { "minor": 99000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 8900, "currency": "GBP" }, "closing": { "minor": 97900, "currency": "GBP" } }, { "year": 3, "opening": { "minor": 97900, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 8790, "currency": "GBP" }, "closing": { "minor": 96690, "currency": "GBP" } } ] } }, { "name": "a withdrawal equal to the growth on the remainder lasts for ever", "args": [ { "minor": 110000, "currency": "GBP" }, { "minor": 10000, "currency": "GBP" }, 1000, 0, 5 ], "expect": { "fullYears": 5, "exhausted": false, "totalWithdrawn": { "minor": 50000, "currency": "GBP" }, "closingBalance": { "minor": 110000, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 110000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 10000, "currency": "GBP" }, "closing": { "minor": 110000, "currency": "GBP" } }, { "year": 2, "opening": { "minor": 110000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 10000, "currency": "GBP" }, "closing": { "minor": 110000, "currency": "GBP" } }, { "year": 3, "opening": { "minor": 110000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 10000, "currency": "GBP" }, "closing": { "minor": 110000, "currency": "GBP" } }, { "year": 4, "opening": { "minor": 110000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 10000, "currency": "GBP" }, "closing": { "minor": 110000, "currency": "GBP" } }, { "year": 5, "opening": { "minor": 110000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 10000, "currency": "GBP" }, "closing": { "minor": 110000, "currency": "GBP" } } ] } }, { "name": "an income rising 10% a year runs out in the fifth year", "args": [ { "minor": 100000, "currency": "GBP" }, { "minor": 20000, "currency": "GBP" }, 0, 1000, 10 ], "expect": { "fullYears": 4, "exhausted": true, "totalWithdrawn": { "minor": 100000, "currency": "GBP" }, "closingBalance": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 100000, "currency": "GBP" }, "withdrawal": { "minor": 20000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 80000, "currency": "GBP" } }, { "year": 2, "opening": { "minor": 80000, "currency": "GBP" }, "withdrawal": { "minor": 22000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 58000, "currency": "GBP" } }, { "year": 3, "opening": { "minor": 58000, "currency": "GBP" }, "withdrawal": { "minor": 24200, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 33800, "currency": "GBP" } }, { "year": 4, "opening": { "minor": 33800, "currency": "GBP" }, "withdrawal": { "minor": 26620, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 7180, "currency": "GBP" } }, { "year": 5, "opening": { "minor": 7180, "currency": "GBP" }, "withdrawal": { "minor": 7180, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "growth is rounded to the penny every year", "args": [ { "minor": 10001, "currency": "GBP" }, { "minor": 3333, "currency": "GBP" }, 333, 0, 10 ], "expect": { "fullYears": 3, "exhausted": true, "totalWithdrawn": { "minor": 10352, "currency": "GBP" }, "closingBalance": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 10001, "currency": "GBP" }, "withdrawal": { "minor": 3333, "currency": "GBP" }, "growth": { "minor": 222, "currency": "GBP" }, "closing": { "minor": 6890, "currency": "GBP" } }, { "year": 2, "opening": { "minor": 6890, "currency": "GBP" }, "withdrawal": { "minor": 3333, "currency": "GBP" }, "growth": { "minor": 118, "currency": "GBP" }, "closing": { "minor": 3675, "currency": "GBP" } }, { "year": 3, "opening": { "minor": 3675, "currency": "GBP" }, "withdrawal": { "minor": 3333, "currency": "GBP" }, "growth": { "minor": 11, "currency": "GBP" }, "closing": { "minor": 353, "currency": "GBP" } }, { "year": 4, "opening": { "minor": 353, "currency": "GBP" }, "withdrawal": { "minor": 353, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "a pot that reaches exactly zero on a full withdrawal counts that year", "args": [ { "minor": 20000, "currency": "GBP" }, { "minor": 10000, "currency": "GBP" }, 0, 0, 5 ], "expect": { "fullYears": 2, "exhausted": true, "totalWithdrawn": { "minor": 20000, "currency": "GBP" }, "closingBalance": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 20000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 10000, "currency": "GBP" } }, { "year": 2, "opening": { "minor": 10000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "a market halving every year", "args": [ { "minor": 100000, "currency": "GBP" }, { "minor": 10000, "currency": "GBP" }, -5000, 0, 10 ], "expect": { "fullYears": 3, "exhausted": true, "totalWithdrawn": { "minor": 33750, "currency": "GBP" }, "closingBalance": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 100000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": -45000, "currency": "GBP" }, "closing": { "minor": 45000, "currency": "GBP" } }, { "year": 2, "opening": { "minor": 45000, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": -17500, "currency": "GBP" }, "closing": { "minor": 17500, "currency": "GBP" } }, { "year": 3, "opening": { "minor": 17500, "currency": "GBP" }, "withdrawal": { "minor": 10000, "currency": "GBP" }, "growth": { "minor": -3750, "currency": "GBP" }, "closing": { "minor": 3750, "currency": "GBP" } }, { "year": 4, "opening": { "minor": 3750, "currency": "GBP" }, "withdrawal": { "minor": 3750, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "one year modelled", "args": [ { "minor": 100000, "currency": "GBP" }, { "minor": 1000, "currency": "GBP" }, 500, 0, 1 ], "expect": { "fullYears": 1, "exhausted": false, "totalWithdrawn": { "minor": 1000, "currency": "GBP" }, "closingBalance": { "minor": 103950, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 100000, "currency": "GBP" }, "withdrawal": { "minor": 1000, "currency": "GBP" }, "growth": { "minor": 4950, "currency": "GBP" }, "closing": { "minor": 103950, "currency": "GBP" } } ] } }, { "name": "an empty pot pays nothing and is exhausted at once", "args": [ { "minor": 0, "currency": "GBP" }, { "minor": 1000, "currency": "GBP" }, 500, 0, 5 ], "expect": { "fullYears": 0, "exhausted": true, "totalWithdrawn": { "minor": 0, "currency": "GBP" }, "closingBalance": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 0, "currency": "GBP" }, "withdrawal": { "minor": 0, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "a falling withdrawal: 50% less each year", "args": [ { "minor": 10000, "currency": "GBP" }, { "minor": 4000, "currency": "GBP" }, 0, -5000, 5 ], "expect": { "fullYears": 5, "exhausted": false, "totalWithdrawn": { "minor": 7750, "currency": "GBP" }, "closingBalance": { "minor": 2250, "currency": "GBP" }, "schedule": [ { "year": 1, "opening": { "minor": 10000, "currency": "GBP" }, "withdrawal": { "minor": 4000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 6000, "currency": "GBP" } }, { "year": 2, "opening": { "minor": 6000, "currency": "GBP" }, "withdrawal": { "minor": 2000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 4000, "currency": "GBP" } }, { "year": 3, "opening": { "minor": 4000, "currency": "GBP" }, "withdrawal": { "minor": 1000, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 3000, "currency": "GBP" } }, { "year": 4, "opening": { "minor": 3000, "currency": "GBP" }, "withdrawal": { "minor": 500, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 2500, "currency": "GBP" } }, { "year": 5, "opening": { "minor": 2500, "currency": "GBP" }, "withdrawal": { "minor": 250, "currency": "GBP" }, "growth": { "minor": 0, "currency": "GBP" }, "closing": { "minor": 2250, "currency": "GBP" } } ] } }, { "name": "a negative pot is an error", "args": [ { "minor": -1, "currency": "GBP" }, { "minor": 1000, "currency": "GBP" }, 0, 0, 5 ], "expectError": "pot must be whole minor units, 0 or more" }, { "name": "a zero withdrawal is an error", "args": [ { "minor": 1000, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, 0, 0, 5 ], "expectError": "annualWithdrawal must be whole minor units greater than zero" }, { "name": "a fractional withdrawal is an error", "args": [ { "minor": 1000, "currency": "GBP" }, { "minor": 10.5, "currency": "GBP" }, 0, 0, 5 ], "expectError": "annualWithdrawal must be whole minor units greater than zero" }, { "name": "growth below -100% is an error", "args": [ { "minor": 1000, "currency": "GBP" }, { "minor": 100, "currency": "GBP" }, -10001, 0, 5 ], "expectError": "annualGrowthBasisPoints must be a whole number, -10000 or more" }, { "name": "an increase below -100% is an error", "args": [ { "minor": 1000, "currency": "GBP" }, { "minor": 100, "currency": "GBP" }, 0, -10001, 5 ], "expectError": "withdrawalIncreaseBasisPoints must be a whole number, -10000 or more" }, { "name": "zero years is an error", "args": [ { "minor": 1000, "currency": "GBP" }, { "minor": 100, "currency": "GBP" }, 0, 0, 0 ], "expectError": "maxYears must be a whole number from 1 to 100" }, { "name": "101 years is an error", "args": [ { "minor": 1000, "currency": "GBP" }, { "minor": 100, "currency": "GBP" }, 0, 0, 101 ], "expectError": "maxYears must be a whole number from 1 to 100" }, { "name": "fractional years are an error", "args": [ { "minor": 1000, "currency": "GBP" }, { "minor": 100, "currency": "GBP" }, 0, 0, 2.5 ], "expectError": "maxYears must be a whole number from 1 to 100" }, { "name": "a withdrawal in another currency is an error", "args": [ { "minor": 1000, "currency": "GBP" }, { "minor": 100, "currency": "EUR" }, 0, 0, 5 ], "expectError": "currency mismatch: GBP and EUR" } ]