import asyncio class MM: def __init__(self, logger, pair, lot, epsilon): self._logger = logger self._pair = pair self._lot = lot self._remain = 0 self._epsilon = epsilon asyncio.create_task(self._main()) async def _main(self): self._logger.info("started") while True: depth = self._pair.depth await depth.wait() if len(depth.bids) == 0 or len(depth.asks) == 0: continue spread = depth.asks[0][0] - depth.bids[0][0] if spread > self._epsilon*2: sell_price = depth.asks[0][0]-self._epsilon buy_price = depth.bids[0][0]+self._epsilon await self._make(sell_price, buy_price) async def _make(self, sell_price, buy_price): if self._remain < self._epsilon/buy_price: amount = self._lot/buy_price try: buy = await self._pair.buy_limit(amount, buy_price, True) except Exception: buy = None try: sell = await self._pair.sell_limit(amount, sell_price, True) except Exception: sell = None else: buy = None try: sell = await self._pair.sell_limit(self._remain, sell_price, True) except Exception: sell = None while (sell is not None) or (buy is not None): await asyncio.sleep(1) try: coro = [] if buy is not None: coro.append(buy .update()) if sell is not None: coro.append(sell.update()) await asyncio.gather(*coro) except Exception as e: continue depth = self._pair.depth if sell is not None: if sell.done: self._remain -= sell.amount-sell.remain sell = None elif sell_price > depth.asks[0][0]: break if buy is not None: if buy.done: self._remain += buy.amount-buy.remain buy = None elif buy_price < depth.bids[0][0]: break async def cancel(self, order, flag): while True: try: await asyncio.sleep(1) await order.cancel() await order.update() break except Exception: continue self._remain += flag*(order.amount-order.remain) coro = [] if sell is not None: coro.append(cancel(self, sell, -1)) if buy is not None: coro.append(cancel(self, buy, 1)) await asyncio.gather(*coro)