polymarket-hft 0.0.7

A high-frequency trading system for Polymarket with built-in API clients (Data API, CLOB, CLOB WebSocket, Gamma, RTDS) and CLI
Documentation
# Architecture

This document describes the architecture for the polymarket-hft trading system.

## Status Legend

| Badge          | Meaning                                        |
| -------------- | ---------------------------------------------- |
| βœ… IMPLEMENTED | Production-ready, available in current release |
| 🚧 IN PROGRESS | Under active development                       |
| πŸ“‹ PLANNED     | Designed but not yet implemented               |

## System Overview

```text
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Client Layer (SDK) βœ… IMPLEMENTED                      β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                     Polymarket API Clients                            β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚  β”‚
β”‚  β”‚  β”‚   Data    β”‚  β”‚   CLOB    β”‚  β”‚   Gamma   β”‚  β”‚   RTDS    β”‚          β”‚  β”‚
β”‚  β”‚  β”‚  (REST)   β”‚  β”‚(REST + WS)β”‚  β”‚  (REST)   β”‚  β”‚   (WS)    β”‚          β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                    CoinMarketCap API Client                           β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚  β”‚
β”‚  β”‚  β”‚  CMC Client (REST) - Listings, Global Metrics, Fear&Greed β”‚       β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                   β”‚                                          β”‚
β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                           β”‚
β”‚                    β”‚    Shared HTTP Client       β”‚                           β”‚
β”‚                    β”‚  (retry, timeout, pooling)  β”‚                           β”‚
β”‚                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
                                    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Ingestors πŸ“‹ PLANNED                                β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚  β”‚  WS Actor   β”‚  β”‚Poller Actor β”‚  β”‚ Cron Actor  β”‚                          β”‚
β”‚  β”‚ (RTDS/CLOB) β”‚  β”‚ (REST APIs) β”‚  β”‚  (Daily)    β”‚                          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                  β”‚
β”‚                          β”‚ MarketEvent                                       β”‚
β”‚                          β–Ό                                                   β”‚
β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                       β”‚
β”‚            β”‚       Dispatcher        β”‚                                       β”‚
β”‚            β”‚  - Message routing      β”‚                                       β”‚
β”‚            β”‚  - Backpressure control β”‚                                       β”‚
β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β–Ό                 β–Ό                 β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Archiver   β”‚   β”‚   State     β”‚   β”‚   Policy    β”‚
β”‚ πŸ“‹ PLANNED  β”‚   β”‚  Manager    β”‚   β”‚   Engine    β”‚
β”‚             β”‚   β”‚ πŸ“‹ PLANNED  β”‚   β”‚ πŸ“‹ PLANNED  β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β–Ό                 β–Ό                 β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Storage Layer πŸ“‹ PLANNED                             β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
β”‚  β”‚     TimescaleDB        β”‚        β”‚         Redis          β”‚               β”‚
β”‚  β”‚  (Cold/Warm Data)      β”‚        β”‚  (Hot Data, TTL:15min) β”‚               β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                          β”‚
                                          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Action Executor πŸ“‹ PLANNED                              β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚
β”‚  β”‚   Order Executor  β”‚ β”‚   Notification    β”‚ β”‚   Audit Logger    β”‚          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

## Components

### Client Layer βœ… IMPLEMENTED

Multi-source client architecture under `src/client/`. Currently implements Polymarket and CoinMarketCap APIs with extensibility for future data sources. See [Client Guide](./client.md) for usage details.

#### Polymarket Clients

| Client | Protocol  | Key Features                                         |
| ------ | --------- | ---------------------------------------------------- |
| Data   | REST      | User positions, trades, portfolio value              |
| CLOB   | REST + WS | Order management, EIP-712 signing, real-time updates |
| Gamma  | REST      | Market metadata, events, search                      |
| RTDS   | WebSocket | Real-time prices, trades, orderbook streams          |

#### CoinMarketCap Client

| Client | Protocol | Key Features                                                |
| ------ | -------- | ----------------------------------------------------------- |
| CMC    | REST     | Cryptocurrency listings, global metrics, fear & greed index |

**Shared Infrastructure**:

- HTTP client with exponential backoff retry (3 attempts)
- WebSocket auto-reconnect with subscription recovery
- Connection pooling (10 idle connections per host)

### Ingestors πŸ“‹ PLANNED

Data collection actors that emit `MarketEvent` messages.

| Actor        | Source              | Description                               |
| ------------ | ------------------- | ----------------------------------------- |
| WS Actor     | RTDS/CLOB WebSocket | Real-time price, orderbook, trade streams |
| Poller Actor | REST APIs           | Market metadata, positions, balances      |
| Cron Actor   | Scheduled tasks     | Daily snapshots, cleanup, aggregations    |

### Dispatcher πŸ“‹ PLANNED

Central message hub routing `MarketEvent` to multiple consumers.

**Design Choice**: Dispatcher pattern over `tokio::sync::broadcast`:

- Independent `mpsc` channel per consumer
- Slow consumers don't block others
- Per-consumer message filtering and backpressure

### Processors πŸ“‹ PLANNED

#### Archiver

Buffers events and batch-writes to TimescaleDB (100 events or 1 second threshold).

#### State Manager

Maintains real-time state using local cache + Redis Pub/Sub to eliminate round-trip latency.

#### Policy Engine

User-defined policies via YAML/JSON configuration. See [Policy Engine Guide](./policy.md) for details.

**Key Features:**

- **Declarative DSL** β€” Define conditions and actions without code
- **Composite Conditions** β€” AND/OR logic with time-window support
- **Multiple Actions** β€” Notifications, orders, webhooks
- **Rate Limiting** β€” Built-in cooldown per policy

```yaml
# Example: Price alert policy
policies:
  - id: btc_low_alert
    conditions:
      field: price
      asset: "BTC"
      operator: crosses_below
      value: 80000
    actions:
      - type: notification
        channel: telegram
        template: "BTC below $80K!"
```

### Action Executor πŸ“‹ PLANNED

| Executor       | Responsibility                            |
| -------------- | ----------------------------------------- |
| Order Executor | Submit/cancel orders via CLOB Trading API |
| Notification   | Send alerts via Telegram                  |
| Audit Logger   | Record all actions to TimescaleDB         |

## Data Layer πŸ“‹ PLANNED

### Hot Data (Redis)

| Key Pattern                            | Description                   |
| -------------------------------------- | ----------------------------- |
| `polymarket:price:{asset_id}`          | Current price, bid, ask       |
| `polymarket:orderbook:{market}`        | Price levels with sizes       |
| `polymarket:position:{wallet}:{asset}` | Position size, avg price, PnL |

### Cold Data (TimescaleDB)

```sql
-- Price time-series with continuous aggregation
CREATE TABLE prices (
    time TIMESTAMPTZ NOT NULL, asset_id TEXT NOT NULL,
    price NUMERIC(20,8), bid NUMERIC(20,8), ask NUMERIC(20,8)
);
SELECT create_hypertable('prices', 'time');

-- Hourly OHLCV aggregation
CREATE MATERIALIZED VIEW prices_1h WITH (timescaledb.continuous) AS
SELECT time_bucket('1 hour', time) AS bucket, asset_id,
       first(price, time) AS open, max(price) AS high,
       min(price) AS low, last(price, time) AS close
FROM prices GROUP BY bucket, asset_id;
```

## Event Types πŸ“‹ PLANNED

```rust
pub enum MarketEvent {
    PriceUpdate { asset_id: String, price: Decimal, bid: Option<Decimal>, ask: Option<Decimal>, timestamp: u64 },
    OrderBookSnapshot { market: String, bids: Vec<PriceLevel>, asks: Vec<PriceLevel>, timestamp: u64 },
    Trade { market: String, side: Side, price: Decimal, size: Decimal, timestamp: u64 },
    PositionUpdate { wallet: String, asset_id: String, size: Decimal, avg_price: Decimal },
}
```

## Directory Structure

```text
src/
β”œβ”€β”€ client/              # API clients
β”‚   β”œβ”€β”€ polymarket/      # βœ… Polymarket APIs (Data, CLOB, Gamma, RTDS)
β”‚   β”œβ”€β”€ coinmarketcap/   # βœ… CoinMarketCap APIs (Listings, Metrics, F&G)
β”‚   β”œβ”€β”€ http.rs          # βœ… Shared HTTP client with retry
β”‚   └── {other}/         # πŸ“‹ Future data sources
β”œβ”€β”€ engine/              # πŸ“‹ HFT engine
β”‚   β”œβ”€β”€ events.rs        #    MarketEvent definitions
β”‚   β”œβ”€β”€ dispatcher.rs    #    Message dispatcher
β”‚   β”œβ”€β”€ ingestors/       #    WS, Poller, Cron actors
β”‚   β”œβ”€β”€ state.rs         #    State Manager
β”‚   β”œβ”€β”€ archiver.rs      #    TimescaleDB batch writer
β”‚   β”œβ”€β”€ policy/          #    Policy engine (user-defined rules)
β”‚   └── executor.rs      #    Action executor
β”œβ”€β”€ storage/             # πŸ“‹ Redis + TimescaleDB clients
└── cli/                 # βœ… CLI commands
```

## Design Decisions

| Decision          | Choice                         | Rationale                           |
| ----------------- | ------------------------------ | ----------------------------------- |
| Message Bus       | Dispatcher (mpsc per consumer) | Avoid slow consumer blocking        |
| Policy Definition | YAML/JSON DSL                  | User-defined without recompilation  |
| State Sync        | Local cache + Pub/Sub          | Eliminate Redis round-trip per tick |
| Data TTL          | Redis 15 minutes               | Support technical indicators        |
| Batch Write       | 100 events / 1 second          | Balance throughput vs latency       |

## Implementation Phases

| Phase                  | Components                      | Status  |
| ---------------------- | ------------------------------- | ------- |
| 1. Core Infrastructure | events, dispatcher, ws ingestor | πŸ“‹ Next |
| 2. Data Persistence    | redis, timescale, archiver      | πŸ“‹      |
| 3. Policy Engine       | state, policy DSL, evaluator    | πŸ“‹      |
| 4. Execution Layer     | executor, notifications         | πŸ“‹      |
| 5. Operations          | Metrics, tracing, health checks | πŸ“‹      |