Dr. Manhattan

repository·main·Indexed 41 days ago

https://github.com/guzus/dr-manhattan

A CCXT-style unified API for prediction markets, including Polymarket, Kalshi, Opinion, and Limitless. Version 0.0.2 provides a scalable framework for fetching market data, managing orders, and building automated trading strategies, featuring an MCP server and a binary token backtester for simulating trades with proportional or fixed sizing.

Tokens
43.9K
Snippets
134
Records
184
Agent score
51%

What's inside Dr. Manhattan

  1. Overview of Polymarket Exchange Integration

    main

    Polymarket is a decentralized prediction market platform built on Polygon. The dr-manhattan integration supports multiple specialized APIs for different use cases:

    • CLOB API: Used for order book operations, trading, and order management (https://clob.polymarket.com/).
    • Gamma API: Used for market discovery and market data (https://gamma-api.polymarket.com/).
    • Data API: Used for user data, holdings, and on-chain activities (https://data-api.polymarket.com/).
    • WebSocket API: Provides real-time orderbook and user updates (wss://ws-subscriptions-clob.polymarket.com/ws/).
    • RTDS WebSocket: Provides real-time data streams like crypto prices and discussions (wss://ws-live-data.polymarket.com).

    Note: This integration uses the py-clob-client dependency. Always verify order placement against current Polymarket SDK guidance before production trading.

  2. Manage outcome tokens with the Conditional Token Framework (CTF)

    main

    Polymarket uses the Conditional Token Framework (CTF) on the Polygon PoS Chain (Chain ID: 137) to manage outcome tokens. Each YES/NO token represents a share in an outcome, with a price range of $0.00 - $1.00. Winning tokens are redeemable for $1.00 each.

    Key Operations

    1. Splitting USDC Convert USDC into conditional outcome tokens (e.g., 100 USDC becomes 100 YES and 100 NO tokens).

    2. Merging Tokens Combine outcome tokens back into USDC.

    3. Redeeming Tokens Claim payouts for resolved markets by redeeming winning tokens.

    # Split 100 USDC into YES and NO tokens
    ctf.split(
        condition_id='condition_id',
        amount=100.0
    )
    
    # Merge 100 YES + 100 NO tokens back to 100 USDC
    ctf.merge(
        condition_id='condition_id',
        amount=100.0
    )
    
    # Redeem winning tokens after market resolution
    ctf.redeem(
        condition_id='resolved_condition_id',
        outcome='Yes'
    )
  3. How the Cross-Exchange data flow works

    main

    The cross-exchange comparison follows a specific lifecycle:

    1. Definition: The user defines an OutcomeMapping linking slugs and outcomes to ExchangeOutcomeRef objects.
    2. Fetching: CrossExchangeManager.fetch(slug) is called. This triggers the manager to fetch market data from every exchange listed in the mapping for that specific slug.
    3. Aggregation: The result is a FetchedMarkets object containing:
      • markets: A dictionary mapping exchange_id to a list of Market objects.
      • outcome_mapping: A reference to the original mapping used.
    4. Alignment: Calling FetchedMarkets.get_matched_outcomes() aligns the disparate market data using the mapping.
    5. Output: The process returns a list of MatchedOutcome objects. Each contains:
      • outcome_key: The user-defined key (e.g., "no-change").
      • prices: A dictionary mapping exchange_id to a TokenPrice.
      • spread: The calculated price difference between exchanges.
  4. Supported Exchanges and Intervals

    main

    The tool supports three different prediction market exchanges, each with different available time intervals:

    • Polymarket (Default): Supports 1m, 1h, 6h, 1d, 1w, max.
    • Limitless: Supports 1m, 1h, 1d, 1w. Best for short-term markets.
    • Opinion: Supports 1m, 1h, 1d, 1w, max. Note: Requires authentication.
  5. Kalshi WebSocket implementation status

    main

    Kalshi supports WebSocket streaming for real-time data (orderbook deltas, tickers, trades, etc.).

    Note: The dr-manhattan wrapper does NOT currently implement Kalshi WebSocket streaming.

    If you require live deltas, you must use the REST methods provided or implement a custom WebSocket adapter. The official WebSocket endpoints are:

    • Production: wss://external-api-ws.kalshi.com/trade-api/ws/v2
    • Demo: wss://external-api-ws.demo.kalshi.co/trade-api/ws/v2
  6. Spike Strategy Core Logic and Risk Management

    main

    The Spike Strategy operates on three main logical pillars:

    1. Detection Logic

    • EMA Calculation: Uses an Exponential Moving Average to track the baseline price.
    • Spike Detection: A spike is detected if the deviation between the current price and the EMA is less than or equal to the negative spike_threshold: deviation = (price - ema) / ema return deviation <= -spike_threshold

    2. Position Management

    • Entry: If a spike is detected, the system is not in a cooldown period, and cash is available, it executes a BUY at the ask price.
    • Exit: Positions are closed based on PnL:
      • Take Profit: If pnl >= profit_target, SELL at the bid price.
      • Stop Loss: If pnl <= -stop_loss, SELL at the bid price.

    3. Risk Management Features

    • Stop Loss/Take Profit: Automated exits to protect capital.
    • Cooldown: A mandatory wait period after an exit before a new entry can be made.
    • Position Limit: Caps total exposure using max_position.
    • Dust Filter: Automatically ignores positions with a value less than 1.

    Cleanup on Shutdown

    When the process is terminated, the strategy performs the following:

    1. Cancels all open orders.
    2. Attempts to liquidate all current positions.
    3. Closes the WebSocket connection.
  7. Optimize positions using Negative Risk management

    main

    Negative risk occurs when holding NO tokens becomes more profitable than holding USDC. If the YES price rises significantly, you can convert your NO tokens into a combination of YES tokens and remaining USDC to lock in profit while maintaining exposure.

    Example Scenario: If a market is at 80% YES and 20% NO, and you hold 100 NO tokens (worth ~$20), converting them might yield ~20 YES tokens + $60 USDC, totaling $76 in value.

    # Convert NO tokens to optimize value
    result = exchange.convert_no_tokens(
        condition_id='condition_id',
        amount=100.0
    )
  8. Automatic Market Matching (Planned)

    main

    The project includes a skeleton for automatic market matching via the MarketMatcher class. This is intended to replace manual mapping with two primary strategies:

    1. Category-Based Matching

    Uses specialized matchers for predictable market structures. Examples include:

    • FedDecisionMatcher: For Federal Reserve rate decisions.
    • ElectionMatcher: For political elections.
    • CryptoHourlyMatcher: For time-based crypto price predictions.
    • SportsMatcher: For team/player-based events.

    2. LLM-Based Matching

    Uses semantic matching via OpenRouter to handle arbitrary markets. This uses the LLMMatchStrategy.

    Example (Planned Usage):

    from dr_manhattan.cross_exchange import MarketMatcher, LLMMatchStrategy
    
    matcher = MarketMatcher(
        strategies=[
            LLMMatchStrategy(
                provider="openrouter",
                model="meta-llama/llama-3-8b-instruct:free",
            )
        ],
    )
    
    candidates = matcher.find_matches(
        source_markets=polymarket_markets,
        target_markets=opinion_markets,
        source_exchange="polymarket",
        target_exchange="opinion",
        threshold=0.7,
    )
  9. Core Concepts of Prediction Market Trading

    main

    Understanding these fundamental concepts is necessary for using dr-manhattan correctly:

    • Prices are Probabilities: Prices range from 0 to 1 (exclusive). A price of 0.65 implies a 65% chance of the outcome occurring.
    • Outcomes: In binary markets, outcomes are typically Yes and No. Their prices sum to approximately 1.
    • Token IDs: These are exchange-specific identifiers for each outcome of a market. They are required for orderbook queries.
    • Slugs: Human-readable URL identifiers (e.g., trump-2024) used by Polymarket and Limitless.
    • Order Types: Supported types include GTC (Good-Til-Cancel), FOK (Fill-Or-Kill), and IOC (Immediate-Or-Cancel).
  10. How Polymarket market identifiers work

    main

    Most market-related methods in the Polymarket class accept either a Market object or a str. If a string is provided, the client automatically detects the identifier type:

    • Condition ID: Starts with 0x (66 characters).
    • Gamma ID: Digits only, less than 20 characters.
    • Token ID: Digits only, 20 or more characters.
    • Slug: Any other string (e.g., will-trump-win).

    Tip: Passing a Market object is more efficient as it avoids the extra API calls required to resolve the identifier.

  11. Important implementation details for Opinion

    main

    When building with the Opinion exchange, keep the following constraints in mind:

    • Network: Operates on BNB Chain (BSC Mainnet, Chain ID: 56).
    • Currency: The quote token is USDT on BSC.
    • Order Validation: You must respect the tickSize for order price validation.
    • Authentication: Trading requires a multi-signature wallet address (multi_sig_addr).
    • Real-time Data: WebSocket support is not yet available; use polling for real-time updates.
    • Limitations: Public trades endpoint is currently unavailable.
  12. Spike Strategy (Mean Reversion) Overview

    main

    The Spike Strategy is a mean reversion strategy designed for binary prediction markets. It detects sudden price drops (spikes down) and executes BUY orders expecting the price to revert to its Exponential Moving Average (EMA).

    Key Characteristics

    • Strategy Type: Mean Reversion
    • Direction: BUY-only
    • Profit Source: Short-term price overshoot recovery
    • Best For: Volatile event markets

    Binary Market Logic

    Because binary markets follow the rule YES + NO = 1.0, the strategy handles both directions using only BUY logic:

    • YES dip: The strategy buys YES when the YES price drops.
    • NO dip: The strategy buys NO when the NO price drops (which effectively acts as a short on YES).