import asyncio import datetime MAX_CANDLES = 200 OPEN = 0 HIGH = 0 LOW = 0 CLOSE = 0 class Candlestick: def __init__(self, ticker, interval): self.values = [] self.latest = None self.interval = interval self._ticker = ticker self._event = asyncio.Event() asyncio.create_task(self._refresh_and_start()) async def _refresh_and_start(self): self.values = await self._fetch(datetime.datetime.now(tz=datetime.timezone.utc)) asyncio.create_task(self._ticker_watcher()) asyncio.create_task(self._main()) async def _fetch(self, data, depth = 0, rem = MAX_CANDLES): assert(False) async def _ticker_watcher(self): while True: await self._ticker.wait() v = self._ticker.price if self.latest is None: self.latest = [v, -1e100, 1e100, None] self.latest[1] = max(self.latest[1], v) self.latest[2] = min(self.latest[2], v) self.latest[3] = v async def _main(self): while True: await asyncio.sleep(self.interval) if self.latest is None: if len(self.values) == 0: continue self.latest = self.values[0] n = min(MAX_CANDLES-1, len(self.values)) self.values = [self.latest, *self.values[0:n]] self.latest = None self._event.set() self._event.clear() async def wait(self): await self._event.wait() def SMA(self, period, offset=0, type = CLOSE): sum = 0 end = min(period+offset, len(self.values)) for i in range(offset, end): sum += self.values[i][type] return sum / (end - offset) def EMA(self, period, offset=0, type = CLOSE): end = min(period+offset, len(self.values)) n = end - offset ret = 0 for i in range(offset, end): ret += self.values[i][type] ret /= n for i in range(offset, end): ret += (2/(n+1)) * (self.values[i][type] - ret) return ret