# T-bill token (tokenized_bills)

Desk: Tokenized assets. Page: https://hedgefund.md/models/tokenized_bills

**What it asks.** When redemptions outrun a T-bill ladder, when do forced sales start, and what do the holders who stay lose?

Values a token backed by a T-bill ladder and cash, gives gross and net yield, then walks a redemption run day by day: maturities in, redemptions paid after settlement, forced sales at the shocked yield and the spread when cash runs short, and the loss on holders who stay. Every number comes from the caller. Not a price, a rating or advice.

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 |
| --- | --- | --- | --- | --- |
| `rungs` | array | 0 to 60 items | yes | The T-bill ladder. Up to 60 rungs. Empty if the pool holds only cash. |
| `rungs[].days` | whole number | 1 to 730 | yes | Days to maturity. |
| `rungs[].face` | number | over 0 to 10000000000000 | yes | Face value paid at maturity. |
| `rungs[].yield_pct` | number | 0 to 50 | yes | Money-market yield, simple, actual/365. 5 means 5%. Not a bank discount rate. |
| `cash` | number | 0 to 10000000000000 | yes | Cash in the pool. It earns nothing here. |
| `tokens_outstanding` | number | over 0 to 10000000000000 | yes | Tokens outstanding. |
| `mgmt_fee_bps` | number | 0 to 1000 | yes | Management fee a year on NAV. 20 means 0.20%. |
| `admin_custody_bps` | number | 0 to 1000 | yes | Admin and custody cost a year on NAV. 10 means 0.10%. |
| `mint_redeem_fee_bps` | number | 0 to 1000 | yes | Fee to mint or to redeem, on NAV. 5 means 0.05%. |
| `settle_days` | whole number | 0 to 60 | yes | Days from a request to its payment. 0 pays the same day. |
| `daily_redemption_pct` | number | 0 to 100 | yes | Share of the tokens left that ask out each day. 3 means 3%. |
| `stress_days` | whole number | 1 to 365 | yes | Days on which requests arrive. |
| `rate_shock_bps` | number | 0 to 5000 | yes | Rise in every rung's yield at a forced sale. 200 means 2 points. |
| `bid_ask_bps` | number | 0 to 1000 | yes | Full bid-ask width in price. A sale gives up half of it. |

## 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
{
  "rungs": [
    { "days": 30, "face": 15000000, "yield_pct": 4 },
    { "days": 60, "face": 20000000, "yield_pct": 4.5 },
    { "days": 90, "face": 25000000, "yield_pct": 5 },
    { "days": 180, "face": 40000000, "yield_pct": 5.5 }
  ],
  "cash": 1500000,
  "tokens_outstanding": 100000000,
  "mgmt_fee_bps": 20,
  "admin_custody_bps": 10,
  "mint_redeem_fee_bps": 5,
  "settle_days": 1,
  "daily_redemption_pct": 3,
  "stress_days": 20,
  "rate_shock_bps": 200,
  "bid_ask_bps": 10
}
```

## What the template gives

On these numbers, NAV is 0.999432 per token, and at 3% a day forced sales start on day 2, cost holders who stay 19.3 bps of NAV per token, and forced sales begin at 0.0755% a day.

- NAV per token: 0.999432
- Hypothetical net yield on NAV: 4.5709%
- Weighted days to maturity: 108.78 days (watch)
- First forced sale: 2 (breach)
- Face sold in forced sales: 44,512,387 (watch)
- Loss per remaining token: 0.00193181 (breach)
- No-profit band around NAV: 6.2523 bps
- NAV per token at the shocked yields: 0.993641 (watch)

Where it flips, with the other inputs held:

- `daily_redemption_pct` at 0.0755: Forced sales begin above this daily redemption rate. Below it, cash and maturities pay every request.
- `cash` at 82713909.49: With this much starting cash, rungs and tokens as sent, no forced sale happens at the sent redemption rate. Cash is then 45.7% of the pool, and more cash lifts NAV and so the redemptions too.

## Formula

Rung value = face / (1 + y * d / 365). NAV = cash + sum of values. Net yield = sum(value * y) / NAV - fees. Forced sale price per face = (1 - bid_ask / 2) / (1 + (y + shock) * days left / 365). Face sold = cash needed / price. Loss = face * (carrying value per face - price). Loss per remaining token adds each day's loss / tokens outstanding that day. Band half-width = fee + net yield * settle_days / 365.

## Assumptions

- Each rung is valued at face / (1 + y * d / 365): simple interest, actual/365. yield_pct is a money-market yield, so convert a bank discount quote first.
- Cash earns nothing. Gross yield on NAV counts it at zero, and the ladder's own yield is shown beside it.
- Fees are a share of NAV a year. They come out of the yield and aren't taken during the walk, so the walk shows the forced sale loss alone.
- Each day runs in this order: rungs maturing that day pay face, the day's request is struck at that day's NAV per token, then payments due that day go out, with forced sales if cash falls short.
- A request is daily_redemption_pct of the tokens left that day, so tokens fall geometrically. Requests stop after stress_days. The walk runs settle_days longer so every request is paid.
- NAV is carried at the original yields the whole way. The shock and the spread reach NAV only when a sale realizes them, so a token leaving at carrying NAV takes no part of a loss not yet realized.
- A forced sale takes the nearest maturity first, in part if needed, at the shocked yield less half of bid_ask_bps, because a sale crosses from mid to bid. Face sold is grossed up so the proceeds meet the need.
- A loss falls on tokens still outstanding after that day's request. Loss per remaining token adds each day's loss per token then outstanding, not the total over the tokens left at the end, because tokens that leave later already shared part of it. A token can't lose more than its NAV.
- The redemption fee goes to the issuer, not the pool, so the pool pays out full NAV per token.
- Band half-width = mint_redeem_fee + net yield * settle_days / 365, to first order. Neither a minter's cash nor a redeemer's claim earns during settlement. Net yield stands in for the cash rate, floored at zero.
- The shadow NAV reprices the whole ladder at the shock on day 0, before spread.

## Not modeled

- New mints during the run, and any gate, pause or credit line the issuer could use.
- Depth: the spread stays the same however much is sold, and one parallel shock hits every rung.
- Reinvestment: cash from a maturity sits until it's paid out.
- A pool that strikes NAV at market yields, where leavers would share the shock and the transfer to them shrinks.
- Where the token itself trades on the secondary market during the run.
- Taxes on the bills or the token.
- Failure of the issuer, the custodian or the system recording the token.
- Whether this holder may acquire, hold, mint, redeem, pledge, sell or transfer this token, or use any pool. Those are legal questions for counsel.

## 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/tokenized_bills \
  -H 'content-type: application/json' \
  -d '{"rungs":[{"days":30,"face":15000000,"yield_pct":4},{"days":60,"face":20000000,"yield_pct":4.5},{"days":90,"face":25000000,"yield_pct":5},{"days":180,"face":40000000,"yield_pct":5.5}],"cash":1500000,"tokens_outstanding":100000000,"mgmt_fee_bps":20,"admin_custody_bps":10,"mint_redeem_fee_bps":5,"settle_days":1,"daily_redemption_pct":3,"stress_days":20,"rate_shock_bps":200,"bid_ask_bps":10}' \
  | jq '{summary, flags, flips, not_modeled, inputs_hash}'
```

### MCP

The tool is `tokenized_bills` 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":"tokenized_bills","arguments":{"rungs":[{"days":30,"face":15000000,"yield_pct":4},{"days":60,"face":20000000,"yield_pct":4.5},{"days":90,"face":25000000,"yield_pct":5},{"days":180,"face":40000000,"yield_pct":5.5}],"cash":1500000,"tokens_outstanding":100000000,"mgmt_fee_bps":20,"admin_custody_bps":10,"mint_redeem_fee_bps":5,"settle_days":1,"daily_redemption_pct":3,"stress_days":20,"rate_shock_bps":200,"bid_ask_bps":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 tokenized_bills > mine.json           # replace every number in it
node hedgefund.mjs run tokenized_bills mine.json | jq '{summary, flags, flips, not_modeled, inputs_hash}'
```

In a script:

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

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