Skip to content

rewired-gh/polyoracle

Repository files navigation

Polyoracle

A lightweight Go service that monitors Polymarket prediction markets for significant probability shifts and delivers Telegram alerts for the top-K highest-signal events.

DOI

How It Works

Each polling cycle:

  1. Fetches events from the Polymarket Gamma + CLOB APIs, filtered by category and volume thresholds

  2. Stores probability snapshots in SQLite (WAL mode)

  3. Detects changes over a rolling detection window using a four-factor composite signal score:

    score = KL(p_new ∥ p_old) × log_volume_weight × historical_SNR × trajectory_consistency
    
  4. Applies pre-score hard filters (minimum absolute change, minimum base probability) to suppress tail-probability noise

  5. Groups per-market changes by parent event, ranks by best score, deduplicates against recent notifications

  6. Sends a Telegram message for the top-K event groups

Multi-market events (e.g., "Bitcoin hits $X by date Y") are tracked per market with composite IDs (EventID:MarketID).

Quick Start

Prerequisites

Setup

git clone <repository-url>
cd polyoracle

make install

cp configs/config.yaml.example configs/config.yaml
# Edit configs/config.yaml and add your bot_token and chat_id

make run

Configuration

Full annotated configuration is in configs/config.yaml.example. Copy it to configs/config.yaml and fill in your Telegram credentials.

Configuration Reference

Section Field Default Description
polymarket poll_interval 5m Polling frequency
polymarket categories geopolitics, tech, finance, world Categories to monitor — see docs/valid-categories.md
polymarket volume_24hr_min 100000 Min $24hr volume (OR filter)
polymarket volume_1wk_min 500000 Min weekly volume (OR filter)
polymarket volume_1mo_min 2000000 Min monthly volume (OR filter)
monitor sensitivity 0.7 Quality threshold — min_score = sensitivity² × 0.05
monitor top_k 10 Max event groups per alert
monitor detection_intervals 8 Polling periods per detection window
monitor min_abs_change 0.1 Min absolute probability change (fraction)
monitor min_base_prob 0.05 Min base probability to avoid tail-zone KL inflation
storage max_events 10000 Max events tracked
storage max_snapshots_per_event 2016 Snapshot history per market
storage db_path $TMPDIR/polyoracle/data.db SQLite database path
telegram bot_token Required when telegram.enabled = true
telegram chat_id Required when telegram.enabled = true
logging level info debug / info / warn / error

See docs/configuration-tuning-results.md for threshold calibration guidance.

Deployment

Binary

make build
./bin/polyoracle --config configs/config.yaml

Docker

make docker-build
docker run -d \
  --name polyoracle \
  -v $(PWD)/configs:/app/configs \
  -v $(PWD)/data:/app/data \
  polyoracle:latest

systemd

sudo cp deployments/systemd/polyoracle.service /etc/systemd/system/
sudo systemctl enable --now polyoracle

Development

make test           # Run all tests
make test-coverage  # With coverage report
make lint           # golangci-lint
make fmt            # gofmt
make dev            # Auto-reload on file change (requires entr)

Project Structure

cmd/polyoracle/        Entry point (main.go)
internal/
  config/               YAML config loading and validation
  logger/               Structured logger (debug/info/warn/error)
  models/               Domain types: Event, Market, Snapshot, Change
  polymarket/           Gamma + CLOB API client
  monitor/              Composite scoring, ranking, deduplication
  storage/              SQLite-backed persistence (WAL mode)
  telegram/             Telegram bot client (MarkdownV2 formatting)
configs/                config.yaml.example, config.test.yaml
deployments/            Dockerfile, systemd service
specs/                  Feature spec documents
docs/                   Tuning notes, valid category reference

Example Notification

🚨 Notable Odds Movements

📅 Detected: 2026-02-18 10:30:00

1. Will candidate X win the election?
   📈 15.0% (60.0% → 75.0%) ⏱ 75m

2. Will Bitcoin hit $100K by March?
   🎯 Will Bitcoin hit $100K by March?
   📉 8.2% (72.3% → 64.1%) ⏱ 75m

Gotchas

  • Config file required: Service exits without a valid configs/config.yaml
  • Polymarket category field: The API category field is frequently null; filtering uses tags[] slugs — see docs/valid-categories.md
  • Tail-probability suppression: Markets below min_base_prob (default 5%) are excluded because KL divergence is structurally unreliable at the tails
  • Cooldown deduplication: Markets recently notified in the same direction are suppressed unless they cross into the high-conviction zone (>90% or <10%)
  • Storage path: Defaults to $TMPDIR/polyoracle/data.db (SQLite); override with POLY_ORACLE_STORAGE_DB_PATH

Dependencies

Disclaimer

This project is an independent, open-source initiative. It has no affiliation, connection, or association with any commercial products, brands, companies, or services.

About

No description, website, or topics provided.

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages