Copy
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),
}
Copy
POLYHUSH_API_KEY=your-key uvicorn bot:app --reload