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 self._buy_price = None self._sell_price = None self._buy = None self._sell = None self._total = 0 asyncio.create_task(self._main()) async def _main(self): self._logger.info("started") while True: pair = self._pair depth = pair.depth await depth.wait() if len(depth.bids) == 0 or len(depth.asks) == 0: continue ask = depth.asks[0][0] bid = depth.bids[0][0] enough_spread = (ask-bid) > self._epsilon*2 # calculate best amount to buy/sell pos = self._remain / self._lot - 2 buy_amount = _quad( pos) * self._lot sell_amount = _quad(-pos) * self._lot if self._sell is not None: # check current SELL order await asyncio.sleep(0.5) await self._sell.update() # get highest ask if ask == self._sell_price and abs(depth.asks[0][1]-self._sell.remain) < pair.price_unit: ask = depth.asks[1][0] if self._sell.done: amount = self._sell.amount - self._sell.remain self._remain -= amount if amount > 0: income = amount*self._sell.price self._total += income self._logger.info(f" {amount} / {income} ({self._remain} / {self._total})") self._sell = None elif abs(self._sell_price-(ask-self._epsilon)) >= pair.price_unit: await self._sell.cancel() elif enough_spread and sell_amount >= pair.order_unit: # order SELL self._sell_price = ask-self._epsilon self._sell = await self._order_sell(sell_amount) if self._buy is not None: # check current BUY order await self._buy.update() # get lowest bid if bid == self._buy_price and abs(depth.bids[0][1]-self._buy.remain) < pair.price_unit: bid = depth.bids[1][0] if self._buy.done: amount = self._buy.amount - self._buy.remain self._remain += amount if amount > 0: outgo = amount*self._buy.price self._total -= outgo self._logger.info(f" {amount} / {outgo} ({self._remain} / {self._total})") self._buy = None elif abs(self._buy_price-(bid+self._epsilon)) >= pair.price_unit: await self._buy.cancel() elif enough_spread and buy_amount > pair.order_unit: # order BUY self._buy_price = bid+self._epsilon self._buy = await self._order_buy(buy_amount) async def _order_sell(self, amount): return await self._pair.sell_limit(amount, self._sell_price, True) async def _order_buy(self, amount): return await self._pair.buy_limit(amount, self._buy_price, True) # https://kijitora-2018.hatenablog.com/entry/2018/12/23/102913 def _quad(x): if x < -1: return 1 if x <= 1: return -1/4 * (x+1)**2 + 1 return 0