Functional Weave
Code in TypeScript

insurance.ipt@1.0.2

README.md

4,369 bytes · view raw

# insurance.ipt

UK Insurance Premium Tax (IPT) on a premium, at the rate in force on a date.
Give it a net premium and it adds the tax; give it a gross (IPT-inclusive)
premium with `includesTax` and it takes the tax out. Either way you get net,
tax and gross together, plus the rate and the day that rate came in.

## Rates are data

The rates are dated rows in `data/ipt-rates.json`, never constants in the
code, and the function takes the date. There are two bands:

- **standard**: most general insurance (motor, home, pet, commercial).
- **higher**: 20% on travel insurance, insurance sold with mechanical or
  electrical appliances, and some vehicle insurance sold through a supplier
  of the vehicle (Finance Act 1994, s.51A; see Notice IPT1 for the detail).
  Which band a policy falls in is the caller's decision.

| from | standard | higher |
|---|---|---|
| 1 October 1994 | 2.5% | - |
| 1 April 1997 | 4% | 17.5% |
| 1 July 1999 | 5% | 17.5% |
| 4 January 2011 | 6% | 20% |
| 1 November 2015 | 9.5% | 20% |
| 1 October 2016 | 10% | 20% |
| 1 June 2017 | 12% | 20% |

A date before 1 October 1994 (or a higher-rate date before 1 April 1997) is
an error, not zero.

## Which date

The rate is fixed by the date the insurer *receives* the premium (or, under
the special accounting scheme, the date it is written), not the policy start
date. Around each rate change there were anti-forestalling rules for premiums
received early for cover starting after the change (HMRC IPT07855); applying
those is the caller's job, by passing the date the rules say to use.

## Rounding

Only one figure is rounded, with the caller's mode: the tax when adding, the
net when taking out (net = gross x 10000 / (10000 + rate)). The other figure is
the difference, so net + tax is exactly the gross. IPT is charged on the whole
premium the insurer receives, including administration charges and any charge
for paying by instalments (HMRC IPT03400), so apply it after those are added.

Negative premiums (return premiums) are allowed and carry their IPT back.

A build installed with `history=current` keeps only the rates in force and
refuses an older date with an explanation rather than answering it at
today's rate.

## Sources

- HMRC, "Historical Insurance Premium Tax rates" (IPT bulletin),
  https://www.gov.uk/government/statistics/insurance-premium-tax-ipt-bulletin/historical-insurance-premium-tax-rates--2
  (read 2026-09-23): every date and rate in the table above.
- HMRC, "Insurance Premium Tax rates",
  https://www.gov.uk/government/publications/rates-and-allowances-insurance-premium-tax/insurance-premium-tax-rates
  (read 2026-09-23): the periods from 3 January 2011 onwards, agreeing.
- HMRC Internal Manual IPT03400, "Overview and the law: the rate of tax",
  https://www.gov.uk/hmrc-internal-manuals/insurance-premium-tax/ipt03400
  (read 2026-09-23): the full history of both rates, and that tax is due on
  the gross premium including administration and instalment charges.

1.0.1 fixes Python accepting a trailing newline or non-ASCII digits in onDate; adds tests.

## Before you rely on this

**Not professional advice.** This capability calculates insurance figures from published rules. It is a software component for developers, not financial advice. Rules change and every rate here has an effective date. Check that the dates cover your case. Verify results against the official sources listed above, and have an actuary review how you use it, before anyone relies on the output. Provided "as is" under its licence, without warranty.

**Unreviewed.** This capability's implementations agree in every language and pass its published test vectors, which were worked out from the official sources cited. But no qualified actuary has yet checked those vectors, or confirmed that the capability covers the cases it claims. Treat it as a draft. Do not use it for real people, money or decisions without your own expert review. Once a qualified reviewer signs off, this notice is replaced with their name, qualification and the date. Each new version needs fresh sign-off.

## Notices

Contains public sector information licensed under the Open Government
Licence v3.0 (https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).

1.0.2 marks it unreviewed and adds its attribution notices (NOTICE). The code and the tests are unchanged.