# Redemption gates (redemption_gates)

Desk: Fund terms and risk. Page: https://hedgefund.md/models/redemption_gates

**What it asks.** If holders ask for this much back, what gets paid on each date, what must be sold, and what is left for the holders who stay?

Walks a redemption request through notice, dealing dates and a gate against assets with their own days to cash and haircuts. Shows what is paid, sold and left on each date, and what the holders who stay end up with. All numbers come from the caller. It is arithmetic on a list of assets, not a liquidity opinion or a reading of any fund's terms.

Results are hypothetical: arithmetic on the numbers sent, a made-up template or a stated default. Nobody achieved them, and they aren't a forecast, a recommendation, an offer or a record of real trading. Don't show any output to investors or clients, or use it to market an investment. Terms: https://hedgefund.md/terms

## Inputs

| Input | Type | Range | Required | What it is |
| --- | --- | --- | --- | --- |
| `assets` | array | 1 to 40 items | yes | What the fund has, at carrying value. |
| `assets[].name` | string |  | yes | A label, such as Bill 90d. |
| `assets[].value` | number | 0 to 10000000000000 | yes | Carrying value in money. |
| `assets[].days_to_cash` | whole number | 0 to 3650 | yes | Days from starting a sale to having the cash. |
| `assets[].haircut_pct` | number | 0 to 99 | yes | Percent below carrying value that a sale brings in. |
| `redemption_request_pct` | number | 0 to 100 | yes | Share of the fund asked for on day 0, in percent. |
| `notice_days` | whole number | 0 to 730 | yes | Days from the request to the first redemption date. |
| `frequency_days` | whole number | 1 to 730 | yes | Days between redemption dates. |
| `gate_pct_per_period` | number | 0 to 100 | yes | Most that can be paid on one date, in percent of NAV on that date. 100 means no gate. |

## Template

Made-up numbers that run as they stand, so you can see the shape of a result. They aren't market levels, typical values or estimates, and the names in them don't exist. Replace every number before you read anything into a run.

```json
{
  "assets": [
    {
      "name": "Cash",
      "value": 5000000,
      "days_to_cash": 0,
      "haircut_pct": 0
    },
    {
      "name": "Bill 90d",
      "value": 10000000,
      "days_to_cash": 2,
      "haircut_pct": 0
    },
    {
      "name": "Stock basket A",
      "value": 15000000,
      "days_to_cash": 10,
      "haircut_pct": 1
    },
    {
      "name": "Loan book B",
      "value": 40000000,
      "days_to_cash": 180,
      "haircut_pct": 6
    },
    {
      "name": "Office tower A tokens",
      "value": 30000000,
      "days_to_cash": 365,
      "haircut_pct": 20
    }
  ],
  "redemption_request_pct": 40,
  "notice_days": 30,
  "frequency_days": 30,
  "gate_pct_per_period": 10
}
```

## What the template gives

On these numbers, a request of 40% clears in 7 dates, by day 210, paying 39,948,896.83, and the holders who stay go from 70% to 100% illiquid, at 98.76 per 100 of carrying value.

- Dates to clear: 7 dates
- Paid in all: 39,948,897 (breach)
- Haircut cost: 794,610
- Illiquid share before: 70%
- Illiquid share of what is left: 100% (watch)
- Holders who stay: carrying value per 100: 98.76 (watch)
- Holders who stay: exit value per 100: 85.84 (watch)

Where it flips, with the other inputs held:

- `redemption_request_pct` at 29.85851082: Up to this request, the request or the gate sets every payment. Above it, on day 120, assets that can reach cash fall short of what the gate would pay. With no gate it happens at about the same request, 29.85%, so the gate adds almost nothing here.
- `gate_pct_per_period` at 6.847631673: At this request, a gate at or below this level pays every date without running short of assets that can reach cash. Above it, a date runs short.

## Formula

On each date: NAV per unit P = NAV / units. Requested = queued units x P. Paid = min(requested, gate x NAV, cash available by that day). Cash from an asset = carrying sold x (1 - haircut). Units fall by paid / P. NAV falls by paid + haircut cost. Flip: the units paid before the first date the gate allows more than the available cash, plus that cash / P, over starting units.

## Assumptions

- The whole request lands on day 0 and the first date falls exactly notice_days later, the kindest timing. Dates then come every frequency_days.
- The gate is on NAV at each date, so it shrinks as the fund shrinks. A 40% request at a 10% gate takes 5 dates, not 4, and a 100% request only shrinks by a share each date.
- An asset can pay on a date if its days_to_cash is at or under that date's day count from day 0. Its sale is assumed to start in time.
- Sales take the fastest asset first, then the lowest haircut, then list order, and raise only what that date pays.
- Each date pays at that date's NAV per unit, before that date's sales. The haircut then falls on all units left, including those still queued.
- NAV moves only through haircuts. There are no returns, fees or expenses while the queue runs.
- Illiquid means days_to_cash over notice_days + frequency_days: the asset can't reach cash within one full redemption cycle.
- Exit value per 100 is what is left if sold at the listed haircuts with no gate or wait, per 100 of starting units, with no further costs.
- Left unpaid is the queued units at that date's price, before that date's haircut, so it is requested less paid. The next date's requested is lower by the haircut those units took.
- The gate flip scans 400 gates upward from 0.01, each about 2.3% above the last, and narrows the first short one by bisection. A run of short gates narrower than that step could be missed.
- The sleeve's tail loss is what the units left at the end would lose per 100 at the listed haircuts. On a long walk that can be far above the fund's average loss, because each earlier date paid before its own haircut.
- A queue or a NAV under one billionth of the fund counts as gone. The walk stops at 240 dates.

## Not modeled

- The run itself: holders who see the gate and join the queue. The request is one fixed size.
- Market moves while the queue runs.
- Haircuts that grow with the amount sold or the hurry. Each asset has one fixed haircut.
- A pro rata slice of every asset. Sales here take the fastest asset first.
- Swing pricing, exit fees, side pockets, payment in kind and suspension.
- Credit lines and other borrowing against the book.
- The settlement lag after a date, holdbacks and audit reserves.
- Taxes, on the fund or on the holder.

## Call it

Every result has the same fields: summary, readings, tables, charts, flags, flips, formula, assumptions, not_modeled, hypothetical and inputs_hash. Read flags, flips and not_modeled with the summary, and pass them along together.

### HTTP

No key. The tools keep nothing you send. Send positions by POST, because a URL can land in a server log.

```bash
curl -s https://hedgefund.md/api/v1/redemption_gates \
  -H 'content-type: application/json' \
  -d '{"assets":[{"name":"Cash","value":5000000,"days_to_cash":0,"haircut_pct":0},{"name":"Bill 90d","value":10000000,"days_to_cash":2,"haircut_pct":0},{"name":"Stock basket A","value":15000000,"days_to_cash":10,"haircut_pct":1},{"name":"Loan book B","value":40000000,"days_to_cash":180,"haircut_pct":6},{"name":"Office tower A tokens","value":30000000,"days_to_cash":365,"haircut_pct":20}],"redemption_request_pct":40,"notice_days":30,"frequency_days":30,"gate_pct_per_period":10}' \
  | jq '{summary, flags, flips, not_modeled, inputs_hash}'
```

### MCP

The tool is `redemption_gates` on the server at https://hedgefund.md/mcp.

```bash
curl -s https://hedgefund.md/mcp \
  -H 'content-type: application/json' -H 'accept: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"redemption_gates","arguments":{"assets":[{"name":"Cash","value":5000000,"days_to_cash":0,"haircut_pct":0},{"name":"Bill 90d","value":10000000,"days_to_cash":2,"haircut_pct":0},{"name":"Stock basket A","value":15000000,"days_to_cash":10,"haircut_pct":1},{"name":"Loan book B","value":40000000,"days_to_cash":180,"haircut_pct":6},{"name":"Office tower A tokens","value":30000000,"days_to_cash":365,"haircut_pct":20}],"redemption_request_pct":40,"notice_days":30,"frequency_days":30,"gate_pct_per_period":10}}}' \
  | jq '.result.structuredContent | {summary, flags, flips, not_modeled, inputs_hash}'
```

### The library

The same code on your own machine, with no dependencies, and nothing is sent anywhere.

```bash
curl -fsSL https://hedgefund.md/hedgefund.mjs -o hedgefund.mjs   # read it before you run it
node hedgefund.mjs template redemption_gates > mine.json           # replace every number in it
node hedgefund.mjs run redemption_gates mine.json | jq '{summary, flags, flips, not_modeled, inputs_hash}'
```

In a script:

```js
import { run, template } from "./hedgefund.mjs";

const inputs = template("redemption_gates"); // replace every number in it
const { summary, flags, flips, not_modeled } = run("redemption_gates", inputs);
```
