Refactor main function and related methods to remove async/await, replacing with synchronous calls for improved performance and simplicity
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import gc
|
import gc
|
||||||
import asyncio
|
import time
|
||||||
from utils.logger import setup_logging
|
from utils.logger import setup_logging
|
||||||
from utils.tokens import fetch_tokens
|
from utils.tokens import fetch_tokens
|
||||||
from utils.orderbook import OrderBook, SIGNALES
|
from utils.orderbook import OrderBook, SIGNALES
|
||||||
@@ -22,21 +22,21 @@ from config import (
|
|||||||
gc.disable()
|
gc.disable()
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
def main():
|
||||||
|
|
||||||
logger = setup_logging()
|
logger = setup_logging()
|
||||||
set_cpu_affinity()
|
set_cpu_affinity()
|
||||||
logger.info("Polymarket HFT Market Maker started")
|
logger.info("Polymarket HFT Market Maker started")
|
||||||
init_global_client()
|
init_global_client()
|
||||||
await asyncio.sleep(2)
|
time.sleep(2)
|
||||||
if not is_client_ready():
|
if not is_client_ready():
|
||||||
logger.error("ClobClient is not ready. Exiting.")
|
logger.error("ClobClient is not ready. Exiting.")
|
||||||
return
|
return
|
||||||
up_token, down_token, market_slug = await fetch_tokens()
|
up_token, down_token, market_slug = fetch_tokens()
|
||||||
book = OrderBook(up_token, down_token, market_slug)
|
book = OrderBook(up_token, down_token, market_slug)
|
||||||
book.start()
|
book.start()
|
||||||
|
|
||||||
await asyncio.sleep(5) # Allow some time for initial order book data
|
time.sleep(5) # Allow some time for initial order book data
|
||||||
|
|
||||||
market_data = book.get_current_market_data()
|
market_data = book.get_current_market_data()
|
||||||
|
|
||||||
@@ -56,11 +56,11 @@ async def main():
|
|||||||
book.stop()
|
book.stop()
|
||||||
logger.info("Trading session ended. Starting new session.")
|
logger.info("Trading session ended. Starting new session.")
|
||||||
gc.collect()
|
gc.collect()
|
||||||
await asyncio.sleep(10)
|
time.sleep(10)
|
||||||
reset_trades()
|
reset_trades()
|
||||||
up_token, down_token, market_slug = await fetch_tokens()
|
up_token, down_token, market_slug = fetch_tokens()
|
||||||
book = OrderBook(up_token, down_token, market_slug)
|
book = OrderBook(up_token, down_token, market_slug)
|
||||||
asyncio.create_task(cache_token_trading_infos(book))
|
cache_token_trading_infos(book)
|
||||||
book.start()
|
book.start()
|
||||||
|
|
||||||
market_data = book.get_current_market_data()
|
market_data = book.get_current_market_data()
|
||||||
@@ -84,7 +84,7 @@ async def main():
|
|||||||
trading_side = book.last_signal
|
trading_side = book.last_signal
|
||||||
|
|
||||||
if (trading_side == SIGNALES.UP) and not up_trend:
|
if (trading_side == SIGNALES.UP) and not up_trend:
|
||||||
await place_anchor_and_hedge(
|
order_ids = place_anchor_and_hedge(
|
||||||
up_token,
|
up_token,
|
||||||
down_token,
|
down_token,
|
||||||
"UP",
|
"UP",
|
||||||
@@ -94,12 +94,12 @@ async def main():
|
|||||||
)
|
)
|
||||||
current_trades = increment_trades()
|
current_trades = increment_trades()
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Placed UP anchor and hedge orders. Total trades: {current_trades}"
|
f"Placed UP anchor and hedge orders. Total trades: {current_trades}, Order IDs: {order_ids}"
|
||||||
)
|
)
|
||||||
await asyncio.sleep(MIN_DELAY_BETWEEN_TRADES_SECONDS)
|
time.sleep(MIN_DELAY_BETWEEN_TRADES_SECONDS)
|
||||||
|
|
||||||
elif (trading_side == SIGNALES.DOWN) and up_trend:
|
elif (trading_side == SIGNALES.DOWN) and up_trend:
|
||||||
await place_anchor_and_hedge(
|
order_ids = place_anchor_and_hedge(
|
||||||
up_token,
|
up_token,
|
||||||
down_token,
|
down_token,
|
||||||
"DOWN",
|
"DOWN",
|
||||||
@@ -109,21 +109,16 @@ async def main():
|
|||||||
)
|
)
|
||||||
current_trades = increment_trades()
|
current_trades = increment_trades()
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Placed DOWN anchor and hedge orders. Total trades: {current_trades}"
|
f"Placed DOWN anchor and hedge orders. Total trades: {current_trades}, Order IDs: {order_ids}"
|
||||||
)
|
)
|
||||||
await asyncio.sleep(MIN_DELAY_BETWEEN_TRADES_SECONDS)
|
time.sleep(MIN_DELAY_BETWEEN_TRADES_SECONDS)
|
||||||
|
|
||||||
await asyncio.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
if os.name == "nt":
|
main()
|
||||||
asyncio.run(main())
|
|
||||||
else:
|
|
||||||
import uvloop
|
|
||||||
|
|
||||||
uvloop.run(main())
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\nMarket maker stopped by user")
|
print("\nMarket maker stopped by user")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import asyncio
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
import time
|
||||||
|
|
||||||
|
async def test():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
|
times = []
|
||||||
|
|
||||||
|
for _ in range(1000):
|
||||||
|
start = time.time()
|
||||||
|
with ThreadPoolExecutor(max_workers=2) as executor:
|
||||||
|
tasks = [
|
||||||
|
loop.run_in_executor(executor, test),
|
||||||
|
loop.run_in_executor(
|
||||||
|
executor,
|
||||||
|
test,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
await asyncio.gather(*tasks)
|
||||||
|
|
||||||
|
end = time.time()
|
||||||
|
times.append(end - start)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sum(times)
|
||||||
+21
-27
@@ -12,7 +12,7 @@ from utils.trade_counter import decrement_trades
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
async def cache_token_trading_infos(
|
def cache_token_trading_infos(
|
||||||
order_book,
|
order_book,
|
||||||
) -> None:
|
) -> None:
|
||||||
client = get_client()
|
client = get_client()
|
||||||
@@ -26,7 +26,7 @@ async def cache_token_trading_infos(
|
|||||||
client.get_fee_rate_bps(down_token_id)
|
client.get_fee_rate_bps(down_token_id)
|
||||||
|
|
||||||
|
|
||||||
async def place_anchor_and_hedge(
|
def place_anchor_and_hedge(
|
||||||
up_token_id, down_token_id, anchor_side, price, size=5, signed_orders_cache=None
|
up_token_id, down_token_id, anchor_side, price, size=5, signed_orders_cache=None
|
||||||
):
|
):
|
||||||
if anchor_side == "UP":
|
if anchor_side == "UP":
|
||||||
@@ -36,31 +36,29 @@ async def place_anchor_and_hedge(
|
|||||||
anchor_token_id = down_token_id
|
anchor_token_id = down_token_id
|
||||||
hedge_token_id = up_token_id
|
hedge_token_id = up_token_id
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
with ThreadPoolExecutor(max_workers=2) as executor:
|
with ThreadPoolExecutor(max_workers=2) as executor:
|
||||||
tasks = [
|
future1 = executor.submit(
|
||||||
loop.run_in_executor(
|
place_limit_order_sync,
|
||||||
executor,
|
anchor_token_id,
|
||||||
place_limit_order_sync,
|
price,
|
||||||
anchor_token_id,
|
size,
|
||||||
price,
|
signed_orders_cache,
|
||||||
size,
|
)
|
||||||
signed_orders_cache,
|
future2 = executor.submit(
|
||||||
),
|
place_limit_order_sync,
|
||||||
loop.run_in_executor(
|
hedge_token_id,
|
||||||
executor,
|
round(1 - price - PROFIT_MARGIN, 2),
|
||||||
place_limit_order_sync,
|
size,
|
||||||
hedge_token_id,
|
signed_orders_cache,
|
||||||
round(1 - price - PROFIT_MARGIN, 2),
|
)
|
||||||
size,
|
|
||||||
signed_orders_cache,
|
# Wait for both to complete
|
||||||
),
|
order_ids = [future1.result(), future2.result()]
|
||||||
]
|
|
||||||
order_ids = await asyncio.gather(*tasks)
|
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Placed anchor and hedge orders: Anchor Token ID={anchor_token_id}, Hedge Token ID={hedge_token_id}, Order IDs={order_ids}"
|
f"Placed anchor and hedge orders: Anchor Token ID={anchor_token_id}, Hedge Token ID={hedge_token_id}, Order IDs={order_ids}"
|
||||||
)
|
)
|
||||||
|
return order_ids
|
||||||
|
|
||||||
|
|
||||||
def place_limit_order_sync(
|
def place_limit_order_sync(
|
||||||
@@ -93,8 +91,4 @@ def place_limit_order_sync(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def place_limit_order(
|
|
||||||
token_id: str, price: float, size: int = 5, signed_orders_cache=None
|
|
||||||
) -> str:
|
|
||||||
"""Async wrapper for backwards compatibility"""
|
|
||||||
return place_limit_order_sync(token_id, price, size, signed_orders_cache)
|
|
||||||
|
|||||||
+5
-6
@@ -1,5 +1,4 @@
|
|||||||
import os
|
import os
|
||||||
import asyncio
|
|
||||||
import bisect
|
import bisect
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
@@ -110,7 +109,7 @@ class OrderBook:
|
|||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
self.monitoring_thread = threading.Thread(
|
self.monitoring_thread = threading.Thread(
|
||||||
target=lambda: asyncio.run(self._continuous_trading_monitor()), daemon=True
|
target=self._continuous_trading_monitor, daemon=True
|
||||||
)
|
)
|
||||||
self.monitoring_thread.start()
|
self.monitoring_thread.start()
|
||||||
|
|
||||||
@@ -182,14 +181,14 @@ class OrderBook:
|
|||||||
"asks": asks,
|
"asks": asks,
|
||||||
}
|
}
|
||||||
|
|
||||||
async def _continuous_trading_monitor(self):
|
def _continuous_trading_monitor(self):
|
||||||
logger.info("Started continuous trading monitor")
|
logger.info("Started continuous trading monitor")
|
||||||
|
|
||||||
while self.monitoring_running:
|
while self.monitoring_running:
|
||||||
try:
|
try:
|
||||||
market_data = self.get_current_market_data()
|
market_data = self.get_current_market_data()
|
||||||
if not market_data:
|
if not market_data:
|
||||||
await asyncio.sleep(0.1)
|
time.sleep(0.1)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
micro_vs_mid_bps = market_data["micro_vs_mid_bps"]
|
micro_vs_mid_bps = market_data["micro_vs_mid_bps"]
|
||||||
@@ -205,11 +204,11 @@ class OrderBook:
|
|||||||
if current_signal and current_signal != self.last_signal:
|
if current_signal and current_signal != self.last_signal:
|
||||||
self.last_signal = current_signal
|
self.last_signal = current_signal
|
||||||
|
|
||||||
await asyncio.sleep(0.005)
|
time.sleep(0.005)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in continuous trading monitor: {e}")
|
logger.error(f"Error in continuous trading monitor: {e}")
|
||||||
await asyncio.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
logger.info("Stopped continuous trading monitor")
|
logger.info("Stopped continuous trading monitor")
|
||||||
|
|
||||||
|
|||||||
+9
-12
@@ -2,7 +2,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
from multiprocessing.util import get_logger
|
from multiprocessing.util import get_logger
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
import aiohttp
|
import requests
|
||||||
from .slug import get_market_slug
|
from .slug import get_market_slug
|
||||||
from config import GAMMA_API_URL, REQUEST_TIMEOUT
|
from config import GAMMA_API_URL, REQUEST_TIMEOUT
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ from config import GAMMA_API_URL, REQUEST_TIMEOUT
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
async def fetch_tokens(
|
def fetch_tokens(
|
||||||
coin: str = "btc",
|
coin: str = "btc",
|
||||||
) -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
) -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
||||||
|
|
||||||
@@ -21,17 +21,14 @@ async def fetch_tokens(
|
|||||||
slug = get_market_slug(coin)
|
slug = get_market_slug(coin)
|
||||||
url = f"{GAMMA_API_URL}/events/slug/{slug}"
|
url = f"{GAMMA_API_URL}/events/slug/{slug}"
|
||||||
|
|
||||||
async with aiohttp.ClientSession() as session:
|
response = requests.get(url, timeout=REQUEST_TIMEOUT)
|
||||||
async with session.get(
|
if response.status_code == 200:
|
||||||
url, timeout=aiohttp.ClientTimeout(total=REQUEST_TIMEOUT)
|
data = response.json()
|
||||||
) as response:
|
return _extract_tokens(data, slug)
|
||||||
if response.status == 200:
|
else:
|
||||||
data = await response.json()
|
logger.warning(f"API request failed with status {response.status_code}")
|
||||||
return _extract_tokens(data, slug)
|
|
||||||
else:
|
|
||||||
logger.warning(f"API request failed with status {response.status}")
|
|
||||||
|
|
||||||
except aiohttp.ClientError as e:
|
except requests.exceptions.RequestException as e:
|
||||||
logger.error(f"Network error fetching tokens: {e}")
|
logger.error(f"Network error fetching tokens: {e}")
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
logger.error(f"Invalid JSON response: {e}")
|
logger.error(f"Invalid JSON response: {e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user