Skip to main content
This example shows a FastAPI service that monitors the BTC 15-minute market and buys the winning side every 30 seconds.
import os
import json
import requests
import asyncio
from datetime import datetime, timezone, timedelta
from contextlib import asynccontextmanager
from fastapi import FastAPI
from polyhush import PolyhushClient

GAMMA_API_URL = "https://gamma-api.polymarket.com"

client = PolyhushClient(api_key=os.environ["POLYHUSH_API_KEY"])


def get_current_15min_slug():
    """Get the slug for the current BTC 15-minute market."""
    now_utc = datetime.now(timezone.utc)
    year = now_utc.year
    
    # Calculate DST boundaries for Eastern Time
    march_1 = datetime(year, 3, 1, tzinfo=timezone.utc)
    dst_start = march_1 + timedelta(days=(6 - march_1.weekday()) % 7 + 7)
    dst_start = dst_start.replace(hour=7)
    
    nov_1 = datetime(year, 11, 1, tzinfo=timezone.utc)
    dst_end = nov_1 + timedelta(days=(6 - nov_1.weekday()) % 7)
    dst_end = dst_end.replace(hour=6)
    
    # Convert UTC to Eastern Time
    offset = timedelta(hours=-4) if dst_start <= now_utc < dst_end else timedelta(hours=-5)
    et_now = datetime.now(timezone(offset))
    
    # Get current 15-min window start
    minute = (et_now.minute // 15) * 15
    window_start = et_now.replace(minute=minute, second=0, microsecond=0)
    return f"btc-updown-15m-{int(window_start.timestamp())}"


def fetch_market():
    """Fetch the current BTC 15m market from Polymarket."""
    slug = get_current_15min_slug()
    response = requests.get(f"{GAMMA_API_URL}/markets/slug/{slug}", timeout=10)
    
    if response.status_code != 200:
        return None
    
    market = response.json()
    token_ids = json.loads(market.get("clobTokenIds", "[]")) if isinstance(market.get("clobTokenIds"), str) else market.get("clobTokenIds", [])
    prices = json.loads(market.get("outcomePrices", "[]")) if isinstance(market.get("outcomePrices"), str) else market.get("outcomePrices", [])
    
    if len(token_ids) < 2 or len(prices) < 2:
        return None
    
    return {
        "up_token": token_ids[0],
        "down_token": token_ids[1],
        "up_price": float(prices[0]),
        "down_price": float(prices[1]),
    }


async def trading_loop():
    """Check prices every 30s and buy 5 shares of the winning side."""
    while True:
        try:
            market = fetch_market()
            if market:
                # Buy whichever side is winning (higher probability)
                if market["up_price"] > market["down_price"]:
                    token_id = market["up_token"]
                    price = round(market["up_price"], 2)
                    side = "UP"
                else:
                    token_id = market["down_token"]
                    price = round(market["down_price"], 2)
                    side = "DOWN"
                
                client.buy(token_id=token_id, shares=5, price=price, order_type="FAK")
                print(f"Bought 5 shares {side} @ {price}")
        except Exception as e:
            print(f"Error: {e}")
        
        await asyncio.sleep(30)


@asynccontextmanager
async def lifespan(app: FastAPI):
    # Start the trading loop on startup
    task = asyncio.create_task(trading_loop())
    yield
    # Cancel on shutdown
    task.cancel()


app = FastAPI(lifespan=lifespan)


@app.get("/status")
def status():
    """Check bot status and current positions."""
    return {
        "status": "running",
        "balance": client.get_balance(),
        "positions": client.get_positions(detailed=True),
    }
Run with:
POLYHUSH_API_KEY=your-key uvicorn bot:app --reload