pythontradingbitmex

What is the best way to repeatedly execute a function in Python?


I am trying to pull some data from a website. The issue I am having is that it pulls the data value and then goes on to just reprint it continuously rather than pull the most recent live data value and update that. I got the code from https://github.com/BitMEX/api-connectors/tree/master/official-ws/python and made a few changes.

from bitmex_websocket import BitMEXWebsocket
import logging
from time import sleep

# Basic use of websocket.
def run():
    logger = setup_logger()

    # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret.
    ws = BitMEXWebsocket(endpoint="https://www.bitmex.com/api/v1", symbol="XBTUSD",
                         api_key=None, api_secret=None)

    logger.info("Instrument data: %s" % ws.get_instrument())

    # Run forever
    while(ws.ws.sock.connected):
        logger.info("Ticker: %s" % ws.get_ticker())
        if ws.api_key:
            logger.info("Funds: %s" % ws.funds())
        #logger.info("Market Depth: %s" % ws.market_depth())
        (logger.info("Recent Trades: %s\n\n" % ws.recent_trades()[0]["size"]))
        sleep(1)


def setup_logger():
    # Prints logger info to terminal
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)  # Change this to DEBUG if you want a lot more info
    ch = logging.StreamHandler()
    # create formatter
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    # add formatter to ch
    ch.setFormatter(formatter)
    logger.addHandler(ch)
    return logger


if __name__ == "__main__":
    run()

Solution

  • The issue is that your ws.get_ticker() call inside the while loop is not actually getting updated values.

    From: https://github.com/BitMEX/api-connectors/blob/febf95659ccd2aa5445e0178c4dbb008d1ae9286/official-ws/python/bitmex_websocket.py#L70

        def get_ticker(self):
            '''Return a ticker object. Generated from quote and trade.'''
            lastQuote = self.data['quote'][-1] # <--SEE HERE. It's just getting the
            lastTrade = self.data['trade'][-1] # information from when the ticker was
                                               # first established.
            ticker = {
                "last": lastTrade['price'],
                "buy": lastQuote['bidPrice'],
                "sell": lastQuote['askPrice'],
                "mid": (float(lastQuote['bidPrice'] or 0) + float(lastQuote['askPrice'] or 0)) / 2
            }
    
            # The instrument has a tickSize. Use it to round values.
            instrument = self.data['instrument'][0]
            return {k: round(float(v or 0), instrument['tickLog']) for k, v in ticker.items()}
    

    See my comments where lastQuote and lastTrade are defined. You should re-create ws after each loop. You'll have to change the condition in your while loop to while True if you want to do it forever.

    from bitmex_websocket import BitMEXWebsocket
    import logging
    from time import sleep
    
    # Basic use of websocket.
    def run():
        logger = setup_logger()
    
    
    
    
        logger.info("Instrument data: %s" % ws.get_instrument())
    
        # Run forever    
        while True:
            # Instantiating the WS will make it connect. Be sure to add your api_key/api_secret.
            ws = BitMEXWebsocket(endpoint="https://www.bitmex.com/api/v1", symbol="XBTUSD",
                                 api_key=None, api_secret=None)
            logger.info("Ticker: %s" % ws.get_ticker())
            if ws.api_key:
                logger.info("Funds: %s" % ws.funds())
            #logger.info("Market Depth: %s" % ws.market_depth())
            (logger.info("Recent Trades: %s\n\n" % ws.recent_trades()[0]["size"]))
            ws.exit()
            sleep(1)
    
    
    def setup_logger():
        # Prints logger info to terminal
        logger = logging.getLogger()
        logger.setLevel(logging.INFO)  # Change this to DEBUG if you want a lot more info
        ch = logging.StreamHandler()
        # create formatter
        formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        # add formatter to ch
        ch.setFormatter(formatter)
        logger.addHandler(ch)
        return logger
    
    
    if __name__ == "__main__":
        run()
    

    EDIT: Added call to ws.exit() in the while loop to gracefully close ws before opening a new one.