Exemplo n.º 1
0
 def run(self, hub, message):
     connection = Connection(self.url, self.session)
     connection.start()
     # get hub
     hub = connection.hub(hub)
     hub.server.invoke('send_message', message)
     connection.close()
Exemplo n.º 2
0
    def request_order_book(self):
        try:
            with Session() as session:
                connection = Connection(self.url, session)
                self.hub = connection.register_hub(self.hub_name)

                connection.received += self.on_receive

                connection.start()

                while self.order_book_is_received is not True:
                    self.hub.server.invoke(
                        BittrexParameters.QUERY_EXCHANGE_STATE, self.pair_name)
                    connection.wait(
                        5
                    )  # otherwise it shoot thousands of query and we will be banned :(

                connection.close()

                msg = "Got orderbook for Bittrex!"
                log_to_file(msg, SOCKET_ERRORS_LOG_FILE_NAME)
                print(msg)

                return STATUS.SUCCESS

        except Exception as e:
            # log_error_on_receive_from_socket("Bittrex", e)
            msg = "Error during order book retrieval for Bittrex {}".format(
                str(e))
            log_to_file(msg, SOCKET_ERRORS_LOG_FILE_NAME)
            print(msg)

        return STATUS.FAILURE
Exemplo n.º 3
0
 def run(self, hub, message):
     connection = Connection(self.url, self.session)
     connection.start()
     # get hub
     hub = connection.hub(hub)
     hub.server.invoke('send_message', message)
     connection.close()
Exemplo n.º 4
0
 def get_value(self, hub, method):
     self.res = {}
     with Session() as session:
         #create a connection
         connection = Connection(self.url, session)
         chat = connection.register_hub(hub)
         chat.client.on(method, self.update_res)
         connection.start()
         connection.wait(3)
         connection.close()
         return self.res
class SignalRHubSensor(Sensor):
    def __init__(self, sensor_service, config=None):
        super(SignalRHubSensor, self).__init__(sensor_service=sensor_service,
                                               config=config)
        self._logger = self._sensor_service.get_logger(__name__)
        self.url = config['hub_url']
        self.hub_name = config['hub_name']
        self._trigger_ref = 'signalr.message_received'
        self._hub = None
        self.connection = None
        self.session = None

    def setup(self):
        self.connection = Connection(self.url, self.session)
        # start a connection
        self.connection.start()
        # add a handler to process notifications to the connection
        self.connection.handlers += \
            lambda data: self._logger.debug(
                'Connection: new notification - %s' % data)
        # get hub
        self._hub = self.connection.hub(self.hub_name)

    def message_received(self, message):
        self._logger.debug('Connection: new notification.' % message)
        self._sensor_service.dispatch(trigger=self._trigger_ref,
                                      payload={message: message})

    def run(self):
        self._hub.client.on('message_received',
                            SignalRHubSensor.message_received)

    def cleanup(self):
        # do not receive new messages
        self._hub.client.off('message_received', self.message_received)
        self.connection.close()
class SignalRHubSensor(Sensor):
    def __init__(self, sensor_service, config=None):
        super(SignalRHubSensor, self).__init__(sensor_service=sensor_service,
                                               config=config)
        self._logger = self._sensor_service.get_logger(__name__)
        self.url = config['hub_url']
        self.hub_name = config['hub_name']
        self._trigger_ref = 'signalr.message_received'
        self._hub = None
        self.connection = None
        self.session = None

    def setup(self):
        self.connection = Connection(self.url, self.session)
        # start a connection
        self.connection.start()
        # add a handler to process notifications to the connection
        self.connection.handlers += \
            lambda data: self._logger.debug(
                'Connection: new notification - %s' % data)
        # get hub
        self._hub = self.connection.hub(self.hub_name)

    def message_received(self, message):
        self._logger.debug('Connection: new notification.' % message)
        self._sensor_service.dispatch(trigger=self._trigger_ref,
                                      payload={message: message})

    def run(self):
        self._hub.client.on('message_received',
                            SignalRHubSensor.message_received)

    def cleanup(self):
        # do not receive new messages
        self._hub.client.off('message_received', self.message_received)
        self.connection.close()
Exemplo n.º 7
0
class OnlineSignalR(OnlineCore):

    __worker_thread = None
    __worker_thread_event = None

    __personal_portfolio_queue_lock = Lock()
    __personal_portfolio_queue = []
    __securities_options_repos_queue_lock = Lock()
    __securities_options_repos_queue = []
    __order_book_queue_lock = Lock()
    __order_book_queue = []

    def __init__(self,
                 auth,
                 on_open=None,
                 on_personal_portfolio=None,
                 on_securities=None,
                 on_options=None,
                 on_repos=None,
                 on_order_book=None,
                 on_error=None,
                 on_close=None,
                 proxy_url=None):
        """
        Class constructor.

        Parameters
        ----------
        auth : home_broker_session
            An object with the authentication information.
        on_open : function(), optional
            Callable object which is called at opening the signalR connection.
            This function has no argument.
        on_personal_portfolio : function(quotes), optional
            Callable object which is called when personal portfolio data is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_securities : function(quotes), optional
            Callable object which is called when security data is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_options : function(quotes), optional
            Callable object which is called when options data is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_repos : function(quotes), optional
            Callable object which is called when repo data is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_order_book : function(quotes), optional
            Callable object which is called when the order book data (level 2) is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_error : function(exception, connection_lost), optional
            Callable object which is called when we get error.
            This function has 2 arguments.
                The 1st argument is the exception object.
                The 2nd argument is if the connection was lost due to the error.
        on_close : function(), optional
            Callable object which is called when closed the connection.
            This function has no argument.
        proxy_url : str, optional
            The proxy URL with one of the following formats:
                - scheme://user:pass@hostname:port
                - scheme://user:pass@ip:port
                - scheme://hostname:port
                - scheme://ip:port

            Ex. https://john:[email protected]:3128
        """

        self._proxies = {
            'http': proxy_url,
            'https': proxy_url
        } if proxy_url else None
        self._auth = auth
        self._on_open = on_open
        self._on_personal_portfolio = on_personal_portfolio
        self._on_securities = on_securities
        self._on_options = on_options
        self._on_repos = on_repos
        self._on_order_book = on_order_book
        self._on_error = on_error
        self._on_close = on_close

        self._connection = None
        self._hub = None

        self.is_connected = False

########################
#### PUBLIC METHODS ####
########################

    def connect(self):
        """
        Connects to the signalR server.

        Raises
        ------
        pyhomebroker.exceptions.SessionException
            If the user is not logged in.
        """

        if not self._auth.is_user_logged_in:
            raise SessionException('User is not logged in')

        url = '{}/signalr/hubs'.format(self._auth.broker['page'])

        with rq.Session() as session:
            rq.utils.add_dict_to_cookiejar(session.cookies, self._auth.cookies)

            if self._proxies:
                session.proxies.update(self._proxies)

            session.headers = {'User-Agent': user_agent}

            self._connection = Connection(url, session)
            self._hub = self._connection.register_hub('stockpriceshub')

            self._hub.client.on('broadcast',
                                self.__internal_securities_options_repos)

            self._hub.client.on('sendStartStockFavoritos',
                                self.__internal_personal_portfolio)
            self._hub.client.on('sendStockFavoritos',
                                self.__internal_personal_portfolio)

            self._hub.client.on('sendStartStockPuntas',
                                self.__internal_order_book)
            self._hub.client.on('sendStockPuntas', self.__internal_order_book)

            if self._on_error:
                self._connection.error += self._on_error

            self._connection.exception += self.__on_internal_exception
            self._connection.start()

            self.is_connected = self._connection.is_open

            if self.is_connected and self._on_open:
                self._on_open()

                self.__worker_thread_event = Event()
                self.__worker_thread = Thread(target=self.__worker_thread_run)
                self.__worker_thread.start()

    def disconnect(self):
        """
        Disconnects from the signalR server.

        Raises
        ------
        pyhomebroker.exceptions.SessionException
            If the user is not logged in.
            If the connection or hub is not assigned.
        """

        if not self._auth.is_user_logged_in:
            raise SessionException('User is not logged in')

        if not self._connection or not self._hub:
            raise SessionException('Connection or hub is not assigned')

        if self._connection.is_open:
            self._connection.close()

        self._connection = None
        self._hub = None

        self.is_connected = False

        if self._on_close:
            self._on_close()

        self.__worker_thread_stop()

    def join_group(self, group_name):
        """
        Subscribe to a group to start receiving event notifications.

        Raises
        ------
        pyhomebroker.exceptions.SessionException
            If the user is not logged in.
            If the connection or hub is not assigned.
            If the connection is not open.
        """

        if not self._auth.is_user_logged_in:
            raise SessionException('User is not logged in')

        if not self._connection or not self._hub:
            raise SessionException('Connection or hub is not assigned')

        if not self._connection.is_open:
            raise SessionException('Connection is not open')

        self._hub.server.invoke('JoinGroup', group_name)

    def quit_group(self, group_name):
        """
        Unsubscribe from a group to stop receiving event notifications.

        Raises
        ------
        pyhomebroker.exceptions.SessionException
            If the user is not logged in.
            If the connection or hub is not assigned.
            If the connection is not open.
        """

        if not self._auth.is_user_logged_in:
            raise SessionException('User is not logged in')

        if not self._connection or not self._hub:
            raise SessionException('Connection or hub is not assigned')

        if not self._connection.is_open:
            raise SessionException('Connection is not open')

        self._hub.server.invoke('QuitGroup', group_name)

#########################
#### PRIVATE METHODS ####
#########################

    def __worker_thread_run(self):

        while not self.__worker_thread_event.wait(0.1):

            with self.__personal_portfolio_queue_lock:
                data = self.__personal_portfolio_queue
                self.__personal_portfolio_queue = []
            self.__process_personal_portfolio(data)

            with self.__securities_options_repos_queue_lock:
                data = self.__securities_options_repos_queue
                self.__securities_options_repos_queue = []
            self.__process_securities_options_repos(data)

            with self.__order_book_queue_lock:
                data = self.__order_book_queue
                self.__order_book_queue = []
            self.__process_order_books(data)

    def __worker_thread_stop(self):

        if self.__worker_thread_event and not self.__worker_thread_event.is_set(
        ):
            self.__worker_thread_event.set()
            self.__worker_thread.join()
            self.__worker_thread_event = None
            self.__worker_thread = None

    def __process_personal_portfolio(self, data):

        try:  #  Handle any exception processing the information or triggered by the user code
            if not self._on_personal_portfolio or len(data) == 0:
                return

            ts = time.time()

            # Remove duplicates from Json Document
            data_filter = {}
            for item in data:
                data_filter[item['Symbol'] + '-' + item['Term']] = item
            data = list(data_filter.values())

            df_portfolio = self.process_personal_portfolio(data)
            ts_pp_process = time.time()

            df_order_book = self.process_order_books(data)
            ts_ob_process = time.time()

            self._on_personal_portfolio(df_portfolio, df_order_book)
            ts_event = time.time()

            logging.debug(
                "[HOMEBROKER: SIGNALR] Performance [__process_personal_portfolio (P: {} - OB: {})]: (PP Proc: {:.3f}s - OB Proc: {:.3f}s - Notif: {:.3f}s)"
                .format(len(df_portfolio.index), len(df_order_book.index),
                        ts_pp_process - ts, ts_ob_process - ts_pp_process,
                        ts_event - ts_ob_process))
        except Exception as ex:
            if self._on_error:
                try:  # Catch user exceptions inside the except block (Inception Mode Activated :D)
                    self._on_error(ex, False)
                except:
                    pass

    def __process_securities_options_repos(self, data):

        try:  # Handle any exception processing the information or triggered by the user code
            if len(data) == 0:
                return

            # Remove duplicates from Json Document
            data_filter = {}
            for item in data:
                data_filter[item['Symbol'] + '-' + item['Term']] = item
            data = list(data_filter.values())

            df = pd.DataFrame(data) if data else pd.DataFrame()

            df_repo = df[df.Group == 'cauciones-'].copy()
            df_options = df[df.Group == 'opciones-'].copy()
            df_securities = df[(df.Group != 'cauciones-')
                               & (df.Group != 'opciones-')].copy()

            if len(df_repo) and self._on_repos:
                ts = time.time()

                repos = self.process_repos(df_repo)
                ts_process = time.time()

                self._on_repos(repos)
                ts_event = time.time()

                logging.debug(
                    "[HOMEBROKER: SIGNALR] Performance [__process_securities_options_repos (R: {})]: (Proc: {:.3f}s - Notif: {:.3f}s)"
                    .format(len(repos.index), ts_process - ts,
                            ts_event - ts_process))

            if len(df_options) and self._on_options:
                ts = time.time()

                options = self.process_options(df_options)
                ts_process = time.time()

                self._on_options(options)
                ts_event = time.time()

                logging.debug(
                    "[HOMEBROKER: SIGNALR] Performance [__process_securities_options_repos (O: {})]: (Proc: {:.3f}s - Notif: {:.3f}s)"
                    .format(len(options.index), ts_process - ts,
                            ts_event - ts_process))

            if len(df_securities) and self._on_securities:
                ts = time.time()

                securities = self.process_securities(df_securities)
                ts_process = time.time()

                self._on_securities(securities)
                ts_event = time.time()

                logging.debug(
                    "[HOMEBROKER: SIGNALR] Performance [__process_securities_options_repos (S: {})]: (Proc: {:.3f}s - Notif: {:.3f}s)"
                    .format(len(securities.index), ts_process - ts,
                            ts_event - ts_process))
        except Exception as ex:
            if self._on_error:
                try:  # Catch user exceptions inside the except block (Inception Mode Activated :D)
                    self._on_error(ex, False)
                except:
                    pass

    def __process_order_books(self, data):

        try:  # Handle any exception processing the information or triggered by the user code
            if not self._on_order_book or len(data) == 0:
                return

            ts = time.time()

            # Remove duplicates from Json Document
            data_filter = {}
            for item in data:
                data_filter[item['Symbol'] + '-' + item['Term']] = item
            data = list(data_filter.values())

            order_books = self.process_order_books(data)
            ts_process = time.time()

            self._on_order_book(order_books)
            ts_event = time.time()

            logging.debug(
                "[HOMEBROKER: SIGNALR] Performance [__process_order_books ({})]: (Proc: {:.3f}s - Notif: {:.3f}s)"
                .format(len(data), ts_process - ts, ts_event - ts_process))
        except Exception as ex:
            if self._on_error:
                try:  # Catch user exceptions inside the except block (Inception Mode Activated :D)
                    self._on_error(ex, False)
                except:
                    pass

#############################################
#### PRIVATE METHODS - SIGNALR CALLBACKS ####
#############################################

    def __internal_personal_portfolio(self, data):

        if not data:
            return

        if not isinstance(data, list):
            data = [data]

        with self.__personal_portfolio_queue_lock:
            self.__personal_portfolio_queue.extend(data)

    def __internal_securities_options_repos(self, data):

        if not data:
            return

        if not isinstance(data, list):
            data = [data]

        with self.__securities_options_repos_queue_lock:
            self.__securities_options_repos_queue.extend(data)

    def __internal_order_book(self, data):

        if not data:
            return

        if not isinstance(data, list):
            data = [data]

        with self.__order_book_queue_lock:
            self.__order_book_queue.extend(data)

    def __on_internal_exception(self, exception_type, value, traceback):

        self.__worker_thread_stop()

        if self._on_error:
            try:  # Catch user exceptions inside the except block (Inception Mode Activated :D)
                self._on_error(exception_type(value), True)
            except:
                pass
Exemplo n.º 8
0
    centralview.client.on('toggleServiceInfo',centralview_toggleServiceInfo)    
    centralview.client.on('setVersion', centralview_setVersion)   
    
    
    connection.error += loading_error
    #start a connection
    connection.start()
    time.sleep(10)
    while not connection.started:
        print("connecting...")
        print(connection.id)

    connectionId = connection.id
   

    #create a connection
    raw_html = simple_get(session,build_url("/Home/SaveConnectionId",{"lang":"Pl","connectionId":connectionId,"mac":mac,"id":id,"password":password}))
    print(raw_html)


    if raw_html is None:
    #if connectionSaved:
        connection.close()
        connectionStopped = True
    

#    simple_get(build_url("/Home/GetUsername",{"userId":connectionId}))
    while not connectionStopped:
        time.sleep(1)
    
Exemplo n.º 9
0
class OnlineSignalR:
    
    def __init__(self, auth, on_open=None, on_personal_portfolio=None, 
        on_securities=None, on_options=None, on_repos=None, on_order_book=None, 
        on_error=None, on_close=None, proxy_url=None):
        """
        Class constructor.
        
        Parameters
        ----------
        auth : home_broker_session
            An object with the authentication information.
        on_open : function(), optional
            Callable object which is called at opening the signalR connection.
            This function has no argument.
        on_personal_portfolio : function(quotes), optional
            Callable object which is called when personal portfolio data is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_securities : function(quotes), optional
            Callable object which is called when security data is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_options : function(quotes), optional
            Callable object which is called when options data is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_repos : function(quotes), optional
            Callable object which is called when repo data is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_order_book : function(quotes), optional
            Callable object which is called when the order book data (level 2) is received.
            This function has 1 argument. The argument is the dataframe with the quotes.
        on_error : function(error), optional
            Callable object which is called when we get error.
            This function has 1 arguments. The argument is the exception object.
        on_close : function(), optional
            Callable object which is called when closed the connection.
            This function has no argument.
        proxy_url : str, optional
            The proxy URL with one of the following formats:
                - scheme://user:pass@hostname:port 
                - scheme://user:pass@ip:port
                - scheme://hostname:port 
                - scheme://ip:port
            
            Ex. https://john:[email protected]:3128
        """

        self._proxies = {'http': proxy_url, 'https': proxy_url} if proxy_url else None
        self._auth = auth
        self._on_open = on_open
        self._on_personal_portfolio = on_personal_portfolio
        self._on_securities = on_securities
        self._on_options = on_options
        self._on_repos = on_repos
        self._on_order_book = on_order_book
        self._on_error = on_error
        self._on_close = on_close
        
        self._connection = None
        self._hub = None
        
        self.is_connected = False

########################
#### PUBLIC METHODS ####
########################
    def connect(self):
        """
        Connects to the signalR server.
        
        Raises
        ------
        pyhomebroker.exceptions.SessionException
            If the user is not logged in.
        """
        
        if not self._auth.is_user_logged_in:
            raise SessionException('User is not logged in')

        url = '{}/signalr/hubs'.format(self._auth.broker['page'])
        
        with rq.Session() as session:
            rq.utils.add_dict_to_cookiejar(session.cookies, self._auth.cookies)

            if self._proxies:
                session.proxies.update(self._proxies)
            
            self._connection = Connection(url, session)
            self._hub = self._connection.register_hub('stockpriceshub')
            
            self._hub.client.on('broadcast', self.__internal_securities_options_repos)

            self._hub.client.on('sendStartStockFavoritos', self.__internal_personal_portfolio)
            self._hub.client.on('sendStockFavoritos', self.__internal_personal_portfolio)

            self._hub.client.on('sendStartStockPuntas', self.__internal_order_book)
            self._hub.client.on('sendStockPuntas', self.__internal_order_book)
            
            if self._on_error:
                self._connection.error += self._on_error
                
            self._connection.exception += self.__on_internal_exception
            self._connection.start()

            self.is_connected = self._connection.is_open
            
            if self.is_connected and self._on_open:
                self._on_open()

    def disconnect(self):
        """
        Disconnects from the signalR server.
        
        Raises
        ------
        pyhomebroker.exceptions.SessionException
            If the user is not logged in.
            If the connection or hub is not assigned.
        """
        
        if not self._auth.is_user_logged_in:
            raise SessionException('User is not logged in')
        
        if not self._connection or not self._hub:
            raise SessionException('Connection or hub is not assigned')
        
        if self._connection.is_open:
            self._connection.close()
                
        self._connection = None
        self._hub = None
        
        self.is_connected = False

        if self._on_close:
            self._on_close()

    def join_group(self, group_name):
        """
        Subscribe to a group to start receiving event notifications.
        
        Raises
        ------
        pyhomebroker.exceptions.SessionException
            If the user is not logged in.
            If the connection or hub is not assigned.
            If the connection is not open.
        """
        
        if not self._auth.is_user_logged_in:
            raise SessionException('User is not logged in')
            
        if not self._connection or not self._hub:
            raise SessionException('Connection or hub is not assigned')
            
        if not self._connection.is_open:
            raise SessionException('Connection is not open')
        
        self._hub.server.invoke('JoinGroup', group_name)
        
    def quit_group(self, group_name):
        """
        Unsubscribe from a group to stop receiving event notifications.
        
        Raises
        ------
        pyhomebroker.exceptions.SessionException
            If the user is not logged in.
            If the connection or hub is not assigned.
            If the connection is not open.
        """
        
        if not self._auth.is_user_logged_in:
            raise SessionException('User is not logged in')
            
        if not self._connection or not self._hub:
            raise SessionException('Connection or hub is not assigned')
            
        if not self._connection.is_open:
            raise SessionException('Connection is not open')
        
        self._hub.server.invoke('QuitGroup', group_name)
        
#########################
#### PRIVATE METHODS ####
#########################       
    def __internal_personal_portfolio(self, data):
        
        try: #  Handle any exception processing the information or triggered by the user code
            if self._on_personal_portfolio:
                if data and not isinstance(data, list):
                    data = [data]
                df = pd.DataFrame(data if data else pd.DataFrame())
            
                self._on_personal_portfolio(helper.process_personal_portfolio(df))            
        except Exception as ex:
            if self._on_error:
                try: # Catch user exceptions inside the except block (Inception Mode Activated :D)
                    self._on_error(ex)
                except:
                    pass
                 
    def __internal_securities_options_repos(self, data):
        
        try: # Handle any exception processing the information or triggered by the user code
            df = pd.DataFrame(data) if data else pd.DataFrame()      
            
            df_repo = df[df.Group == 'cauciones-']
            df_options = df[df.Group == 'opciones-']
            df_securities = df[(df.Group != 'cauciones-') & (df.Group != 'opciones-')]
            
            if len(df_repo) and self._on_repos:
                self._on_repos(helper.process_repos(df_repo))

            if len(df_options) and self._on_options:
                self._on_options(helper.process_options(df_options))
            
            if len(df_securities) and self._on_securities:
                self._on_securities(helper.process_securities(df_securities))

        except Exception as ex:
            if self._on_error:
                try: # Catch user exceptions inside the except block (Inception Mode Activated :D)
                    self._on_error(ex)
                except:
                    pass
             
    def __internal_order_book(self, data):

        try: # Handle any exception processing the information or triggered by the user code
            if self._on_order_book and data:
                symbol = data['Symbol']
                settlement = data['Term']
                
                if data['StockDepthBox'] and data['StockDepthBox']['PriceDepthBox']:
                    df_buy = pd.DataFrame(data['StockDepthBox']['PriceDepthBox']['BuySide'])
                    df_sell = pd.DataFrame(data['StockDepthBox']['PriceDepthBox']['SellSide'])
                else:        
                    df_buy = pd.DataFrame()
                    df_sell = pd.DataFrame()
                    
                self._on_order_book(helper.process_order_book(symbol, settlement, df_buy, df_sell))
            
        except Exception as ex:
            if self._on_error:
                try: # Catch user exceptions inside the except block (Inception Mode Activated :D)
                    self._on_error(ex)
                except:
                    pass
                
    def __on_internal_exception(self, exception_type, value, traceback):
        
        if self._on_error:
            self._on_error(exception_type(value))
Exemplo n.º 10
0
class SubscriptionBittrex:
    def __init__(self,
                 pair_id,
                 on_update=default_on_public,
                 base_url=BittrexParameters.URL,
                 hub_name=BittrexParameters.HUB):
        """
        :param pair_id:     - currency pair to be used for trading
        :param base_url:    - web-socket subscription end points
        :param hub_name:    - Bittrex-specific url for market update
        :param on_update:   - idea is the following:
            we pass reference to method WITH initialized order book for that pair_id
            whenever we receive update we update order book and trigger checks for arbitrage
        """

        self.url = base_url
        self.hub_name = hub_name

        self.pair_id = pair_id
        self.pair_name = get_currency_pair_to_bittrex(self.pair_id)

        self.on_update = on_update

        self.hub = None

        self.order_book_is_received = False

        self.initial_order_book = None

        self.should_run = False

    def on_public(self, args):
        msg = process_message(args)
        log_to_file(msg, "bittrex.log")
        order_book_delta = parse_socket_update_bittrex(msg)

        if order_book_delta is None:
            err_msg = "Bittrex - cant parse update from message: {msg}".format(
                msg=msg)
            log_to_file(err_msg, SOCKET_ERRORS_LOG_FILE_NAME)
        else:
            self.on_update(EXCHANGE.BITTREX, order_book_delta)

    def on_receive(self, **kwargs):
        """
            heart beat and other stuff
        :param kwargs:
        :return:
        """

        if 'R' in kwargs and type(kwargs['R']) is not bool:
            msg = process_message(kwargs['R'])

            log_to_file(msg, "bittrex.log")

            if msg is not None:

                self.order_book_is_received = True
                self.initial_order_book = parse_socket_order_book_bittrex(
                    msg, self.pair_id)

        else:
            try:
                msg = process_message(str(kwargs))
            except:
                msg = kwargs

            log_to_file(msg, "bittrex.log")

    def request_order_book(self):
        try:
            with Session() as session:
                connection = Connection(self.url, session)
                self.hub = connection.register_hub(self.hub_name)

                connection.received += self.on_receive

                connection.start()

                while self.order_book_is_received is not True:
                    self.hub.server.invoke(
                        BittrexParameters.QUERY_EXCHANGE_STATE, self.pair_name)
                    connection.wait(
                        5
                    )  # otherwise it shoot thousands of query and we will be banned :(

                connection.close()

                msg = "Got orderbook for Bittrex!"
                log_to_file(msg, SOCKET_ERRORS_LOG_FILE_NAME)
                print(msg)

                return STATUS.SUCCESS

        except Exception as e:
            # log_error_on_receive_from_socket("Bittrex", e)
            msg = "Error during order book retrieval for Bittrex {}".format(
                str(e))
            log_to_file(msg, SOCKET_ERRORS_LOG_FILE_NAME)
            print(msg)

        return STATUS.FAILURE

    def subscribe(self):

        #
        #       FIXME DBG PART - REMOVE AFTER TESTS
        #

        if self.should_run:
            die_hard("Bittrex another running?")

        msg = "Bittrex - call subscribe!"
        log_to_file(msg, SOCKET_ERRORS_LOG_FILE_NAME)
        print msg

        self.should_run = True

        try:
            with Session() as session:

                self.connection = Connection(self.url, session)
                self.hub = self.connection.register_hub(self.hub_name)

                self.hub.client.on(BittrexParameters.MARKET_DELTA,
                                   self.on_public)

                self.connection.start()

                log_conect_to_websocket("Bittrex")

                while self.connection.started and self.should_run:
                    try:
                        self.hub.server.invoke(
                            BittrexParameters.SUBSCRIBE_EXCHANGE_DELTA,
                            self.pair_name)
                    except Exception as e:
                        log_send_heart_beat_failed("Bittrex", e)

                        # FIXME NOTE - still not sure - connection.wait(1)
                        self.should_run = False

                        break
                    sleep_for(1)
        except Exception as e:
            log_error_on_receive_from_socket("Bittrex", e)

        log_subscription_cancelled("Bittrex")

        self.disconnect()

    def disconnect(self):
        self.should_run = False

        # FIXME NOTE:   due to implementation of bittrex order book retrieval
        #               dedicated method that create and destroy new instance of bittrex subscription
        #               we are not really relying on this flag anywhere
        # self.order_book_is_received = False

        try:
            self.connection.close()
        except Exception as e:
            log_websocket_disconnect("Bittrex", e)

    def is_running(self):
        return self.should_run