From d3b3a2fdb4b51ac3ccd319de769da2cf075ad92f Mon Sep 17 00:00:00 2001 From: Nawaz Haider Date: Fri, 2 Jan 2026 12:40:25 +0600 Subject: [PATCH] Refactor trading logic and client initialization; remove unused clob_client_and_order module --- config.py | 2 + main.py | 24 ++++---- utils/clob_client.py | 56 +++++++++++++++++++ ...lob_client_and_order.py => clob_orders.py} | 48 +++++----------- utils/orderbook.py | 3 +- 5 files changed, 87 insertions(+), 46 deletions(-) create mode 100644 utils/clob_client.py rename utils/{clob_client_and_order.py => clob_orders.py} (53%) diff --git a/config.py b/config.py index 65bc530..f57a435 100644 --- a/config.py +++ b/config.py @@ -2,6 +2,7 @@ LOG_FOLDER = "logs/" GAMMA_API_URL = "https://gamma-api.polymarket.com" POLYMARKET_HOST = "https://clob.polymarket.com" POLYMARKET_WS_MARKET_URL = "wss://ws-subscriptions-clob.polymarket.com/ws/market" +POLYMARKET_WS_USER_URL = "wss://ws-subscriptions-clob.polymarket.com/ws/user" CHAIN_ID = 137 REQUEST_TIMEOUT = 5 PROFIT_MARGIN = 0.02 @@ -9,3 +10,4 @@ TRADING_BPS_THRESHOLD = 50 MARKET_SESSION_SECONDS = 900 TIMEZONE = "US/Eastern" MAX_TRADES = 1 +PLACE_OPPOSITE_ORDER = True # Hedge orders diff --git a/main.py b/main.py index 3017b01..41b8d3d 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,13 @@ +import os import gc import asyncio import requests from utils.logger import setup_logging from utils.tokens import fetch_tokens -from utils.clob_client_and_order import init_clob_client from utils.orderbook import OrderBook, SIGNALES -from utils.market_time import is_in_trading_window, get_period_elapsed_seconds -from utils.clob_client_and_order import ( +from utils.clob_client import init_global_client +from utils.market_time import is_in_trading_window +from utils.clob_orders import ( place_anchor_and_hedge, cache_tocken_trading_infos, ) @@ -26,16 +27,17 @@ requests.options = session.options async def main(): + trades = 0 logger = setup_logging() set_cpu_affinity() logger.info("Polymarket HFT Market Maker started") - + init_global_client() up_token, down_token, market_slug = await fetch_tokens() - client = init_clob_client() + book = OrderBook(up_token, down_token, market_slug) - await asyncio.create_task(cache_tocken_trading_infos(client, book)) + await asyncio.create_task(cache_tocken_trading_infos(book)) book.start() await asyncio.sleep(5) # Allow some time for initial order book data @@ -62,7 +64,7 @@ async def main(): trades = 0 up_token, down_token, market_slug = await fetch_tokens() book = OrderBook(up_token, down_token, market_slug) - asyncio.create_task(cache_tocken_trading_infos(client, book)) + asyncio.create_task(cache_tocken_trading_infos(book)) book.start() market_data = book.get_current_market_data() @@ -83,7 +85,6 @@ async def main(): if trading_side == SIGNALES.UP: await place_anchor_and_hedge( - client, up_token, down_token, "UP", @@ -97,7 +98,6 @@ async def main(): elif trading_side == SIGNALES.DOWN: await place_anchor_and_hedge( - client, up_token, down_token, "DOWN", @@ -114,12 +114,12 @@ async def main(): if __name__ == "__main__": try: - try: + if os.name == "nt": + asyncio.run(main()) + else: import uvloop uvloop.run(main()) - except ImportError: - asyncio.run(main()) except KeyboardInterrupt: print("\nMarket maker stopped by user") except Exception as e: diff --git a/utils/clob_client.py b/utils/clob_client.py new file mode 100644 index 0000000..1b2d246 --- /dev/null +++ b/utils/clob_client.py @@ -0,0 +1,56 @@ +import os +import logging +from dotenv import load_dotenv +from py_clob_client.client import ClobClient +from config import POLYMARKET_HOST, CHAIN_ID + +load_dotenv() + +PRIVATE_KEY = os.getenv("PRIVATE_KEY") +POLYMARKET_PROXY_ADDRESS = os.getenv("POLYMARKET_PROXY_ADDRESS") +SIGNATURE_TYPE = os.getenv("SIGNATURE_TYPE") + +logger = logging.getLogger(__name__) + + +_client = None +_client_creds = None + + +def init_clob_client() -> ClobClient: + try: + client = ClobClient( + POLYMARKET_HOST, + key=PRIVATE_KEY, + chain_id=CHAIN_ID, + signature_type=int(SIGNATURE_TYPE), + funder=POLYMARKET_PROXY_ADDRESS, + ) + creds = client.create_or_derive_api_creds() + client.set_api_creds(creds) + logger.info("ClobClient initialized successfully") + return client, creds + except Exception as e: + logger.error(f"Failed to initialize ClobClient: {e}") + return None, None + + +def init_global_client(): + global _client, _client_creds + _client, _client_creds = init_clob_client() + + +def is_client_ready(): + return _client is not None + + +def get_client(): + if _client is None: + init_clob_client() + return _client + + +def get_client_creds(): + if _client_creds is None: + init_clob_client() + return _client_creds diff --git a/utils/clob_client_and_order.py b/utils/clob_orders.py similarity index 53% rename from utils/clob_client_and_order.py rename to utils/clob_orders.py index c411eba..1bdac02 100644 --- a/utils/clob_client_and_order.py +++ b/utils/clob_orders.py @@ -1,42 +1,19 @@ -import os import asyncio import logging -from dotenv import load_dotenv from py_clob_client.client import ClobClient from py_clob_client.clob_types import OrderArgs from py_clob_client.order_builder.constants import BUY -from config import POLYMARKET_HOST, CHAIN_ID, PROFIT_MARGIN +from config import PROFIT_MARGIN, PLACE_OPPOSITE_ORDER +from utils.clob_client import get_client -load_dotenv() - -PRIVATE_KEY = os.getenv("PRIVATE_KEY") -POLYMARKET_PROXY_ADDRESS = os.getenv("POLYMARKET_PROXY_ADDRESS") -SIGNATURE_TYPE = os.getenv("SIGNATURE_TYPE") logger = logging.getLogger(__name__) -def init_clob_client() -> ClobClient: - try: - client = ClobClient( - POLYMARKET_HOST, - key=PRIVATE_KEY, - chain_id=CHAIN_ID, - signature_type=int(SIGNATURE_TYPE), - funder=POLYMARKET_PROXY_ADDRESS, - ) - client.set_api_creds(client.create_or_derive_api_creds()) - logger.info("ClobClient initialized successfully") - return client - except Exception as e: - logger.error(f"Failed to initialize ClobClient: {e}") - return None - - async def cache_tocken_trading_infos( - client: ClobClient, order_book, ) -> None: + client = get_client() up_token_id, down_token_id = order_book.up_token_id, order_book.down_token_id client.get_tick_size(up_token_id) @@ -48,7 +25,7 @@ async def cache_tocken_trading_infos( async def place_anchor_and_hedge( - client, up_token_id, down_token_id, anchor_side, price, size=5 + up_token_id, down_token_id, anchor_side, price, size=5 ): if anchor_side == "UP": anchor_token_id = up_token_id @@ -57,15 +34,19 @@ async def place_anchor_and_hedge( anchor_token_id = down_token_id hedge_token_id = up_token_id - asyncio.create_task(place_limit_order(client, anchor_token_id, price, size)) - asyncio.create_task( - place_limit_order(client, hedge_token_id, 1 - price - PROFIT_MARGIN, size) - ) + asyncio.create_task(place_limit_order(anchor_token_id, price, size)) + if PLACE_OPPOSITE_ORDER: + asyncio.create_task( + place_limit_order(hedge_token_id, 1 - price - PROFIT_MARGIN, size) + ) - logger.info(f"Order prices: {price} and {1 - price - PROFIT_MARGIN}") + logger.info(f"Order prices: {price} and {1 - price - PROFIT_MARGIN}") + else: + logger.info(f"Order price: {price}") -async def place_limit_order(client: ClobClient, token_id: str, price: float, size: int): +async def place_limit_order(token_id: str, price: float, size: int): + client = get_client() start_time = asyncio.get_event_loop().time() try: response = client.create_and_post_order( @@ -83,3 +64,4 @@ async def place_limit_order(client: ClobClient, token_id: str, price: float, siz logger.info( f"Order placed! ID: {response['orderID']} in {end_time - start_time:.2f} sec" ) + return response["orderID"] diff --git a/utils/orderbook.py b/utils/orderbook.py index d512d32..7a5b29f 100644 --- a/utils/orderbook.py +++ b/utils/orderbook.py @@ -8,6 +8,7 @@ import threading import websocket from enum import Enum from config import POLYMARKET_WS_MARKET_URL, TRADING_BPS_THRESHOLD +from utils.clob_client import get_client logger = logging.getLogger(__name__) @@ -24,7 +25,7 @@ class OrderBook: self.down_token_id = down_token_id self.slug = slug self.ws_url = POLYMARKET_WS_MARKET_URL - self.client = None + self.client = get_client() self.orderbook = { "best_bid": 0.0,