Skip to main content
Ultra Feature. Requires an Ultra subscription. Get started at api.mathematicalcompany.com
Monitor your portfolio in real time with graduated drawdown levels, automated risk reduction, hedge recommendations, and Cornish-Fisher VaR/CVaR.

Full Code

"""Sentinel: real-time portfolio risk monitoring."""

import horizon as hz

engine = hz.Engine()

# Simulate some positions
engine.process_fill(hz.Fill(
    order_id="p1", market_id="election-winner", side=hz.Side.Yes,
    order_side=hz.OrderSide.Buy, price=0.55, size=100.0, timestamp=0.0,
    fee=0.0, is_maker=True,
))
engine.process_fill(hz.Fill(
    order_id="p2", market_id="btc-100k", side=hz.Side.Yes,
    order_side=hz.OrderSide.Buy, price=0.60, size=80.0, timestamp=0.0,
    fee=0.0, is_maker=True,
))

# ── Standalone risk report ──
report = hz.sentinel_report(engine)

print("Sentinel Risk Report")
print(f"  Portfolio value:     ${report.portfolio_value:,.2f}")
print(f"  Unrealized PnL:     ${report.unrealized_pnl:,.2f}")
print(f"  Current drawdown:   {report.drawdown_pct:.2%}")
print(f"  Drawdown level:     {report.drawdown_level.name}")
print(f"  VaR (95%):          ${report.var_95:,.2f}")
print(f"  CVaR (95%):         ${report.cvar_95:,.2f}")
print(f"  Position count:     {report.position_count}")
print(f"  Concentration risk: {report.concentration_risk:.2%}")

# ── Hedge suggestions ──
hedges = hz.suggest_hedges(engine)

print(f"\nHedge Suggestions:")
for h in hedges:
    print(f"  {h.action}: {h.side} {h.size:.0f} contracts on {h.market_id}")
    print(f"    Reason: {h.reason}")
    print(f"    Expected delta reduction: {h.delta_reduction:.2f}")

Pipeline Mode

Run sentinel monitoring as part of a live strategy with graduated drawdown response:
"""Sentinel pipeline with graduated drawdown management."""

import horizon as hz
from horizon.context import FeedData


def fair_value(ctx: hz.Context) -> float:
    feed = ctx.feeds.get("polymarket", FeedData())
    return feed.price if feed.price > 0 else 0.50


def quoter(ctx: hz.Context, fair: float) -> list[hz.Quote]:
    return hz.quotes(fair, spread=0.04, size=10)


# Sentinel pipeline: monitors risk and takes action
risk_monitor = hz.sentinel(
    config=hz.SentinelConfig(
        # Graduated drawdown levels
        alert_drawdown_pct=5.0,     # alert at -5%
        reduce_drawdown_pct=10.0,   # reduce positions at -10%
        pause_drawdown_pct=20.0,    # pause quoting at -20%
        exit_drawdown_pct=30.0,     # exit all positions at -30%

        # Risk budgets
        max_var_pct=5.0,            # max portfolio VaR as % of capital
        max_concentration=0.40,     # max 40% in one market

        # Reporting
        report_interval=60,         # log risk report every 60 seconds
    ),
)

hz.run(
    name="sentinel_monitored",
    markets=["election-winner", "btc-100k"],
    feeds={
        "polymarket": hz.PolymarketBook("election-winner"),
    },
    pipeline=[fair_value, quoter, risk_monitor],
    risk=hz.Risk(max_position=200, max_drawdown_pct=35),
    interval=1.0,
    mode="paper",
)

How It Works

  1. sentinel_report() computes a risk snapshot:
  • Cornish-Fisher VaR/CVaR (adjusts for skew and kurtosis)
  • Current drawdown level and classification
  • Position concentration risk
  • Correlation alerts between positions
  1. suggest_hedges() recommends trades to reduce portfolio delta
  2. sentinel() pipeline function takes graduated action:
  • Alert (-5%) - log warning, no action
  • Reduce (-10%) - cut position sizes by 50%
  • Pause (-20%) - stop submitting new quotes
  • Exit (-30%) - close all positions

Cornish-Fisher Risk Metrics

You can also compute VaR/CVaR directly from Rust:
import horizon as hz

returns = [-0.02, 0.01, -0.03, 0.02, -0.01, 0.005, -0.015, 0.03, -0.04, 0.01]

var = hz.cornish_fisher_var(returns, confidence=0.95)
cvar = hz.cornish_fisher_cvar(returns, confidence=0.95)

print(f"VaR (95%):  {var:.4f}")
print(f"CVaR (95%): {cvar:.4f}")

Run It

python examples/sentinel_risk_monitor.py
See Sentinel for the full reference.