[ { "name": "quarterly payer at 250p: 22p trailing is 8.8%, 6p a quarter forward is 9.6%", "args": [ { "minor": 250, "currency": "GBP" }, [ { "minor": 5, "currency": "GBP" }, { "minor": 6, "currency": "GBP" }, { "minor": 5, "currency": "GBP" }, { "minor": 6, "currency": "GBP" } ], { "minor": 6, "currency": "GBP" }, 4 ], "expect": { "trailingAnnual": { "minor": 22, "currency": "GBP" }, "forwardAnnual": { "minor": 24, "currency": "GBP" }, "trailingBasisPoints": 880, "forwardBasisPoints": 960 } }, { "name": "after a dividend cut the forward yield halves while the trailing yield has not moved", "args": [ { "minor": 1000, "currency": "GBP" }, [ { "minor": 10, "currency": "GBP" }, { "minor": 10, "currency": "GBP" }, { "minor": 10, "currency": "GBP" }, { "minor": 10, "currency": "GBP" } ], { "minor": 5, "currency": "GBP" }, 4 ], "expect": { "trailingAnnual": { "minor": 40, "currency": "GBP" }, "forwardAnnual": { "minor": 20, "currency": "GBP" }, "trailingBasisPoints": 400, "forwardBasisPoints": 200 } }, { "name": "a special dividend lifts the trailing yield only", "args": [ { "minor": 2000, "currency": "GBP" }, [ { "minor": 30, "currency": "GBP" }, { "minor": 50, "currency": "GBP" }, { "minor": 30, "currency": "GBP" } ], { "minor": 30, "currency": "GBP" }, 2 ], "expect": { "trailingAnnual": { "minor": 110, "currency": "GBP" }, "forwardAnnual": { "minor": 60, "currency": "GBP" }, "trailingBasisPoints": 550, "forwardBasisPoints": 300 } }, { "name": "fractions of a penny: 11.8p twice a year on 1,234.56p, given per 100 shares", "args": [ { "minor": 123456, "currency": "GBP" }, [ { "minor": 1180, "currency": "GBP" }, { "minor": 1180, "currency": "GBP" } ], { "minor": 1180, "currency": "GBP" }, 2 ], "expect": { "trailingAnnual": { "minor": 2360, "currency": "GBP" }, "forwardAnnual": { "minor": 2360, "currency": "GBP" }, "trailingBasisPoints": 191, "forwardBasisPoints": 191 } }, { "name": "a third of a basis point rounds down", "args": [ { "minor": 3, "currency": "GBP" }, [ { "minor": 1, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 1 ], "expect": { "trailingAnnual": { "minor": 1, "currency": "GBP" }, "forwardAnnual": { "minor": 1, "currency": "GBP" }, "trailingBasisPoints": 3333, "forwardBasisPoints": 3333 } }, { "name": "half a basis point rounds up", "args": [ { "minor": 20000, "currency": "GBP" }, [ { "minor": 1, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 1 ], "expect": { "trailingAnnual": { "minor": 1, "currency": "GBP" }, "forwardAnnual": { "minor": 1, "currency": "GBP" }, "trailingBasisPoints": 1, "forwardBasisPoints": 1 } }, { "name": "a quarter of a basis point rounds down to zero", "args": [ { "minor": 40000, "currency": "GBP" }, [ { "minor": 1, "currency": "GBP" } ], { "minor": 0, "currency": "GBP" }, 1 ], "expect": { "trailingAnnual": { "minor": 1, "currency": "GBP" }, "forwardAnnual": { "minor": 0, "currency": "GBP" }, "trailingBasisPoints": 0, "forwardBasisPoints": 0 } }, { "name": "no dividends in the last year and none declared", "args": [ { "minor": 500, "currency": "GBP" }, [], { "minor": 0, "currency": "GBP" }, 4 ], "expect": { "trailingAnnual": { "minor": 0, "currency": "GBP" }, "forwardAnnual": { "minor": 0, "currency": "GBP" }, "trailingBasisPoints": 0, "forwardBasisPoints": 0 } }, { "name": "monthly payer in dollars", "args": [ { "minor": 2500, "currency": "USD" }, [ { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" }, { "minor": 10, "currency": "USD" } ], { "minor": 11, "currency": "USD" }, 12 ], "expect": { "trailingAnnual": { "minor": 120, "currency": "USD" }, "forwardAnnual": { "minor": 132, "currency": "USD" }, "trailingBasisPoints": 480, "forwardBasisPoints": 528 } }, { "name": "a yield above 100% is reported, not capped", "args": [ { "minor": 100, "currency": "GBP" }, [ { "minor": 150, "currency": "GBP" } ], { "minor": 150, "currency": "GBP" }, 1 ], "expect": { "trailingAnnual": { "minor": 150, "currency": "GBP" }, "forwardAnnual": { "minor": 150, "currency": "GBP" }, "trailingBasisPoints": 15000, "forwardBasisPoints": 15000 } }, { "name": "a price of zero is an error", "args": [ { "minor": 0, "currency": "GBP" }, [ { "minor": 1, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 1 ], "expectError": "price must be whole minor units greater than zero" }, { "name": "a negative price is an error", "args": [ { "minor": -100, "currency": "GBP" }, [ { "minor": 1, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 1 ], "expectError": "price must be whole minor units greater than zero" }, { "name": "a fractional price is an error", "args": [ { "minor": 99.5, "currency": "GBP" }, [ { "minor": 1, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 1 ], "expectError": "price must be whole minor units greater than zero" }, { "name": "a negative dividend is an error", "args": [ { "minor": 100, "currency": "GBP" }, [ { "minor": -1, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 1 ], "expectError": "dividends must be whole minor units, 0 or more" }, { "name": "a fractional dividend is an error: give amounts per lot instead", "args": [ { "minor": 100, "currency": "GBP" }, [ { "minor": 11.8, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 1 ], "expectError": "dividends must be whole minor units, 0 or more" }, { "name": "a dividend in another currency is an error", "args": [ { "minor": 100, "currency": "GBP" }, [ { "minor": 1, "currency": "USD" } ], { "minor": 1, "currency": "GBP" }, 1 ], "expectError": "currency mismatch: GBP and USD" }, { "name": "zero payments a year is an error", "args": [ { "minor": 100, "currency": "GBP" }, [ { "minor": 1, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 0 ], "expectError": "paymentsPerYear must be a whole number from 1 to 52" }, { "name": "53 payments a year is an error", "args": [ { "minor": 100, "currency": "GBP" }, [ { "minor": 1, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 53 ], "expectError": "paymentsPerYear must be a whole number from 1 to 52" }, { "name": "fractional payments a year is an error", "args": [ { "minor": 100, "currency": "GBP" }, [ { "minor": 1, "currency": "GBP" } ], { "minor": 1, "currency": "GBP" }, 2.5 ], "expectError": "paymentsPerYear must be a whole number from 1 to 52" } ]