---
title: "Triggers"
description: "IFTTT-style trigger system for automated actions. Price thresholds, percent changes, crossovers, webhooks, and a built-in oracle HTTP server."
icon: "bell"
---

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

# Triggers

Set conditions, get actions. Horizon's trigger system evaluates rules each cycle and fires actions when conditions are met. Supports 8 condition types, 5 action types, cooldown periods, and hysteresis to prevent trigger storms. The evaluation logic is pure Rust (stateless); all mutable state lives in the Python closure.

## Overview

<CardGroup cols={2}>
  <Card title="8 Conditions" icon="code-branch">
    Above, below, cross above/below, percent change, absolute change, between, outside.
  </Card>
  <Card title="5 Actions" icon="bolt">
    Alert, webhook, order, hedge, kill switch.
  </Card>
  <Card title="Cooldown & Hysteresis" icon="shield-halved">
    Prevent trigger storms with configurable cooldown and hysteresis bands.
  </Card>
  <Card title="Oracle Server" icon="server">
    `hz.oracle()` exposes feed prices as a JSON HTTP endpoint.
  </Card>
</CardGroup>

---

## Core Functions

### hz.evaluate_trigger

Evaluate a trigger rule against current market state. Pure function (no side effects).

```python
import horizon as hz

rule = hz.create_trigger(
    name="btc_pump",
    condition=hz.TriggerCondition.Above,
    threshold=0.75,
    action=hz.TriggerActionType.Alert,
)
result = hz.evaluate_trigger(
    rule=rule,
    current_value=0.80,
    previous_value=0.70,
    last_fire_time=0.0,
    current_time=1000.0,
    armed=True,
)
if result.fired:
    print(f"Fired: {result.reason}")
```

### hz.create_trigger

Create a trigger rule with full configuration.

```python
rule = hz.create_trigger(
    name="volatility_spike",
    condition=hz.TriggerCondition.PercentChange,
    threshold=0.10,                     # 10% move
    action=hz.TriggerActionType.Webhook,
    threshold_upper=0.0,                # for Between/Outside conditions
    cooldown_secs=300.0,                # 5 minute cooldown
    hysteresis=0.02,                    # 2% hysteresis band
)
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `name` | `str` | required | Trigger name |
| `condition` | `TriggerCondition` | required | Condition type |
| `threshold` | `float` | required | Primary threshold |
| `action` | `TriggerActionType` | required | Action to take |
| `threshold_upper` | `float` | `0.0` | Upper threshold (for Between/Outside) |
| `cooldown_secs` | `float` | `60.0` | Minimum seconds between fires |
| `hysteresis` | `float` | `0.0` | Hysteresis band to prevent flapping |

### Condition Types

| Condition | Fires when |
|-----------|-----------|
| `Above` | value &gt; threshold |
| `Below` | value &lt; threshold |
| `CrossAbove` | previous &lt;= threshold AND current &gt; threshold |
| `CrossBelow` | previous &gt;= threshold AND current &lt; threshold |
| `PercentChange` | abs(current - previous) / previous &gt; threshold |
| `AbsoluteChange` | abs(current - previous) &gt; threshold |
| `Between` | threshold &lt;= value &lt;= threshold\_upper |
| `Outside` | value &lt; threshold OR value &gt; threshold\_upper |

### Action Types

| Action | Description |
|--------|-----------|
| `Alert` | Send alert via AlertManager |
| `Webhook` | Fire HTTP POST to configured URL |
| `Order` | Submit an order |
| `Hedge` | Trigger a hedge trade |
| `KillSwitch` | Activate kill switch |

---

## Pipeline Functions

### hz.trigger

Evaluate multiple trigger rules each cycle.

```python
triggers = hz.trigger(
    triggers=[
        hz.TriggerConfig(
            name="price_pump",
            feed_name="btc",
            condition="cross_above",
            threshold=0.75,
            action="alert",
            cooldown_secs=300,
        ),
        hz.TriggerConfig(
            name="price_dump",
            feed_name="btc",
            condition="cross_below",
            threshold=0.25,
            action="webhook",
            webhook_url="https://hooks.slack.com/...",
            cooldown_secs=60,
        ),
    ],
)
```

| Parameter | Type | Description |
|-----------|------|-------------|
| `triggers` | `list[TriggerConfig]` | Trigger configurations |
| `alert_manager` | `Any` | Optional AlertManager for alert actions |

### hz.conditional_hedge

Automatically hedge when a condition is met.

```python
hedge = hz.conditional_hedge(
    feed_name="btc",
    condition="below",
    threshold=0.3,
    hedge_size=100.0,
    cooldown_secs=300,
)
```

### hz.oracle

Start a minimal HTTP server exposing live feed prices as JSON.

```python
oracle = hz.oracle(port=8099)
# GET http://localhost:8099/ returns {"feeds": {"btc": 0.65, "eth": 0.42}}
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `port` | `int` | `8099` | HTTP server port |

---

## Examples

### Alert on Price Moves

```python
import horizon as hz

hz.run(
    name="trigger_bot",
    feeds={
        "btc": hz.PolymarketBook("will-btc-hit-100k"),
        "fed": hz.PolymarketBook("will-fed-cut-rates"),
    },
    pipeline=[
        hz.trigger(triggers=[
            hz.TriggerConfig(
                name="btc_breakout", feed_name="btc",
                condition="cross_above", threshold=0.80,
                action="alert", cooldown_secs=600,
            ),
            hz.TriggerConfig(
                name="fed_crash", feed_name="fed",
                condition="percent_change", threshold=0.10,
                action="webhook",
                webhook_url="https://hooks.slack.com/services/...",
                cooldown_secs=120,
            ),
        ]),
        my_strategy,
    ],
)
```

### Oracle for External Systems

```python
import horizon as hz

hz.run(
    name="price_oracle",
    feeds={
        "btc": hz.PolymarketBook("will-btc-hit-100k"),
        "eth": hz.PolymarketBook("will-eth-hit-10k"),
    },
    pipeline=[hz.oracle(port=8099)],
)
# External systems can now GET http://localhost:8099/ for live prices
```
