from threading import Thread import numpy as np import time from binance.spot import Spot class Volume: def __init__(self, group): self.threads = [] self.binance = Spot('', '') self.pwr = 0 self.volumes = [] self.bgt = int(time.time()) self.target_f = open(f"/mnt/pt_telemetry/{group}", "r") self.price = 0 def target(self): lines = self.target_f.readlines() for line in lines: if 'price' in line: self.price = float(eval(line.split(' price ')[1])['price']) return self.price def _process(self, market, daily_volume, left_bound, right_bound, history_mode, threshold, tight_spread, smart, smart_spread): book = market.get_info()['book'] self.price = (book['ask_price'] + book['bid_price']) / 2 bal_f = open(f"/mnt/volume_telemetry/{market.symbol[1].upper()}_{market.symbol[2].upper()}_{market.market}", "a") flush = lambda _: bal_f.flush() log = lambda name, obj: flush(bal_f.write(f'{int(time.time() * 1000)} {name} {obj}\n')) log("alert", {'op': 'start'}) price = (book['ask_price'] + book['bid_price']) / 2 counter = 0 self.step = 0.1 ** market.symbol[3] last_price = None last_day = 0 last_5m = 0 iter_len = [0] while True: bg = time.time() print(bg, flush=True) coef = 1 cd = 10 try: info = market.get_info() log('book', info['book']) log('balance', info['balance']) public_trades = market.get_new_public_trades() private_trades = market.get_new_private_trades() log('public_trades', public_trades) log('private_trades', private_trades) try: fees_res = market.get_fees() if type(fees_res) == tuple: taker_fees, maker_fees = fees_res[0], fees_res[1] log('fees', {'taker': taker_fees, 'maker': maker_fees}) else: print('not tuple fees result', fees_res) except Exception as e: print(f'exception: {e} ({market.market})') log('alert', {'op': 'stop', 'type':'fees', 'msg':f'{e}'}) return book = market.get_info()['book'] bal = market.get_info()['balance'] spread = book['ask_price'] / book['bid_price'] - 1 if spread >= 0.1: counter += 1 if counter >= 10: log('alert', {'op': 'stop', 'type':'spread'}) return time.sleep(10) continue else: counter = 0 print(f'balances: {bal['base']} {bal['quote']}') print(f'spread: {spread} {market.market}') if history_mode: cur_5m = (int(time.time()) % 86400) // 288 cur_day = int(time.time()) // 86400 if cur_day > last_day: kline_history = self.binance.klines(symbol='BTCUSDT', interval='5m', limit=289, endTime = cur_day * 86400000)[:-1] volume_1d = np.sum(float(kline[7]) for kline in kline_history) last_day = cur_day kline_5m = kline_history[:cur_5m + 1] else: volume_1d = float(self.binance.ticker_24hr(symbol='BTCUSDT')['quoteVolume']) kline_5m = self.binance.klines(symbol='BTCUSDT', interval='5m', limit=60) print(f'len: {len(kline_5m)}') pmn = np.min([float(z[4]) for z in kline_5m]) pmx = np.max([float(z[4]) for z in kline_5m]) V = daily_volume / float(volume_1d) * float(kline_5m[-2][7]) if V >= 100: mean_cd = 5 elif V >= 50: mean_cd = 10 elif V >= 25: mean_cd = 60 elif V >= 10: mean_cd = 120 else: mean_cd = 180 mean_vol = V * ((mean_cd + np.mean(iter_len)) / 300) print(np.mean(iter_len)) cd = min(120, max(1, np.random.uniform(mean_cd / 10, mean_cd * 1.9))) norm_price = (float(kline_5m[-1][4]) - pmn) / (pmx - pmn) * (right_bound - left_bound) + left_bound step_size = 0.1 ** market.symbol[3] cur_price = (book['bid_price'] + step_size) + (book['ask_price'] - book['bid_price'] - 2 * step_size) * norm_price target_price = self.target() try: print(target_price) print(f'target: {target_price} (clip inside ({target_price * (1 - threshold / 100)}; {target_price * (1 + threshold / 100)}))') cur_price = np.clip(cur_price, target_price * (1 - threshold / 100), target_price * (1 + threshold / 100)) except Exception as e: print(e) print(mean_vol) qty = min((bal['base'] * cur_price + bal['quote']) / 3, 3.5 + max(1.6, np.random.normal(mean_vol, mean_vol / 3))) / cur_price cur_price = float(f'%.{market.symbol[3]}f' % cur_price) print(f"iteration: {qty}, {cur_price}, {norm_price}") if last_price != None: if abs(cur_price / last_price - 1) >= 0.08: log('alert', {'op': 'stop'}) break cur_5m = (int(time.time()) % 86400) // 288 if cur_5m > last_5m: cur_price = last_price last_5m = cur_5m book = market.get_info()['book'] print(f'{cur_price} {book['bid_price'] + step_size} {book['ask_price'] - step_size}') print(f'{market.market} {book}') if bal['base'] < qty: if last_price == None or abs(book['ask_price'] / last_price - 1) <= 0.01: market.new_limit(book['ask_price'], qty, True) elif bal['quote'] < qty * cur_price: if last_price == None or abs(book['bid_price'] / last_price - 1) <= 0.01: market.new_limit(book['bid_price'], qty, False) else: if smart: print('doing smart') if book['ask_price'] / book['bid_price'] - 1 <= smart_spread: print('spread is ok') threads = [] threads.append(Thread(target=market.new_limit, args=(book['ask_price'], qty, True))) threads[-1].start() threads.append(Thread(target=market.new_limit, args=(book['bid_price'], qty, False))) threads[-1].start() for t in threads: t.join() elif cur_price <= book['ask_price'] - step_size / 2 and cur_price >= book['bid_price'] + step_size / 2: last_price = cur_price print(f"proceeding {type(market)}") # log('info', f'{{"price": {cur_price}, "quantity": {qty}, "book": {book}}}') threads = [] if np.random.randint(0, 2): threads.append(Thread(target=market.new_limit, args=(cur_price, qty, False))) threads[-1].start() threads.append(Thread(target=market.new_limit, args=(cur_price, qty, True))) threads[-1].start() else: threads.append(Thread(target=market.new_limit, args=(cur_price, qty, True))) threads[-1].start() threads.append(Thread(target=market.new_limit, args=(cur_price, qty, False))) threads[-1].start() for t in threads: t.join() elif tight_spread: print(f"tight {type(market)}") qty /= 2 qty = max(qty, 6 / cur_price) # log('info', f'{{"price": {cur_price}, "quantity": {qty}, "book": {book}}}') threads = [] if last_price != None and last_price > book['ask_price']: is_buy = True else: is_buy = False tp = self.target() print(qty) print(book['ask_price']) is_buy = (tp >= book['ask_price']) if is_buy: print('buying in tight') threads.append(Thread(target=market.new_limit, args=(book['ask_price'], qty, True))) threads[-1].start() else: print('selling in tight') threads.append(Thread(target=market.new_limit, args=(book['bid_price'], qty, False))) threads[-1].start() for t in threads: t.join() last_price = cur_price except Exception as e: print(f'exception: {e} ({market.market})') try: market.cancel_open_orders() except Exception as e: print(f'exception cancel: {e} ({market.market})') finally: if len(iter_len) == 100: iter_len = iter_len[1:] iter_len.append(time.time() - bg) time.sleep(cd) def add_market(self, market, daily_volume, left_bound=1/4, right_bound=3/4, history_mode=False, threshold=1.5, tight_spread=False, smart_daily_volume=0, smart_spread_size=2): daily_volume = float(daily_volume) left_bound = float(left_bound) right_bound = float(right_bound) threshold = float(threshold) if threshold < 0: threshold = None if smart_daily_volume: self.threads.append(Thread(target=self._process, args=(market, smart_daily_volume / 2, left_bound, right_bound, history_mode, threshold, tight_spread, True, smart_spread_size))) self.threads.append(Thread(target=self._process, args=(market, daily_volume, left_bound, right_bound, history_mode, threshold, tight_spread, False, 0))) def run_event_loop(self): for thread in self.threads: thread.start() for thread in self.threads: thread.join()