
    8'h~                         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y)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                 ,    t        t        | 
  |i | y)z9Initialize protocol with all options passed from factory.N)superr   __init__selfargskwargs	__class__s      N/var/www/html/trade_iq/venv/lib/python3.12/site-packages/kiteconnect/ticker.pyr   z!KiteTickerClientProtocol.__init__(   s    &6GG    c                     | | j                   _        | j                   j                  r| j                   j                  | |       | j                   j                          y)z7Called when WebSocket server connection was establishedN)factoryws
on_connect
resetDelayr   responses     r   	onConnectz"KiteTickerClientProtocol.onConnect-   s@    <<""LL##D(3 	!r   c                     | j                          | j                          | j                  j                  r| j                  j                  |        yy)zBCalled when the initial WebSocket opening handshake was completed.N)
_loop_ping_loop_pong_checkr   on_openr   s    r   onOpenzKiteTickerClientProtocol.onOpen8   s>     	<<LL  &  r   c                 l    | j                   j                  r| j                   j                  | ||       yy)z/Called when text or binary message is received.N)r   
on_message)r   payload	is_binarys      r   	onMessagez"KiteTickerClientProtocol.onMessageC   s*    <<""LL##D'9= #r   c                    |s3| j                   j                  r| j                   j                  | ||       | j                   j                  r| j                   j                  | ||       d| _        d| _        | j
                  r| j
                  j                          | j                  r| j                  j                          yy)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<<  LL!!$f5  $#??OO""$  !!((* !r   c                 v   | j                   rY| j                  j                  rCt        j                  dj	                  t        j
                         | j                   z
               t        j
                         | _         | j                  j                  r%t        j                  dj	                  |             yy)z%Called when pong message is received.zlast pong was {} seconds back.z
pong => {}N)r2   r   debugr   formattimer    s     r   onPongzKiteTickerClientProtocol.onPong\   sw    DLL$6$6II6==diikDL`L`>`ab#yy{<<IIl))(34 r   c                 ~   | j                   j                  rO| j                  rCt        j                  dj	                  t        j
                         | j                  z
               t        j
                         | _        | j                   j                  j                  | j                  | j                        | _
        y)z>Start a ping loop where it sends ping message every X seconds.zlast ping was {} seconds back.N)r   r;   r1   r   r<   r=   r   	callLaterPING_INTERVALr$   r3   r'   s    r   r$   z#KiteTickerClientProtocol._loop_pingj   s|    <<##		:AA$))+PTPdPdBdef  $yy{ ,,..889K9KT__]r   c                    | j                   rt        j                         | j                   z
  }|d| j                  z  kD  rL| j                  j                  r$t
        j	                  dj                  |             | j                  d       | j                  j                  j                  | j                  | j                        | _        y)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)r2   r=   rA   r   r;   r   r<   dropConnectionr   r@   r%   r5   )r   last_pong_diffs     r   r%   z)KiteTickerClientProtocol._loop_pong_checkv   s     !YY[4+?+??NT%7%7!78<<%%IIbii&( ) ##$#/ !% 4 4 > >t?Q?QSWShSh ir   )__name__
__module____qualname____doc__rA   KEEPALIVE_INTERVALr3   r5   r2   r1   r   r"   r(   r-   r9   r>   r$   r%   __classcell__r   s   @r   r   r      sV    2MJOOH
"'>+&5
^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        | .  |i | y)z/Initialize with default callback method values.FN)r;   r   r&   r/   r0   r*   r   on_reconnecton_noreconnectr   rO   r   r   s      r   r   z KiteTickerClientFactory.__init__   sY    
 "%t5tFvFr   c                     | j                   s!| j                  rt        j                  d       t        j                         | _         y)z$On connecting start or reconnection.zStart WebSocket connection.N)_last_connection_timer;   r   r=   )r   	connectors     r   startedConnectingz)KiteTickerClientFactory.startedConnecting   s,    ))djjII34%)YY["r   c           
      H   | j                   dkD  rrt        j                  dj                  | j                   t	        t        | j                                           | j                  r| j                  | j                          | j                  |       | j                          y)z2On connection failure (When connect request fails)r   zNRetrying connection. Retry attempt count: {}. Next retry in around: {} secondsN)
retriesr   errorr<   introunddelayrR   retrysend_noreconnectr   rV   r8   s      r   clientConnectionFailedz.KiteTickerClientFactory.clientConnectionFailed   s    <<!IIfmmnrnznz|  AF  GK  GQ  GQ  AR  }S  T  U   !!$,,/ 	

9r   c                     | j                   dkD  r'| j                  r| j                  | j                          | j                  |       | j                          y)z>On connection lost (When ongoing connection got disconnected).r   N)rY   rR   r^   r_   r`   s      r   clientConnectionLostz,KiteTickerClientFactory.clientConnectionLost   sC    <<!  !!$,,/ 	

9r   c                     | j                   | j                  | j                   kD  rh| j                  r>t        j                  dj	                  | j                                | j                          | j                  r| j                          yyyy)z5Callback `no_reconnect` if max retries are exhausted.NzMaximum retries ({}) exhausted.)
maxRetriesrY   r;   r   r<   stoprS   r'   s    r   r_   z(KiteTickerClientFactory.send_noreconnect   sj    ??&DLL4??,Jzz		;BB4??ST		""##% # -K&r   )rG   rH   rI   rJ   r   protocolmaxDelayre   rU   r   rW   ra   rc   r_   rL   rM   s   @r   rO   rO      s5    ['HHJ G1 	 	&r   rO   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d3dZd Zd4d Zd4d!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(d5d1Z)d2 Z*y)6
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.
    r   rC         r            	   )
nsenfocdsbsebfobcdmcxmcxsxindicesbsecds   <   2   zwss://ws.kite.tradefullquoteltpT   	subscribeunsubscribemodei,  FNc	                    |xs | j                   | _        || j                  kD  rAt        j	                  dj                  | j                               | j                  | _        n|| _        || j                  k  rAt        j	                  dj                  | j                               | j                  | _        n|| _        || _	        dj                  | j                  ||      | _
        || _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        i | _        y)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}.z4{root}?api_key={api_key}&access_token={access_token})rootapi_keyaccess_tokenN)ROOT_URIr   _maximum_reconnect_max_triesr   warningr<   reconnect_max_tries_minimum_reconnect_max_delayreconnect_max_delayconnect_timeout
socket_urlr;   r   on_ticksr&   r0   r/   r   r*   rR   rS   on_order_updatesubscribed_tokens)	r   r   r   r;   r   	reconnectr   r   r   s	            r   r   zKiteTicker.__init__  sD   ( )DMM	 !B!BBKKv}}55 ~ 7 8'+'H'HD$':D$ !B!BBKKu||55 } 7 8'+'H'HD$':D$.++16YY) ,2 , 	 
   "  $ "$r   c                 x   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                  _        y)z%Create a WebSocket client connection.N)rO   r   r   r;   _on_openr&   	_on_errorr/   	_on_closer0   _on_messager*   _on_connectr   _on_reconnectrR   _on_noreconnectrS   r   rh   r   re   )r   urlr   s      r   _create_connectionzKiteTicker._create_connection  s    .s=f= ,,//!ZZ  $}} $ $"&"2"2"&"2"2$($6$6!&*&:&:# $ 8 8"&":":r   c                 >    t         dz   j                         t        z   S )Nz-python/)r   
capitalizer   r'   s    r   _user_agentzKiteTicker._user_agent  s    J&224{BBr   c                 n   ddi}| j                  | j                  | j                         ||       d}| j                  j                  r|st        j                         }t        | j                  || j                         | j                  r#t        j                  t        j                         i }t        j                  ss|r[d|d<   t!        j"                  t        j$                  |      | _        d	| j&                  _        | j&                  j+                          yt        j$                  d
i | yy)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  s     c

 	*.*:*:*<&+W 	  	>
 <<  )A!668O 	$,,H\H\]::$$SZZ0  05,-(1(8(8TX(Y%/3%%,%%++-#d# r   c                 x    | j                   r.| j                   j                  | j                   j                  k(  ryy)z-Check if WebSocket connection is established.TF)r   state
STATE_OPENr'   s    r   is_connectedzKiteTicker.is_connected  s(    77tww}}(:(::r   c                 V    | j                   r| j                   j                  ||       yyzClose the WebSocket connection.N)r   	sendCloser   r7   r8   s      r   _closezKiteTicker._close"  s"    77GGdF+ r   c                 H    | j                          | j                  ||       yr   )
stop_retryr   r   s      r   closezKiteTicker.close'  s    D&!r   c                 ,    t        j                          y)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   rf   r'   s    r   rf   zKiteTicker.stop,  s     	r   c                 R    | j                   r| j                   j                          yy)z'Stop auto retry when it is in progress.N)r   
stopTryingr'   s    r   r   zKiteTicker.stop_retry2  s    <<LL##% r   c           	      Z   	 | j                   j                  t        j                  t	        j
                  | j                  |d                   |D ]  }| j                  | j                  |<    y# t        $ r0}| j                  dj                  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: {}r8   N)r   sendMessagesixbjsondumps_message_subscribe
MODE_QUOTEr   	Exceptionr   r<   strr   instrument_tokenstokenes       r   r   zKiteTicker.subscribe7  s    	GGdjjt'>'>EV!WXY + @04&&u-@  	KK:AA#a&IKJ	s   A.A1 1	B*:+B%%B*c           	      b   	 | j                   j                  t        j                  t	        j
                  | j                  |d                   |D ]  }	 | j                  |=  y# t        $ r Y w xY w# t        $ r0}| j                  dj                  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.unsubscribeJ  s    	GGdjjt'@'@GX!YZ[ + //6      	KK<CCCFKKL	s<   AA5 A&#A5 &	A2/A5 1A22A5 5	B.>+B))B.c           	      J   	 | j                   j                  t        j                  t	        j
                  | j                  ||gd                   |D ]  }|| j                  |<    y# t        $ r0}| j                  dj                  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    	GGdjjt'<'<DJ[C\!]^_
 + 504&&u-5  	KK=DDSVLKM	s   A&A) )	B"2+BB"c                 d   i }| j                   D ];  }| j                   |   }|j                  |      sg ||<   ||   j                  |       = |D ]_  }| j                  r(t        j                  dj                  |||                | j                  ||          | j                  |||          a y)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.resubscribev  s    ++ 	#E&&u-A99Q<a!HOOE"	#  	-Dzz		=DDT5QU;WXNN5;'MM$d,	-r   c                 P    || _         | j                  r| j                  | |       y y N)r   r   )r   r   r!   s      r   r   zKiteTicker._on_connect  s#    ??OOD(+ r   c                     t         j                  dj                  |t        |                   | j                  r| j	                  | ||       yy)z3Call `on_close` callback when connection is closed.zConnection closed: {} - {}N)r   rZ   r<   r   r0   r   r   r7   r8   s       r   r   zKiteTicker._on_close  s<    		.55dCKHI==MM$f- r   c                     t         j                  dj                  |t        |                   | j                  r| j	                  | ||       yy)z9Call `on_error` callback when connection throws an error.zConnection error: {} - {}N)r   rZ   r<   r   r/   r   s       r   r   zKiteTicker._on_error  s<    		-44T3v;GH==MM$f- r   c                     | j                   r| j                  | ||       | j                  r1|r/t        |      dkD  r!| j                  | | j                  |             |s| j	                  |       yy)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`    ??OOD'95 ==Y3w<!+;MM$ 2 27 ;< $$W- r   c                     | j                   s| j                          d| _         | j                  r| j                  |       S y )NF)_is_first_connectr   r&   )r   r   s     r   r   zKiteTicker._on_open  s<    %% "'<<<<%% r   c                 @    | j                   r| j                  | |      S y r   )rR   )r   attempts_counts     r   r   zKiteTicker._on_reconnect  s#    $$T>:: r   c                 >    | j                   r| j                  |       S y r   )rS   r'   s    r   r   zKiteTicker._on_noreconnect  s!    &&t,, r   c                    t         j                  s#t        |      t        k(  r|j	                  d      }	 t        j                  |      }| j                  r:|j                  d      dk(  r&|j                  d      r| j                  | |d          |j                  d      dk(  r#| j                  | d|j                  d             yy# t        $ r Y yw xY w)zParse text message.zutf-8NtypeorderdatarZ   r   )r   PY2r   bytesdecoder   loads
ValueErrorr   r   r   )r   r+   r   s      r   r   zKiteTicker._parse_text_message  s     ww4=E1nnW-G	::g&D
 DHHV$4$?DHHVDT  tF|4 88Fw&NN4DHHV$45 '  		s   C 	CCc                 `	   | j                  |      }g }|D ]^  }| j                  |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(  r5|j	                  || j
                  || j                  |dd      |z  d       t        |      dk(  st        |      dk(  rt        |      dk(  r| j                  n| j                  }	||	|| j                  |dd      |z  | j                  |dd      |z  | j                  |dd      |z  | j                  |dd      |z  | j                  |dd      |z  dd}
d|
d<   |
d   d   dk7  r|
d   |
d   d   z
  dz  |
d   d   z  |
d<   t        |      dk(  r,	 t        j                  | j                  |dd            }||
d<   |j	                  |
       t        |      dk(  st        |      dk(  st        |      dk(  r| j                  n| j                  }	||	|| j                  |dd      |z  | j                  |dd      | j                  |dd      |z  | j                  |dd      | j                  |dd      | j                  |dd      | j                  |dd      |z  | j                  |dd      |z  | j                  |dd       |z  | j                  |d d      |z  d!d"
}
d|
d<   |
d   d   dk7  r|
d   |
d   d   z
  dz  |
d   d   z  |
d<   t        |      dk(  r1	 t        j                  | j                  |dd#            }	 t        j                  | j                  |d$d%            }||
d&<   | j                  |d#d'      |
d(<   | j                  |d'd)      |
d*<   | j                  |d)d$      |
d+<   ||
d<   g g d,}t        t        d%t        |      d            D ]k  \  }}||d-k\  rd.nd/   j	                  | j                  |||dz         | j                  ||dz   |dz         |z  | j                  ||dz   |d0z   d12      d3       m ||
d4<   |j	                  |
       a |S # t        $ r d}Y w xY w# t        $ r d}Y @w xY w# t        $ r d}Y +w xY w)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&  rP   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  sd   %%c* t	F#//1=&-G $++E22$D--e44! !(4+<+<Y+G GuTH 6{a ( MM(8"&"2"261a"@7"J	  V"c&kR&7*-f+*;t !) (8"&"2"261a"@7"J $ 0 0B ?' I#//B?'I $ 0 0R @7 J!%!1!1&"b!AG!K	  (fIg&!+#$\?QvYw5G#G3"NQRSYQZ[bQc"cAhK v;"$)$,$:$:4;K;KFTVXZ;[$\	 /8A*+AV"c&kS&8*-f+*;t !) (8"&"2"261a"@7"J,0,<,<VQ,K,0,<,<VR,Lw,V%)%5%5fb"%E*.*:*:62r*J+/+;+;FB+K $ 0 0R @7 J $ 0 0R @7 J#//B?'I!%!1!1&"b!AG!K	&  (fIg&!+#$\?QvYw5G#G3"NQRSYQZ[bQc"cAhK v;#%/*2*@*@AQAQRXZ\^`Aa*b)$,$:$:4;K;KFTVXZ;[$\	 ,;A'("..vr2>AdG'+'7'7B'GAm$&*&6&6vr2&FAlO.7A*+  " "E !*%CK*D E 1QfE:AA(,(8(8AE(J%)%5%5fa!eQU%Kg%U&*&6&6vq1ua"fZ]&6&^C  "'AgJAit	l K % )$(	)J % /*./
 % )$(	)s6   '&Q:4&R&R:R	R	RRR-,R-c                 @    t        j                  d|z   |||       d   S )z(Unpack binary data as unsgined interger.>r   )structunpack)r   r7  r   endr*  s        r   r0  zKiteTicker._unpack_intL  s#    }}S;.E#?BBr   c                     t        |      dk  rg S | j                  |ddd      }g }d}t        |      D ]?  }| j                  |||dz   d      }|j                  ||dz   |dz   |z           |dz   |z   }A |S )z.Split the data to individual packets of ticks.rC   r   r(  r)  )r   r0  r6  r   )r   r7  number_of_packetsr8  jr>  packet_lengths          r   r/  zKiteTicker._split_packetsP  s     s8a<I ,,S!QC,H() 	&A ,,S!QU,LMNN3q1ua!em&;<=A%A	&
 r   )FFN)NN)I)+rG   rH   rI   rJ   r1  CONNECT_TIMEOUTRECONNECT_MAX_DELAYRECONNECT_MAX_TRIESr   r3  r   r2  r   _message_coder   r   r   r   r   r   r   r   r   r   r   r   rf   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r0  r/  r   r   r   rj   rj      s   Xv  L  O %H IJH  M$( $% #& 495H^q!0C$J;*C)$V,
"
&
&,,-&,
...	&;-6&{zCr   rj   )rJ   r   r   r=   r   rB  loggingr   r   twisted.internetr   r   twisted.pythonr   r   twisted.internet.protocolr   autobahn.twisted.websocketr   r	   r
   r   r   	getLoggerrG   r   rO   objectrj   r   r   r   <module>rU     s     
       ) - ?& & 0g!jj6 jjZ?&46O ?&DS
 S
r   