One of yesterday’s budget announcements was the lowering of the minimum premium bond purchase from £100 to £25 by March 2019. Inevitably the usual conspiracy theorists and/or people who don’t understand probability came out to play on various forums.

Some facts:

- Every bond in every draw has an equal chance of winning a prize. Currently, these odds are 24,500 to 1 against.
- If you hold a single £1 bond, then with average luck you’ll win a prize once every 24,500 months – or once every 2,041 years.
- A £100 holding would improve these odds to once every 20 years or so.
- Someone with the maximum holding of £50,000 could therefore expect to win around two prizes a month. 2.04, to be precise.

However, two myths seem to be in common circulation. The widespread belief in these myths perhaps explains why 42% still think that the NHS will get £350m/week extra after Brexit. (Also a myth – along with the idea that a Brexit of any type will deliver a dividend to the UK).

- Myth 1 – blocks of consecutive bond numbers stand a better chance of winning than widely scattered bond numbers.
- Myth 2 – a newer bond has a better chance of winning than an older bond.

Neither is true – as every bond in the draw has an equal chance of winning a prize.

### Myth 1

It makes no difference whether you hold a single block of consecutive bonds or if they are scattered. Believing otherwise is as fallacious as suggesting that the sequence 6,6,6,6,6,6 is more or less likely than 1,2,3,4,5,6 when rolling a die six times. Assuming a fair die, any six number sequence is as likely as any other, as a die has no memory for what was rolled previously. The same is true for premium bonds – there’s no memory for which numbers have been drawn.

### Myth 2

The old number / new number myth probably stems from the observation that new bonds seem to win more frequently than older ones – if you just look at lists of prize winners. However, this neglects the obvious point that older bonds are more likely to have been cashed in than newer ones. Regardless of when a bond was bought, it still has an equal chance of winning a prize. This myth is especially pernicious, as someone who withdraws older bonds to purchase newer ones loses at least a month of opportunity. This is because a bond bought (say) in November won’t be entered into a draw until the following January.

### Crunching the numbers

Now, I realise that if you’re still struggling to see past these myths, some proof might be useful. So as part of my mental recovery from chemotherapy, I’ve written a premium bond simulator this morning. It’s aim is to dispel these two myths.

It works by simulating 82 years worth of bond draws. 81 is the average UK life expectancy. The extra year stems from the rule that bonds can be left in the draw for up to a year after someone’s death.

To make the programme run in a reasonable length of time, the number of bonds in each draw has been scaled back from 60 billion (approximately the number in circulation) to 6 million. Maximum bond holdings have been scaled back proportionately – from 50,000 to 5. This means that the outcome – an average 2.04 prizes per month – is maintained in line with the real NS&I draw.

There are four bondholder types defined. Someone with a block of consecutive numbers, someone with widely scattered numbers, a holder who has old bonds (represented by low numbers) and a holder with new bonds (represented by high numbers).

Here’s the output of a couple of runs from earlier on this afternoon. They demonstrate that every bondholder type has an approximately equal chance of winning over a lifetime of bondholding.

If you’re still not convinced, here’s the source code so you can play with it yourself.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | #include <stdio.h> #include <stdbool.h> #include <stdint.h> #include <time.h> #include <stdlib.h> #define TOTALBONDS 6000000 #define WINODDS 2.45 #define BONDSHELD 5 #define TOTALDRAWS 984 double rand0to1() { /* return a pseudorandom number between 0 and 1 */ return ((double)rand()/(double)RAND_MAX); } void main() { int prizes, winner, i, drawnumber, prizesallocated; int blocktotal=0, singletotal=0, oldtotal=0, newtotal=0; /* Different bondholder types and their bond numbers */ int blockbonds[BONDSHELD]={200000,200001,200002,200003,200004}; int singlebonds[BONDSHELD]={10534,248491,1000302,4000522,5200976}; int oldbonds[BONDSHELD]={1,10,100,1000,10000}; int newbonds[BONDSHELD]={5999900,5999910,5999920,5999930,5999940}; bool allbonds[TOTALBONDS]; /* Seed the pseudorandom number generator */ srand(time(NULL)); /* Total prizes are calculated using current NS&I odds of 24,500 to 1 per bond held, scaled to 2.45 to 1 per bond held for this simulation */ /* The total number of bonds in ciruclation is also scaled back by the same propotion, from around 60 billion to 6 million */ /* Therefore the maximum holding in this simulation is 5 bonds, equivalent to 50,000 in the real draw */ /* Average luck implies each bondholder should win 2.04 times per draw - the same as in the real draw*/ /* Run the draw multiple times - 12 is equivalent to 1 year's worth of real draws */ for (drawnumber=0; drawnumber<TOTALDRAWS; drawnumber++) { /* Set up the draw - no-one has won yet */ for (i=0;i<TOTALBONDS;i++) { allbonds[i]=false; } /* Work out the total number of prizes */ prizes = (int) (TOTALBONDS / WINODDS); /* Draw a new bond to win until all prizes are allocated */ prizesallocated=0; while (prizesallocated<prizes) { winner = (int) (rand0to1()*TOTALBONDS); /* The NS&I rules state that the same bond cannot win twice in the same draw */ /* prizesallocated is not incremented in this event and the prize is reallocated */ if (!allbonds[winner]) { allbonds[winner] = true; ++prizesallocated; } } /* Check each bondholder against the draw, and increment the total number of times they have won */ printf("\nWinners for draw %d\n",drawnumber+1); for (i=0;i<BONDSHELD;i++) { if (allbonds[blockbonds[i]]) { printf("Block bond %d wins!\n",blockbonds[i]); ++blocktotal; } if (allbonds[singlebonds[i]]) { printf("Single bond %d wins!\n",singlebonds[i]); ++singletotal; } if (allbonds[oldbonds[i]]) { printf("Old bond %d wins!\n",oldbonds[i]); ++oldtotal; } if (allbonds[newbonds[i]]) { printf("New bond %d wins!\n",newbonds[i]); ++newtotal; } } } /* Calculate what the average luck was for each of the bondholders */ printf("\nSummary of results\n"); printf("Block bond holder won on average %.2f times per draw\n", (float) blocktotal/TOTALDRAWS); printf("Single bond holder won on average %.2f times per draw\n", (float) singletotal/TOTALDRAWS); printf("Old bond holder won on average %.2f times per draw\n", (float) oldtotal/TOTALDRAWS); printf("New bond holder won on average %.2f times per draw\n", (float) newtotal/TOTALDRAWS); } |

Looks like recovery is on track to me – faultless. And an interesting read

Hi Andrew – my logic, code or both? 😀

Recovery seems to be on track – but I’m waiting until I see the consultant on the 7th before I declare that!

Tim.