Skip to main content
Resolution Sniping monitors news sources and uses LLM analysis to detect when a prediction market’s underlying event has resolved. When resolution is detected with high confidence, it generates aggressive quotes to buy the resolving side near parity.

Standalone Scan

import horizon as hz

markets = [
    {"id": "market-1", "title": "Will team X win the championship?"},
    {"id": "market-2", "title": "Will bill Y pass the Senate?"},
]

signals = hz.scan_resolutions(markets)
for s in signals:
    print(f"{s.market_title}: resolved={s.resolved} side={s.resolution_side}")
    print(f"  Confidence: {s.confidence:.2%}")
    print(f"  Evidence: {s.evidence}")

Pipeline Mode

Integrate sniping into your hz.run() pipeline:
hz.run(
    name="sniper-bot",
    markets=["championship-2026", "senate-bill-xyz"],
    feeds={"poly": hz.PolymarketBook("championship-2026")},
    pipeline=[hz.resolution_sniper()],
)
When resolution is detected:
  1. Fetches latest news from configured RSS sources
  2. LLM evaluates if the event has definitively resolved
  3. If confidence >= threshold: generates aggressive quote at near-parity
  4. Tracks already-triggered markets to avoid double-sniping

Configuration

config = hz.SniperConfig(
    provider="anthropic",           # or "openai", or any litellm provider
    model="",                       # empty = provider default; or "openrouter/..."
    news_sources=[                  # RSS feeds to monitor
        "https://feeds.bbci.co.uk/news/rss.xml",
    ],
    exa_query="election results",   # Exa.ai semantic search (optional)
    tavily_query="vote count",      # Tavily real-time search (optional)
    confidence_threshold=0.85,      # minimum confidence to trigger
    max_position_size=50.0,         # max USDC per snipe
    price_offset=0.02,              # offset from 1.0 for pricing
    scan_interval_cycles=5,         # cycles between scans
    cache_ttl=60.0,                 # signal cache TTL
)

hz.run(
    pipeline=[hz.resolution_sniper(config=config)],
    ...
)

Kalshi Markets

The MCP sniper_scan tool supports Kalshi markets via the exchange parameter. Market discovery will pull from Kalshi instead of Polymarket:
# Via MCP tool
sniper_scan(exchange="kalshi")
The resolution detection logic (news + LLM) is exchange-agnostic: it works identically for both Polymarket and Kalshi markets.

How It Works

News Feed -> LLM Analysis -> Resolution Signal -> Aggressive Quote
                                |
                        confidence >= 0.85?
                           /        \
                         yes         no
                          |           |
                    Generate Quote   Skip
                    (bid=0.98)

Confidence Tuning

ThresholdBehavior
0.95+Very conservative, few false positives
0.85 (default)Balanced sensitivity
0.70Aggressive, more false positives
Higher confidence = fewer trades but higher accuracy. Lower confidence = more trades but risk of sniping before actual resolution.

Types

ResolutionSignal

FieldTypeDescription
market_idstrMarket identifier
market_titlestrMarket question
resolvedboolWhether event appears resolved
confidencefloatDetection confidence [0, 1]
resolution_sidestr”yes” or “no”
evidencelist[str]Triggering headlines
reasoningstrLLM reasoning
timestampfloatUnix timestamp

SniperConfig

FieldDefaultDescription
provider"anthropic"LLM provider (or any litellm provider)
model""Model name. Accepts litellm strings like "openrouter/..."
news_sources[]RSS feed URLs
exa_query""Exa.ai semantic search query
tavily_query""Tavily real-time search query
confidence_threshold0.85Min confidence to trigger
max_position_size50.0Max USDC per snipe
price_offset0.02Offset from parity
scan_interval_cycles5Cycles between scans
cache_ttl60.0Signal cache TTL