import asyncio SHORT_PERIOD = 13 LONG_PERIOD = 200 EXPECT_CYCLE_DUR_IN_CANDLE_INTERVALS = 10 class MA_Cross: def __init__(self, logger, pair, candlestick, lot, limit_rate, stop_rate): self._logger = logger self._pair = pair self._candlestick = candlestick self._lot = lot self._limit_rate = limit_rate self._stop_rate = stop_rate asyncio.create_task(self._main()) async def _main(self): self._logger.info("started") while True: await self._candlestick.wait() if len(self._candlestick.values) < LONG_PERIOD: continue short = self._candlestick.SMA(SHORT_PERIOD) long = self._candlestick.SMA(LONG_PERIOD) plong = self._candlestick.SMA(LONG_PERIOD, 1) expect_sell = self._pair.ticker.buy * (1+self._limit_rate) ask_volume = self._pair.depth.askVolumeUntil(expect_sell) interval_volume = self._pair.ticker.volume / 24 / 3600 * self._candlestick.interval if plong < long and short > long: if ask_volume < interval_volume * EXPECT_CYCLE_DUR_IN_CANDLE_INTERVALS: await self._buy() async def _buy(self): self._logger.info("buy signal received") # buy (market) and sell (limit) amount = self._lot/self._pair.ticker.buy try: buy = await self._pair.buy_market(amount) except Exception as e: self._logger.warn("failed to buy", e) return while not buy.done: await asyncio.sleep(0.1) await buy.update() self._logger.info(f"BUY confirmed (+{amount} / -{buy.price*amount})") limit_price = buy.price*(1+self._limit_rate) stop_price = buy.price*(1-self._stop_rate) try: stop = await self._pair.sell_stop(amount, stop_price) limit = await self._pair.sell_limit(amount, limit_price) except Exception as e: print("failed to order", e.message) self._logger.error("FAILED TO ORDER for STOPPING and LIMITATION!!") return self._logger.debug("waiting for STOP or LIMIT") while (not stop.done) and (not limit.done): await asyncio.sleep(2) try: await asyncio.gather(limit.update(), stop.update()) except Exception: continue if stop.done: self._logger.info(f"STOP confirmed (-{amount} / +{stop.price*amount})") # cancel limit and cooldown await asyncio.gather(asycio.sleep(5), limit.cancel()) return if limit.done: self._logger.info(f"LIMIT confirmed (-{amount} / +{limit.price*amount})") await stop.cancel() return