75 lines
1.9 KiB
Python
75 lines
1.9 KiB
Python
|
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
|