
    bg                        d Z ddlZddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
mZ ddlmZ ddlmZ ddlmZmZmZ ddlmZmZ  ej        e          Z G d	 d
e          Z G d dee          Z G d de          ZdS )z
    ticker.py

    Websocket implementation for kite ticker

    :copyright: (c) 2021 by Zerodha Technology Pvt. Ltd.
    :license: see LICENSE for details.
    N)datetime)reactorssl)log)ReconnectingClientFactory)WebSocketClientProtocolWebSocketClientFactory	connectWS)__version__	__title__c                   f     e Zd ZdZdZdZdZdZdZdZ	 fdZ
d Zd Zd Zd	 Zd
 Z	 d Zd Z xZS )KiteTickerClientProtocolz(Kite ticker autobahn WebSocket protocol.g      @   Nc                 H     t          t          |           j        |i | dS )z9Initialize protocol with all options passed from factory.N)superr   __init__selfargskwargs	__class__s      ;e:\HARSH\Automation\J_Work\zerodha_ticker\zerodha_ticker.pyr   z!KiteTickerClientProtocol.__init__(   s,    6&--6GGGGGG    c                     | | j         _        | j         j        r| j                             | |           | j                                          dS )z7Called when WebSocket server connection was establishedN)factoryws
on_connect
resetDelayr   responses     r   	onConnectz"KiteTickerClientProtocol.onConnect-   sL    <" 	4L##D(333 	!!!!!r   c                     |                                   |                                  | j        j        r| j                            |            dS dS )zBCalled when the initial WebSocket opening handshake was completed.N)
_loop_ping_loop_pong_checkr   on_openr   s    r   onOpenzKiteTickerClientProtocol.onOpen8   sY     	< 	'L  &&&&&	' 	'r   c                 Z    | j         j        r| j                             | ||           dS dS )z/Called when text or binary message is received.N)r   
on_message)r   payload	is_binarys      r   	onMessagez"KiteTickerClientProtocol.onMessageC   s9    <" 	>L##D'9=====	> 	>r   c                 J   |s(| j         j        r| j                             | ||           | j         j        r| j                             | ||           d| _        d| _        | j        r| j                                         | j        r| j                                         dS dS )z!Called when connection is closed.N)r   on_erroron_close_last_ping_time_last_pong_time
_next_pingcancel_next_pong_check)r   	was_cleancodereasons       r   onClosez KiteTickerClientProtocol.onCloseI   s     	:|$ :%%dD&999<  	6L!!$f555  $#? 	%O""$$$  	+!((*****	+ 	+r   c                 ^   | j         rR| j        j        rFt                              d                    t          j                    | j         z
                       t          j                    | _         | j        j        r/t                              d                    |                     dS dS )z%Called when pong message is received.zlast pong was {} seconds back.z
pong => {}N)r1   r   debugr   formattimer   s     r   onPongzKiteTickerClientProtocol.onPong\   s     	cDL$6 	cII6==dikkDL`>`aabbb#y{{< 	5IIl))(3344444	5 	5r   c                 F   | j         j        rM| j        rFt                              d                    t          j                    | j        z
                       t          j                    | _        | j         j                            | j        | j	                  | _
        dS )z>Start a ping loop where it sends ping message every X seconds.zlast ping was {} seconds back.N)r   r:   r0   r   r;   r<   r   	callLaterPING_INTERVALr#   r2   r&   s    r   r#   z#KiteTickerClientProtocol._loop_pingj   s    < 	g# g		:AA$)++PTPdBdeefff  $y{{ ,.889KT_]]r   c                 b   | j         rxt          j                    | j         z
  }|d| j        z  k    rO| j        j        r-t
                              d                    |                     |                     d           | j        j        	                    | j        | j
                  | _        dS )z
        Timer sortof to check if connection is still there.

        Checks last pong message time and disconnects the existing connection to make sure it doesn't become a ghost connection.
           zBLast pong was {} seconds ago. So dropping connection to reconnect.T)abortN)r1   r<   r@   r   r:   r   r;   dropConnectionr   r?   r$   r4   )r   last_pong_diffs     r   r$   z)KiteTickerClientProtocol._loop_pong_checkv   s      	0!Y[[4+??NT%7!788<% )IIbii&( ( ) ) ) ##$#/// !% 4 > >t?QSWSh i ir   )__name__
__module____qualname____doc__r@   KEEPALIVE_INTERVALr2   r4   r1   r0   r   r!   r'   r,   r8   r=   r#   r$   __classcell__r   s   @r   r   r      s        22MJOOH H H H H
" " "' ' '> > >+ + +&5 5 5
^ 
^ 
^j j j j j j jr   r   c                   J     e Zd ZdZeZdZdZdZ fdZ	d Z
d Zd Zd	 Z xZS )
KiteTickerClientFactoryzQAutobahn WebSocket client factory to implement reconnection and custom callbacks.r   
   Nc                     d| _         d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _         t          t          |           j        |i | dS )z/Initialize with default callback method values.FN)r:   r   r%   r.   r/   r)   r   on_reconnecton_noreconnectr   rN   r   r   s      r   r   z KiteTickerClientFactory.__init__   sm    
 "5%t,,5tFvFFFFFr   c                     | j         s!| j        rt                              d           t          j                    | _         dS )z$On connecting start or reconnection.zStart WebSocket connection.N)_last_connection_timer:   r   r<   )r   	connectors     r   startedConnectingz)KiteTickerClientFactory.startedConnecting   s=    ) 	5dj 	5II3444%)Y[["""r   c           
      T   | j         dk    rst                              d                    | j         t	          t          | j                                                 | j        r|                     | j                    |                     |           | 	                                 dS )z2On connection failure (When connect request fails)r   zNRetrying connection. Retry attempt count: {}. Next retry in around: {} secondsN)
retriesr   errorr;   introunddelayrQ   retrysend_noreconnectr   rU   r7   s      r   clientConnectionFailedz.KiteTickerClientFactory.clientConnectionFailed   s    <!IIfmmnrnz|  AF  GK  GQ  AR  AR  }S  }S  T  T  U  U  U   0!!$,/// 	

9r   c                     | j         dk    r!| j        r|                     | j                    |                     |           |                                  dS )z>On connection lost (When ongoing connection got disconnected).r   N)rX   rQ   r]   r^   r_   s      r   clientConnectionLostz,KiteTickerClientFactory.clientConnectionLost   s\    <!  0!!$,/// 	

9r   c                    | j         z| j        | j         k    rl| j        rFt                              d                    | j                              |                                  | j        r|                                  dS dS dS dS )z5Callback `no_reconnect` if max retries are exhausted.NzMaximum retries ({}) exhausted.)
maxRetriesrX   r:   r   r;   stoprR   r&   s    r   r^   z(KiteTickerClientFactory.send_noreconnect   s    ?&DL4?,J,Jz 		;BB4?SSTTT		" &##%%%%% '&,J,J& &r   )rF   rG   rH   rI   r   protocolmaxDelayrd   rT   r   rV   r`   rb   r^   rK   rL   s   @r   rN   rN      s        [['HHJ G G G G G1 1 1     	  	  	 	& 	& 	& 	& 	& 	& 	&r   rN   c                   
   e Zd ZdZdddddddd	d
dd
ZdZdZdZdZdZ	dZ
dZdZdZdZdZdZdZdZdddeeefdZd Zd Zd4dZd Zd5d Zd5d!Zd" Zd# Zd$ Zd% Zd& Zd' Zd( Z d) Z!d* Z"d+ Z#d, Z$d- Z%d. Z&d/ Z'd0 Z(d6d2Z)d3 Z*dS )7
KiteTickera  
    The WebSocket client for connecting to Kite Connect's streaming quotes service.

    Getting started:
    ---------------
        #!python
        import logging
        from kiteconnect import KiteTicker

        logging.basicConfig(level=logging.DEBUG)

        # Initialise
        kws = KiteTicker("your_api_key", "your_access_token")

        def on_ticks(ws, ticks):
            # Callback to receive ticks.
            logging.debug("Ticks: {}".format(ticks))

        def on_connect(ws, response):
            # Callback on successful connect.
            # Subscribe to a list of instrument_tokens (RELIANCE and ACC here).
            ws.subscribe([738561, 5633])

            # Set RELIANCE to tick in `full` mode.
            ws.set_mode(ws.MODE_FULL, [738561])

        def on_close(ws, code, reason):
            # On connection close stop the event loop.
            # Reconnection will not happen after executing `ws.stop()`
            ws.stop()

        # Assign the callbacks.
        kws.on_ticks = on_ticks
        kws.on_connect = on_connect
        kws.on_close = on_close

        # Infinite loop on the main thread. Nothing after this will run.
        # You have to use the pre-defined callbacks to manage subscriptions.
        kws.connect()

    Callbacks
    ---------
    In below examples `ws` is the currently initialised WebSocket object.

    - `on_ticks(ws, ticks)` -  Triggered when ticks are recevied.
        - `ticks` - List of `tick` object. Check below for sample structure.
    - `on_close(ws, code, reason)` -  Triggered when connection is closed.
        - `code` - WebSocket standard close event code (https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent)
        - `reason` - DOMString indicating the reason the server closed the connection
    - `on_error(ws, code, reason)` -  Triggered when connection is closed with an error.
        - `code` - WebSocket standard close event code (https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent)
        - `reason` - DOMString indicating the reason the server closed the connection
    - `on_connect` -  Triggered when connection is established successfully.
        - `response` - Response received from server on successful connection.
    - `on_message(ws, payload, is_binary)` -  Triggered when message is received from the server.
        - `payload` - Raw response from the server (either text or binary).
        - `is_binary` - Bool to check if response is binary type.
    - `on_reconnect(ws, attempts_count)` -  Triggered when auto reconnection is attempted.
        - `attempts_count` - Current reconnect attempt number.
    - `on_noreconnect(ws)` -  Triggered when number of auto reconnection attempts exceeds `reconnect_tries`.
    - `on_order_update(ws, data)` -  Triggered when there is an order update for the connected user.


    Tick structure (passed to the `on_ticks` callback)
    ---------------------------
        [{
            'instrument_token': 53490439,
            'mode': 'full',
            'volume_traded': 12510,
            'last_price': 4084.0,
            'average_traded_price': 4086.55,
            'last_traded_quantity': 1,
            'total_buy_quantity': 2356
            'total_sell_quantity': 2440,
            'change': 0.46740467404674046,
            'last_trade_time': datetime.datetime(2018, 1, 15, 13, 16, 54),
            'exchange_timestamp': datetime.datetime(2018, 1, 15, 13, 16, 56),
            'oi': 21845,
            'oi_day_low': 0,
            'oi_day_high': 0,
            'ohlc': {
                'high': 4093.0,
                'close': 4065.0,
                'open': 4088.0,
                'low': 4080.0
            },
            'tradable': True,
            'depth': {
                'sell': [{
                    'price': 4085.0,
                    'orders': 1048576,
                    'quantity': 43
                }, {
                    'price': 4086.0,
                    'orders': 2752512,
                    'quantity': 134
                }, {
                    'price': 4087.0,
                    'orders': 1703936,
                    'quantity': 133
                }, {
                    'price': 4088.0,
                    'orders': 1376256,
                    'quantity': 70
                }, {
                    'price': 4089.0,
                    'orders': 1048576,
                    'quantity': 46
                }],
                'buy': [{
                    'price': 4084.0,
                    'orders': 589824,
                    'quantity': 53
                }, {
                    'price': 4083.0,
                    'orders': 1245184,
                    'quantity': 145
                }, {
                    'price': 4082.0,
                    'orders': 1114112,
                    'quantity': 63
                }, {
                    'price': 4081.0,
                    'orders': 1835008,
                    'quantity': 69
                }, {
                    'price': 4080.0,
                    'orders': 2752512,
                    'quantity': 89
                }]
            }
        },
        ...,
        ...]

    Auto reconnection
    -----------------

    Auto reconnection is enabled by default and it can be disabled by passing `reconnect` param while initialising `KiteTicker`.
    On a side note, reconnection mechanism cannot happen if event loop is terminated using `stop` method inside `on_close` callback.

    Auto reonnection mechanism is based on [Exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) algorithm in which
    next retry interval will be increased exponentially. `reconnect_max_delay` and `reconnect_max_tries` params can be used to tewak
    the alogrithm where `reconnect_max_delay` is the maximum delay after which subsequent reconnection interval will become constant and
    `reconnect_max_tries` is maximum number of retries before its quiting reconnection.

    For example if `reconnect_max_delay` is 60 seconds and `reconnect_max_tries` is 50 then the first reconnection interval starts from
    minimum interval which is 2 seconds and keep increasing up to 60 seconds after which it becomes constant and when reconnection attempt
    is reached upto 50 then it stops reconnecting.

    method `stop_retry` can be used to stop ongoing reconnect attempts and `on_reconnect` callback will be called with current reconnect
    attempt and `on_noreconnect` is called when reconnection attempts reaches max retries.
       rB         r            	   )
nsenfocdsbsebfobcdmcxmcxsxindicesbsecds   <   2   zwss://ws.zerodha.comfullquoteltpT   	subscribeunsubscribemodei,  FNc                 .   |p| j         | _        || j        k    r@t                              d                    | j                             | j        | _        n|| _        || j        k     r@t                              d                    | j                             | j        | _        n|| _        || _	        d| _
        || _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        i | _        dS )a  
        Initialise websocket client instance.

        - `api_key` is the API key issued to you
        - `access_token` is the token obtained after the login flow in
            exchange for the `request_token`. Pre-login, this will default to None,
            but once you have obtained it, you should
            persist it in a database or session to pass
            to the Kite Connect class initialisation for subsequent requests.
        - `root` is the websocket API end point root. Unless you explicitly
            want to send API requests to a non-default endpoint, this
            can be ignored.
        - `reconnect` is a boolean to enable WebSocket autreconnect in case of network failure/disconnection.
        - `reconnect_max_delay` in seconds is the maximum delay after which subsequent reconnection interval will become constant. Defaults to 60s and minimum acceptable value is 5s.
        - `reconnect_max_tries` is maximum number reconnection attempts. Defaults to 50 attempts and maximum up to 300 attempts.
        - `connect_timeout` in seconds is the maximum interval after which connection is considered as timeout. Defaults to 30s.
        z\`reconnect_max_tries` can not be more than {val}. Setting to highest possible value - {val}.)valz[`reconnect_max_delay` can not be less than {val}. Setting to lowest possible value - {val}.zwss://ws.zerodha.com/?api_key=kitefront&user_id=GMG829&enctoken=RHLoVLJsgBvjuc57OY5KgXXSJp%2BV7G9obmNSY%2BdC0asC8Q2mww%2FxBiuH5dkx4djnRcZ3NWKWDo6TLnniC8ABrQFgFrCzKJGPC05YcjWhWKVNkFVgl%2BUeEg%3D%3D&uid=1729741105152&user-agent=kite3-web&version=3.0.0N)ROOT_URIroot_maximum_reconnect_max_triesr   warningr;   reconnect_max_tries_minimum_reconnect_max_delayreconnect_max_delayconnect_timeout
socket_urlr:   r   on_ticksr%   r/   r.   r   r)   rQ   rR   on_order_updatesubscribed_tokens)r   r:   r   	reconnectr   r   r   s          r   r   zKiteTicker.__init__  sB   ( )DM	 !BBBKKv}}5 ~ 7 7 8 8 8'+'HD$$':D$ !BBBKKu||5 } 7 7 8 8 8'+'HD$$':D$. V 
   "  $ "$r   c                    t          |fi || _        | j        j        | _        | j        | j        _        | j        | j        _        | j        | j        _        | j        | j        _	        | j
        | j        _        | j        | j        _        | j        | j        _        | j        | j        _        | j        | j        _        | j        | j        _        dS )z%Create a WebSocket client connection.N)rN   r   r   r:   _on_openr%   	_on_errorr.   	_on_closer/   _on_messager)   _on_connectr   _on_reconnectrQ   _on_noreconnectrR   r   rg   r   rd   )r   urlr   s      r   _create_connectionzKiteTicker._create_connection  s    .s==f== ,/!Z  $} $ $"&"2"&"2$($6!&*&:# $ 8"&":r   c                 J    t           dz                                   t          z   S )Nz-python/)r   
capitalizer   r&   s    r   _user_agentzKiteTicker._user_agent  s    J&2244{BBr   c                    ddi}|                      | j        |                                 ||           d}| j        j        r|st          j                    }t          | j        || j                   | j	        rt          j        t          j                   i }t          j        sf|rQd|d<   t!          j        t          j        |          | _        d	| j        _        | j                                         dS t          j        d
i | dS dS )aA  
        Establish a websocket connection.

        - `threaded` is a boolean indicating if the websocket client has to be run in threaded mode or not
        - `disable_ssl_verification` disables building ssl context
        - `proxy` is a dictionary with keys `host` and `port` which denotes the proxy settings
        zX-Kite-Version3)	useragentproxyheadersN)contextFactorytimeoutFinstallSignalHandlers)targetr   T )r   r   r   r   isSecurer   ClientContextFactoryr
   r   r:   twisted_logstartLoggingsysstdoutr   running	threadingThreadrunwebsocket_threaddaemonstart)r   threadeddisable_ssl_verificationr   r   context_factoryoptss          r   connectzKiteTicker.connect  s7    c
 	*.*:*:*<*<&+W 	  	> 	> 	>
 <  	9)A 	9!688O 	$,H\]]]]: 	1$SZ000   	$ $05,-(1(8TX(Y(Y(Y%/3%,%++-----##d#####	$ 	$r   c                 L    | j         r| j         j        | j         j        k    rdS dS )z-Check if WebSocket connection is established.TF)r   state
STATE_OPENr&   s    r   is_connectedzKiteTicker.is_connected  s)    7 	tw}(:::45r   c                 N    | j         r| j                             ||           dS dS zClose the WebSocket connection.N)r   	sendCloser   r6   r7   s      r   _closezKiteTicker._close   s4    7 	,GdF+++++	, 	,r   c                 Z    |                                   |                     ||           dS r   )
stop_retryr   r   s      r   closezKiteTicker.close%  s,    D&!!!!!r   c                 ,    t          j                     dS )zStop the event loop. Should be used if main thread has to be closed in `on_close` method.
        Reconnection mechanism cannot happen past this method
        N)r   re   r&   s    r   re   zKiteTicker.stop*  s     	r   c                 J    | j         r| j                                          dS dS )z'Stop auto retry when it is in progress.N)r   
stopTryingr&   s    r   r   zKiteTicker.stop_retry0  s0    < 	&L##%%%%%	& 	&r   c           	      N   	 | j                             t          j        t	          j        | j        |d                               |D ]}| j        | j        |<   dS # t          $ r<}| 
                    d                    t          |                                d}~ww xY w)z
        Subscribe to a list of instrument_tokens.

        - `instrument_tokens` is list of instrument instrument_tokens to subscribe
        avTzError while subscribe: {}r7   N)r   sendMessagesixbjsondumps_message_subscribe
MODE_QUOTEr   	Exceptionr   r;   strr   instrument_tokenstokenes       r   r   zKiteTicker.subscribe5  s    	Gdjt'>EV!W!WXXYY   + @ @04&u--4 	 	 	KK:AA#a&&IIKJJJ	s   AA 
B$(7BB$c           	      b   	 | j                             t          j        t	          j        | j        |d                               |D ]}	 | j        |= # t          $ r Y w xY wdS # t          $ r<}| 
                    d                    t          |                                d}~ww xY w)z
        Unsubscribe the given list of instrument_tokens.

        - `instrument_tokens` is list of instrument_tokens to unsubscribe.
        r   TzError while unsubscribe: {}r   N)r   r   r   r   r   r   _message_unsubscriber   KeyErrorr   r   r;   r   r   s       r   r   zKiteTicker.unsubscribeH  s    	Gdjt'@GX!Y!YZZ[[   +  /66   D 4 	 	 	KK<CCCFFKKKLLL	s<   A
A( AA( 
A# A( "A##A( (
B.27B))B.c           	      H   	 | j                             t          j        t	          j        | j        ||gd                               |D ]}|| j        |<   dS # t          $ r<}| 	                    d
                    t          |                                d}~ww xY w)a'  
        Set streaming mode for the given list of tokens.

        - `mode` is the mode to set. It can be one of the following class constants:
            MODE_LTP, MODE_QUOTE, or MODE_FULL.
        - `instrument_tokens` is list of instrument tokens on which the mode should be applied
        r   TzError while setting mode: {}r   N)r   r   r   r   r   r   _message_setmoder   r   r   r;   r   )r   r   r   r   r   s        r   set_modezKiteTicker.set_mode^  s    	Gdjt'<DJ[C\!]!]^^__  
 + 5 504&u--4 	 	 	KK=DDSVVLLKMMM	s   AA 
B!%7BB!c                    i }| j         D ]D}| j         |         }|                    |          sg ||<   ||                             |           E|D ]t}| j        r4t                              d                    |||                              |                     ||                    |                     |||                    udS )z-Resubscribe to all current subscribed tokens.z!Resubscribe and set mode: {} - {}N)r   getappendr:   r   r;   r   r   )r   modesr   mr   s        r   resubscribezKiteTicker.resubscribet  s    + 	# 	#E&u-A99Q<< a!HOOE"""" 	- 	-Dz Y		=DDT5QU;WWXXXNN5;'''MM$d,,,,	- 	-r   c                 R    || _         | j        r|                     | |           d S d S N)r   r   )r   r   r    s      r   r   zKiteTicker._on_connect  s7    ? 	,OOD(+++++	, 	,r   c                     t                               d                    |t          |                               | j        r|                     | ||           dS dS )z3Call `on_close` callback when connection is closed.zConnection closed: {} - {}N)r   rY   r;   r   r/   r   r   r6   r7   s       r   r   zKiteTicker._on_close  s[    		.55dCKKHHIII= 	.MM$f-----	. 	.r   c                     t                               d                    |t          |                               | j        r|                     | ||           dS dS )z9Call `on_error` callback when connection throws an error.zConnection error: {} - {}N)r   rY   r;   r   r.   r   s       r   r   zKiteTicker._on_error  s[    		-44T3v;;GGHHH= 	.MM$f-----	. 	.r   c                     | j         r|                      | ||           | j        r>|r<t          |          dk    r)|                     | |                     |                     |s|                     |           dS dS )z9Call `on_message` callback when text message is received.rl   N)r)   r   len_parse_binary_parse_text_message)r   r   r*   r+   s       r   r   zKiteTicker._on_message  s    ? 	6OOD'9555 = 	=Y 	=3w<<!+;+;MM$ 2 27 ; ;<<<  	.$$W-----	. 	.r   c                     | j         s|                                  d| _         | j        r|                     |           S d S )NF)_is_first_connectr   r%   )r   r   s     r   r   zKiteTicker._on_open  sO    % 	 "'< 	&<<%%%	& 	&r   c                 @    | j         r|                      | |          S d S r   )rQ   )r   attempts_counts     r   r   zKiteTicker._on_reconnect  s-     	;$$T>:::	; 	;r   c                 >    | j         r|                      |           S d S r   )rR   r&   s    r   r   zKiteTicker._on_noreconnect  s+     	-&&t,,,	- 	-r   c                    t           j        s-t          |          t          k    r|                    d          }	 t          j        |          }n# t          $ r Y dS w xY w| j        rJ|	                    d          dk    r1|	                    d          r|                     | |d                    |	                    d          dk    r,| 
                    | d|	                    d                     dS dS )zParse text message.zutf-8NtypeorderdatarY   r   )r   PY2r   bytesdecoder   loads
ValueErrorr   r   r   )r   r*   r   s      r   r   zKiteTicker._parse_text_message  s     w 	.4==E11nnW--G	:g&&DD 	 	 	FF	  	5DHHV$4$4$?$?DHHVDTDT$?  tF|444 88Fw&&NN4DHHV$4$455555 '&s   A 
AAc                 
   |                      |          }g }|D ]V}|                     |dd          }|dz  }|| j        d         k    rd}n|| j        d         k    rd}nd}|| j        d	         k    rd
nd}t          |          dk    r8|                    || j        ||                     |dd          |z  d           t          |          dk    st          |          dk    rUt          |          dk    r| j        n| j        }	||	||                     |dd          |z  |                     |dd          |z  |                     |dd          |z  |                     |dd          |z  |                     |dd          |z  dd}
d|
d<   |
d         d         dk    r,|
d         |
d         d         z
  dz  |
d         d         z  |
d<   t          |          dk    rB	 t          j	        |                     |dd                    }n# t          $ r d}Y nw xY w||
d<   |                    |
           %t          |          dk    st          |          dk    r
t          |          dk    r| j        n| j        }	||	||                     |dd          |z  |                     |dd          |                     |dd          |z  |                     |dd          |                     |dd          |                     |dd          |                     |dd          |z  |                     |dd          |z  |                     |dd           |z  |                     |d d          |z  d!d"
}
d|
d<   |
d         d         dk    r,|
d         |
d         d         z
  dz  |
d         d         z  |
d<   t          |          dk    r	 t          j	        |                     |dd#                    }n# t          $ r d}Y nw xY w	 t          j	        |                     |d$d%                    }n# t          $ r d}Y nw xY w||
d&<   |                     |d#d'          |
d(<   |                     |d'd)          |
d*<   |                     |d)d$          |
d+<   ||
d<   g g d,}t          t          d%t          |          d                    D ]\  }}||d-k    rd.nd/                             |                     |||dz             |                     ||dz   |dz             |z  |                     ||dz   |d0z   d12          d3           ||
d4<   |                    |
           X|S )5z1Parse binary data to a (list of) ticks structure.r   rl      rs   g    cArv   g     @g      Y@ry   FTro   )tradabler   instrument_token
last_price                   )highlowopenr   )r  r   r  r  ohlcchanger  r   r  d   Nexchange_timestamp,      $   (   )r  r  r  r   )
r  r   r  r  last_traded_quantityaverage_traded_pricevolume_tradedtotal_buy_quantitytotal_sell_quantityr  0   r|   @   last_trade_time4   oi8   oi_day_high
oi_day_low)buysellr   r%  r$  rO   Hbyte_format)quantitypriceordersdepth)_split_packets_unpack_intEXCHANGE_MAPr   r   MODE_LTPr   	MODE_FULLr   fromtimestampr   	enumeraterange)r   binpacketsr   packetr  segmentdivisorr  r   d	timestampr  r,  ips                   r   r   zKiteTicker._parse_binary  sm   %%c** t	 t	F#//1==&-G $+E222$D-e444! !(4+<Y+G G GuuTH 6{{a ( M(8"&"2"261a"@"@7"J	      V""c&kkR&7&7*-f++*;*;t !) (8"&"2"261a"@"@7"J $ 0 0B ? ?' I#//B??'I $ 0 0R @ @7 J!%!1!1&"b!A!AG!K	    (fIg&!++#$\?QvYw5G#G3"NQRSYQZ[bQc"cAhK v;;"$$)$,$:4;K;KFTVXZ;[;[$\$\		$ ) ) )$(			) /8A*+AV""c&kkS&8&8*-f++*;*;t !) (8"&"2"261a"@"@7"J,0,<,<VQ,K,K,0,<,<VR,L,Lw,V%)%5%5fb"%E%E*.*:*:62r*J*J+/+;+;FB+K+K $ 0 0R @ @7 J $ 0 0R @ @7 J#//B??'I!%!1!1&"b!A!AG!K	  &  (fIg&!++#$\?QvYw5G#G3"NQRSYQZ[bQc"cAhK v;;#%%/*2*@AQAQRXZ\^`AaAa*b*b$ / / /*./)$,$:4;K;KFTVXZ;[;[$\$\		$ ) ) )$(			) ,;A'("..vr2>>AdG'+'7'7B'G'GAm$&*&6&6vr2&F&FAlO.7A*+  " " E !*%CKK*D*D E E  1QffE:AA(,(8(8AE(J(J%)%5%5fa!eQU%K%Kg%U&*&6&6vq1ua"fZ]&6&^&^C C     "'AgJAs6   ')HH H )O??PP)P<<Q
QIc                 N    t          j        d|z   |||                   d         S )z(Unpack binary data as unsgined interger.>r   )structunpack)r   r5  r   endr(  s        r   r.  zKiteTicker._unpack_intJ  s&    }S;.E#I??BBr   c                 "   t          |          dk     rg S |                     |ddd          }g }d}t          |          D ]L}|                     |||dz   d          }|                    ||dz   |dz   |z                       |dz   |z   }M|S )z.Split the data to individual packets of ticks.rB   r   r&  r'  )r   r.  r4  r   )r   r5  number_of_packetsr6  jr<  packet_lengths          r   r-  zKiteTicker._split_packetsN  s     s88a<<I ,,S!QC,HH()) 	& 	&A ,,S!QU,LLMNN3q1ua!em&;;<===A%AAr   )FFN)NN)r>  )+rF   rG   rH   rI   r/  CONNECT_TIMEOUTRECONNECT_MAX_DELAYRECONNECT_MAX_TRIESr   r1  r   r0  r   _message_coder   r   r   r   r   r   r   r   r   r   r   r   re   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r.  r-  r   r   r   ri   ri      sH       X Xv   L  O &H IJH  M$( $% #& "5H^q!0?$ ?$ ?$ ?$B; ; ;*C C C*$ *$ *$ *$X  , , , ,
" " " "
  & & &
  &  ,  ,- - -&, , ,
. . .. . .. . .	& 	& 	&; ; ;- - -6 6 6&{ { {zC C C C    r   ri   )rI   r   r   r<   r   rA  loggingr   r   twisted.internetr   r   twisted.pythonr   r   twisted.internet.protocolr   autobahn.twisted.websocketr   r	   r
   r   r   	getLoggerrF   r   rN   objectri   r   r   r   <module>rS     s    


 



               ) ) ) ) ) ) ) ) - - - - - - ? ? ? ? ? ?& & & & & & & & & & / . . . . . . .g!!jj jj jj jj jj6 jj jj jjZ?& ?& ?& ?& ?&46O ?& ?& ?&DQ
 Q
 Q
 Q
 Q
 Q
 Q
 Q
 Q
 Q
r   