Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mathematicalcompany.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Ultra Feature. Requires an Ultra subscription. Get started at api.mathematicalcompany.com

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

Yield-Adjusted Kelly

hz.yield_adjusted_kelly() reduces Kelly size by the risk-free rate opportunity cost.

Opportunity Cost

hz.opportunity_cost() and hz.breakeven_edge() quantify the hurdle rate for a trade.

Live Yield Feed

TreasuryFeed polls FRED for the full yield curve (1M through 30Y).

Collateral Optimizer

hz.collateral_optimizer() adjusts capital allocation based on curve steepness.

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.
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}")
ParameterTypeDefaultDescription
probfloatrequiredEstimated probability of the event
pricefloatrequiredCurrent market price
rfrfloatrequiredRisk-free rate (annualized decimal)
duration_daysfloatrequiredExpected holding period in days
fractionfloat0.5Kelly 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.
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}")
ParameterTypeDefaultDescription
probfloatrequiredEstimated probability
pricefloatrequiredMarket price
rfrfloatrequiredRisk-free rate
duration_daysfloatrequiredHolding period in days
bankrollfloatrequiredTotal bankroll
fractionfloat0.5Kelly fraction
max_sizefloatinfMaximum position size cap

hz.opportunity_cost

Dollar cost of locking capital at the risk-free rate.
cost = hz.opportunity_cost(notional=5000.0, rfr=0.05, duration_days=30)
print(f"Opportunity cost: ${cost:.2f}")  # ~$20.55
ParameterTypeDescription
notionalfloatCapital locked in the position
rfrfloatRisk-free rate (annualized)
duration_daysfloatHolding period in days

hz.breakeven_edge

Minimum edge required to beat the risk-free rate.
be = hz.breakeven_edge(rfr=0.05, duration_days=30)
print(f"Breakeven edge: {be:.4f}")  # ~0.41%
ParameterTypeDescription
rfrfloatRisk-free rate
duration_daysfloatHolding period in days

Feed

TreasuryFeed

Polls the Federal Reserve Economic Data (FRED) API for yield curve data.
import horizon as hz

feed = hz.TreasuryFeed(
    api_key="your_fred_api_key",  # or set FRED_API_KEY env var
    primary_series="DGS10",
)
ParameterTypeDefaultDescription
api_keystrFRED_API_KEY env varFRED API key
series_idslist[str]9 standard maturitiesTreasury series to fetch
primary_seriesstr"DGS10"Series used as main price
intervalfloat300.0Poll 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.
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],
)
ParameterTypeDefaultDescription
rfr_feedstr"treasury"Feed name for the yield data
duration_daysfloat30.0Expected holding period
fractionfloat0.5Kelly fraction
bankrollfloat10000.0Total bankroll
max_sizefloat1000.0Maximum position size
Returns each cycle:
{
    "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.
filter_fn = hz.opportunity_cost_filter(
    rfr_feed="treasury",
    duration_days=30,
    min_edge_multiple=2.0,  # need 2x breakeven edge to trade
)
ParameterTypeDefaultDescription
rfr_feedstr"treasury"Feed name for yield data
duration_daysfloat30.0Holding period
min_edge_multiplefloat2.0Required multiple of breakeven edge

hz.collateral_optimizer

Adjusts capital allocation based on yield curve steepness.
optimizer = hz.collateral_optimizer(rfr_feed="treasury", max_utilization=0.8)
ParameterTypeDefaultDescription
rfr_feedstr"treasury"Feed name
max_utilizationfloat0.8Maximum capital utilization
Steeper curves reduce allocation (higher opportunity cost of capital).

Examples

Yield-Aware Market Making

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

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.
The minimum edge that justifies locking capital:breakeven = rfr * duration / 365At 5% rates and a 30-day hold, the breakeven is about 0.41%. Any edge below that is better invested in T-bills.
Dollar cost of capital deployment:cost = notional * rfr * duration / 365This represents the forgone interest on the locked collateral.