[
{
"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"
}
]