---
title: "TER, ongoing charges and fund fees: how to compare fund costs programmatically"
description: "TER vs OCF vs total cost of ownership, why 0.20 % and 1.50 % end up 30 % apart over 25 years, and how to parse and rank fund fees from API data."
canonical: https://fundfactsapi.com/blog/ter-ongoing-charges-fund-fees
published: 2026-08-05
updated: 2026-08-05
publisher: FundFacts API
---

# TER, ongoing charges and fund fees: how to compare fund costs programmatically

> TER vs OCF vs total cost of ownership, why 0.20 % and 1.50 % end up 30 % apart over 25 years, and how to parse and rank fund fees from API data.

Fees are the one input to fund returns that is known in advance, which makes them the most useful field for screening. This article untangles the acronyms, shows the long-term arithmetic and gives you code to parse, normalise and rank fund costs from the `headlineMetrics.ter` field of a fund data API.

## The acronyms

| Term | Where you see it | What it includes |
| --- | --- | --- |
| **TER** – Total Expense Ratio | Factsheets, ETF product pages | Management fee + administration, custody, audit, legal, regulatory costs, as a % of average assets |
| **OCF / Ongoing charges** | UCITS KIID, UK documents | Essentially the same as TER; the regulatory name |
| **Management fee / AMC** | Prospectus | Only the manager's fee — a subset of TER |
| **Transaction costs** | PRIIPs KID | Trading costs inside the fund, disclosed separately |
| **Performance fee** | Prospectus, KID | Charged only above a hurdle; excluded from TER |
| **Entry / exit charges** | KID, platform | One-off, often waived by platforms |

Rule of thumb: **TER ≈ OCF ≈ "the running cost"**. It is what `headlineMetrics.ter` contains, as published: `"0.20%"`.

## Why small differences matter

Fees compound in reverse. On a €100,000 investment growing at 6 % gross:

| TER | Value after 25 years | Fees paid (incl. lost growth) |
| --- | --- | --- |
| 0.10 % | €419,000 | €10,000 |
| 0.20 % | €409,000 | €20,000 |
| 0.75 % | €358,000 | €71,000 |
| 1.50 % | €300,000 | €129,000 |

A 1.3-percentage-point fee gap becomes a **27 % difference in final wealth**. This is why fee ranking is the first filter in most fund screeners.

```typescript
export function finalValue(principal: number, grossReturn: number, ter: number, years: number) {
  return principal * Math.pow(1 + grossReturn - ter, years);
}
finalValue(100_000, 0.06, 0.0020, 25); // ≈ 409,000
```

## Parsing the fee from API data

Formatted metrics are returned as strings so the unit is never lost. Convert once at the edge:

```typescript
export function pct(s: string | null | undefined): number | null {
  if (!s) return null;
  const m = /-?\d+(\.\d+)?/.exec(s.replace(",", "."));
  return m ? Number(m[0]) : null;
}

const ter = pct(fund.data.headlineMetrics.ter);   // "0.20%" -> 0.2
```

Then ranking a universe is a sort:

```typescript
const ranked = funds
  .map((f) => ({ isin: f.isin, name: f.name, ter: pct(f.data.headlineMetrics.ter) }))
  .filter((f) => f.ter != null)
  .sort((a, b) => a.ter! - b.ter!);
```

## Fee is not the whole cost: tracking difference

For index funds the fee you *pay* is the [tracking difference](https://fundfactsapi.com/blog/fund-performance-data-explained) — the gap between the fund's return and the index's. Securities-lending income can offset part of the TER; sampling and cash drag can add to it. Compare both:

```typescript
const oneYear = fund.data.annualisedReturns.find((r) => r.label === "1 Year");
const trackingDifference = oneYear && oneYear.index != null ? oneYear.fund! - oneYear.index : null;
// e.g. TER 0.20 %, tracking difference +0.13 % -> lending income more than covered the fee
```

## Comparing share classes

The same fund often has a cheap institutional class and an expensive retail class with different ISINs. When you build a comparison, group by fund name and show the cheapest accessible class — the `keyFacts.manager`, `benchmarkName` and `investmentObjective` fields are identical across classes, which makes grouping straightforward.

## What to display

1. **TER** as published (`headlineMetrics.ter`).
2. **Cost in currency per year** on the client's amount — €20 per €10,000 lands better than 0.20 %.
3. **Tracking difference** for index products.
4. **A note on other costs** (platform fee, transaction costs, FX) so the TER is not mistaken for the total cost of ownership.

## Try it on your funds

Every response from [FundFacts API](https://fundfactsapi.com/) includes `headlineMetrics.ter` alongside the [performance series](https://fundfactsapi.com/blog/fund-performance-data-explained), so a fee-versus-return scatter plot for a whole universe is one loop. [Create a free key](https://fundfactsapi.com/signup) or see the [field reference](https://fundfactsapi.com/docs).

## About FundFacts API

FundFacts turns any fund or ETF ISIN into one dated factsheet (fees and KID costs, the 1–7 risk indicator, holdings, sector and country exposure, returns) read from the fund house's own documents: as a client-ready PDF under your firm's name for advisers and wealth managers, as JSON through its API for developers, or inside ChatGPT and Claude through its MCP server.

FundFacts works inside ChatGPT and Claude as a connector (a remote MCP server): ask about any fund or ETF by ISIN, ticker or name and the assistant answers from FundFacts' dated figures, fees, risk, holdings, exposure and returns, with fund cards, side-by-side comparisons, holdings overlap and portfolio look-through.

- Free API key, no card: https://fundfactsapi.com/signup
- Documentation: https://fundfactsapi.com/docs (OpenAPI: https://fundfactsapi.com/openapi.json)
- MCP server: https://fundfactsapi.com/api/mcp (set-up for every client: https://fundfactsapi.com/mcp-server)
- Pricing: https://fundfactsapi.com/pricing
- Site index for AI assistants: https://fundfactsapi.com/llms.txt
- Informational data, not investment advice.
