# Property token (tokenized_property)

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

**What it asks.** What would this property token pay on these numbers, which cap rate move hits its covenant, and how does a secondary discount compare with waiting in the redemption queue?

Takes a pool of properties with debt: cap rate, debt service cover, LTV, NAV per token, distribution after debt service, reserves and fees. A shock grid of cap rate moves and vacancy, per property. Quarters to get a request through a gate, and the secondary discount that equals waiting. Every number comes from the caller. Not an appraisal, a price 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 |
| --- | --- | --- | --- | --- |
| `properties` | array | 1 to 50 items | yes | The properties in the pool. Up to 50. |
| `properties[].name` | string |  | yes | A label, such as Office tower A. |
| `properties[].value` | number | over 0 to 1000000000000 | yes | Current value. |
| `properties[].noi` | number | over 0 to 100000000000 | yes | Net operating income a year. The cap rate is noi / value. |
| `properties[].debt` | number | 0 to 1000000000000 | yes | Debt outstanding. 0 if none. |
| `properties[].debt_rate_pct` | number | 0 to 50 | yes | Interest rate on the debt. 5 means 5%. |
| `properties[].amort_pct` | number | 0 to 50 | yes | Principal repaid a year, as a share of the debt. 1 means 1%. |
| `tokens_outstanding` | number | over 0 to 10000000000000 | yes | Tokens outstanding. |
| `platform_fee_bps` | number | 0 to 2000 | yes | Platform fee a year on NAV. 100 means 1%. |
| `reserve_pct_of_noi` | number | 0 to 100 | yes | Share of NOI held back as reserves. 10 means 10%. |
| `cap_rate_shock_bps` | number | 0 to 2000 | yes | Rise in each property's cap rate in the shock. 100 means 1 point. |
| `vacancy_shock_pct` | number | 0 to 95 | yes | Fall in NOI from vacancy in the shock. 5 means NOI falls 5%. |
| `ltv_covenant_pct` | number | over 0 to 200 | yes | Loan covenant: the highest LTV allowed, tested per property. 65 means 65%. |
| `gate_pct_per_quarter` | number | 0 to 100 | yes | Share of tokens outstanding that can leave each quarter. 0 means redemptions are shut. |
| `redemption_request_pct` | number | 0 to 100 | yes | Share of all tokens asking out, shared pro rata under the gate. |
| `secondary_discount_pct` | number | 0 to 100 | yes | The discount to NAV you say a sale would take now. Whether a sale is allowed isn't checked. |

## 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
{
  "properties": [
    {
      "name": "Office tower A",
      "value": 40000000,
      "noi": 2200000,
      "debt": 24000000,
      "debt_rate_pct": 5.5,
      "amort_pct": 1
    },
    {
      "name": "Warehouse B",
      "value": 30000000,
      "noi": 1950000,
      "debt": 15000000,
      "debt_rate_pct": 5,
      "amort_pct": 1
    },
    {
      "name": "Retail park C",
      "value": 10000000,
      "noi": 750000,
      "debt": 6000000,
      "debt_rate_pct": 6,
      "amort_pct": 2
    }
  ],
  "tokens_outstanding": 1000000,
  "platform_fee_bps": 100,
  "reserve_pct_of_noi": 10,
  "cap_rate_shock_bps": 100,
  "vacancy_shock_pct": 5,
  "ltv_covenant_pct": 65,
  "gate_pct_per_quarter": 5,
  "redemption_request_pct": 25,
  "secondary_discount_pct": 12
}
```

## What the template gives

On these numbers, NAV is 35 per token with a hypothetical 3.2% distribution yield, a 25% request takes 6 quarters under the gate and costs 2.5% in present value with NAV flat, against a 12% secondary discount, and at the sent shock NAV is 20.24 with the worst LTV at 74.64%.

- NAV per token: 35
- Pool LTV: 56.25% (watch)
- Debt service cover: 1.667x
- Distribution per token: 1.12
- Hypothetical distribution yield on NAV: 3.2%
- Quarters to clear a request: 6 (watch)
- Break-even secondary discount: 2.504% (watch)
- NAV per token at the sent shock: 20.24 (breach)

Where it flips, with the other inputs held:

- `cap_rate_shock_bps` at 16.04: With vacancy at the sent shock, Office tower A reaches the 65% covenant at this cap rate move, the first property to do so.
- `cap_rate_shock_bps` at 59.22: With vacancy at the sent shock, the pool's LTV as a whole reaches the 65% covenant at this cap rate move.
- `cap_rate_shock_bps` at 418.84: With vacancy at the sent shock, pool equity is gone at this cap rate move: value equals debt and NAV is zero.
- `vacancy_shock_pct` at 33.1239: With the cap rate move as sent, the distribution reaches zero at this vacancy.
- `cap_rate_shock_bps` at 26.95: With no vacancy change, at this cap rate move the queue, paid at the NAV that move gives, is worth what a sale now at the sent discount brings. Above it a sale at the sent discount shows the higher present value, if a sale is allowed at all.

## Formula

Cap rate = NOI / value. Debt service = debt * (rate + amort). Cover = NOI / debt service. LTV = debt / value. NAV = value - debt. Distribution = NOI - debt service - reserve - fee. Shocked value per property = NOI * (1 - vacancy) / (cap + shock). Queue fills = min(left, gate * tokens outstanding) each quarter. Break-even discount = 1 - sum(fill_q / (1 + y / 4)^q).

## Assumptions

- Debt service for the year = debt * (debt_rate_pct + amort_pct) / 100, with interest on the opening balance.
- The platform fee is a share of NAV, so a lower NAV means a lower fee. Reserves are a share of NOI, held back and not added to NAV. Distribution is what remains. It is floored at zero, and a deficit is flagged.
- Distribution yield is on NAV, not on a secondary price. Amortization builds equity but isn't counted in it.
- The shock moves each property's own cap rate, then sums. Vacancy takes the same share off NOI, with operating costs falling in step. Debt rates stay as sent.
- The covenant is tested per property, and the pool's LTV is shown beside it. Debt is netted across the pool, floored at zero per token.
- The gate is a share of tokens outstanding at the start of each quarter, so it shrinks as the queue is paid. Fills are pro rata and paid at quarter end. The tail stops once under 1 part in 10,000 of the request is left. The count stops at 400 quarters, and anything still unpaid then is given no value in the break-even.
- Break-even discount: a request in the queue earns no distribution, and money out now can earn the pool's distribution yield. Quarterly compounding, NAV flat. If the queue did keep earning the distribution at that same rate, the break-even would be zero.
- Flips on the cap rate hold vacancy at the sent shock. The flip against the secondary discount is the exception: it holds vacancy at zero, so it reads as a pure cap rate move.

## Not modeled

- Operating leverage: with fixed costs, NOI falls faster than revenue in a vacancy shock.
- Refinancing and floating debt: a cap rate move usually comes with a rate move, and maturing loans reprice.
- Non-recourse loans: a lender's claim here reaches the whole pool. If a loan can't reach it, a property under water costs less than shown.
- How the pool finds cash for redemptions, and what that does to LTV. Sales, costs and new borrowing are ignored.
- First-in-first-out queues, where a place at the back waits longer than the pro rata figure.
- Appraisal lag and error: value is what was sent.
- Capital spending, leasing costs, and the use of reserves.
- Taxes at the property, the pool or the holder, and transfer costs on a secondary sale.
- Where the secondary market's depth can absorb a sale at the sent discount.
- 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_property \
  -H 'content-type: application/json' \
  -d '{"properties":[{"name":"Office tower A","value":40000000,"noi":2200000,"debt":24000000,"debt_rate_pct":5.5,"amort_pct":1},{"name":"Warehouse B","value":30000000,"noi":1950000,"debt":15000000,"debt_rate_pct":5,"amort_pct":1},{"name":"Retail park C","value":10000000,"noi":750000,"debt":6000000,"debt_rate_pct":6,"amort_pct":2}],"tokens_outstanding":1000000,"platform_fee_bps":100,"reserve_pct_of_noi":10,"cap_rate_shock_bps":100,"vacancy_shock_pct":5,"ltv_covenant_pct":65,"gate_pct_per_quarter":5,"redemption_request_pct":25,"secondary_discount_pct":12}' \
  | jq '{summary, flags, flips, not_modeled, inputs_hash}'
```

### MCP

The tool is `tokenized_property` 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_property","arguments":{"properties":[{"name":"Office tower A","value":40000000,"noi":2200000,"debt":24000000,"debt_rate_pct":5.5,"amort_pct":1},{"name":"Warehouse B","value":30000000,"noi":1950000,"debt":15000000,"debt_rate_pct":5,"amort_pct":1},{"name":"Retail park C","value":10000000,"noi":750000,"debt":6000000,"debt_rate_pct":6,"amort_pct":2}],"tokens_outstanding":1000000,"platform_fee_bps":100,"reserve_pct_of_noi":10,"cap_rate_shock_bps":100,"vacancy_shock_pct":5,"ltv_covenant_pct":65,"gate_pct_per_quarter":5,"redemption_request_pct":25,"secondary_discount_pct":12}}}' \
  | 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_property > mine.json           # replace every number in it
node hedgefund.mjs run tokenized_property mine.json | jq '{summary, flags, flips, not_modeled, inputs_hash}'
```

In a script:

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

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