Polymarket¶
Connector for Polymarket prediction market protocol.
almanak.framework.connectors.polymarket
¶
Polymarket prediction market connector.
This module provides integration with Polymarket's hybrid CLOB + on-chain architecture for prediction market trading.
Architecture Overview
- CLOB (Central Limit Order Book): Off-chain order matching via API
- CTF (Conditional Token Framework): On-chain ERC-1155 outcome tokens
- Market Making: Specialized utilities for automated market making
- Signals: Integration with news, social sentiment, and prediction models
Export Organization
This connector exports 103 items across 14 categories due to Polymarket's unique hybrid architecture. See notes/tech-debt/polymarket-export-list.md for detailed analysis and justification.
Major categories: - Clients & SDK: Core client classes (ClobClient, CtfSDK, PolymarketSDK) - Adapter & Results: Adapter interface and transaction results - Constants: Contract addresses, EIP-712 domains, CTF SDK constants - Configuration: Credentials and config management - Enums: Order types, statuses, signature types - Market Data: Market info, order books, prices - Orders: Order parameters and state transitions - Positions & Trades: Position tracking and trade history - Filters: Query filters for markets, orders, trades - Historical Data: Price history and historical trades - Receipt Parser: Event parsing for on-chain transactions - Market Making: Quote generation and risk management - Signals: Prediction signal providers and aggregation - Exceptions: Comprehensive error hierarchy
Example
from almanak.framework.connectors.polymarket import ( ClobClient, PolymarketConfig, MarketFilters, )
Initialize client¶
config = PolymarketConfig.from_env() client = ClobClient(config)
Fetch markets¶
markets = client.get_markets(MarketFilters(active=True, limit=10)) for market in markets: print(f"{market.question}: YES={market.yes_price}, NO={market.no_price}")
OrderResult
dataclass
¶
OrderResult(
success: bool,
order_id: str | None = None,
signed_order_payload: dict[str, Any] | None = None,
error: str | None = None,
token_id: str | None = None,
side: str | None = None,
price: Decimal | None = None,
size: Decimal | None = None,
)
Result of building and signing an order.
Attributes:
| Name | Type | Description |
|---|---|---|
success |
bool
|
Whether the order was built successfully |
order_id |
str | None
|
Order ID if submitted |
signed_order_payload |
dict[str, Any] | None
|
Signed order payload for submission |
error |
str | None
|
Error message if failed |
PolymarketAdapter
¶
Adapter for compiling prediction market intents to ActionBundles.
This adapter integrates with the Almanak Strategy Framework to compile high-level prediction market intents into executable orders and transactions.
The compilation process: 1. Resolve market_id to a GammaMarket (supports ID or slug) 2. Determine token_id based on outcome (YES or NO) 3. Build order/transaction based on intent type 4. Return ActionBundle for execution
Attributes:
| Name | Type | Description |
|---|---|---|
config |
Polymarket configuration |
|
clob |
CLOB API client for order management |
|
ctf |
CTF SDK for on-chain operations |
|
web3 |
Optional Web3 instance for on-chain operations |
Example
config = PolymarketConfig.from_env() adapter = PolymarketAdapter(config)
intent = Intent.prediction_buy( ... market_id="btc-100k", ... outcome="YES", ... amount_usd=Decimal("100"), ... ) bundle = adapter.compile_intent(intent, market_snapshot)
Initialize the Polymarket adapter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
PolymarketConfig
|
Polymarket configuration with wallet and credentials |
required |
web3
|
Any | None
|
Optional Web3 instance for on-chain operations. Required for redeem intents. |
None
|
compile_intent
¶
compile_intent(
intent: PredictionBuyIntent
| PredictionSellIntent
| PredictionRedeemIntent,
market_snapshot: MarketSnapshot | None = None,
) -> ActionBundle
Compile a prediction market intent to an ActionBundle.
This is the main entry point for intent compilation. It dispatches to the appropriate handler based on intent type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
intent
|
PredictionBuyIntent | PredictionSellIntent | PredictionRedeemIntent
|
The prediction intent to compile |
required |
market_snapshot
|
MarketSnapshot | None
|
Optional market snapshot for additional context |
None
|
Returns:
| Type | Description |
|---|---|
ActionBundle
|
ActionBundle containing the compiled orders/transactions |
Raises:
| Type | Description |
|---|---|
ValueError
|
If intent type is not supported |
RedeemResult
dataclass
¶
RedeemResult(
success: bool,
transactions: list[dict[str, Any]] = list(),
error: str | None = None,
condition_id: str | None = None,
outcome: str | None = None,
amount: Decimal | None = None,
)
Result of building a redeem transaction.
Attributes:
| Name | Type | Description |
|---|---|---|
success |
bool
|
Whether the transaction was built successfully |
transactions |
list[dict[str, Any]]
|
List of transaction data dicts |
error |
str | None
|
Error message if failed |
ClobClient
¶
ClobClient(
config: PolymarketConfig,
http_client: Client | None = None,
rate_limiter: TokenBucketRateLimiter | None = None,
)
Client for Polymarket CLOB API.
Handles both L1 (EIP-712) and L2 (HMAC) authentication and provides methods for market data and order management.
Attributes:
| Name | Type | Description |
|---|---|---|
config |
Polymarket configuration |
|
credentials |
API credentials (may be None until created) |
Thread Safety
This class is NOT thread-safe. Use separate instances per thread.
Initialize CLOB client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
PolymarketConfig
|
Polymarket configuration with wallet and keys |
required |
http_client
|
Client | None
|
Optional HTTP client for testing |
None
|
rate_limiter
|
TokenBucketRateLimiter | None
|
Optional rate limiter for testing. If not provided, creates one based on config settings. |
None
|
rate_limiter
property
¶
Access the rate limiter for configuration or testing.
create_api_credentials
¶
Create new API credentials using L1 authentication.
This signs an EIP-712 message to prove wallet ownership and creates new API credentials for L2 authentication.
Returns:
| Type | Description |
|---|---|
ApiCredentials
|
ApiCredentials with api_key, secret, and passphrase |
Raises:
| Type | Description |
|---|---|
PolymarketAuthenticationError
|
If credential creation fails |
derive_api_credentials
¶
Derive existing API credentials using L1 authentication.
If credentials were previously created, this retrieves them using wallet signature.
Returns:
| Type | Description |
|---|---|
ApiCredentials
|
ApiCredentials with api_key, secret, and passphrase |
Raises:
| Type | Description |
|---|---|
PolymarketAuthenticationError
|
If credential derivation fails |
get_or_create_credentials
¶
Get existing credentials or create new ones.
First attempts to derive existing credentials. If that fails, creates new ones.
Returns:
| Type | Description |
|---|---|
ApiCredentials
|
ApiCredentials |
Raises:
| Type | Description |
|---|---|
PolymarketAuthenticationError
|
If both operations fail |
health_check
¶
Check if CLOB API is healthy.
Returns:
| Type | Description |
|---|---|
bool
|
True if API is responding |
get_server_time
¶
Get server timestamp.
Returns:
| Type | Description |
|---|---|
int
|
Unix timestamp from server |
get_markets
¶
Get list of markets from Gamma API.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filters
|
MarketFilters | None
|
Optional filters for the query |
None
|
Returns:
| Type | Description |
|---|---|
list[GammaMarket]
|
List of GammaMarket objects |
get_market
¶
Get single market by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market_id
|
str
|
Market ID |
required |
Returns:
| Type | Description |
|---|---|
GammaMarket
|
GammaMarket object |
Raises:
| Type | Description |
|---|---|
PolymarketAPIError
|
If market not found |
get_market_by_slug
¶
Get market by URL slug.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
Market URL slug |
required |
Returns:
| Type | Description |
|---|---|
GammaMarket | None
|
GammaMarket or None if not found |
get_orderbook
¶
Get orderbook for a token.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_id
|
str
|
CLOB token ID (YES or NO) |
required |
Returns:
| Type | Description |
|---|---|
OrderBook
|
OrderBook with bids and asks |
get_price
¶
Get price for a token.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_id
|
str
|
CLOB token ID |
required |
Returns:
| Type | Description |
|---|---|
TokenPrice
|
TokenPrice with bid, ask, and mid |
get_midpoint
¶
Get midpoint price for a token.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_id
|
str
|
CLOB token ID |
required |
Returns:
| Type | Description |
|---|---|
Decimal
|
Midpoint price |
get_tick_size
¶
Get minimum tick size for a token.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_id
|
str
|
CLOB token ID |
required |
Returns:
| Type | Description |
|---|---|
Decimal
|
Minimum tick size |
get_balance_allowance
¶
get_balance_allowance(
asset_type: str = "COLLATERAL",
token_id: str | None = None,
) -> BalanceAllowance
Get balance and allowance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
asset_type
|
str
|
"COLLATERAL" for USDC or "CONDITIONAL" for position tokens |
'COLLATERAL'
|
token_id
|
str | None
|
Token ID (required for CONDITIONAL) |
None
|
Returns:
| Type | Description |
|---|---|
BalanceAllowance
|
BalanceAllowance with current balance and allowance |
round_price_to_tick
¶
round_price_to_tick(
price: Decimal,
side: str,
market: GammaMarket | None = None,
tick_size: Decimal | None = None,
) -> Decimal
Round price to valid tick size for the market.
Public method for rounding prices before order submission. Use this when you want automatic rounding instead of validation errors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
price
|
Decimal
|
Price to round |
required |
side
|
str
|
Order side ("BUY" or "SELL") |
required |
market
|
GammaMarket | None
|
Optional GammaMarket for market-specific tick size |
None
|
tick_size
|
Decimal | None
|
Optional explicit tick size (overrides market) |
None
|
Returns:
| Type | Description |
|---|---|
Decimal
|
Price rounded to nearest valid tick |
Example
market = client.get_market(market_id) rounded = client.round_price_to_tick(Decimal("0.655"), "BUY", market=market)
build_limit_order
¶
Build an unsigned limit order.
Limit orders specify exact price and size. They remain on the orderbook until filled, cancelled, or expired.
For BUY orders
- You spend USDC (maker_amount = size * price)
- You receive shares (taker_amount = size)
For SELL orders
- You spend shares (maker_amount = size)
- You receive USDC (taker_amount = size * price)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
LimitOrderParams
|
Limit order parameters |
required |
market
|
GammaMarket | None
|
Optional GammaMarket metadata for market-specific validation. If provided, uses market.order_min_size for size validation and market.order_price_min_tick_size for tick validation. |
None
|
Returns:
| Type | Description |
|---|---|
UnsignedOrder
|
UnsignedOrder ready for signing |
Raises:
| Type | Description |
|---|---|
PolymarketInvalidPriceError
|
If price is out of range (0.01-0.99) |
PolymarketInvalidTickSizeError
|
If price is not a valid tick multiple |
PolymarketMinimumOrderError
|
If size is below market minimum |
Example
params = LimitOrderParams( ... token_id="123...", ... side="BUY", ... price=Decimal("0.65"), ... size=Decimal("100"), ... ) order = client.build_limit_order(params)
With market metadata for proper minimum and tick validation¶
market = client.get_market(market_id) order = client.build_limit_order(params, market=market)
build_market_order
¶
build_market_order(
params: MarketOrderParams,
market: GammaMarket | None = None,
) -> UnsignedOrder
Build an unsigned market order.
Market orders execute immediately at the best available price. They should be submitted with IOC (Immediate or Cancel) order type.
For BUY orders
- You specify USDC amount to spend
- worst_price sets the maximum price per share
For SELL orders
- You specify number of shares to sell
- worst_price sets the minimum price per share
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
MarketOrderParams
|
Market order parameters |
required |
market
|
GammaMarket | None
|
Optional GammaMarket metadata for market-specific validation. If provided, uses market.order_min_size for size validation and market.order_price_min_tick_size for tick validation. |
None
|
Returns:
| Type | Description |
|---|---|
UnsignedOrder
|
UnsignedOrder ready for signing |
Raises:
| Type | Description |
|---|---|
PolymarketInvalidPriceError
|
If worst_price is out of range (0.01-0.99) |
PolymarketInvalidTickSizeError
|
If worst_price is not a valid tick multiple |
PolymarketMinimumOrderError
|
If amount is below market minimum |
Example
params = MarketOrderParams( ... token_id="123...", ... side="BUY", ... amount=Decimal("100"), # USDC to spend ... worst_price=Decimal("0.70"), # Max price per share ... ) order = client.build_market_order(params)
With market metadata for proper minimum and tick validation¶
market = client.get_market(market_id) order = client.build_market_order(params, market=market)
sign_order
¶
Sign an order using EIP-712 typed data signing.
This creates a cryptographic signature that proves the order was created by the wallet owner.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
order
|
UnsignedOrder
|
Unsigned order to sign |
required |
Returns:
| Type | Description |
|---|---|
SignedOrder
|
SignedOrder with signature attached |
Example
unsigned = client.build_limit_order(params) signed = client.sign_order(unsigned) response = client.submit_order(signed)
create_and_sign_limit_order
¶
create_and_sign_limit_order(
params: LimitOrderParams,
market: GammaMarket | None = None,
) -> SignedOrder
Build and sign a limit order in one call.
Convenience method that combines build_limit_order and sign_order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
LimitOrderParams
|
Limit order parameters |
required |
market
|
GammaMarket | None
|
Optional GammaMarket metadata for market-specific validation |
None
|
Returns:
| Type | Description |
|---|---|
SignedOrder
|
SignedOrder ready for submission |
create_and_sign_market_order
¶
create_and_sign_market_order(
params: MarketOrderParams,
market: GammaMarket | None = None,
) -> SignedOrder
Build and sign a market order in one call.
Convenience method that combines build_market_order and sign_order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
MarketOrderParams
|
Market order parameters |
required |
market
|
GammaMarket | None
|
Optional GammaMarket metadata for market-specific validation |
None
|
Returns:
| Type | Description |
|---|---|
SignedOrder
|
SignedOrder ready for submission |
submit_order
¶
Submit a signed order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
order
|
SignedOrder
|
Signed order to submit |
required |
order_type
|
OrderType
|
Order type (GTC, IOC, FOK) |
GTC
|
Returns:
| Type | Description |
|---|---|
OrderResponse
|
OrderResponse with order ID and status |
submit_order_payload
¶
Submit an order from a pre-built payload dict.
This method is used by ClobActionHandler to submit orders from ActionBundle metadata where the payload is already prepared.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
dict[str, Any]
|
Order payload dict containing 'order', 'signature', and 'orderType' |
required |
Returns:
| Type | Description |
|---|---|
OrderResponse
|
OrderResponse with order ID and status |
get_order
¶
Get a single order by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
order_id
|
str
|
Order ID to retrieve |
required |
Returns:
| Type | Description |
|---|---|
OpenOrder | None
|
OpenOrder if found, None otherwise |
cancel_order
¶
Cancel an order by ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
order_id
|
str
|
Order ID to cancel |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if cancelled successfully |
cancel_orders
¶
Cancel multiple orders.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
order_ids
|
list[str]
|
List of order IDs to cancel |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if cancelled successfully |
cancel_all_orders
¶
Cancel all open orders.
Returns:
| Type | Description |
|---|---|
bool
|
True if cancelled successfully |
get_open_orders
¶
Get open orders.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filters
|
OrderFilters | None
|
Optional filters |
None
|
Returns:
| Type | Description |
|---|---|
list[OpenOrder]
|
List of open orders |
get_trades
¶
Get trade history.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filters
|
TradeFilters | None
|
Optional filters |
None
|
Returns:
| Type | Description |
|---|---|
list[Trade]
|
List of trades |
get_positions
¶
get_positions(
wallet: str | None = None,
filters: PositionFilters | None = None,
) -> list[Position]
Get positions for a wallet.
Queries the Polymarket Data API to retrieve all open prediction market positions for the specified wallet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wallet
|
str | None
|
Wallet address to query. Defaults to config wallet if not specified. |
None
|
filters
|
PositionFilters | None
|
Optional filters for market or outcome |
None
|
Returns:
| Type | Description |
|---|---|
list[Position]
|
List of Position objects with size, prices, and PnL data |
Example
positions = client.get_positions() for pos in positions: ... print(f"{pos.outcome}: {pos.size} shares at {pos.avg_price}")
get_price_history
¶
get_price_history(
token_id: str,
interval: str | PriceHistoryInterval | None = None,
start_ts: int | None = None,
end_ts: int | None = None,
fidelity: int | None = None,
) -> PriceHistory
Get historical price data for a token.
Fetches time-series price data from the CLOB API. Can query by predefined interval or custom time range.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_id
|
str
|
CLOB token ID (YES or NO outcome) |
required |
interval
|
str | PriceHistoryInterval | None
|
Predefined interval (1m, 1h, 6h, 1d, 1w, max). Mutually exclusive with start_ts/end_ts. |
None
|
start_ts
|
int | None
|
Unix timestamp for start of range (UTC). Requires end_ts. Mutually exclusive with interval. |
None
|
end_ts
|
int | None
|
Unix timestamp for end of range (UTC). Requires start_ts. Mutually exclusive with interval. |
None
|
fidelity
|
int | None
|
Data resolution in minutes (e.g., 1, 5, 15, 60). Optional for both modes. |
None
|
Returns:
| Type | Description |
|---|---|
PriceHistory
|
PriceHistory with list of timestamped prices |
Raises:
| Type | Description |
|---|---|
PolymarketAPIError
|
If request fails |
ValueError
|
If both interval and start_ts/end_ts are provided |
Example
Get last 24 hours¶
history = client.get_price_history(token_id, interval="1d") print(f"Open: {history.open_price}, Close: {history.close_price}")
Get custom range¶
history = client.get_price_history( ... token_id, ... start_ts=1700000000, ... end_ts=1700100000, ... fidelity=5, # 5-minute resolution ... )
get_trade_tape
¶
Get recent executed trades (trade tape).
Fetches the most recent trades for analysis. Can be filtered by token ID for market-specific trades.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_id
|
str | None
|
Optional CLOB token ID to filter trades |
None
|
limit
|
int
|
Maximum number of trades to return (default 100, max 500) |
100
|
Returns:
| Type | Description |
|---|---|
list[HistoricalTrade]
|
List of HistoricalTrade objects, newest first |
Raises:
| Type | Description |
|---|---|
PolymarketAPIError
|
If request fails |
Example
Get recent trades for YES token¶
trades = client.get_trade_tape(token_id="123...", limit=50) for trade in trades: ... print(f"{trade.side} {trade.size} @ {trade.price}")
TokenBucketRateLimiter
¶
Token bucket rate limiter for API calls.
Implements a token bucket algorithm that allows bursting while maintaining an average rate over time. Tokens are added to the bucket at a fixed rate, and each request consumes one token.
The algorithm: 1. Bucket starts full (capacity = rate_per_second tokens) 2. Tokens are added at rate_per_second tokens per second 3. Each request consumes 1 token 4. If bucket is empty, the caller waits until a token is available
Thread Safety
This implementation is NOT thread-safe. Use separate instances per thread or add locking if needed.
Example
limiter = TokenBucketRateLimiter(rate_per_second=30.0) limiter.acquire() # Blocks if rate limit exceeded
Make API call¶
Initialize the rate limiter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rate_per_second
|
float
|
Maximum average requests per second |
required |
enabled
|
bool
|
Whether rate limiting is active (can be disabled for testing) |
True
|
available_tokens
property
¶
Number of tokens currently available (after refill).
acquire
¶
Acquire a token, blocking if necessary.
Waits until a token is available, then consumes it. If the bucket is empty, sleeps until enough time has passed for a new token.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timeout
|
float | None
|
Maximum time to wait in seconds. None means wait forever. If timeout expires before a token is available, returns False. |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if token was acquired, False if timeout expired (only when timeout is set) |
Example
if limiter.acquire(timeout=5.0): ... make_api_call() ... else: ... print("Timeout waiting for rate limit")
try_acquire
¶
Try to acquire a token without blocking.
Returns:
| Type | Description |
|---|---|
bool
|
True if token was acquired, False if bucket is empty |
Example
if limiter.try_acquire(): ... make_api_call() ... else: ... print("Rate limit would be exceeded, skipping")
reset
¶
Reset the rate limiter to full capacity.
Useful for testing or after a period of inactivity.
AllowanceStatus
dataclass
¶
AllowanceStatus(
usdc_balance: int,
usdc_allowance_ctf_exchange: int,
usdc_allowance_neg_risk_exchange: int,
ctf_approved_for_ctf_exchange: bool,
ctf_approved_for_neg_risk_adapter: bool,
)
Status of token allowances for Polymarket trading.
Attributes:
| Name | Type | Description |
|---|---|---|
usdc_balance |
int
|
USDC balance in token units |
usdc_allowance_ctf_exchange |
int
|
USDC allowance for CTF Exchange |
usdc_allowance_neg_risk_exchange |
int
|
USDC allowance for Neg Risk Exchange |
ctf_approved_for_ctf_exchange |
bool
|
ERC-1155 approved for CTF Exchange |
ctf_approved_for_neg_risk_adapter |
bool
|
ERC-1155 approved for Neg Risk Adapter |
CtfSDK
¶
CtfSDK(
chain_id: int = POLYGON_CHAIN_ID,
ctf_exchange: str = CTF_EXCHANGE,
neg_risk_exchange: str = NEG_RISK_EXCHANGE,
conditional_tokens: str = CONDITIONAL_TOKENS,
neg_risk_adapter: str = NEG_RISK_ADAPTER,
usdc: str = USDC_POLYGON,
)
Low-level SDK for Polymarket CTF on-chain operations.
This SDK provides methods to: - Check and set token approvals - Query token balances - Build split, merge, and redeem transactions - Check condition resolution status
All transaction building methods return TransactionData objects that can be signed and submitted using a signer.
Example
sdk = CtfSDK() web3 = Web3(Web3.HTTPProvider(rpc_url))
Check if wallet needs approvals¶
status = sdk.check_allowances("0x...", web3)
if not status.usdc_approved_ctf_exchange: tx = sdk.build_approve_usdc_tx(CTF_EXCHANGE, MAX_UINT256, "0x...") # Sign and submit tx...
Build redeem transaction for resolved market¶
tx = sdk.build_redeem_tx( condition_id="0x...", index_sets=[1, 2], sender="0x...", )
Initialize the CTF SDK.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_id
|
int
|
Chain ID (default: Polygon 137) |
POLYGON_CHAIN_ID
|
ctf_exchange
|
str
|
CTF Exchange contract address |
CTF_EXCHANGE
|
neg_risk_exchange
|
str
|
Neg Risk Exchange contract address |
NEG_RISK_EXCHANGE
|
conditional_tokens
|
str
|
Conditional Tokens contract address |
CONDITIONAL_TOKENS
|
neg_risk_adapter
|
str
|
Neg Risk Adapter contract address |
NEG_RISK_ADAPTER
|
usdc
|
str
|
USDC token address |
USDC_POLYGON
|
build_approve_usdc_tx
¶
Build USDC approval transaction.
Approves the spender (typically CTF Exchange or Neg Risk Exchange) to spend USDC on behalf of the sender.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spender
|
str
|
Address to approve (e.g., CTF_EXCHANGE) |
required |
amount
|
int
|
Amount to approve (use MAX_UINT256 for unlimited) |
required |
sender
|
str
|
Transaction sender address |
required |
Returns:
| Type | Description |
|---|---|
TransactionData
|
TransactionData for the approval |
build_approve_conditional_tokens_tx
¶
build_approve_conditional_tokens_tx(
operator: str, approved: bool, sender: str
) -> TransactionData
Build ERC-1155 setApprovalForAll transaction.
Approves the operator (typically CTF Exchange or Neg Risk Adapter) to transfer conditional tokens on behalf of the sender.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operator
|
str
|
Address to approve (e.g., CTF_EXCHANGE) |
required |
approved
|
bool
|
True to approve, False to revoke |
required |
sender
|
str
|
Transaction sender address |
required |
Returns:
| Type | Description |
|---|---|
TransactionData
|
TransactionData for the approval |
check_allowances
¶
Check all relevant token allowances.
Queries USDC allowances and ERC-1155 operator approvals needed for trading on Polymarket.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wallet
|
str
|
Wallet address to check |
required |
web3
|
Any
|
Web3 instance |
required |
Returns:
| Type | Description |
|---|---|
AllowanceStatus
|
AllowanceStatus with all allowance information |
ensure_allowances
¶
Build transactions to ensure all necessary approvals.
Checks current allowance status and returns a list of transactions needed to set up all required approvals for trading.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wallet
|
str
|
Wallet address |
required |
web3
|
Any
|
Web3 instance |
required |
Returns:
| Type | Description |
|---|---|
list[TransactionData]
|
List of TransactionData for any needed approvals |
get_token_balance
¶
Get ERC-1155 token balance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wallet
|
str
|
Wallet address |
required |
token_id
|
int
|
Conditional token ID (position ID) |
required |
web3
|
Any
|
Web3 instance |
required |
Returns:
| Type | Description |
|---|---|
int
|
Token balance in base units |
get_token_balances
¶
Get multiple ERC-1155 token balances in a single call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wallet
|
str
|
Wallet address |
required |
token_ids
|
list[int]
|
List of conditional token IDs |
required |
web3
|
Any
|
Web3 instance |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
List of token balances in base units |
get_usdc_balance
¶
Get USDC balance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wallet
|
str
|
Wallet address |
required |
web3
|
Any
|
Web3 instance |
required |
Returns:
| Type | Description |
|---|---|
int
|
USDC balance in base units (6 decimals) |
get_collection_id
¶
get_collection_id(
condition_id: bytes,
index_set: int,
parent_collection_id: bytes = ZERO_BYTES32,
) -> bytes
Calculate collection ID for an outcome.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition_id
|
bytes
|
Condition ID (32 bytes) |
required |
index_set
|
int
|
Outcome index set (1=YES, 2=NO for binary) |
required |
parent_collection_id
|
bytes
|
Parent collection (default: root) |
ZERO_BYTES32
|
Returns:
| Type | Description |
|---|---|
bytes
|
Collection ID (32 bytes) |
get_position_id
¶
Calculate ERC-1155 position ID from collection ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collateral
|
str
|
Collateral token address (USDC) |
required |
collection_id
|
bytes
|
Collection ID (32 bytes) |
required |
Returns:
| Type | Description |
|---|---|
int
|
Position ID (uint256) |
get_token_ids_for_condition
¶
Get YES and NO token IDs for a binary condition.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition_id
|
str | bytes
|
Condition ID (hex string or bytes) |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int]
|
Tuple of (yes_token_id, no_token_id) |
build_split_tx
¶
Build split position transaction.
Splits USDC into YES and NO conditional tokens. Requires USDC approval for Conditional Tokens contract.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition_id
|
str | bytes
|
Condition ID (hex string or bytes) |
required |
amount
|
int
|
Amount of USDC to split (in base units) |
required |
sender
|
str
|
Transaction sender address |
required |
Returns:
| Type | Description |
|---|---|
TransactionData
|
TransactionData for the split operation |
build_merge_tx
¶
Build merge positions transaction.
Merges equal amounts of YES and NO tokens back into USDC. Requires ERC-1155 approval for Conditional Tokens contract.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition_id
|
str | bytes
|
Condition ID (hex string or bytes) |
required |
amount
|
int
|
Amount of each outcome token to merge |
required |
sender
|
str
|
Transaction sender address |
required |
Returns:
| Type | Description |
|---|---|
TransactionData
|
TransactionData for the merge operation |
build_redeem_tx
¶
build_redeem_tx(
condition_id: str | bytes,
index_sets: list[int],
sender: str,
) -> TransactionData
Build redeem positions transaction.
Redeems winning positions after market resolution. Only works if the condition has been resolved.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition_id
|
str | bytes
|
Condition ID (hex string or bytes) |
required |
index_sets
|
list[int]
|
List of index sets to redeem (e.g., [1, 2] for both) |
required |
sender
|
str
|
Transaction sender address |
required |
Returns:
| Type | Description |
|---|---|
TransactionData
|
TransactionData for the redemption |
get_condition_resolution
¶
Get resolution status of a condition.
Checks if a condition has been resolved and returns payout information.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition_id
|
str | bytes
|
Condition ID (hex string or bytes) |
required |
web3
|
Any
|
Web3 instance |
required |
Returns:
| Type | Description |
|---|---|
ResolutionStatus
|
ResolutionStatus with resolution information |
ResolutionStatus
dataclass
¶
ResolutionStatus(
condition_id: str,
is_resolved: bool,
payout_denominator: int,
payout_numerators: list[int],
winning_outcome: int | None = None,
)
Resolution status of a condition.
Attributes:
| Name | Type | Description |
|---|---|---|
condition_id |
str
|
The condition ID (bytes32 hex string) |
is_resolved |
bool
|
Whether the condition has been resolved |
payout_denominator |
int
|
Denominator for payout calculation |
payout_numerators |
list[int]
|
List of payout numerators for each outcome |
winning_outcome |
int | None
|
Index of winning outcome (0=YES, 1=NO) or None if not resolved |
TransactionData
dataclass
¶
TransactionData(
to: str,
data: str,
value: int = 0,
gas_estimate: int = 100000,
description: str = "",
)
Transaction data for on-chain operations.
Attributes:
| Name | Type | Description |
|---|---|---|
to |
str
|
Contract address to call |
data |
str
|
Encoded function call data |
value |
int
|
ETH value to send (usually 0) |
gas_estimate |
int
|
Estimated gas for the transaction |
description |
str
|
Human-readable description |
to_tx_params
¶
Convert to web3 transaction parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sender
|
str
|
Transaction sender address |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dict with transaction parameters for web3 |
PolymarketAPIError
¶
PolymarketAuthenticationError
¶
Bases: PolymarketError
Authentication failed with Polymarket.
PolymarketCredentialsError
¶
Bases: PolymarketError
API credentials are invalid or missing.
PolymarketError
¶
Bases: Exception
Base exception for all Polymarket errors.
PolymarketInsufficientBalanceError
¶
PolymarketInvalidPriceError
¶
PolymarketMarketClosedError
¶
PolymarketMarketError
¶
Bases: PolymarketError
Error related to market operations.
PolymarketMarketNotFoundError
¶
PolymarketMarketNotResolvedError
¶
PolymarketMinimumOrderError
¶
PolymarketOrderError
¶
Bases: PolymarketError
Error related to order operations.
PolymarketOrderNotFoundError
¶
PolymarketRateLimitError
¶
PolymarketRedemptionError
¶
Bases: PolymarketError
Error during position redemption.
PolymarketSignatureError
¶
Bases: PolymarketError
Error creating or verifying signature.
Quote
dataclass
¶
A single quote with price, size, and side.
Represents a single order that can be placed on the orderbook. Used in quote ladders for market making.
Attributes:
| Name | Type | Description |
|---|---|---|
price |
Decimal
|
Quote price (0.01 to 0.99 for prediction markets) |
size |
Decimal
|
Number of shares to quote |
side |
Literal['BUY', 'SELL']
|
"BUY" for bid, "SELL" for ask |
Example
quote = Quote(price=Decimal("0.50"), size=Decimal("100"), side="BUY") print(f"Bid {quote.size} @ {quote.price}") Bid 100 @ 0.50
RiskParameters
dataclass
¶
RiskParameters(
base_spread: Decimal = Decimal("0.02"),
skew_factor: Decimal = Decimal("0.5"),
max_position: Decimal = Decimal("1000"),
min_edge: Decimal = Decimal("0.001"),
volatility_multiplier: Decimal = Decimal("1.0"),
tick_size: Decimal = Decimal("0.01"),
)
Parameters for market making risk management.
These parameters control how the market maker adjusts spreads and quotes based on inventory position and market conditions.
Attributes:
| Name | Type | Description |
|---|---|---|
base_spread |
Decimal
|
Minimum spread to maintain (e.g., 0.02 = 2%) |
skew_factor |
Decimal
|
How much to skew quotes based on inventory (0-1). Higher values mean more aggressive skewing to reduce inventory. |
max_position |
Decimal
|
Maximum position size allowed. Orders beyond this size will not be quoted on the accumulating side. |
min_edge |
Decimal
|
Minimum expected edge (profit margin) per trade. Quotes will not be placed if edge falls below this threshold. |
volatility_multiplier |
Decimal
|
Multiplier for spread based on volatility. Higher volatility leads to wider spreads. |
tick_size |
Decimal
|
Minimum price increment (default 0.01). |
Example
params = RiskParameters( ... base_spread=Decimal("0.02"), ... skew_factor=Decimal("0.5"), ... max_position=Decimal("1000"), ... )
ApiCredentials
¶
Bases: BaseModel
Polymarket API credentials from L1 authentication.
These credentials are obtained by signing an EIP-712 message and calling the create/derive API key endpoint.
Credential Handling Limitations
The current implementation has the following limitations that users should be aware of:
-
Storage: Credentials are stored in environment variables only. There is no integration with secret management systems (e.g., AWS Secrets Manager, HashiCorp Vault). Users are responsible for secure credential storage in their deployment environment.
-
No Automatic Rotation: API credentials do not auto-rotate. The Polymarket CLOB API credentials have an expiration (typically 7 days from creation). Users must manually regenerate credentials before expiration by calling
ClobClient.create_api_credentials()orClobClient.derive_api_credentials()and updating environment variables. -
No Expiration Monitoring: The connector does not monitor credential expiration. If credentials expire, API calls will fail with authentication errors. Users should implement their own monitoring or credential refresh workflow.
-
Manual Renewal Process:
- Generate new credentials using L1 authentication (EIP-712 signature)
- Update environment variables: POLYMARKET_API_KEY, POLYMARKET_SECRET, POLYMARKET_PASSPHRASE
- Restart the application or reload configuration
Environment Variables
- POLYMARKET_API_KEY: API key for L2 HMAC authentication (required for trading)
- POLYMARKET_SECRET: Base64-encoded HMAC secret (required for trading)
- POLYMARKET_PASSPHRASE: Passphrase for API requests (required for trading)
Example
Load from environment¶
creds = ApiCredentials.from_env()
Or create manually¶
creds = ApiCredentials( api_key="your-api-key", secret=SecretStr("your-base64-secret"), passphrase=SecretStr("your-passphrase"), )
from_env
classmethod
¶
from_env(
api_key_env: str = "POLYMARKET_API_KEY",
secret_env: str = "POLYMARKET_SECRET",
passphrase_env: str = "POLYMARKET_PASSPHRASE",
) -> ApiCredentials
Load credentials from environment variables.
BalanceAllowance
¶
Bases: BaseModel
Balance and allowance information.
GammaMarket
¶
Bases: BaseModel
Market data from Gamma Markets API.
from_api_response
classmethod
¶
Create from Gamma API response.
HistoricalPrice
dataclass
¶
Single historical price point.
Represents a price at a specific timestamp from the CLOB API. Price values represent probability (0.0 to 1.0).
from_api_response
classmethod
¶
Create from API response.
HistoricalTrade
dataclass
¶
HistoricalTrade(
id: str,
token_id: str,
side: Literal["BUY", "SELL"],
price: Decimal,
size: Decimal,
timestamp: datetime,
maker: str | None = None,
taker: str | None = None,
)
Historical trade from the market.
Represents a single executed trade from the trade tape.
from_api_response
classmethod
¶
Create from API response.
LimitOrderParams
dataclass
¶
LimitOrderParams(
token_id: str,
side: Literal["BUY", "SELL"],
price: Decimal,
size: Decimal,
expiration: int | None = None,
fee_rate_bps: int = 0,
)
Parameters for building a limit order.
MarketFilters
¶
Bases: BaseModel
Filters for market queries.
MarketOrderParams
dataclass
¶
MarketOrderParams(
token_id: str,
side: Literal["BUY", "SELL"],
amount: Decimal,
worst_price: Decimal | None = None,
)
Parameters for building a market order.
OpenOrder
¶
Bases: BaseModel
Open order information.
OrderBook
¶
Bases: BaseModel
Orderbook for a token.
OrderFilters
¶
Bases: BaseModel
Filters for order queries.
OrderResponse
¶
Bases: BaseModel
Response from order submission.
from_api_response
classmethod
¶
Create from CLOB API response.
OrderSide
¶
Bases: int, Enum
Order side.
OrderStatus
¶
Bases: str, Enum
Order status values.
OrderType
¶
Bases: str, Enum
Order time-in-force types.
PolymarketConfig
¶
Bases: BaseModel
Configuration for Polymarket connector.
This configuration supports both L1 (EIP-712 signing) and L2 (HMAC API) authentication for Polymarket's hybrid CLOB + on-chain architecture.
Credential Management
Polymarket uses a two-tier authentication system:
L1 Authentication (Wallet Signing): - Used for: Creating/deriving API credentials, signing on-chain transactions - Requires: wallet_address and private_key - No expiration: Wallet keys don't expire
L2 Authentication (HMAC API): - Used for: Orderbook operations (place/cancel orders, fetch positions) - Requires: api_credentials (api_key, secret, passphrase) - Expiration: Credentials typically expire after 7 days - Storage: Environment variables only (no secret manager integration)
Current Limitations: 1. Credentials stored in environment variables only 2. No automatic credential rotation or renewal 3. No expiration monitoring - API calls will fail silently when expired 4. Manual renewal required before expiration
Renewal Process: When credentials expire, you must: 1. Use ClobClient with a valid wallet to call create_api_credentials() or derive_api_credentials() 2. Update environment variables with new credentials 3. Restart the application or reload configuration
Configurable URLs
All API URLs are configurable to support proxies, test environments, or alternative endpoints:
- clob_base_url: CLOB API for orderbook, prices, and trading (default: https://clob.polymarket.com)
- gamma_base_url: Gamma Markets API for market metadata (default: https://gamma-api.polymarket.com)
- data_api_base_url: Data API for positions and user data (default: https://data-api.polymarket.com)
Environment Variables
Required for wallet operations: - POLYMARKET_WALLET_ADDRESS: Wallet address for signing and transactions - POLYMARKET_PRIVATE_KEY: Private key for EIP-712 signing (0x prefixed hex)
Required for trading operations (L2 auth): - POLYMARKET_API_KEY: API key from credential creation/derivation - POLYMARKET_SECRET: Base64-encoded HMAC secret - POLYMARKET_PASSPHRASE: Passphrase from credential creation/derivation
Optional: - POLYGON_RPC_URL: RPC endpoint for Polygon (for on-chain operations) - POLYMARKET_CLOB_URL: Override clob_base_url - POLYMARKET_GAMMA_URL: Override gamma_base_url - POLYMARKET_DATA_API_URL: Override data_api_base_url
Example
Basic configuration (wallet only, for read operations and credential creation)¶
config = PolymarketConfig( wallet_address="0x...", private_key=SecretStr("0x..."), )
Full configuration with API credentials (for trading)¶
config = PolymarketConfig( wallet_address="0x...", private_key=SecretStr("0x..."), api_credentials=ApiCredentials( api_key="your-api-key", secret=SecretStr("your-base64-secret"), passphrase=SecretStr("your-passphrase"), ), )
Load from environment¶
config = PolymarketConfig.from_env() creds = ApiCredentials.from_env() config.api_credentials = creds
With custom URLs (for proxies or testing)¶
config = PolymarketConfig( wallet_address="0x...", private_key=SecretStr("0x..."), data_api_base_url="https://my-proxy.example.com/data", )
from_env
classmethod
¶
from_env(
wallet_env: str = "POLYMARKET_WALLET_ADDRESS",
private_key_env: str = "POLYMARKET_PRIVATE_KEY",
rpc_env: str = "POLYGON_RPC_URL",
clob_url_env: str = "POLYMARKET_CLOB_URL",
gamma_url_env: str = "POLYMARKET_GAMMA_URL",
data_api_url_env: str = "POLYMARKET_DATA_API_URL",
) -> PolymarketConfig
Load configuration from environment variables.
Required Environment Variables
- POLYMARKET_WALLET_ADDRESS: Wallet address
- POLYMARKET_PRIVATE_KEY: Private key for signing
Optional Environment Variables
- POLYGON_RPC_URL: RPC endpoint for Polygon
- POLYMARKET_CLOB_URL: Override CLOB API base URL
- POLYMARKET_GAMMA_URL: Override Gamma Markets API base URL
- POLYMARKET_DATA_API_URL: Override Data API base URL
Position
¶
Bases: BaseModel
Position information.
PriceHistory
dataclass
¶
PriceHistory(
token_id: str,
interval: str,
prices: list[HistoricalPrice],
start_time: datetime | None = None,
end_time: datetime | None = None,
)
Historical price data for a token.
Contains a time series of prices for OHLC-style analysis.
PriceHistoryInterval
¶
Bases: str, Enum
Supported intervals for price history queries.
PriceLevel
¶
Bases: BaseModel
Single price level in orderbook.
SignatureType
¶
Bases: int, Enum
Signature types for Polymarket authentication.
SignedOrder
dataclass
¶
Signed order ready for submission.
TokenPrice
¶
Bases: BaseModel
Price information for a token.
from_api_response
classmethod
¶
Create from CLOB API response.
Trade
¶
Bases: BaseModel
Trade information.
TradeFilters
¶
Bases: BaseModel
Filters for trade queries.
TradeStatus
¶
Bases: str, Enum
Trade status values.
UnsignedOrder
dataclass
¶
UnsignedOrder(
salt: int,
maker: str,
signer: str,
taker: str,
token_id: int,
maker_amount: int,
taker_amount: int,
expiration: int,
nonce: int,
fee_rate_bps: int,
side: int,
signature_type: int,
)
Unsigned order ready for signing.
CtfEvent
dataclass
¶
CtfEvent(
event_type: PolymarketEventType,
event_name: str,
log_index: int,
transaction_hash: str,
block_number: int,
contract_address: str,
data: dict[str, Any],
raw_topics: list[str] = list(),
raw_data: str = "",
timestamp: datetime = (lambda: datetime.now(UTC))(),
)
Parsed CTF/ERC-1155 event.
Attributes:
| Name | Type | Description |
|---|---|---|
event_type |
PolymarketEventType
|
Type of event |
event_name |
str
|
Name of event |
log_index |
int
|
Index of log in transaction |
transaction_hash |
str
|
Transaction hash |
block_number |
int
|
Block number |
contract_address |
str
|
Contract that emitted event |
data |
dict[str, Any]
|
Parsed event data |
raw_topics |
list[str]
|
Raw event topics |
raw_data |
str
|
Raw event data |
timestamp |
datetime
|
Event timestamp |
CtfParseResult
dataclass
¶
CtfParseResult(
success: bool,
events: list[CtfEvent] = list(),
transfer_singles: list[TransferSingleData] = list(),
transfer_batches: list[TransferBatchData] = list(),
redemptions: list[PayoutRedemptionData] = list(),
erc20_transfers: list[Erc20TransferData] = list(),
redemption_result: RedemptionResult | None = None,
error: str | None = None,
transaction_hash: str = "",
block_number: int = 0,
transaction_success: bool = True,
)
Result of parsing a CTF transaction receipt.
Attributes:
| Name | Type | Description |
|---|---|---|
success |
bool
|
Whether parsing succeeded |
events |
list[CtfEvent]
|
List of all parsed events |
transfer_singles |
list[TransferSingleData]
|
TransferSingle events |
transfer_batches |
list[TransferBatchData]
|
TransferBatch events |
redemptions |
list[PayoutRedemptionData]
|
PayoutRedemption events |
erc20_transfers |
list[Erc20TransferData]
|
ERC-20 Transfer events |
redemption_result |
RedemptionResult | None
|
High-level redemption result |
error |
str | None
|
Error message if parsing failed |
transaction_hash |
str
|
Transaction hash |
block_number |
int
|
Block number |
transaction_success |
bool
|
Whether transaction succeeded |
Erc20TransferData
dataclass
¶
Parsed data from ERC-20 Transfer event.
Event: Transfer(from, to, value)
Attributes:
| Name | Type | Description |
|---|---|---|
from_addr |
str
|
Sender address |
to_addr |
str
|
Recipient address |
value |
int
|
Amount transferred |
token_address |
str
|
Token contract address |
PayoutRedemptionData
dataclass
¶
PayoutRedemptionData(
redeemer: str,
collateral_token: str,
parent_collection_id: str,
condition_id: str,
index_sets: list[int],
payout: int,
contract_address: str,
)
Parsed data from PayoutRedemption event.
Event: PayoutRedemption(redeemer, collateralToken, parentCollectionId, conditionId, indexSets[], payout)
Attributes:
| Name | Type | Description |
|---|---|---|
redeemer |
str
|
Address that received payout |
collateral_token |
str
|
Collateral token address (USDC) |
parent_collection_id |
str
|
Parent collection ID (usually 0x0) |
condition_id |
str
|
CTF condition ID |
index_sets |
list[int]
|
Which outcomes were redeemed |
payout |
int
|
Total payout amount |
contract_address |
str
|
Contract that emitted event |
PolymarketEventType
¶
Bases: Enum
Polymarket/CTF event types.
PolymarketReceiptParser
¶
Parser for Polymarket CLOB responses and CTF transaction receipts.
This parser handles two types of data: 1. CLOB API responses - order submissions, fills, status updates 2. CTF transaction receipts - on-chain token transfers and redemptions
Example
parser = PolymarketReceiptParser()
Parse CLOB order submission response¶
trade_result = parser.parse_order_response(api_response) if trade_result.success: print(f"Order {trade_result.order_id}: {trade_result.status}")
Parse CTF redemption transaction receipt¶
ctf_result = parser.parse_ctf_receipt(tx_receipt) if ctf_result.success and ctf_result.redemption_result: print(f"Redeemed: {ctf_result.redemption_result.amount_redeemed} USDC")
Initialize the receipt parser.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
Any
|
Additional arguments (ignored for compatibility) |
{}
|
parse_order_response
¶
Parse a CLOB order submission response.
The response contains order details and initial status after submission.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
dict[str, Any]
|
CLOB API order response dict |
required |
Returns:
| Type | Description |
|---|---|
TradeResult
|
TradeResult with order details |
Example response
{ "orderID": "0x1234...", "status": "LIVE", "owner": "0xYourAddress", "market": "19045189...", "side": "BUY", "price": "0.65", "size": "100", "filledSize": "0", "createdAt": "2025-01-15T10:30:00Z" }
parse_fill_notification
¶
Parse a CLOB fill notification.
Fill notifications are received when an order is matched.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
notification
|
dict[str, Any]
|
Fill notification from CLOB |
required |
Returns:
| Type | Description |
|---|---|
TradeResult
|
TradeResult with fill details |
Example notification
{ "type": "fill", "orderId": "0x1234...", "matchId": "0x5678...", "fillSize": "50", "fillPrice": "0.65", "fee": "0", "timestamp": "2025-01-15T10:30:00Z" }
parse_order_status
¶
Parse a CLOB order status query response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
status_response
|
dict[str, Any]
|
Order status response from CLOB |
required |
Returns:
| Type | Description |
|---|---|
TradeResult
|
TradeResult with current order status |
parse_ctf_receipt
¶
Parse a CTF transaction receipt for on-chain events.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs', 'transactionHash', etc. |
required |
filter_by_contract
|
bool
|
If True (default), only parse logs from known Polymarket contracts (CONDITIONAL_TOKENS, CTF_EXCHANGE, NEG_RISK_EXCHANGE, NEG_RISK_ADAPTER, USDC_POLYGON). Set to False to parse all matching event signatures regardless of contract address (useful for testing or analyzing multi-protocol transactions). |
True
|
Returns:
| Type | Description |
|---|---|
CtfParseResult
|
CtfParseResult with extracted events and redemption data |
is_polymarket_event
¶
Check if a topic is a known Polymarket/CTF event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
topic
|
str | bytes
|
Event topic (supports bytes, hex string with/without 0x, any case) |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if topic is a known event |
is_polymarket_contract
¶
Check if an address is a known Polymarket contract.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
address
|
str
|
Contract address |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if address is a known Polymarket contract |
get_event_type
¶
Get the event type for a topic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
topic
|
str | bytes
|
Event topic (supports bytes, hex string with/without 0x, any case) |
required |
Returns:
| Type | Description |
|---|---|
PolymarketEventType
|
Event type or UNKNOWN |
extract_outcome_tokens_received
¶
Extract outcome tokens received from transaction receipt.
Note: Without the user's address, we cannot determine transfer direction. This method sums all TransferSingle values as a proxy for tokens involved. For precise directional filtering, pass the user address to your own logic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
Total outcome tokens from all TransferSingle events if found, None otherwise |
extract_cost_basis
¶
Extract cost basis (USDC involved) from transaction receipt.
Note: Without the user's address, we cannot determine transfer direction. This method sums all USDC transfer values as a proxy for the transaction size. For precise directional filtering, pass the user address to your own logic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
Total USDC in base units (6 decimals) from transfers if found, None otherwise |
extract_market_id
¶
Extract market ID (condition ID) from transaction receipt.
For redemptions, extracts the condition ID directly from PayoutRedemption event.
For trades, returns the raw token ID as hex. Note: CTF token IDs use a complex encoding where conditionId = keccak256(oracle, questionId, outcomeSlotCount) and tokenId = positionId derived from collateral + conditionId + indexSet. Decoding the actual conditionId from a tokenId requires reverse lookup via CTF contract. For simplified use cases, the raw tokenId serves as a unique market identifier.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
Condition ID hex string for redemptions, raw token ID hex for trades, |
str | None
|
or None if not found. |
extract_outcome_tokens_sold
¶
Extract outcome tokens sold from transaction receipt.
Note: Polymarket sells are transfers to the exchange, not burns. Without the exchange contract address, we cannot reliably distinguish sells from other transfers. This method sums all TransferSingle values as a proxy for tokens involved in the transaction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
Total outcome tokens from all TransferSingle events if found, None otherwise |
extract_proceeds
¶
Extract proceeds (USDC involved) from transaction receipt.
Note: Without the user's address, we cannot determine transfer direction. This method sums all USDC transfer values as a proxy for the transaction size. For precise directional filtering, pass the user address to your own logic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
Total USDC in base units (6 decimals) from transfers if found, None otherwise |
extract_redemption_amount
¶
Extract redemption amount (outcome tokens redeemed) from receipt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
Total tokens redeemed if found, None otherwise |
extract_payout
¶
Extract payout amount from redemption transaction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs' field |
required |
Returns:
| Type | Description |
|---|---|
int | None
|
Payout amount in USDC base units if found, None otherwise |
RedemptionResult
dataclass
¶
RedemptionResult(
success: bool,
tx_hash: str = "",
amount_redeemed: Decimal = (lambda: Decimal("0"))(),
condition_id: str | None = None,
index_sets: list[int] = list(),
payout_amounts: list[Decimal] = list(),
redeemer: str | None = None,
gas_used: int = 0,
error: str | None = None,
)
Result of parsing a CTF redemption transaction receipt.
Attributes:
| Name | Type | Description |
|---|---|---|
success |
bool
|
Whether parsing succeeded |
tx_hash |
str
|
Transaction hash |
amount_redeemed |
Decimal
|
Total USDC received from redemption |
condition_id |
str | None
|
CTF condition ID |
index_sets |
list[int]
|
Which index sets were redeemed |
payout_amounts |
list[Decimal]
|
Amount redeemed per index set |
redeemer |
str | None
|
Address that received the payout |
gas_used |
int
|
Gas used by the transaction |
error |
str | None
|
Error message if parsing failed |
TradeResult
dataclass
¶
TradeResult(
success: bool,
order_id: str | None = None,
status: str | None = None,
filled_size: Decimal = (lambda: Decimal("0"))(),
avg_price: Decimal = (lambda: Decimal("0"))(),
fee: Decimal = (lambda: Decimal("0"))(),
tx_hash: str | None = None,
side: str | None = None,
token_id: str | None = None,
timestamp: datetime | None = None,
error: str | None = None,
)
Result of parsing a CLOB order response or fill.
Attributes:
| Name | Type | Description |
|---|---|---|
success |
bool
|
Whether parsing succeeded |
order_id |
str | None
|
Order ID from CLOB |
status |
str | None
|
Order status (LIVE, MATCHED, CANCELLED, etc.) |
filled_size |
Decimal
|
Amount filled (in shares) |
avg_price |
Decimal
|
Average fill price |
fee |
Decimal
|
Trading fee (in USDC) |
tx_hash |
str | None
|
On-chain settlement tx hash (if settled) |
side |
str | None
|
Order side (BUY or SELL) |
token_id |
str | None
|
CLOB token ID |
timestamp |
datetime | None
|
Order/fill timestamp |
error |
str | None
|
Error message if parsing failed |
TransferBatchData
dataclass
¶
TransferBatchData(
operator: str,
from_addr: str,
to_addr: str,
token_ids: list[int],
values: list[int],
contract_address: str,
)
Parsed data from TransferBatch event.
Event: TransferBatch(operator, from, to, ids[], values[])
Attributes:
| Name | Type | Description |
|---|---|---|
operator |
str
|
Address that triggered the transfer |
from_addr |
str
|
Sender address |
to_addr |
str
|
Recipient address |
token_ids |
list[int]
|
List of ERC-1155 token IDs |
values |
list[int]
|
List of amounts transferred |
contract_address |
str
|
Contract that emitted event |
TransferSingleData
dataclass
¶
TransferSingleData(
operator: str,
from_addr: str,
to_addr: str,
token_id: int,
value: int,
contract_address: str,
)
Parsed data from TransferSingle event.
Event: TransferSingle(operator, from, to, id, value)
Attributes:
| Name | Type | Description |
|---|---|---|
operator |
str
|
Address that triggered the transfer |
from_addr |
str
|
Sender address |
to_addr |
str
|
Recipient address |
token_id |
int
|
ERC-1155 token ID |
value |
int
|
Amount transferred |
contract_address |
str
|
Contract that emitted event |
PolymarketSDK
¶
Unified SDK for Polymarket prediction market operations.
Orchestrates both CLOB API client (off-chain order management) and CTF SDK (on-chain token operations) to provide a seamless trading experience.
Key features: - Lazy credential creation: API credentials are created on first authenticated request - Unified market lookups: Find markets by ID, slug, or condition ID - Automatic approval checking: Ensure all token approvals are set up - Convenience methods: Common operations wrapped in simple methods
Attributes:
| Name | Type | Description |
|---|---|---|
config |
Polymarket configuration |
|
clob |
CLOB API client for order management |
|
ctf |
CTF SDK for on-chain operations |
|
web3 |
Web3 instance for on-chain queries (optional) |
Thread Safety
This class is NOT thread-safe. Use separate instances per thread.
Example
config = PolymarketConfig.from_env() web3 = Web3(Web3.HTTPProvider(rpc_url)) sdk = PolymarketSDK(config, web3)
Get market data¶
market = sdk.get_market_by_slug("btc-100k") print(f"YES: {market.yes_price}, NO: {market.no_price}")
Check and set up approvals¶
approval_txs = sdk.ensure_allowances() if approval_txs: ... print(f"Need {len(approval_txs)} approval(s)")
Initialize Polymarket SDK.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
PolymarketConfig
|
Polymarket configuration with wallet and keys |
required |
web3
|
Any | None
|
Optional Web3 instance for on-chain operations. Required for allowance checking and CTF operations. |
None
|
get_or_create_credentials
¶
Get existing credentials or create new ones lazily.
This method is called automatically when making authenticated requests. It first attempts to derive existing credentials, and if that fails, creates new ones.
Returns:
| Type | Description |
|---|---|
ApiCredentials
|
ApiCredentials with api_key, secret, and passphrase |
Raises:
| Type | Description |
|---|---|
PolymarketAuthenticationError
|
If credential creation fails |
get_market_by_slug
¶
Get market by URL slug.
Convenience method that searches for a market by its URL slug and raises an error if not found.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
Market URL slug (e.g., "will-bitcoin-exceed-100k-2025") |
required |
Returns:
| Type | Description |
|---|---|
GammaMarket
|
GammaMarket object |
Raises:
| Type | Description |
|---|---|
PolymarketMarketNotFoundError
|
If market not found |
Example
market = sdk.get_market_by_slug("btc-100k") print(market.question)
get_market_by_condition_id
¶
Get market by CTF condition ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition_id
|
str
|
CTF condition ID (0x...) |
required |
Returns:
| Type | Description |
|---|---|
GammaMarket
|
GammaMarket object |
Raises:
| Type | Description |
|---|---|
PolymarketMarketNotFoundError
|
If market not found |
Example
market = sdk.get_market_by_condition_id("0x9915bea...")
get_market_by_token_id
¶
Get market by CLOB token ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_id
|
str
|
CLOB token ID (YES or NO token) |
required |
Returns:
| Type | Description |
|---|---|
GammaMarket
|
GammaMarket object |
Raises:
| Type | Description |
|---|---|
PolymarketMarketNotFoundError
|
If market not found |
Example
market = sdk.get_market_by_token_id("19045189...")
get_yes_no_prices
¶
Get YES and NO prices for a market.
Fetches the market and returns the current prices for both YES and NO outcomes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market_id
|
str
|
Market ID |
required |
Returns:
| Type | Description |
|---|---|
tuple[Decimal, Decimal]
|
Tuple of (yes_price, no_price) |
Example
yes_price, no_price = sdk.get_yes_no_prices("12345") print(f"YES: ${yes_price}, NO: ${no_price}")
get_prices_by_slug
¶
Get YES and NO prices for a market by slug.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slug
|
str
|
Market URL slug |
required |
Returns:
| Type | Description |
|---|---|
tuple[Decimal, Decimal]
|
Tuple of (yes_price, no_price) |
Example
yes_price, no_price = sdk.get_prices_by_slug("btc-100k")
ensure_allowances
¶
Build transactions to ensure all necessary approvals.
Checks current allowance status and returns a list of transactions needed to set up all required approvals for trading on Polymarket.
This includes: - USDC approval for CTF Exchange - USDC approval for Neg Risk Exchange - ERC-1155 approval for CTF Exchange - ERC-1155 approval for Neg Risk Adapter
Returns:
| Type | Description |
|---|---|
list[TransactionData]
|
List of TransactionData for any needed approvals. |
list[TransactionData]
|
Empty list if all approvals are already in place. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If web3 instance is not configured |
Example
txs = sdk.ensure_allowances() if txs: ... print(f"Need {len(txs)} approval(s)") ... for tx in txs: ... # Sign and submit transaction ... pass
check_allowances
¶
Check all relevant token allowances.
Queries USDC allowances and ERC-1155 operator approvals needed for trading on Polymarket.
Returns:
| Type | Description |
|---|---|
AllowanceStatus
|
AllowanceStatus with all allowance information |
Raises:
| Type | Description |
|---|---|
ValueError
|
If web3 instance is not configured |
Example
status = sdk.check_allowances() print(f"USDC approved: {status.usdc_approved_ctf_exchange}") print(f"Fully approved: {status.fully_approved}")
get_usdc_balance
¶
Get USDC balance for configured wallet.
Returns:
| Type | Description |
|---|---|
int
|
USDC balance in base units (6 decimals) |
Raises:
| Type | Description |
|---|---|
ValueError
|
If web3 instance is not configured |
Example
balance = sdk.get_usdc_balance() print(f"USDC balance: {balance / 1e6}")
get_position_balance
¶
Get ERC-1155 position token balance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token_id
|
int
|
Conditional token ID (position ID) |
required |
Returns:
| Type | Description |
|---|---|
int
|
Token balance in base units |
Raises:
| Type | Description |
|---|---|
ValueError
|
If web3 instance is not configured |
Example
balance = sdk.get_position_balance(token_id) print(f"Position: {balance / 1e6} shares")
ModelPredictionProvider
¶
ModelPredictionProvider(
model: Callable | None = None,
confidence_calibration: float = 1.0,
threshold_bullish: float = 0.6,
threshold_bearish: float = 0.4,
)
Signal provider that wraps a machine learning model.
This provider allows integration of custom ML models that predict market outcomes. The model should output a probability for the YES outcome, which is then converted to a SignalResult.
Attributes:
| Name | Type | Description |
|---|---|---|
model |
The prediction model (any callable returning float 0-1) |
|
confidence_calibration |
Calibration factor for model confidence |
Example
from sklearn.linear_model import LogisticRegression
Train your model¶
model = LogisticRegression() model.fit(X_train, y_train)
Wrap in provider¶
def predict_fn(market_id, features): return model.predict_proba([features])[0][1]
provider = ModelPredictionProvider(model=predict_fn) signal = provider.get_signal("market-123", features=[0.5, 0.3, 0.8])
Initialize the model prediction provider.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Callable | None
|
Callable that takes (market_id, **kwargs) and returns probability 0-1 |
None
|
confidence_calibration
|
float
|
Factor to scale model confidence |
1.0
|
threshold_bullish
|
float
|
Probability above which signal is BULLISH |
0.6
|
threshold_bearish
|
float
|
Probability below which signal is BEARISH |
0.4
|
get_signal
¶
Get signal from model prediction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market_id
|
str
|
The Polymarket market ID |
required |
**kwargs
|
Parameters to pass to the model (e.g., features) |
{}
|
Returns:
| Type | Description |
|---|---|
SignalResult
|
SignalResult based on model prediction |
NewsAPISignalProvider
¶
NewsAPISignalProvider(
api_key: str | None = None,
base_url: str = "https://newsapi.org/v2",
sentiment_threshold: float = 0.3,
)
Example signal provider using news sentiment analysis.
This is a reference implementation showing how to build a news-based signal provider. In production, you would integrate with a real news API (e.g., NewsAPI, Aylien, or a custom NLP pipeline).
The provider analyzes news headlines and articles related to the market question, extracts sentiment, and converts it to a trading signal.
Attributes:
| Name | Type | Description |
|---|---|---|
api_key |
API key for the news service |
|
base_url |
Base URL for the news API |
|
sentiment_threshold |
Minimum sentiment score to generate a signal |
Example
provider = NewsAPISignalProvider(api_key="your-api-key") signal = provider.get_signal( "market-123", question="Will Bitcoin reach $100k by end of 2024?" )
Initialize the news signal provider.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
api_key
|
str | None
|
API key for NewsAPI (or similar service) |
None
|
base_url
|
str
|
Base URL for the news API |
'https://newsapi.org/v2'
|
sentiment_threshold
|
float
|
Minimum absolute sentiment to generate non-neutral signal |
0.3
|
get_signal
¶
Get signal based on news sentiment.
This example implementation demonstrates the pattern. In production, replace _analyze_sentiment with actual API calls and NLP analysis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market_id
|
str
|
The Polymarket market ID |
required |
**kwargs
|
Optional parameters: - question: Market question text for keyword extraction - keywords: Explicit keywords to search for - lookback_hours: How far back to search (default 24) |
{}
|
Returns:
| Type | Description |
|---|---|
SignalResult
|
SignalResult with sentiment-based direction and confidence |
PredictionSignal
¶
Bases: Protocol
Protocol for prediction market signal providers.
Any class implementing this protocol can be used as a signal provider. The protocol is runtime-checkable, so isinstance() can be used.
Example
class MyProvider: def get_signal(self, market_id: str, **kwargs) -> SignalResult: return SignalResult(SignalDirection.BULLISH, 0.8)
provider = MyProvider() assert isinstance(provider, PredictionSignal) # True
get_signal
¶
Get signal for a specific market.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market_id
|
str
|
The Polymarket market ID to analyze |
required |
**kwargs
|
Additional parameters (market question, end date, etc.) |
{}
|
Returns:
| Type | Description |
|---|---|
SignalResult
|
SignalResult with direction and confidence |
SignalDirection
¶
Bases: str, Enum
Direction of a prediction signal.
BULLISH: Expect the YES outcome to increase in probability BEARISH: Expect the YES outcome to decrease in probability (NO increases) NEUTRAL: No clear directional signal
SignalResult
dataclass
¶
SignalResult(
direction: SignalDirection,
confidence: float,
timestamp: datetime = (lambda: datetime.now(UTC))(),
metadata: dict | None = None,
source: str | None = None,
raw_score: float | None = None,
)
Result from a signal provider.
Represents the output of a signal analysis with direction, confidence, and optional metadata for debugging and auditing.
Attributes:
| Name | Type | Description |
|---|---|---|
direction |
SignalDirection
|
The predicted direction (BULLISH, BEARISH, NEUTRAL) |
confidence |
float
|
Confidence level from 0.0 (no confidence) to 1.0 (certain) |
timestamp |
datetime
|
When the signal was generated (defaults to now) |
metadata |
dict | None
|
Additional data from the signal source (for debugging) |
source |
str | None
|
Identifier for the signal provider |
raw_score |
float | None
|
Raw numerical score before directional interpretation |
Example
result = SignalResult( direction=SignalDirection.BULLISH, confidence=0.85, source="news_sentiment", metadata={"headline": "Positive developments..."} )
neutral
classmethod
¶
Create a neutral signal with low confidence.
Useful for error cases or when no signal is available.
SocialSentimentProvider
¶
SocialSentimentProvider(
platforms: list[str] | None = None,
min_engagement: int = 10,
sentiment_model: str = "vader",
)
Example signal provider using social media sentiment.
This is a reference implementation showing how to build a social media signal provider. In production, you would integrate with social APIs (e.g., Twitter/X API, Reddit API) or social listening platforms.
The provider analyzes social media posts and discussions related to the market topic, extracts sentiment and engagement metrics, and converts them to a trading signal.
Attributes:
| Name | Type | Description |
|---|---|---|
platforms |
List of platforms to analyze (twitter, reddit, etc.) |
|
min_engagement |
Minimum engagement score to consider |
|
sentiment_model |
Sentiment analysis approach to use |
Example
provider = SocialSentimentProvider(platforms=["twitter", "reddit"]) signal = provider.get_signal( "market-123", topic="Bitcoin ETF approval", hashtags=["#Bitcoin", "#ETF"] )
Initialize the social sentiment provider.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
platforms
|
list[str] | None
|
Platforms to analyze (default: ["twitter", "reddit"]) |
None
|
min_engagement
|
int
|
Minimum engagement (likes, upvotes) to consider |
10
|
sentiment_model
|
str
|
Model for sentiment analysis ("vader", "textblob", "ml") |
'vader'
|
get_signal
¶
Get signal based on social media sentiment.
This example implementation demonstrates the pattern. In production, replace with actual social API integration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market_id
|
str
|
The Polymarket market ID |
required |
**kwargs
|
Optional parameters: - topic: Topic to search for - hashtags: Hashtags to track - lookback_hours: How far back to search (default 6) |
{}
|
Returns:
| Type | Description |
|---|---|
SignalResult
|
SignalResult with social-sentiment-based direction and confidence |
calculate_inventory_skew
¶
Calculate inventory skew factor based on current position.
The skew factor represents how much the position deviates from neutral as a proportion of the maximum allowed position. It's used to adjust bid/ask prices to encourage trades that reduce inventory.
Returns:
| Type | Description |
|---|---|
Decimal
|
Skew factor from -1.0 (max short) to +1.0 (max long). |
Decimal
|
|
Decimal
|
|
Decimal
|
|
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
position
|
Decimal
|
Current position in shares. Positive = long, negative = short. |
required |
max_position
|
Decimal
|
Maximum allowed position size (absolute value). |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If max_position is not positive |
Example
skew = calculate_inventory_skew(Decimal("500"), Decimal("1000")) print(f"Skew: {skew}") # 0.5 (50% of max long position) Skew: 0.5
skew = calculate_inventory_skew(Decimal("-250"), Decimal("1000")) print(f"Skew: {skew}") # -0.25 (25% of max short position) Skew: -0.25
calculate_optimal_spread
¶
calculate_optimal_spread(
orderbook: OrderBook,
inventory: Decimal,
risk_params: RiskParameters,
) -> tuple[Decimal, Decimal]
Calculate optimal bid and ask prices based on inventory and market state.
Uses the Avellaneda-Stoikov market making model adapted for prediction markets. The spread is adjusted based on: 1. Base spread requirement (minimum profit margin) 2. Inventory skew (encourage position reduction) 3. Market volatility (wider spreads in volatile markets)
The algorithm: 1. Calculate mid price from orderbook 2. Calculate base half-spread 3. Apply inventory skew adjustment 4. Apply volatility adjustment 5. Clamp to valid price range [0.01, 0.99]
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
orderbook
|
OrderBook
|
Current orderbook with bids and asks |
required |
inventory
|
Decimal
|
Current position (positive = long, negative = short) |
required |
risk_params
|
RiskParameters
|
Risk management parameters |
required |
Returns:
| Type | Description |
|---|---|
Decimal
|
Tuple of (bid_price, ask_price) representing optimal quotes. |
Decimal
|
Returns (MIN_PRICE, MAX_PRICE) if orderbook is empty. |
Example
orderbook = client.get_orderbook(token_id) risk_params = RiskParameters(base_spread=Decimal("0.02")) bid, ask = calculate_optimal_spread(orderbook, Decimal("100"), risk_params) print(f"Quote: {bid} - {ask}")
generate_quote_ladder
¶
generate_quote_ladder(
mid_price: Decimal,
spread: Decimal,
num_levels: int,
size_per_level: Decimal,
tick_size: Decimal = Decimal("0.01"),
skew: Decimal = Decimal("0"),
) -> list[Quote]
Generate a quote ladder with multiple price levels.
Creates a symmetric ladder of bids and asks around the mid price, with optional skew adjustment for inventory management.
The ladder places quotes at increasing distances from mid: - Level 1: mid +/- spread/2 - Level 2: mid +/- spread - Level 3: mid +/- spread*1.5 - etc.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mid_price
|
Decimal
|
Center price for the ladder |
required |
spread
|
Decimal
|
Base spread between best bid and ask |
required |
num_levels
|
int
|
Number of price levels on each side (1-10) |
required |
size_per_level
|
Decimal
|
Size to quote at each price level |
required |
tick_size
|
Decimal
|
Minimum price increment (default 0.01) |
Decimal('0.01')
|
skew
|
Decimal
|
Inventory skew factor (-1 to +1) to shift the ladder. Positive skew shifts asks closer (encourage selling). Negative skew shifts bids closer (encourage buying). |
Decimal('0')
|
Returns:
| Type | Description |
|---|---|
list[Quote]
|
List of Quote objects, sorted by price (highest first). |
list[Quote]
|
Bids have side="BUY", asks have side="SELL". |
Raises:
| Type | Description |
|---|---|
ValueError
|
If num_levels is not between 1 and 10, or if parameters produce invalid prices. |
Example
quotes = generate_quote_ladder( ... mid_price=Decimal("0.50"), ... spread=Decimal("0.02"), ... num_levels=3, ... size_per_level=Decimal("10"), ... ) for q in quotes: ... print(f"{q.side} {q.size} @ {q.price}") SELL 10 @ 0.53 SELL 10 @ 0.52 SELL 10 @ 0.51 BUY 10 @ 0.49 BUY 10 @ 0.48 BUY 10 @ 0.47
should_requote
¶
should_requote(
current_quotes: list[Quote],
orderbook: OrderBook,
threshold: Decimal = Decimal("0.01"),
) -> bool
Determine if quotes should be updated based on market changes.
Compares current quotes against the orderbook to decide if requoting is necessary. Requoting is recommended when:
- The market has moved significantly (mid price change > threshold)
- Our quotes are no longer at competitive prices
- Our quotes have been fully filled (detected by absence in orderbook)
This function helps avoid excessive requoting while ensuring quotes remain competitive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
current_quotes
|
list[Quote]
|
List of currently active quotes |
required |
orderbook
|
OrderBook
|
Current orderbook state |
required |
threshold
|
Decimal
|
Price movement threshold that triggers requote (default 0.01). A threshold of 0.01 means requote if mid price moves by 1% or more. |
Decimal('0.01')
|
Returns:
| Type | Description |
|---|---|
bool
|
True if quotes should be updated, False otherwise. |
Example
quotes = [Quote(Decimal("0.49"), Decimal("10"), "BUY"), ... Quote(Decimal("0.51"), Decimal("10"), "SELL")] orderbook = client.get_orderbook(token_id) if should_requote(quotes, orderbook, threshold=Decimal("0.01")): ... # Cancel and replace quotes ... pass
aggregate_signals
¶
aggregate_signals(
signals: list[SignalResult],
weights: list[float] | None = None,
min_agreement: float = 0.0,
) -> SignalResult
Aggregate multiple signals into a single signal.
Combines signals from multiple providers using weighted averaging. Each signal's contribution is weighted by both its explicit weight and its confidence level.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signals
|
list[SignalResult]
|
List of SignalResult objects to aggregate |
required |
weights
|
list[float] | None
|
Optional weights for each signal (default: equal weights) |
None
|
min_agreement
|
float
|
Minimum fraction of signals that must agree on direction for non-neutral result (0.0 to 1.0) |
0.0
|
Returns:
| Type | Description |
|---|---|
SignalResult
|
Aggregated SignalResult |
Example
signals = [ SignalResult(SignalDirection.BULLISH, 0.8, source="news"), SignalResult(SignalDirection.BULLISH, 0.6, source="social"), SignalResult(SignalDirection.NEUTRAL, 0.5, source="model"), ] result = aggregate_signals(signals)
result.direction = BULLISH (2/3 agreement)¶
result.confidence = weighted average of confidences¶
Note
- Empty signals list returns neutral with 0.5 confidence
- Signals with higher confidence have more influence
- Direction is determined by vote weighted by confidence
- Final confidence is the average confidence of the winning direction
combine_with_market_price
¶
combine_with_market_price(
signal: SignalResult,
current_price: Decimal,
edge_threshold: Decimal = Decimal("0.05"),
) -> SignalResult
Combine signal with market price to calculate expected edge.
Adjusts signal confidence based on the potential edge between the signal's implied probability and the current market price.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signal
|
SignalResult
|
The signal to evaluate |
required |
current_price
|
Decimal
|
Current YES token price (0-1) |
required |
edge_threshold
|
Decimal
|
Minimum edge required for confident signal |
Decimal('0.05')
|
Returns:
| Type | Description |
|---|---|
SignalResult
|
Adjusted SignalResult with edge metadata |