Skip to content

Repository files navigation

polyalpha

Python SDK for Polymarket — discover prediction markets, stream live prices, trade paper or real, run bots with composable strategy conditions, analyse with 19 TA indicators and AI signals, track P&L with full reporting, and manage wallets.

git clone https://github.com/Genius740Code/polyalpha.git
cd polyalpha
pip install -e .

Quick start

import polyalpha

client = polyalpha.Client()
market = client.markets.latest("BTC", "5m")

stream = client.stream(market)
@stream.on("price")
def on_price(up, down):
    print(f"UP={up:.4f}  DOWN={down:.4f}")
stream.start(background=True)

client.paper.buy(market, side="UP", amount=10.0)
client.paper.summary()

Market discovery

Find any Up/Down market by asset + timeframe, slug, keyword, or browse all active.

client.markets.latest("BTC", "5m")
client.markets.latest("ETH", "15m")
client.markets.latest("SOL", "1h")
client.markets.get("btc-updown-5m-1751234700")
client.markets.search("ETH 15m")
client.markets.available("5m")      # all active 5m markets

Assets: BTC, ETH, SOL, XRP, DOGE, HYPE, BNB
Timeframes: 5m, 15m, 1h, 4h, 24h


Price streaming

WebSocket stream with auto-reconnect, PING keepalive, and five event hooks.

stream = client.stream(market)

@stream.on("price")   def on_price(up, down): ...
@stream.on("book")    def on_book(data): ...
@stream.on("trade")   def on_trade(data): ...
@stream.on("close")   def on_close(): ...
@stream.on("error")   def on_error(exc): ...

stream.start()                    # blocking
stream.start(background=True)     # daemon thread
stream.stop()

# Latest prices without a handler
stream.up
stream.down

See examples/stream.py.


Paper trading

Simulate orders with configurable fees, slippage, execution delay, and risk limits. Attach a stream for live P&L.

client = polyalpha.Client(balance=500.0)

client.paper.buy(market, side="UP", amount=10.0)
client.paper.sell_position(market, side="UP", amount=5.0)
client.paper.limit(market, side="UP", price=0.92, amount=25.0)
client.paper.cancel(order.id)

client.paper.positions()       # open positions
client.paper.all_positions()   # all, incl. resolved
client.paper.balance
client.paper.summary()         # P&L table

# Advanced order types (stop_loss_pct / take_profit_pct as decimals)
client.paper.buy(market, side="UP", amount=10.0,
    stop_loss_pct=0.05,         # 5% stop-loss
    take_profit_pct=0.50)       # 50% take-profit
client.paper.buy_with_tp_sl(market, side="UP", amount=10.0,
    stop_loss=0.45,             # absolute stop-loss price
    take_profit=0.65)           # absolute take-profit price
client.paper.oco_order(market, side="UP", amount=10.0,
    stop_loss=0.40, take_profit=0.70)  # one-cancels-other

# Attach a stream for auto-fill + live P&L
client.paper.attach_stream(stream, market)

# Resolve after settlement
client.paper.resolve(market, outcome="UP")

See examples/paper.py and examples/advanced_orders.py.


Calculations library

Unified calculation functions for market data analysis across all data sources (Chainlink, Binance, Coinbase).

from polyalpha.calculations import MarketCalculations, VolumeCalculations

# Universal price calculations (all data sources)
MarketCalculations.change_pct(data, period=1)     # % change over N periods
MarketCalculations.change_abs(data, period=1)     # absolute price change
MarketCalculations.rate_of_change(data, period=1) # speed of change per second
MarketCalculations.trend(data, period=1)          # UP/DOWN/NEUTRAL
MarketCalculations.direction(data, period=1)       # "up"/"down"/"flat"
MarketCalculations.volatility(data, period=10)     # price volatility
MarketCalculations.high(data, period=10)          # highest price
MarketCalculations.low(data, period=10)           # lowest price
MarketCalculations.range(data, period=10)         # price range

# Volume calculations (Binance/Coinbase only)
VolumeCalculations.vol_ratio(data, period=10)      # current / avg volume
VolumeCalculations.volume_trend(data, period=5)    # INCREASING/DECREASING/STABLE
VolumeCalculations.volume_surge(data, multiplier=2.0) # detect volume spikes
VolumeCalculations.avg_volume(data, period=10)    # average volume
VolumeCalculations.volume_momentum(data, period=5) # volume % change
VolumeCalculations.relative_volume(data, percentile=0.75) # percentile-based

Data source accessors

Source-specific accessors that integrate calculations with live data:

from polyalpha.calculations import ChainlinkAccessor
from polyalpha.windows import TimeWindow

# Chainlink accessor (price calculations only)
window = TimeWindow(max_age=120)
cl_accessor = ChainlinkAccessor(window)
cl_accessor.update(67850.0)  # Update with Chainlink price
cl_accessor.change_pct(30)    # % change over 30 seconds
cl_accessor.trend(60)         # trend direction
cl_accessor.is_rising(30)     # convenience method
cl_accessor.is_falling(30)    # convenience method

Source availability:

  • Chainlink: Price calculations only (no volume data)
  • Binance: Price + volume calculations
  • Coinbase: Price + volume calculations (future)

See src/polyalpha/calculations/ for implementation details.


Paper config & presets

Tune realism: fee model, slippage, fill probability, execution delay, risk limits.

from polyalpha.trading.paper_config import get_paper_config_from_preset, list_presets

print(list_presets())
config = get_paper_config_from_preset("REALISTIC")    # 2s delay, polymarket fees, 85% fill prob
config = get_paper_config_from_preset("AGGRESSIVE")   # no delay, high fill prob
config = get_paper_config_from_preset("CONSERVATIVE") # polymarket fees, 1% slippage, 95% fill prob
config = get_paper_config_from_preset("TEST")         # zero fees, instant, 100% fill

client = polyalpha.Client(balance=500.0, paper_config=config)
# or load from .env:
client = polyalpha.Client(paper_config_from_env=True)

Built-in presets

Preset Slippage Delay Fill prob Risk
CONSERVATIVE 1% 500ms 95% Low
REALISTIC 3% 2000ms 85% Medium
AGGRESSIVE 5% 100ms 70% High
ZERO_FEE 0% 0ms 100% Medium
HIGH_LATENCY 8% 5000ms 60% Medium
LIQUIDITY_PROVIDER 2% 1000ms 90% Low
SCALPER 2% 50ms 98% Low
TEST 0% 0ms 100% None

Bots

Bot handles the full lifecycle: discover → stream → tick → resolve → rollover → repeat.

bot = polyalpha.Bot("BTC", "5m", balance=500, mode="simple")

@bot.on_tick
def strategy(ctx):
    if ctx.price.up > 0.9 and ctx.rsi > 50:
        ctx.buy("UP", 20)

bot.run()  # blocking, auto-rollover

Modes

Three execution templates via the mode parameter:

Mode Fees Delay Slippage Fill prob
"simple" (default) Zero Instant 0% 100%
"realistic" Polymarket fees 2000ms 3% 85%
"custom" Your PaperConfig Your config Your config Your config
# Simple — zero fees, instant, 100% fill (default)
bot = polyalpha.Bot("BTC", "5m", balance=500)

# Realistic — polymarket fees, slippage, delay
bot = polyalpha.Bot("BTC", "5m", balance=500, mode="realistic")

# Custom — your own PaperConfig
from polyalpha.trading.paper_config import PaperConfig, get_paper_config_from_preset

bot = polyalpha.Bot("BTC", "5m", balance=500, mode="custom",
    paper_config=PaperConfig(fee_mode="custom", custom_fee_rate=0.015))

TickContext

ctx.price.up / ctx.price.down   # current prices
ctx.balance                     # paper balance
ctx.positions                   # open positions
ctx.pnl                         # realised P&L
ctx.rsi / ctx.sma_20 / ctx.ema_12   # indicators (requires pandas)
ctx.tick_count / ctx.trade_count
ctx.chainlink.last_price        # BTC spot from Chainlink oracle
ctx.cl.value                    # latest Chainlink price
ctx.cl.change_pct(30)           # % change over 30 seconds
ctx.cl.change_pct(60)           # % change over 60 seconds
ctx.cl.age_s                    # seconds since last CL update
ctx.cl.trend(60)               # trend direction (UP/DOWN/NEUTRAL)
ctx.cl.direction(30)           # simple direction ("up"/"down"/"flat")
ctx.cl.volatility(120)         # price volatility
ctx.binance.macd(12, 26, 9)     # MACD from Binance data
ctx.binance.price_change(3)     # BTC price change over 3 candles
ctx.binance.change_pct(3)       # % price change over 3 candles
ctx.binance.vol_ratio(10)       # current volume / avg of last 10 candles
ctx.binance.volume_trend(5)     # volume trend (increasing/decreasing/stable)
ctx.binance.volume_surge(2.0)    # detect volume spikes
ctx.buy("UP", 20)               # market buy
ctx.limit("UP", 0.92, 25)       # limit order
ctx.close_position("UP")        # close position

Composable conditions

Use declarative conditions with and_, or_, not_ (or &, |, ~).

from polyalpha.conditions import rsi_above, price_above, and_

bot.when(and_(rsi_above(50), price_above("up", 0.9))).buy("UP", 20)
bot.when(rsi_below(30) & price_below("down", 0.15)).buy("DOWN", 20)
bot.run()

Built-in conditions: rsi_above, rsi_below, price_above, price_below, price_change_pct_above, sma_above, sma_below, trending_up, trending_down, volatility_above, volume_above, min_tick_count, max_spend, stopped, macd_bullish_crossover, macd_bearish_crossover, macd_above_zero, macd_below_zero, price_change_above, price_change_below, price_up, price_down

Mixing data sources: Conditions like macd_bullish_crossover() read from Binance BTC data via ctx.binance, while price_above() reads Polymarket UP/DOWN prices. Both work together in the same declarative rule:

from polyalpha.conditions import and_, price_above, macd_bullish_crossover

bot.when(
    and_(price_above("UP", 0.90), macd_bullish_crossover())
).buy("UP", 20)
bot.run()

Chainlink BTC spot is also available at ctx.chainlink.last_price in on_tick strategies or via ctx.chainlink in BotHub strategies.

See examples/bot_simple.py.

BotHub — Multi-Strategy Hub

Run multiple strategies from a single data connection. One market discovery, one WebSocket stream — N isolated paper engines. Eliminates redundant rate-limited connections.

hub = polyalpha.BotHub("BTC", "5m", default_balance=500)

@hub.strategy("momentum")
def momentum(ctx):
    if ctx.price.up > 0.9 and ctx.rsi > 50:
        ctx.buy("UP", 20)

@hub.strategy("value", balance=1000)
def value(ctx):
    if ctx.price.down < 0.10:
        ctx.buy("DOWN", 10)

hub.run()

Each strategy gets its own balance, positions, and P&L. Error isolation — one crash doesn't stop the others.

Event hooks & timers: hub.on("tick"), hub.on("candle_open"), hub.every(30) for lifecycle callbacks.

Variants: Register strategies with params metadata and compare side-by-side via hub.compare_variants() (Rich table sorted by P&L, win rate, Sharpe, max drawdown).

Order book: ctx.orderbook.up.bids, ctx.orderbook.down.asks, ctx.orderbook.refresh() — auto-attached to the shared stream.

Scenario Use
One strategy Bot
20+ strategies, same asset/timeframe BotHub
Different assets per strategy Bot.run_async()

See examples/bot_hub.py and docs/bot.md.


Real trading

Trade live on Polymarket via CLOB with EIP-712 signing.

client = polyalpha.Client(
    private_key="0x...",
    rpc_url="https://polygon-rpc.com",
    polymarket_api_key="...",
)

client.real.buy(market, side="UP", amount=10.0)
client.real.cancel(order.id)
client.real.positions()
client.real.balance

Real trading presets: CONSERVATIVE, REALISTIC, AGGRESSIVE, MINIMAL, HIGH_FREQUENCY, POSITION_TRADER, HEDGING_ENABLED, TEST.

Real trading is available via client.real — see docs/trading.md for the full API.


Auto-redeem

Schedule automatic redemption of winning positions.

from polyalpha import AutoRedeemConfig

config = AutoRedeemConfig(time_interval="1d", min_value_usd=100.0)
client.paper.set_auto_redeem_config(config)
client.paper.auto_redeem.start_scheduler()

# Manual
client.paper.auto_redeem.redeem()
client.paper.auto_redeem.get_redeem_history()

Triggers: time interval, market count, value threshold. Safety: dry-run, min age, max value caps.

Auto-redeem is available via client.paper.auto_redeem — see docs/trading.md for usage.


Order book

REST snapshots + optional WebSocket deltas, in-memory O(1) manager, analytics, and backtestable strategies.

# REST
feed = client.orderbook(market)
feed.refresh()
feed.bids[:3]
feed.asks[:3]

# Attach stream for live updates
feed.attach_stream(client.stream(market))

# Analytics
from polyalpha.orderbook import estimate_fill, book_summary, cumulative_depth
estimate_fill(snapshot, side="UP", amount=100.0)

# Strategies + backtesting
from polyalpha.orderbook import MomentumStrategy, SpreadStrategy, BacktestEngine

Strategies: MomentumStrategy, SpreadStrategy (market making), ImbalanceStrategy.

See docs/orderbook.md for the full order book API.


Technical analysis

Multi-source data feed and 19 TA indicators.

from polyalpha.analysis import DataFeed, IndicatorCalculator, SignalGenerator

feed = DataFeed(DataFeedConfig(source="binance", timeframe="5m"))
data = feed.fetch("BTC")

ind = IndicatorCalculator(data)
ind.rsi(14)
ind.bollinger_bands(20, 2.0)
ind.macd(12, 26, 9)
ind.adx(14)
ind.atr(14)
ind.stochastic(14, 3, 3)
ind.obv()

sig = SignalGenerator(ind)
sig.rsi_above(50)
sig.price_above_sma(20)
sig.price_above_bb_upper()
sig.macd_bullish_crossover()
sig.summary()  # all signals at once

Data sources: scraping (default), binance, chainlink, custom, websocket.

Live Binance feeds (polyalpha.analysis): CVDTracker streams spot aggTrades for cumulative volume delta (cvd, z, velocity, …), and LiquidationTracker streams futures forceOrder events for one-sided liquidation clusters (cluster()). Both run their own connection and reconnect forever.

from polyalpha.analysis import CVDTracker, LiquidationTracker

cvd = CVDTracker(); cvd.start()
liq = LiquidationTracker(); liq.start()

cvd.z()                       # CVD z-score, or None
liq.cluster()                 # {"direction", "notional", "count"} or None

Shared Globals (polyalpha.Globals): one instance of every continuously-running feed, shared by all strategies so adding one costs zero extra connections. default_globals("BTC", cvd=True, liq=True) builds the feeds; .start() / .stop() manage them all. Per-market scope is MarketCtx / watch_market().

See examples/analysis.py and examples/price_change_signals.py.


AI-powered signals

Analyse markets and generate trading signals via OpenRouter.

client = polyalpha.Client(openrouter_api_key="sk-or-...")

analysis = client.ai.analyze_market(market_data)
analysis.sentiment    # "bullish" | "bearish" | "neutral"
analysis.confidence   # 0.0 – 1.0
analysis.reasoning    # markdown explanation

signal = client.ai.generate_trading_signal(market_data)
signal.action         # "BUY" | "SELL" | "HOLD"
signal.side           # "UP" | "DOWN" | None
signal.confidence     # 0.0 – 1.0

AI analysis is available via client.ai — see docs/ai.md for usage.


Reporting

Generate terminal summaries, interactive HTML dashboards, and PNG snapshots of paper-trading performance.

client.paper.report.show()                    # terminal (rich tables)
client.paper.report.html(open_browser=True)   # interactive HTML
client.paper.report.save_png("report.png")    # requires kaleido

30+ metrics: Sharpe, Sortino, Calmar, Omega, Kelly criterion, VaR, CVaR, profit factor, win rate, average win/loss, max drawdown, recovery factor.

12 charts: equity curve, underwater drawdown, P&L per trade, win/loss distribution, monthly returns, rolling Sharpe, correlation matrix, P&L hourly heatmap.

See docs/reporting.md for the full reporting API.


Database

SQLite-backed trade persistence with optional encryption.

client = polyalpha.Client(db_path="./trades.db")

db = client.paper.database
db.get_statistics()                                   # aggregate stats (no args)
db.load_trades(filters={"asset": "btc"})              # filtered trades
db.load_trades_by_market("btc-updown-5m-1751234700")  # trades for one market
db.export_json("trades.json")
db.export_csv("trades.csv")

See docs/database.md for the full database API.


Sniper bot

Time-window execution bot with configurable thresholds and auto-rollover. Supports advanced time windows: multiple disjoint periods, burst patterns, absolute time windows, conditional windows (indicator-based), and day/hour filtering.

from polyalpha import Sniper, SniperConfig, TimeWindow, ConditionalWindow, TimeFilter

# Simple time window (backward compatible)
Sniper(SniperConfig(
    asset="BTC", timeframe="5m",
    balance=500.0, window_seconds=30,
    side="UP", order_size=25.0,
    auto_rollover=True,
)).run()

# Advanced: Multiple time windows with conditions
Sniper(SniperConfig(
    asset="BTC", timeframe="5m",
    side="UP", entry_price=0.92, exit_price=0.88,
    time_windows=[
        TimeWindow(start_time="01:00", end_time="02:00"),
        TimeWindow(start_time="02:30", end_time="03:00"),
    ],
    conditional_windows=[
        ConditionalWindow(indicator="btc_change", operator="lt", threshold=2.0, periods=5),
    ],
    time_filter=TimeFilter(days=[0, 1, 2, 3, 4], hours=[9, 10, 11, 12, 13, 14, 15, 16, 17]),
    amount=20.0,
)).run()

timeframe is required (one of 5m, 15m, 1h, 4h, 24h — no silent 5m default). By default each bot buys only once per market (buy_once_per_market=True); set it to False on the config to allow multiple entries within the same market.

See examples/sniper.py, examples/sniper_minimal.py, examples/sniper_ta.py, and docs/bots.md.


Tracker

Real-time P&L tracking with JSON/CSV export.

from polyalpha import Tracker

tracker = Tracker(client.paper)
tracker.sync()
tracker.summary()
tracker.export_json("trades.json")
tracker.export_csv("trades.csv")

See docs/bot.md for Tracker usage.


Wallet management

Multi-wallet paper trading and secure wallet storage (AES-256, multi-sig, audit logging).

from polyalpha.trading.wallet import WalletManager, PaperWallet

manager = WalletManager()
manager.add_wallet(PaperWallet("trader-1", balance=1000.0))
client.paper.enable_multi_wallet(manager)

See examples/multi_wallet_paper.py.


Errors

Typed exceptions for every failure mode:

from polyalpha import (
    PolyalphaError,          # base
    MarketNotFound,          # slug not found
    MarketClosed,            # window closed
    StreamDisconnected,      # WS retry exhausted
    InsufficientBalance,     # balance too low
    OrderNotFound,           # unknown order
    OrderRejected,           # CLOB rejection
    OrderTimeout,            # not filled
    RiskLimitExceeded,       # risk check failed
    NetworkError,            # HTTP/WS failure
)

Logging

Variable Default Description
POLYALPHA_LOG_LEVEL WARNING DEBUG / INFO / WARNING / ERROR
POLYALPHA_LOG_FILE File path (10 MB rotate)
POLYALPHA_LOG_FORMAT text text or json

Sensitive data (keys, addresses, tokens) is auto-redacted in both formats.


Configuration

client = polyalpha.Client(
    balance         = 100.0,        # paper USDC balance
    timeout         = 10,           # HTTP timeout (s)
    retries         = 3,            # HTTP retries
    log_level       = "WARNING",
    rate_limit      = None,         # requests/s
    paper_config    = None,         # PaperConfig instance
    paper_config_from_env = False,
    db_path         = None,         # SQLite path
    openrouter_api_key = None,      # AI features
    private_key     = None,         # real trading key
    rpc_url         = None,         # Polygon RPC
    polymarket_api_key = None,      # CLOB API key
    real_config     = None,         # RealTradingConfig
)

Examples index

| File | What it shows | |---|---|---| | examples/stream.py | Price streaming with all event hooks | | examples/paper.py | Paper trading — buy, sell, limit, summary | | examples/advanced_orders.py | Trailing stop, OCO, take-profit | | examples/conditions.py | Composable trading conditions | | examples/bot_simple.py | Bot with on_tick strategy | | examples/bot_hub.py | BotHub — multi-strategy from one connection | | examples/sniper.py | Sniper time-window bot | | examples/sniper_minimal.py | Minimal Sniper bot (~10 lines) | | examples/sniper_ta.py | Sniper + technical analysis | | examples/analysis.py | TA data feed, indicators, signals | | examples/multi_wallet_paper.py | Multi-wallet paper trading | | examples/risk_management.py | Risk limits and controls | | examples/pairsum_arb.py | Arbitrage example | | examples/price_change_signals.py | Price change detection signals | | examples/chainlink_btc_scraper.py | Chainlink BTC data scraper | | examples/multi_arb_bot.py | Multi-arbitrage bot | | examples/telegram_notifications.py | Telegram notification integration |


Project layout

src/polyalpha/
├── __init__.py          Public API surface
├── client.py            Client — single entry point
├── markets.py           MarketClient — discovery
├── stream.py            Stream — WebSocket price feed
├── bot.py               Bot — lifecycle runner
├── bot_hub.py           BotHub — multi-strategy hub
├── conditions.py        Composable strategy conditions
│
├── core/                Constants, errors, market models, env
├── trading/             PaperEngine, RealTradingEngine, auto-redeem, retry
├── orderbook/           REST + WS book, manager, strategies, backtest
├── analysis/            DataFeed, 19 indicators, 30+ signals
├── ai/                  OpenRouterClient, MarketAnalysis, TradingSignal
├── report/              ReportEngine, metrics (30+), charts (12), HTML
├── bots/                Sniper, Tracker
├── database/            SQLite, encryption, auth
├── wallet/              WalletSecurity, MultiSig, TransactionSigner, AuditLogger
└── utils/               Sensitive-data logging

License

MIT

About

Polymarket sdk to quickly build strategies

Topics

Resources

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages