async def lay_out_smart_sell_orders(self, symbol, amount, max_price, min_price, d, max_deflation_ratio, max_count): assert self.positions is not None assert symbol in self.positions assert self.positions[symbol]['amount'] > 0 a0 = self.positions[symbol]['amount'] a1 = self.mos[symbol] pr = max_price - min_price epr = max_price - max_price / d count = ((a0 * max_deflation_ratio) * pr / epr - amount) / a1 count = math.floor(min(max_count, count)) if count < 1: return a2 = amount / count exposed_amount = (a1 + a2) * (epr / pr * count) assert exposed_amount <= a0 * max_deflation_ratio p1 = max_price notify_admin('{} {} {} {} {} {} {} {}'.format(a0, a1, a2, max_price, min_price, pr, epr, count)) for i in range(count): p2 = p1 / d await self.place_stop_order(symbol, -(a1 + a2), p1, False, 111) await self.place_limit_order(symbol, a1, p2, False, 111) # log(a1 + a2, a1, p1, p2) p1 -= pr / count
async def main(cfg, data_manager, actor): bitfinex = Bitfinex() while True: log('Vulture gogo') bitfinex.reset_bf_state() try: await bitfinex.run(cfg, data_manager, actor) # except IndexError as e: # log(repr(e)) # notify_admin(repr(e)) except websockets.exceptions.ConnectionClosedError as e: log(repr(e)) notify_admin(repr(e)) except websockets.exceptions.ConnectionClosedOK as e: log(repr(e)) notify_admin(repr(e)) # except Exception as e: # log(repr(e)) # notify_admin(repr(e)) # except websockets.exceptions.IncompleteReadError as e: # log(repr(e)) # notify_admin(repr(e)) # except websockets.exceptions.ConnectionResetError as e: # log(repr(e)) # notify_admin(repr(e)) # except websockets.exceptions.CancelledError as e: # log(repr(e)) # notify_admin(repr(e)) sleep(30)
async def on_close_order(self, data): log('flowcheck', data) order = data[2] order_id = order[0] group_id = order[1] symbol = order[3] original_amount = order[7] order_type = order[8] price = order[17] if symbol in self.orders and order_id in self.orders[symbol]: del self.orders[symbol][order_id] # if order[13] != 'CANCELED': # position_amount = self.positions[symbol]['amount'] # price = self.positions[symbol]['price'] # if position_amount != 0: # await place_trailing_stop_order(websocket, symbol, -position_amount, price * 0.01) if order[13] == 'CANCELED': if order[28] == 'API>BFX': # assert symbol in self.pending_order_request # self.pending_order_request[symbol] -= 1 # log('Order canceled - pending_order_request:', self.pending_order_request[symbol]) pass else: # if order_type != 'TRAILING STOP': # if group_id != 999 and group_id != 9999: # await self.create_liquidation(symbol, price, original_amount) notify_admin('Order fulfilled: {} {} {} {}'.format( group_id, symbol, original_amount, price)) if symbol in self.positions: self.positions[symbol]['dirty'] = True
async def on_new_order(self, data): # log(data) order = data[2] order_id = order[0] group_id = order[1] symbol = order[3] amount = order[6] order_type = order[8] price = order[16] log('flowcheck', order_id, symbol, amount, price, order_type) if symbol not in self.orders: self.orders[symbol] = {} self.orders[symbol][order_id] = { 'id': order_id, 'gid': group_id, 'symbol': symbol, 'amount': amount, 'price': price, 'type': order_type } if order[28] == 'API>BFX': self.pending_order_request[symbol] -= 1 log('pending_order_request:', self.pending_order_request) if self.pending_order_request[symbol] == 0: notify_admin('New order(s) for {} complete!'.format(symbol))
def update_tradable_balance(self): res = post2('/v2/auth/r/info/margin/sym_all', {}) log(res.content) # ["error",10100,"apikey: invalid"] data = json.loads(res.content) if data[0] == "error": notify_admin(res.content) return for item in data: # log(item) self.tb[item[1]] = min(float(item[2][2]), float(item[2][3]))
async def producer_ub(self): print(self.symbols) while True: ws_ub = await websockets.connect('wss://api.upbit.com/websocket/v1' ) await ws_ub.send( json.dumps([{ "ticket": "test" }, { "format": "SIMPLE" }, { "type": "orderbook", "codes": self.symbols }, { "type": "ticker", "codes": self.symbols }])) try: while 1: data = json.loads(await ws_ub.recv()) # print(data) symbol = data['cd'].split('-') x = symbol[1] y = symbol[0] if data['ty'] == 'ticker': now = time.time() self.ub_ticker_history[x][y] = np.append( self.ub_ticker_history[x][y], [[now, data['tp']]], axis=0) # print('ub', data['tp']) # {'ty': 'ticker', 'cd': 'KRW-LTC', 'op': 107300.0, 'hp': 107650.0, 'lp': 100000.0, 'tp': 101000.0, 'pcp': 107200.0, 'atp': 1570438236.214195, 'c': 'FALL', 'cp': 6200.0, 'scp': -6200.0, 'cr': 0.0578358209, 'scr': -0.0578358209, 'ab': 'ASK', 'tv': 17.24103294, 'atv': 15105.92397352, 'tdt': '20190809', 'ttm': '171327', 'ttms': 1565370807000, 'aav': 7523.65477131, 'abv': 7582.26920221, 'h52wp': 173000.0, 'h52wdt': '2019-06-12', 'l52wp': 25040.0, 'l52wdt': '2018-12-07', 'ts': None, 'ms': 'ACTIVE', 'msfi': None, 'its': False, 'dd': None, 'mw': 'NONE', 'tms': 1565370807605, 'atp24h': 1926291918.7091465, 'atv24h': 18411.92718214, 'st': 'SNAPSHOT'} elif data['ty'] == 'orderbook': snapshot = {} snapshot['ts'] = data['tms'] / 1000 snapshot['ts_'] = time.time() snapshot['bp'] = data['obu'][0]['bp'] snapshot['ap'] = data['obu'][0]['ap'] # print('ub:', symbol, snapshot) self.ub_orderbook_history[x][y] = np.append( self.ub_orderbook_history[x][y], [[snapshot['ts'], snapshot['bp'], snapshot['ap']]], axis=0) self.snapshot = snapshot if snapshot['bp'] > 0: await self.check_transitive_arbitrage( snapshot, 1.0035, 0.3, x, y, 'KRW', 20000) except websockets.exceptions.ConnectionClosedError as e: log(repr(e)) notify_admin(repr(e)) # except Exception as e: # traceback.print_exc() # sys.exit() time.sleep(30)
async def on_update_order(self, data): log('flowcheck', data) order = data[2] order_id = order[0] # group_id = order[1] symbol = order[3] amount = order[6] order_type = order[8] price = order[16] self.orders[symbol][order_id]['amount'] = amount self.orders[symbol][order_id]['price'] = price # self.pending_order_request[symbol] -= 1 notify_admin('Order update for {} success!'.format(symbol))
async def handle_liquidations(c): notify_admin('handle_liquidations is up and running!') while True: try: pair = c.pair upbit_cancel_orders(pair) free_balances = get_free_balances() log(free_balances) if pair in free_balances: log('balance', free_balances[pair]) # await skim(pair, free_balances[pair], 1.002, 1.002) await trailing_oco(pair, free_balances[pair], c) await asyncio.sleep(1) except Exception as e: log(repr(e)) notify_admin(repr(e)) await asyncio.sleep(30)
async def place_stop_limit_orders(self, group_id, symbol, amount, ppps): assert amount != 0 if symbol in self.pending_order_request: self.pending_order_request[symbol] += len(ppps) else: self.pending_order_request[symbol] = len(ppps) for it in ppps: log(it) await self.ws.send( json.dumps([ 0, "on", 0, { "gid": group_id if group_id is not None else 0, "cid": 1234522267, "type": "STOP LIMIT", "symbol": symbol, "amount": str(amount), "price": str(it[0]), "price_aux_limit": str(it[1]) } ])) log(self.pending_order_request) notify_admin('Requested {} stop limit orders'.format(len(ppps)))
async def on_positions(self, data): if self.positions is None: self.positions = {} log(data[2]) # notify_admin(json.dumps(data[2])) # if self.positions is None: # self.positions = {} for symbol, position in self.positions.items(): position['dirty'] = True log('Previous data:', symbol, position) for position in data[2]: symbol = position[0] if position[2] == 0: if symbol in self.positions: del self.positions[symbol] log('Deleted position for', symbol) self.positions[symbol] = { 'amount': position[2], 'price': position[3], 'pl': position[6], 'plp': position[7], 'time': time.time(), 'dirty': False, 'peak_amount': position[2] } notify_admin(json.dumps(self.positions[symbol])) # await websocket.send(json.dumps({'event': 'subscribe', 'channel': 'ticker', 'symbol': position[0]})) # await normalize_liquidations(websocket, symbol) # await cancel_all_for_volatility_breakthrough_orders(symbol) self.positions = { symbol: position for symbol, position in self.positions.items() if not position['dirty'] } for symbol, position in self.positions.items(): log('Checked data:', symbol, position) notify_admin('{} {} {}'.format(symbol, position['amount'], position['price']))
async def run(self, configuration, data_manager, actor): log('gogo') notify_admin('bitfinex loop is up and running!') # send_photo_to_admin() global cfg global symbol if configuration is not None: cfg = configuration if data_manager is None: self.dm = DataManager(cfg.symbols_of_interest, cfg.candles_of_interest) else: self.dm = data_manager append_only = actor is None self.update_mos() nonce = str(int(time.time() * 10000000)) auth_string = 'AUTH' + nonce auth_sig = hmac.new(api_secret.encode(), auth_string.encode(), hashlib.sha384).hexdigest() payload = { 'event': 'auth', 'apiKey': api_key, 'authSig': auth_sig, 'authPayload': auth_string, 'authNonce': nonce } payload = json.dumps(payload) # Print JSON # log(json.dumps(payload, ensure_ascii=False, indent="\t") ) # async with websockets.connect('wss://api.bitfinex.com/ws/2', ssl=ssl_context) as websocket: async with websockets.connect( 'wss://api.bitfinex.com/ws/2') as websocket: self.ws = websocket await websocket.send(payload) # await websocket.send(json.dumps({ 'event': 'subscribe', 'channel': 'bu' })) await self.dm.subscribe(websocket) # await websocket.send(json.dumps([ # 0, # "oc", # 0, # { # "id": 20707578488 # } # ] # )) # await websocket.send(json.dumps([ # 0, # 'ou', # 0, # { # "id": 20707705570, # "price": '151.' # } # ] # )) # await place_trailing_stop_order(websocket, "tETHUSD", 0.2, 3) # await self.place_stop_order(websocket, "tETHUSD", -0.2, 130, False, None) while 1: data = json.loads(await websocket.recv()) # log(data) if isinstance(data, list): if data[1] == 'fos': None elif data[1] == 'fcs': None elif data[1] == 'fls': None elif data[1] == 'fls': None elif data[1] == 'ws': None elif data[1] == 'on' and not append_only: # log('on', data[2][3], data[2][7], data[2][16], data[2][8]) await self.on_new_order(data) elif data[1] == 'os' and not append_only: await self.on_orders(data) elif data[1] == 'ou' and not append_only: await self.on_update_order(data) elif data[1] == 'oc' and not append_only: # log('oc', data[2][3], data[2][7], data[2][16], data[2][8], data[2][13]) # log(data) await self.on_close_order(data) elif data[1] == 'te' and not append_only: log('te', data[2][1], data[2][4], data[2][5], data[2][6]) elif data[1] == 'tu' and not append_only: log('tu', data[2][1], data[2][4], data[2][5], data[2][6]) elif data[1] == 'ps' and not append_only: await self.on_positions(data) elif data[1] == 'pn' and not append_only: await self.on_position_update(data) elif data[1] == 'pu' and not append_only: await self.on_position_update(data) elif data[1] == 'pc' and not append_only: await self.on_position_update(data) elif data[1] == 'hb': None elif data[0] > 0: result = await self.dm.on_candles(data, append_only) if result[0]: symbol = result[1] if self.positions is not None: if self.orders is not None: # if symbol not in self.positions or not self.positions[symbol]['dirty']: if True: if not append_only: assert actor is not None if self.update_mos(): await actor( self, self.dm, result[1], result[2]) else: notify_admin( '{} position data dirty!'.format( symbol)) else: notify_admin('Orders not yet received!') else: notify_admin('Positions not yet received!') else: log(result) elif data[1] == 'n': # 06/13/2019 06:14:41 PM run: [0, 'n', [1560417281153, 'on-req', None, None, [None, 0, 1234522267, 'tLTCUSD', None, None, -0.6081493395007104, None, 'STOP', None, None, None, None, None, None, None, 130.99514563106794, None, 0, 0, None, None, None, 0, None, None, None, None, None, None, None, None], None, 'ERROR', 'Invalid order: not enough tradable balance for -0.6081493395007104 LTCUSD at 130.99514563106794']] log(data) if data[2][1] == 'on-req' and data[2][6] == 'ERROR': failed_order_symbol = data[2][4][3] assert failed_order_symbol in self.pending_order_request self.pending_order_request[ failed_order_symbol] -= 1 log( 'Handle order fail:', self. pending_order_request[failed_order_symbol]) notify_admin(json.dumps(data)) else: log(data) else: if 'caps' in data: None elif 'event' in data: if data['event'] == 'info': None elif data['event'] == 'subscribed': if data['channel'] == 'candles': self.dm.on_subscribed(data) elif data['channel'] == 'ticker': log('Subscribed to ticker:', data['symbol'], data['chanId']) else: log(data) else: log(data) else: log(data) sleep(0.001)