# Token and NAV gap (token_nav_gap)

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

**What it asks.** How wide is the gap between a token's price and its NAV, how much of it can stale NAV explain, and at what size does redemption pay more than the pool?

Measures a token's premium or discount to NAV: mean, stdev, worst, share of days outside the mint and redeem band, AR(1) half-life, and how far NAV can drift unobserved between strikes. Compares exit through a constant-product pool with exit by redemption, and finds the size where they cross. Every number comes from the caller. Not a price, a quote 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 |
| --- | --- | --- | --- | --- |
| `token_prices` | array | 30 to 2000 items | no | Token price, one per day, oldest first. Send with nav_values, or leave both out and send premium_pct. |
| `nav_values` | array | 30 to 2000 items | no | NAV per token as published, same days and length as token_prices. It may repeat between strikes. |
| `premium_pct` | number | -90 to 200 | no | Today's premium to NAV, when no series is sent. -1 means 1% below NAV. NAV is then the pool's price over 1 + premium. |
| `asset_vol_pct` | number | 0 to 500 | yes | Annual volatility of the asset under the token. 10 means 10%. |
| `days_between_strikes` | number | 0 to 400 | yes | Days between NAV strikes. 7 means weekly. 0 means NAV is always fresh. |
| `pool_token_depth` | number | over 0 to 10000000000000 | yes | Tokens in the constant-product pool. |
| `pool_cash_depth` | number | over 0 to 10000000000000 | yes | Cash in the constant-product pool. |
| `position_tokens` | number | over 0 to 10000000000000 | yes | Tokens to exit. |
| `redeem_fee_bps` | number | 0 to 5000 | yes | Fee to redeem, on NAV. 100 means 1%. |
| `mint_fee_bps` | number | 0 to 5000 | no | Optional. Fee to mint, for the top of the band. Default: the redeem fee. |
| `pool_fee_bps` | number | 0 to 5000 | no | Optional. Pool fee on tokens sold in. Default 0. |
| `settle_days` | number | 0 to 400 | yes | Days from a redemption request to its payment. |
| `cash_rate_pct` | number | 0 to 50 | yes | Rate that money could earn during settlement. 5 means 5%. |

## 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
{
  "token_prices": [
    99.9, 99.85, 99.95, 100.05, 99.95, 99.9, 99.85, 100, 100.05, 99.95,
    100, 100.1, 100.05, 99.95, 100.1, 100.15, 100.05, 100.1, 100, 100.1,
    100.05, 100.2, 100.1, 99.5, 98.8, 98.2, 97.9, 98, 98.2, 98,
    97.8, 97.9, 98, 98.1, 98.05, 98, 98.1, 98.2, 98.25, 98.2,
    98.1, 98.15, 98.3, 98.35, 98.3, 98.4, 98.35, 98.3, 98.25, 98.4,
    98.5, 98.45, 98.5, 98.45, 98.4, 98.45, 98.55, 98.5, 98.55, 98.4
  ],
  "nav_values": [
    100, 100, 100, 100, 100, 100, 100, 100.1, 100.1, 100.1,
    100.1, 100.1, 100.1, 100.1, 100.2, 100.2, 100.2, 100.2, 100.2, 100.2,
    100.2, 100.3, 100.3, 100.3, 100.3, 100.3, 100.3, 100.3, 98.5, 98.5,
    98.5, 98.5, 98.5, 98.5, 98.5, 98.4, 98.4, 98.4, 98.4, 98.4,
    98.4, 98.4, 98.5, 98.5, 98.5, 98.5, 98.5, 98.5, 98.5, 98.6,
    98.6, 98.6, 98.6, 98.6, 98.6, 98.6, 98.7, 98.7, 98.7, 98.7
  ],
  "asset_vol_pct": 10,
  "days_between_strikes": 7,
  "pool_token_depth": 100000,
  "pool_cash_depth": 9840000,
  "position_tokens": 5000,
  "redeem_fee_bps": 100,
  "mint_fee_bps": 50,
  "pool_fee_bps": 10,
  "settle_days": 10,
  "cash_rate_pct": 5
}
```

## What the template gives

On these numbers, the gap averages -0.331% with 6.7% of days outside the band, against 1.38% of unobserved NAV drift, redemption pays more above 740.93 tokens, and at 5,000 tokens redemption pays 19,771 more in present value.

- Mean premium: -0.3308%
- Stdev of the premium: 0.5036%
- Worst gap: -2.3928% (watch)
- Days outside the band: 6.667% (watch)
- Half-life of the gap: 3.295 days
- NAV drift between strikes, one stdev: 1.3848% (watch)
- Exit through the pool: 468,125 (watch)
- Exit by redemption, present value: 487,897

Where it flips, with the other inputs held:

- `position_tokens` at 740.9288: On these numbers, below this size the pool pays more per token. Above it redemption does, with its fee and settlement carry counted. Neither route is checked as open to this holder.
- `settle_days` at 318.7415: At this size, a settlement this long brings redemption's present value down to what the pool pays. Longer settlement gives the pool the higher value.
- `redeem_fee_bps` at 501.1871: At this size, a redeem fee this high brings redemption's value down to what the pool pays.

## Formula

Premium = (price / NAV - 1) * 100. AR(1): x[t+1] = a + phi x[t], half-life = -ln 2 / ln phi. NAV drift, one stdev = vol * sqrt(days / 365). Pool exit: out = y * q(1 - f) / (x + q(1 - f)). Redemption = NAV * (1 - fee) / (1 + r * settle / 365). Sizes cross at q = y / R - x / (1 - f). The pool's marginal price meets R at q = (sqrt(y x (1 - f) / R) - x) / (1 - f).

## Assumptions

- Premium uses each day's published NAV, stale or not. A gap between strikes mixes market moves with NAV that hasn't caught up.
- Stdev is the sample stdev, n - 1. Worst is the largest gap by size, with its sign.
- Band: the top is mint fee plus carry, the bottom is minus redeem fee and carry. Carry = cash rate * settle_days / 365. The mint fee defaults to the redeem fee. Outside means strictly outside, by more than a billionth of a point, so a price exactly on an edge isn't counted.
- AR(1) is ordinary least squares with an intercept on all points, in steps of one observation. If NAV changes only on strike days, part of the reversion is the strike resetting the gap, not the market closing it.
- NAV drift between strikes is one stdev of the asset's lognormal move over the full interval, vol * sqrt(days / 365). The average day is less stale than that.
- The pool is constant-product. The fee comes off the tokens sold in, before the swap. Slippage is measured against the pool's own mid, y / x, and includes the fee.
- Redemption pays NAV less the fee after settle_days, discounted at the cash rate, simple, actual/365. With a series, NAV is its last value. With premium_pct only, NAV is the pool's mid / (1 + premium).
- The split sells into the pool until its marginal price falls to the redemption value, and redeems the rest. It pays at least as much as either route alone.

## Not modeled

- NAV moving between the request and the strike that sets the payment.
- Other trades in the pool, other pools, and arbitrage while a large exit is under way.
- Limits on redemption size, minimum redemption size, gates and queues.
- Transaction costs on the system recording the token, and the risk of a failed settlement.
- Liquidity providers leaving the pool in a stress, which would make the slippage worse.
- Whether this holder may acquire, hold, mint, redeem, pledge, sell or transfer this token, or use any pool. Those are legal questions for counsel.
- Fat tails in the asset: one stdev is only the scale of the drift.
- Taxes.

## 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/token_nav_gap \
  -H 'content-type: application/json' \
  -d '{"token_prices":[99.9,99.85,99.95,100.05,99.95,99.9,99.85,100,100.05,99.95,100,100.1,100.05,99.95,100.1,100.15,100.05,100.1,100,100.1,100.05,100.2,100.1,99.5,98.8,98.2,97.9,98,98.2,98,97.8,97.9,98,98.1,98.05,98,98.1,98.2,98.25,98.2,98.1,98.15,98.3,98.35,98.3,98.4,98.35,98.3,98.25,98.4,98.5,98.45,98.5,98.45,98.4,98.45,98.55,98.5,98.55,98.4],"nav_values":[100,100,100,100,100,100,100,100.1,100.1,100.1,100.1,100.1,100.1,100.1,100.2,100.2,100.2,100.2,100.2,100.2,100.2,100.3,100.3,100.3,100.3,100.3,100.3,100.3,98.5,98.5,98.5,98.5,98.5,98.5,98.5,98.4,98.4,98.4,98.4,98.4,98.4,98.4,98.5,98.5,98.5,98.5,98.5,98.5,98.5,98.6,98.6,98.6,98.6,98.6,98.6,98.6,98.7,98.7,98.7,98.7],"asset_vol_pct":10,"days_between_strikes":7,"pool_token_depth":100000,"pool_cash_depth":9840000,"position_tokens":5000,"redeem_fee_bps":100,"mint_fee_bps":50,"pool_fee_bps":10,"settle_days":10,"cash_rate_pct":5}' \
  | jq '{summary, flags, flips, not_modeled, inputs_hash}'
```

### MCP

The tool is `token_nav_gap` 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":"token_nav_gap","arguments":{"token_prices":[99.9,99.85,99.95,100.05,99.95,99.9,99.85,100,100.05,99.95,100,100.1,100.05,99.95,100.1,100.15,100.05,100.1,100,100.1,100.05,100.2,100.1,99.5,98.8,98.2,97.9,98,98.2,98,97.8,97.9,98,98.1,98.05,98,98.1,98.2,98.25,98.2,98.1,98.15,98.3,98.35,98.3,98.4,98.35,98.3,98.25,98.4,98.5,98.45,98.5,98.45,98.4,98.45,98.55,98.5,98.55,98.4],"nav_values":[100,100,100,100,100,100,100,100.1,100.1,100.1,100.1,100.1,100.1,100.1,100.2,100.2,100.2,100.2,100.2,100.2,100.2,100.3,100.3,100.3,100.3,100.3,100.3,100.3,98.5,98.5,98.5,98.5,98.5,98.5,98.5,98.4,98.4,98.4,98.4,98.4,98.4,98.4,98.5,98.5,98.5,98.5,98.5,98.5,98.5,98.6,98.6,98.6,98.6,98.6,98.6,98.6,98.7,98.7,98.7,98.7],"asset_vol_pct":10,"days_between_strikes":7,"pool_token_depth":100000,"pool_cash_depth":9840000,"position_tokens":5000,"redeem_fee_bps":100,"mint_fee_bps":50,"pool_fee_bps":10,"settle_days":10,"cash_rate_pct":5}}}' \
  | 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 token_nav_gap > mine.json           # replace every number in it
node hedgefund.mjs run token_nav_gap mine.json | jq '{summary, flags, flips, not_modeled, inputs_hash}'
```

In a script:

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

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