Functional Weave
Code in Python

invest.fee-drag@1.0.1

README.md

2,654 bytes · view raw

# invest.fee-drag

How much an ongoing charge (a fund's OCF, a platform fee, an adviser's
percentage) costs over a number of years, by running the same investment
twice, with and without the charge, and comparing.

## The convention

Each year, in this order, in whole minor units:

1. growth = value x `annualGrowthBasisPoints` / 10000, rounded half away from
   zero (`money.apply-rate`, half-up), and added;
2. fee = the grown value x `annualFeeBasisPoints` / 10000, rounded the same
   way, and taken off (the "with fee" run only).

So the fee is charged once a year on the year-end value, as an annual
management charge on a statement is. Real platforms often charge monthly on
the average value; the difference is small and this capability does not model
it. Growth is a constant rate you choose; it is an illustration, not a
forecast.

## Why the drag is more than the fees

`feesPaid` is the charges taken. `drag` is the whole difference in the final
value, which also includes the growth the charged money would have earned.
With no growth they are equal; with positive growth the drag is larger, and
the gap widens with the years. That gap is the point of the capability, and
the reason an answer computed as "fee x years" is wrong.

## Edge cases

- `years` 0 returns the start value twice and an empty schedule.
- Growth of -10000 (a total loss) is allowed; anything lower is an error.
- `dragBasisPoints` is 0 when the value without the fee is 0.
- Errors: negative or fractional start value, years outside 0-100, a fee
  outside 0-10000, growth below -10000.

## Before you rely on this

**Not professional advice.** This capability calculates investment 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 a tax adviser 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 tax adviser 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.

1.0.1 marks it unreviewed. The code and the tests are unchanged.