> ## Documentation Index
> Fetch the complete documentation index at: https://mathematicalcompany.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Treasury Yield Curve

> Integrate Treasury yield data via FRED API. Yield-adjusted Kelly sizing, opportunity cost filtering, and collateral optimization based on the yield curve shape.

<Warning>
  **Ultra Feature.** Requires an Ultra subscription. [Get started at api.mathematicalcompany.com](https://api.mathematicalcompany.com)
</Warning>

# Treasury Yield Curve

Prediction market positions tie up capital that could earn risk-free yield in Treasuries. When rates are high, a trade needs more edge to justify the opportunity cost. Horizon's treasury module provides a live yield curve feed (via FRED), yield-adjusted Kelly sizing, breakeven edge calculation, and collateral optimization. All math is in Rust.

## Overview

<CardGroup cols={2}>
  <Card title="Yield-Adjusted Kelly" icon="calculator">
    `hz.yield_adjusted_kelly()` reduces Kelly size by the risk-free rate opportunity cost.
  </Card>

  <Card title="Opportunity Cost" icon="coins">
    `hz.opportunity_cost()` and `hz.breakeven_edge()` quantify the hurdle rate for a trade.
  </Card>

  <Card title="Live Yield Feed" icon="chart-line">
    `TreasuryFeed` polls FRED for the full yield curve (1M through 30Y).
  </Card>

  <Card title="Collateral Optimizer" icon="scale-balanced">
    `hz.collateral_optimizer()` adjusts capital allocation based on curve steepness.
  </Card>
</CardGroup>

***

## Core Functions

All math runs in Rust. Every output is guarded against NaN/Inf.

### hz.yield\_adjusted\_kelly

Standard Kelly fraction minus the annualized opportunity cost of locked capital.

```python theme={null}
import horizon as hz

fraction = hz.yield_adjusted_kelly(
    prob=0.60,
    price=0.50,
    rfr=0.05,        # 5% risk-free rate
    duration_days=30,
    fraction=0.5,     # half-Kelly
)
print(f"Adjusted Kelly: {fraction:.4f}")
```

| Parameter       | Type    | Default  | Description                         |
| --------------- | ------- | -------- | ----------------------------------- |
| `prob`          | `float` | required | Estimated probability of the event  |
| `price`         | `float` | required | Current market price                |
| `rfr`           | `float` | required | Risk-free rate (annualized decimal) |
| `duration_days` | `float` | required | Expected holding period in days     |
| `fraction`      | `float` | `0.5`    | Kelly fraction (0.5 = half-Kelly)   |

Returns 0.0 if the edge does not exceed the opportunity cost.

### hz.yield\_adjusted\_kelly\_size

Convert yield-adjusted Kelly fraction to a dollar position size.

```python theme={null}
size = hz.yield_adjusted_kelly_size(
    prob=0.60, price=0.50, rfr=0.05,
    duration_days=30, bankroll=10000.0,
    fraction=0.5, max_size=1000.0,
)
print(f"Position size: ${size:.2f}")
```

| Parameter       | Type    | Default  | Description               |
| --------------- | ------- | -------- | ------------------------- |
| `prob`          | `float` | required | Estimated probability     |
| `price`         | `float` | required | Market price              |
| `rfr`           | `float` | required | Risk-free rate            |
| `duration_days` | `float` | required | Holding period in days    |
| `bankroll`      | `float` | required | Total bankroll            |
| `fraction`      | `float` | `0.5`    | Kelly fraction            |
| `max_size`      | `float` | `inf`    | Maximum position size cap |

### hz.opportunity\_cost

Dollar cost of locking capital at the risk-free rate.

```python theme={null}
cost = hz.opportunity_cost(notional=5000.0, rfr=0.05, duration_days=30)
print(f"Opportunity cost: ${cost:.2f}")  # ~$20.55
```

| Parameter       | Type    | Description                    |
| --------------- | ------- | ------------------------------ |
| `notional`      | `float` | Capital locked in the position |
| `rfr`           | `float` | Risk-free rate (annualized)    |
| `duration_days` | `float` | Holding period in days         |

### hz.breakeven\_edge

Minimum edge required to beat the risk-free rate.

```python theme={null}
be = hz.breakeven_edge(rfr=0.05, duration_days=30)
print(f"Breakeven edge: {be:.4f}")  # ~0.41%
```

| Parameter       | Type    | Description            |
| --------------- | ------- | ---------------------- |
| `rfr`           | `float` | Risk-free rate         |
| `duration_days` | `float` | Holding period in days |

***

## Feed

### TreasuryFeed

Polls the Federal Reserve Economic Data (FRED) API for yield curve data.

```python theme={null}
import horizon as hz

feed = hz.TreasuryFeed(
    api_key="your_fred_api_key",  # or set FRED_API_KEY env var
    primary_series="DGS10",
)
```

| Parameter        | Type        | Default                | Description               |
| ---------------- | ----------- | ---------------------- | ------------------------- |
| `api_key`        | `str`       | `FRED_API_KEY` env var | FRED API key              |
| `series_ids`     | `list[str]` | 9 standard maturities  | Treasury series to fetch  |
| `primary_series` | `str`       | `"DGS10"`              | Series used as main price |
| `interval`       | `float`     | `300.0`                | Poll interval in seconds  |

Default series: DGS1MO, DGS3MO, DGS6MO, DGS1, DGS2, DGS5, DGS10, DGS20, DGS30.

FeedSnapshot mapping:

* `price` = primary series yield (decimal)
* `bid` = short-term yield (DGS3MO)
* `ask` = long-term yield (DGS30)
* `volume_24h` = curve slope in basis points (long - short)

***

## Pipeline Functions

### hz.yield\_adjusted\_sizer

Size positions using yield-adjusted Kelly each cycle.

```python theme={null}
sizer = hz.yield_adjusted_sizer(
    rfr_feed="treasury",
    duration_days=30,
    fraction=0.5,
    bankroll=10000.0,
    max_size=1000.0,
)

hz.run(
    name="yield_aware",
    feeds={"treasury": hz.TreasuryFeed(), "market": hz.PolymarketBook("...")},
    pipeline=[sizer, my_strategy],
)
```

| Parameter       | Type    | Default      | Description                  |
| --------------- | ------- | ------------ | ---------------------------- |
| `rfr_feed`      | `str`   | `"treasury"` | Feed name for the yield data |
| `duration_days` | `float` | `30.0`       | Expected holding period      |
| `fraction`      | `float` | `0.5`        | Kelly fraction               |
| `bankroll`      | `float` | `10000.0`    | Total bankroll               |
| `max_size`      | `float` | `1000.0`     | Maximum position size        |

Returns each cycle:

```python theme={null}
{
    "size": 245.0,
    "yield_adjusted_kelly": 0.049,
    "breakeven_edge": 0.004,
    "opportunity_cost": 20.55,
    "rfr": 0.05,
}
```

### hz.opportunity\_cost\_filter

Skip trades where edge does not justify the opportunity cost.

```python theme={null}
filter_fn = hz.opportunity_cost_filter(
    rfr_feed="treasury",
    duration_days=30,
    min_edge_multiple=2.0,  # need 2x breakeven edge to trade
)
```

| Parameter           | Type    | Default      | Description                         |
| ------------------- | ------- | ------------ | ----------------------------------- |
| `rfr_feed`          | `str`   | `"treasury"` | Feed name for yield data            |
| `duration_days`     | `float` | `30.0`       | Holding period                      |
| `min_edge_multiple` | `float` | `2.0`        | Required multiple of breakeven edge |

### hz.collateral\_optimizer

Adjusts capital allocation based on yield curve steepness.

```python theme={null}
optimizer = hz.collateral_optimizer(rfr_feed="treasury", max_utilization=0.8)
```

| Parameter         | Type    | Default      | Description                 |
| ----------------- | ------- | ------------ | --------------------------- |
| `rfr_feed`        | `str`   | `"treasury"` | Feed name                   |
| `max_utilization` | `float` | `0.8`        | Maximum capital utilization |

Steeper curves reduce allocation (higher opportunity cost of capital).

***

## Examples

### Yield-Aware Market Making

```python theme={null}
import horizon as hz

def my_mm(ctx):
    if ctx.feed is None or ctx.feed.price <= 0:
        return []
    # Use yield-adjusted size from upstream pipeline
    size = ctx.params.get("size", 10)
    return hz.quotes(fair=ctx.feed.price, spread=0.04, size=size)

hz.run(
    name="yield_mm",
    exchange=hz.Polymarket(),
    feeds={
        "market": hz.PolymarketBook("will-fed-cut-rates"),
        "treasury": hz.TreasuryFeed(),
    },
    pipeline=[
        hz.yield_adjusted_sizer(rfr_feed="treasury", bankroll=10000),
        hz.opportunity_cost_filter(rfr_feed="treasury", min_edge_multiple=2.0),
        my_mm,
    ],
)
```

***

## Mathematical Background

<AccordionGroup>
  <Accordion title="Yield-Adjusted Kelly">
    Standard Kelly: **f* = (p - q) / (b - 1)*\* where p is probability, q = 1-p, and b is the payout odds.

    Yield adjustment subtracts the annualized opportunity cost:

    **f\_adj = max(0, f* - rfr \* duration / 365) \* fraction*\*

    When the risk-free rate is high relative to the edge, the adjusted fraction drops to zero, meaning the trade is not worth taking.
  </Accordion>

  <Accordion title="Breakeven Edge">
    The minimum edge that justifies locking capital:

    **breakeven = rfr \* duration / 365**

    At 5% rates and a 30-day hold, the breakeven is about 0.41%. Any edge below that is better invested in T-bills.
  </Accordion>

  <Accordion title="Opportunity Cost">
    Dollar cost of capital deployment:

    **cost = notional \* rfr \* duration / 365**

    This represents the forgone interest on the locked collateral.
  </Accordion>
</AccordionGroup>
