tmm/logic/ma_cross.py
2022-07-15 19:17:55 +09:00

85 lines
2.5 KiB
Python

import asyncio
SHORT_PERIOD = 13
LONG_PERIOD = 200
EXPECT_CYCLE_DUR_IN_CANDLE_INTERVALS = 5
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