def on_message(ws, message, drop=drop, pair=pair, high=high, deal=deal): dictionary = json.loads(message) percentoff = Decimal(drop) sessionmax = Decimal(high.getvalue()) # Uncomment this statement to debug messages: logger.debug(dictionary) # Process "type": "update" messages with events only. if 'update' in dictionary['type']: if dictionary['events'] != []: events = dictionary['events'] # Process "type": "trade" events for latest price. for event in events: if event['type'] == 'trade': last = Decimal(event["price"]) if last.compare(Decimal(sessionmax)) == 1: sessionmax = last high.setvalue(last) # Calculate movement away from high [if any]. move = 100 * (sessionmax - last) / sessionmax # Display impact of event information received. logger.info( f'{move:.2f}% off highs [{sessionmax}] : {pair} is {last} presently : [Message ID: {dictionary["socket_sequence"]}].' ) # Define bargain (sale) price. sale = Decimal(sessionmax * (1 - percentoff)) # Exit loop if there's a sale. if sale.compare(last) == 1: logger.info( f'{pair} [now {last:.2f}] just went on sale [dropped below {sale:.2f}].' ) smsalert( f'There was a {percentoff*100}% drop in the price of the {pair} pair on Gemini.' ) # Update deal price. deal.setvalue(last) ws.close()
def on_message(ws, message, orderid=orderid): dictionary = json.loads(message) exitstatus = '' # Remove comment to debug with: logger.debug( dictionary ) # Check if this is an 'initial' message from Gemini. # It is actually the second message. The subscription acknowledgement is first. if dictionary == []: exitstatus = f'Order {orderid} not active.' if isinstance(dictionary, list): for listitem in dictionary: size = listitem['original_amount'] pair = listitem['symbol'].upper() rate = listitem['price'] side = listitem['side'] cost = Decimal(size) * Decimal(rate) bit0 = f'{pair} {side} order {orderid} valued at ' bit1 = f'{cost.quantize( Decimal(rate) )} {pair[3:].upper()} ' bit2 = f'[{size} {pair[:3].upper()} at {rate} {pair[3:].upper()}] was ' text = f'{bit0}{bit1}{bit2}' if listitem['order_id'] == orderid: # Exit upon receiving order cancellation message. if listitem['is_cancelled']: exitstatus = f'{text} cancelled.' if listitem['type'] == 'cancelled': exitstatus = f'{text} cancelled [reason:{listitem["reason"]}].' if listitem['type'] == 'rejected': exitstatus = f'{text} rejected.' if listitem['type'] == 'fill': # Make sure that the order was completely filled. if listitem['remaining_amount'] == '0': exitstatus = f'{text} filled.' if exitstatus: ws.close() logger.info(exitstatus) smsalert(exitstatus) poststatus.setvalue(exitstatus) bidpricing.setvalue(rate)
def askfall(pair: str, drop: str) -> None: # Define dataset class. # Purpose: Stores the offers received during the websocket connection session. dataset = [] # Construct subscription request. subscriptionrequest = f'{{"type": "subscribe","subscriptions":[{{"name":"l2","symbols":["{pair}"]}}]}}' # Construct payload. request = resourcelocator.sockserver + '/v2/marketdata' nonce = int(time.time() * 1000) payload = {'request': request, 'nonce': nonce} authenticator.authenticate(payload) # Establish websocket connection. ws = create_connection(request) ws.send(subscriptionrequest) while True: newmessage = ws.recv() dictionary = json.loads(newmessage) percentoff = Decimal(drop) # Uncomment this statement to debug messages: logger.debug(dictionary) # Process "type": "update" messages with events only. if 'l2_updates' in dictionary['type']: if dictionary['changes'] != []: changes = dictionary['changes'] # Rank asks and determine the lowest ask among the changes in the Gemini L2 update response. askranking = [ Decimal(change[1]) for change in changes if change[0] == 'sell' ] if askranking != []: minimum = min(askranking) dataset.append(minimum) # Define session maximum and average values. sessionmax = Decimal(max(dataset)) sessionavg = Decimal(statistics.mean(dataset)) # Calculate movement away from high [if any]. move = 100 * (sessionmax - minimum) / sessionmax # Determine how much the minimum deviates away from the session average. # If it deviated by more than four standard deviations, then do nothing further. # Continue at the start of the loop. deviatedby = minimum - sessionavg if len(dataset) != 1: if deviatedby.compare(4 * statistics.stdev(dataset)) == 1: logger.info( f'{move:.2f}% off highs [{sessionmax}] : {pair} is {minimum} presently. Aberration... The mean is: {sessionavg:.2f}. Dumping!' ) dataset.pop() continue # Display impact of event information received. logger.info( f'{move:.2f}% off highs [{sessionmax}] : {pair} is {minimum} presently.' ) # Define bargain (sale) price. sale = Decimal(sessionmax * (1 - percentoff)) # Exit loop and set "deal"... # Only if there's a sale (bargain) offer. if sale.compare(minimum) == 1: text = f'{pair} fell {percentoff*100}% in price. ' text = text + f'It is now {minimum:.2f} on Gemini. ' text = text + f'{sale:.2f} is a deal.' logger.info(text) smsalert(text) ws.close() break # Return value on discount only. if minimum.compare(0) == 1: return minimum else: return False
def askfall ( pair: str, drop: str ) -> None: # Define high class. # Purpose: Stores the highest ask offer reached during the websocket connection session. class High: def __init__(self, price): self.__price = price def getvalue(self): return self.__price def setvalue(self, price): self.__price = price # Define deal class. # Purpose: Stores the deal (ask) offer reached during the websocket connection session. class Deal: def __init__(self, price): self.__price = price def getvalue(self): return self.__price def setvalue(self, price): self.__price = price # Instantiate high/deal objects. high = High(0) deal = Deal(0) # Construct subscription request. subscriptionrequest = f'{{ "type": "subscribe", "channels": [{{ "name": "orderbook", "marketIds": ["{pair}"]}}] }}' # Establish websocket connection. ws = create_connection(resourcelocator.sockserver) ws.send( subscriptionrequest ) while True: newmessage = ws.recv() dictionary = json.loads( newmessage ) percentoff = Decimal( drop ) sessionmax = Decimal( high.getvalue() ) # Unncomment this statement to debug messages: logger.debug(dictionary) # Process "type": "level2OrderbookSnapshot" messages. if 'level2OrderbookSnapshot' in dictionary['type']: if dictionary['asks'] != []: asks = dictionary['asks'] # Rank bids and determine the highest bid in the orderbook from dYdX update response. askranking = [ Decimal(ask['price']) for ask in asks ] if askranking != []: minimumask = min(askranking) if minimumask.compare( Decimal(sessionmax) ) == 1 : sessionmax = minimumask high.setvalue(minimumask) # Process "type": "level2OrderbookUpdate" messages. if 'level2OrderbookUpdate' in dictionary['type']: if dictionary['changes'] != []: changes = dictionary['changes'] # Rank bids and determine the highest bid in the orderbook from dYdX update response. askranking = [ Decimal(change['price']) for change in changes if change['side'] == 'sell' ] if askranking != []: minimumask = min(askranking) if minimumask.compare( Decimal(sessionmax) ) == 1 : sessionmax = minimumask high.setvalue(minimumask) # Calculate movement away from high [if any]. move = 100 * ( sessionmax - minimumask ) / sessionmax # Display impact of event information received. logger.info( f'{move:.2f}% off highs [{sessionmax}] : {pair} is {minimumask} presently.' ) # Define bargain (sale) price. sale = Decimal( sessionmax * ( 1 - percentoff ) ) # Exit loop if there's a sale. if sale.compare( minimumask ) == 1 : logger.info( f'{pair} [now {minimumask:.2f}] just went on sale [dropped below {sale:.2f}].' ) smsalert( f'There was a {percentoff*100}% drop in the ask offer [{minimumask}] on the {pair} pair on DDEX.' ) # Update deal price. deal.setvalue(minimumask) ws.close() break # Return value on discount only. last = Decimal( deal.getvalue() ) if last.compare(0) == 1 : return last else: return False
def bidrise(pair: str, gain: str) -> None: # Define base class. # Purpose: Stores the first best bid offer of the websocket connection session. class Base: def __init__(self, price): self.__price = price def getvalue(self): return self.__price def setvalue(self, price): self.__price = price # Instantiate base object. base = Base(0) # Construct subscription request. subscriptionrequest = f'{{ "type": "subscribe", "channels": [{{ "name": "orderbook", "marketIds": ["{pair}"]}}] }}' # Establish websocket connection. ws = create_connection(resourcelocator.sockserver) ws.send(subscriptionrequest) while True: newmessage = ws.recv() dictionary = json.loads(newmessage) profitable = Decimal(gain) # Unncomment this statement to debug messages: logger.debug(dictionary) # Process "type": "level2OrderbookSnapshot" messages. if 'level2OrderbookSnapshot' in dictionary['type']: if dictionary['bids'] != []: bids = dictionary['bids'] # Rank bids and determine the highest bid in the orderbook from dYdX update response. bidranking = [Decimal(bid['price']) for bid in bids] if bidranking != []: maximumbid = max(bidranking) base.setvalue(maximumbid) # Define bargain (sale) bid offer. deal = Decimal(Decimal(base.getvalue()) * (1 + profitable)) # Process "type": "level2OrderbookUpdate" messages. if 'level2OrderbookUpdate' in dictionary['type']: if dictionary['changes'] != []: changes = dictionary['changes'] # Rank bids and determine the highest bid in the orderbook from dYdX update response. bidranking = [ Decimal(change['price']) for change in changes if change['side'] == 'buy' ] if bidranking != []: maximumbid = max(bidranking) if maximumbid.compare(deal) == 1: logger.info( f'{pair} [now {maximumbid:.2f}] just rose above {deal:.2f}.' ) smsalert( f'There was a {profitable*100}% rise in the bid offer [{maximumbid}] on the {pair} pair on DDEX.' ) ws.close() break else: # Calculate movement away from base [if any]. move = 100 * (maximumbid - base.getvalue()) / base.getvalue() # Display impact of event information received. logger.info( f'{move:.2f}% move away from [{base.getvalue()}] : {pair} is {maximumbid} presently.' ) # Return value on discount only. if maximumbid.compare(0) == 1: return maximumbid else: return False
def bidrise(pair: str, rise: str) -> None: # Define dataset class. # Purpose: Stores the offers received during the websocket connection session. dataset = [] # Construct subscription request. subscriptionrequest = f'{{"type": "subscribe","subscriptions":[{{"name":"l2","symbols":["{pair}"]}}]}}' # Construct payload. request = resourcelocator.sockserver + '/v2/marketdata' nonce = int(time.time() * 1000) payload = {'request': request, 'nonce': nonce} authenticator.authenticate(payload) # Establish websocket connection. ws = create_connection(request) ws.send(subscriptionrequest) while True: newmessage = ws.recv() dictionary = json.loads(newmessage) grossmargin = Decimal(rise) # Uncomment this statement to debug messages: logger.debug(dictionary) # Process "type": "update" messages with events only. if 'l2_updates' in dictionary['type']: if dictionary['changes'] != []: changes = dictionary['changes'] # Rank bids and determine the highest bid among the changes in the Gemini L2 update response. bidranking = [ Decimal(change[1]) for change in changes if change[0] == 'buy' ] if bidranking != []: maximum = max(bidranking) dataset.append(maximum) # Define session minimum and average values. sessionmin = Decimal(min(dataset)) sessionavg = Decimal(statistics.mean(dataset)) # Calculate movement away from cost [if any]. move = 100 * (maximum - sessionmin) / sessionmin # Determine how much the maximum deviates away from the session average. # If it deviated by more than four standard deviations, then do nothing further. # Continue at the start of the loop. deviatedby = maximum - sessionavg if len(dataset) != 1: if deviatedby.compare(4 * statistics.stdev(dataset)) == 1: logger.info( f'{move:.2f}% off lows [{sessionmin}] : {pair} is {maximum} presently. Aberration... The mean is: {sessionavg:.2f}. Dumping!' ) dataset.pop() continue # Display impact of event information received. logger.info( f'{move:.2f}% off lows [{sessionmin}] : {pair} is {maximum} presently.' ) # Define profitable (rent) price. rent = Decimal(sessionmin * (1 + grossmargin)) # Exit loop if profitable. # Return maximum bid. if maximum.compare(rent) == 1: text = f'{pair} rose {grossmargin*100}% in price. ' text = text + f'It is now {maximum:.2f} on Gemini. ' text = text + f'Selling above {rent:.2f} is profitable.' logger.info(text) smsalert(text) ws.close() break # Return value when profitable only. if maximum.compare(0) == 1: return maximum else: return False