---
title: "Treasury Yield Curve"
description: "Integrate Treasury yield data via FRED API. Yield-adjusted Kelly sizing, opportunity cost filtering, and collateral optimization based on the yield curve shape."
icon: "landmark"
---

<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
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
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
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
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
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
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
{
    "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
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
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
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>
