[ { "name": "£1,000 at 5% growth and a 1% fee for two years: the drag (£21.93) exceeds the fees (£21.41)", "args": [ { "minor": 100000, "currency": "GBP" }, 500, 100, 2 ], "expect": { "valueWithoutFee": { "minor": 110250, "currency": "GBP" }, "valueWithFee": { "minor": 108057, "currency": "GBP" }, "drag": { "minor": 2193, "currency": "GBP" }, "dragBasisPoints": 199, "feesPaid": { "minor": 2141, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 105000, "currency": "GBP" }, "valueWithFee": { "minor": 103950, "currency": "GBP" }, "fee": { "minor": 1050, "currency": "GBP" } }, { "year": 2, "valueWithoutFee": { "minor": 110250, "currency": "GBP" }, "valueWithFee": { "minor": 108057, "currency": "GBP" }, "fee": { "minor": 1091, "currency": "GBP" } } ] } }, { "name": "with no growth the drag is exactly the fees", "args": [ { "minor": 1000000, "currency": "GBP" }, 0, 100, 3 ], "expect": { "valueWithoutFee": { "minor": 1000000, "currency": "GBP" }, "valueWithFee": { "minor": 970299, "currency": "GBP" }, "drag": { "minor": 29701, "currency": "GBP" }, "dragBasisPoints": 297, "feesPaid": { "minor": 29701, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 1000000, "currency": "GBP" }, "valueWithFee": { "minor": 990000, "currency": "GBP" }, "fee": { "minor": 10000, "currency": "GBP" } }, { "year": 2, "valueWithoutFee": { "minor": 1000000, "currency": "GBP" }, "valueWithFee": { "minor": 980100, "currency": "GBP" }, "fee": { "minor": 9900, "currency": "GBP" } }, { "year": 3, "valueWithoutFee": { "minor": 1000000, "currency": "GBP" }, "valueWithFee": { "minor": 970299, "currency": "GBP" }, "fee": { "minor": 9801, "currency": "GBP" } } ] } }, { "name": "a falling market: 10% down a year with a 0.5% fee", "args": [ { "minor": 100000, "currency": "GBP" }, -1000, 50, 2 ], "expect": { "valueWithoutFee": { "minor": 81000, "currency": "GBP" }, "valueWithFee": { "minor": 80192, "currency": "GBP" }, "drag": { "minor": 808, "currency": "GBP" }, "dragBasisPoints": 100, "feesPaid": { "minor": 853, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 90000, "currency": "GBP" }, "valueWithFee": { "minor": 89550, "currency": "GBP" }, "fee": { "minor": 450, "currency": "GBP" } }, { "year": 2, "valueWithoutFee": { "minor": 81000, "currency": "GBP" }, "valueWithFee": { "minor": 80192, "currency": "GBP" }, "fee": { "minor": 403, "currency": "GBP" } } ] } }, { "name": "no fee, no drag", "args": [ { "minor": 100000, "currency": "GBP" }, 500, 0, 1 ], "expect": { "valueWithoutFee": { "minor": 105000, "currency": "GBP" }, "valueWithFee": { "minor": 105000, "currency": "GBP" }, "drag": { "minor": 0, "currency": "GBP" }, "dragBasisPoints": 0, "feesPaid": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 105000, "currency": "GBP" }, "valueWithFee": { "minor": 105000, "currency": "GBP" }, "fee": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "zero years changes nothing", "args": [ { "minor": 100000, "currency": "GBP" }, 500, 100, 0 ], "expect": { "valueWithoutFee": { "minor": 100000, "currency": "GBP" }, "valueWithFee": { "minor": 100000, "currency": "GBP" }, "drag": { "minor": 0, "currency": "GBP" }, "dragBasisPoints": 0, "feesPaid": { "minor": 0, "currency": "GBP" }, "schedule": [] } }, { "name": "£10,000 at 5% over 10 years with a 0.75% platform fee", "args": [ { "minor": 1000000, "currency": "GBP" }, 500, 75, 10 ], "expect": { "valueWithoutFee": { "minor": 1628894, "currency": "GBP" }, "valueWithFee": { "minor": 1510771, "currency": "GBP" }, "drag": { "minor": 118123, "currency": "GBP" }, "dragBasisPoints": 725, "feesPaid": { "minor": 95484, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 1050000, "currency": "GBP" }, "valueWithFee": { "minor": 1042125, "currency": "GBP" }, "fee": { "minor": 7875, "currency": "GBP" } }, { "year": 2, "valueWithoutFee": { "minor": 1102500, "currency": "GBP" }, "valueWithFee": { "minor": 1086024, "currency": "GBP" }, "fee": { "minor": 8207, "currency": "GBP" } }, { "year": 3, "valueWithoutFee": { "minor": 1157625, "currency": "GBP" }, "valueWithFee": { "minor": 1131773, "currency": "GBP" }, "fee": { "minor": 8552, "currency": "GBP" } }, { "year": 4, "valueWithoutFee": { "minor": 1215506, "currency": "GBP" }, "valueWithFee": { "minor": 1179449, "currency": "GBP" }, "fee": { "minor": 8913, "currency": "GBP" } }, { "year": 5, "valueWithoutFee": { "minor": 1276281, "currency": "GBP" }, "valueWithFee": { "minor": 1229133, "currency": "GBP" }, "fee": { "minor": 9288, "currency": "GBP" } }, { "year": 6, "valueWithoutFee": { "minor": 1340095, "currency": "GBP" }, "valueWithFee": { "minor": 1280911, "currency": "GBP" }, "fee": { "minor": 9679, "currency": "GBP" } }, { "year": 7, "valueWithoutFee": { "minor": 1407100, "currency": "GBP" }, "valueWithFee": { "minor": 1334870, "currency": "GBP" }, "fee": { "minor": 10087, "currency": "GBP" } }, { "year": 8, "valueWithoutFee": { "minor": 1477455, "currency": "GBP" }, "valueWithFee": { "minor": 1391102, "currency": "GBP" }, "fee": { "minor": 10512, "currency": "GBP" } }, { "year": 9, "valueWithoutFee": { "minor": 1551328, "currency": "GBP" }, "valueWithFee": { "minor": 1449702, "currency": "GBP" }, "fee": { "minor": 10955, "currency": "GBP" } }, { "year": 10, "valueWithoutFee": { "minor": 1628894, "currency": "GBP" }, "valueWithFee": { "minor": 1510771, "currency": "GBP" }, "fee": { "minor": 11416, "currency": "GBP" } } ] } }, { "name": "£10,000 at 7% over 30 years: 1% costs far more than 30 x 1%", "args": [ { "minor": 1000000, "currency": "GBP" }, 700, 100, 30 ], "expect": { "valueWithoutFee": { "minor": 7612260, "currency": "GBP" }, "valueWithFee": { "minor": 5630780, "currency": "GBP" }, "drag": { "minor": 1981480, "currency": "GBP" }, "dragBasisPoints": 2603, "feesPaid": { "minor": 835573, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 1070000, "currency": "GBP" }, "valueWithFee": { "minor": 1059300, "currency": "GBP" }, "fee": { "minor": 10700, "currency": "GBP" } }, { "year": 2, "valueWithoutFee": { "minor": 1144900, "currency": "GBP" }, "valueWithFee": { "minor": 1122116, "currency": "GBP" }, "fee": { "minor": 11335, "currency": "GBP" } }, { "year": 3, "valueWithoutFee": { "minor": 1225043, "currency": "GBP" }, "valueWithFee": { "minor": 1188657, "currency": "GBP" }, "fee": { "minor": 12007, "currency": "GBP" } }, { "year": 4, "valueWithoutFee": { "minor": 1310796, "currency": "GBP" }, "valueWithFee": { "minor": 1259144, "currency": "GBP" }, "fee": { "minor": 12719, "currency": "GBP" } }, { "year": 5, "valueWithoutFee": { "minor": 1402552, "currency": "GBP" }, "valueWithFee": { "minor": 1333811, "currency": "GBP" }, "fee": { "minor": 13473, "currency": "GBP" } }, { "year": 6, "valueWithoutFee": { "minor": 1500731, "currency": "GBP" }, "valueWithFee": { "minor": 1412906, "currency": "GBP" }, "fee": { "minor": 14272, "currency": "GBP" } }, { "year": 7, "valueWithoutFee": { "minor": 1605782, "currency": "GBP" }, "valueWithFee": { "minor": 1496691, "currency": "GBP" }, "fee": { "minor": 15118, "currency": "GBP" } }, { "year": 8, "valueWithoutFee": { "minor": 1718187, "currency": "GBP" }, "valueWithFee": { "minor": 1585444, "currency": "GBP" }, "fee": { "minor": 16015, "currency": "GBP" } }, { "year": 9, "valueWithoutFee": { "minor": 1838460, "currency": "GBP" }, "valueWithFee": { "minor": 1679461, "currency": "GBP" }, "fee": { "minor": 16964, "currency": "GBP" } }, { "year": 10, "valueWithoutFee": { "minor": 1967152, "currency": "GBP" }, "valueWithFee": { "minor": 1779053, "currency": "GBP" }, "fee": { "minor": 17970, "currency": "GBP" } }, { "year": 11, "valueWithoutFee": { "minor": 2104853, "currency": "GBP" }, "valueWithFee": { "minor": 1884551, "currency": "GBP" }, "fee": { "minor": 19036, "currency": "GBP" } }, { "year": 12, "valueWithoutFee": { "minor": 2252193, "currency": "GBP" }, "valueWithFee": { "minor": 1996305, "currency": "GBP" }, "fee": { "minor": 20165, "currency": "GBP" } }, { "year": 13, "valueWithoutFee": { "minor": 2409847, "currency": "GBP" }, "valueWithFee": { "minor": 2114686, "currency": "GBP" }, "fee": { "minor": 21360, "currency": "GBP" } }, { "year": 14, "valueWithoutFee": { "minor": 2578536, "currency": "GBP" }, "valueWithFee": { "minor": 2240087, "currency": "GBP" }, "fee": { "minor": 22627, "currency": "GBP" } }, { "year": 15, "valueWithoutFee": { "minor": 2759034, "currency": "GBP" }, "valueWithFee": { "minor": 2372924, "currency": "GBP" }, "fee": { "minor": 23969, "currency": "GBP" } }, { "year": 16, "valueWithoutFee": { "minor": 2952166, "currency": "GBP" }, "valueWithFee": { "minor": 2513639, "currency": "GBP" }, "fee": { "minor": 25390, "currency": "GBP" } }, { "year": 17, "valueWithoutFee": { "minor": 3158818, "currency": "GBP" }, "valueWithFee": { "minor": 2662698, "currency": "GBP" }, "fee": { "minor": 26896, "currency": "GBP" } }, { "year": 18, "valueWithoutFee": { "minor": 3379935, "currency": "GBP" }, "valueWithFee": { "minor": 2820596, "currency": "GBP" }, "fee": { "minor": 28491, "currency": "GBP" } }, { "year": 19, "valueWithoutFee": { "minor": 3616530, "currency": "GBP" }, "valueWithFee": { "minor": 2987858, "currency": "GBP" }, "fee": { "minor": 30180, "currency": "GBP" } }, { "year": 20, "valueWithoutFee": { "minor": 3869687, "currency": "GBP" }, "valueWithFee": { "minor": 3165038, "currency": "GBP" }, "fee": { "minor": 31970, "currency": "GBP" } }, { "year": 21, "valueWithoutFee": { "minor": 4140565, "currency": "GBP" }, "valueWithFee": { "minor": 3352725, "currency": "GBP" }, "fee": { "minor": 33866, "currency": "GBP" } }, { "year": 22, "valueWithoutFee": { "minor": 4430405, "currency": "GBP" }, "valueWithFee": { "minor": 3551542, "currency": "GBP" }, "fee": { "minor": 35874, "currency": "GBP" } }, { "year": 23, "valueWithoutFee": { "minor": 4740533, "currency": "GBP" }, "valueWithFee": { "minor": 3762148, "currency": "GBP" }, "fee": { "minor": 38002, "currency": "GBP" } }, { "year": 24, "valueWithoutFee": { "minor": 5072370, "currency": "GBP" }, "valueWithFee": { "minor": 3985243, "currency": "GBP" }, "fee": { "minor": 40255, "currency": "GBP" } }, { "year": 25, "valueWithoutFee": { "minor": 5427436, "currency": "GBP" }, "valueWithFee": { "minor": 4221568, "currency": "GBP" }, "fee": { "minor": 42642, "currency": "GBP" } }, { "year": 26, "valueWithoutFee": { "minor": 5807357, "currency": "GBP" }, "valueWithFee": { "minor": 4471907, "currency": "GBP" }, "fee": { "minor": 45171, "currency": "GBP" } }, { "year": 27, "valueWithoutFee": { "minor": 6213872, "currency": "GBP" }, "valueWithFee": { "minor": 4737091, "currency": "GBP" }, "fee": { "minor": 47849, "currency": "GBP" } }, { "year": 28, "valueWithoutFee": { "minor": 6648843, "currency": "GBP" }, "valueWithFee": { "minor": 5018000, "currency": "GBP" }, "fee": { "minor": 50687, "currency": "GBP" } }, { "year": 29, "valueWithoutFee": { "minor": 7114262, "currency": "GBP" }, "valueWithFee": { "minor": 5315567, "currency": "GBP" }, "fee": { "minor": 53693, "currency": "GBP" } }, { "year": 30, "valueWithoutFee": { "minor": 7612260, "currency": "GBP" }, "valueWithFee": { "minor": 5630780, "currency": "GBP" }, "fee": { "minor": 56877, "currency": "GBP" } } ] } }, { "name": "a total loss in year one leaves nothing either way", "args": [ { "minor": 50000, "currency": "GBP" }, -10000, 100, 2 ], "expect": { "valueWithoutFee": { "minor": 0, "currency": "GBP" }, "valueWithFee": { "minor": 0, "currency": "GBP" }, "drag": { "minor": 0, "currency": "GBP" }, "dragBasisPoints": 0, "feesPaid": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 0, "currency": "GBP" }, "valueWithFee": { "minor": 0, "currency": "GBP" }, "fee": { "minor": 0, "currency": "GBP" } }, { "year": 2, "valueWithoutFee": { "minor": 0, "currency": "GBP" }, "valueWithFee": { "minor": 0, "currency": "GBP" }, "fee": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "a penny grows by half-penny roundings, year by year", "args": [ { "minor": 1, "currency": "GBP" }, 5000, 0, 3 ], "expect": { "valueWithoutFee": { "minor": 5, "currency": "GBP" }, "valueWithFee": { "minor": 5, "currency": "GBP" }, "drag": { "minor": 0, "currency": "GBP" }, "dragBasisPoints": 0, "feesPaid": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 2, "currency": "GBP" }, "valueWithFee": { "minor": 2, "currency": "GBP" }, "fee": { "minor": 0, "currency": "GBP" } }, { "year": 2, "valueWithoutFee": { "minor": 3, "currency": "GBP" }, "valueWithFee": { "minor": 3, "currency": "GBP" }, "fee": { "minor": 0, "currency": "GBP" } }, { "year": 3, "valueWithoutFee": { "minor": 5, "currency": "GBP" }, "valueWithFee": { "minor": 5, "currency": "GBP" }, "fee": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "a 100% fee takes everything after the first year", "args": [ { "minor": 10000, "currency": "GBP" }, 1000, 10000, 1 ], "expect": { "valueWithoutFee": { "minor": 11000, "currency": "GBP" }, "valueWithFee": { "minor": 0, "currency": "GBP" }, "drag": { "minor": 11000, "currency": "GBP" }, "dragBasisPoints": 10000, "feesPaid": { "minor": 11000, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 11000, "currency": "GBP" }, "valueWithFee": { "minor": 0, "currency": "GBP" }, "fee": { "minor": 11000, "currency": "GBP" } } ] } }, { "name": "nothing invested", "args": [ { "minor": 0, "currency": "GBP" }, 500, 100, 2 ], "expect": { "valueWithoutFee": { "minor": 0, "currency": "GBP" }, "valueWithFee": { "minor": 0, "currency": "GBP" }, "drag": { "minor": 0, "currency": "GBP" }, "dragBasisPoints": 0, "feesPaid": { "minor": 0, "currency": "GBP" }, "schedule": [ { "year": 1, "valueWithoutFee": { "minor": 0, "currency": "GBP" }, "valueWithFee": { "minor": 0, "currency": "GBP" }, "fee": { "minor": 0, "currency": "GBP" } }, { "year": 2, "valueWithoutFee": { "minor": 0, "currency": "GBP" }, "valueWithFee": { "minor": 0, "currency": "GBP" }, "fee": { "minor": 0, "currency": "GBP" } } ] } }, { "name": "negative start value is an error", "args": [ { "minor": -1, "currency": "GBP" }, 500, 100, 1 ], "expectError": "startValue must be whole minor units, 0 or more" }, { "name": "fractional minor units are an error", "args": [ { "minor": 10.5, "currency": "GBP" }, 500, 100, 1 ], "expectError": "startValue must be whole minor units, 0 or more" }, { "name": "growth below -100% is an error", "args": [ { "minor": 100, "currency": "GBP" }, -10001, 100, 1 ], "expectError": "annualGrowthBasisPoints must be a whole number, -10000 or more" }, { "name": "a fractional growth rate is an error", "args": [ { "minor": 100, "currency": "GBP" }, 512.5, 100, 1 ], "expectError": "annualGrowthBasisPoints must be a whole number, -10000 or more" }, { "name": "a negative fee is an error", "args": [ { "minor": 100, "currency": "GBP" }, 500, -1, 1 ], "expectError": "annualFeeBasisPoints must be a whole number from 0 to 10000" }, { "name": "a fee over 100% is an error", "args": [ { "minor": 100, "currency": "GBP" }, 500, 10001, 1 ], "expectError": "annualFeeBasisPoints must be a whole number from 0 to 10000" }, { "name": "101 years is an error", "args": [ { "minor": 100, "currency": "GBP" }, 500, 100, 101 ], "expectError": "years must be a whole number from 0 to 100" }, { "name": "negative years are an error", "args": [ { "minor": 100, "currency": "GBP" }, 500, 100, -1 ], "expectError": "years must be a whole number from 0 to 100" }, { "name": "fractional years are an error", "args": [ { "minor": 100, "currency": "GBP" }, 500, 100, 2.5 ], "expectError": "years must be a whole number from 0 to 100" } ]