o
    ͿSi*                     @   sp   d dl mZmZ d dlmZmZ d dlZd dlZd dl	Z	d dl
Z
d dlZedZeej G dd dZdS )    )KiteConnect
KiteTicker)OptionalUnionNZerodhaClientc                   @   s  e Zd ZdMdededee fddZdedefd	d
Zde	ddfddZ
dNdede	fddZdefddZdedefddZdedefddZ								dOded e	d!eded"ed#ed$ed%ee d&ee d'ee	 d(ee defd)d*Zdefd+d,Zdefd-d.Zdefd/d0Zd1edefd2d3Zdefd4d5Zdefd6d7ZdMd8ee defd9d:Zd;edefd<d=Zd>edefd?d@Z	A	AdPdBeee	f dCedDedEedFedGedejfdHdIZdAdAdJdBeee	f dCedFedGedef
dKdLZ dS )Qr   Napi_key
api_secretaccess_tokenc                 C   sz   || _ || _|| _t| j d| _| jr| j| j i | _i | _tt	
dd| _tt	
dd| _tt	
dd| _d S )N)r   ZERODHA_MAX_RETRIES3ZERODHA_RETRY_BASE_SLEEP_SECz0.6ZERODHA_THROTTLE_SLEEP_SECz0.05)r   r   r	   r   kiteset_access_token_instruments_cache_instruments_cache_tsintosgetenv_max_retriesfloat_retry_base_sleep_throttle_sleep)selfr   r   r	    r   </var/www/html/Trade-python/app/v1/services/zerodha/client.py__init__   s   zZerodhaClient.__init__ereturnc                 C   s$   t | }d|v pd|v pd|v S )Nztoo many requests429z
rate limit)strlower)r   r   msgr   r   r   _should_retry    s   zZerodhaClient._should_retryattemptc                 C   s2   | j dt|d  }|t d  }t| d S )N   r   g333333?)r   maxrandomtimesleep)r   r$   delayr   r   r   _sleep_backoff$   s   zZerodhaClient._sleep_backoffNSE  exchangettl_secondsc           
      C   s   |pd   }t }| j|}|r$|| |k r$|| jv r$| j| S d}t| jd D ]H}z"| jdkr;t	| j | j
|}|| j|< t | j|< |W   S  tyu }	 z|	}|| jk rp| |	rp| | W Y d}	~	q- d}	~	ww |)z+Cached wrapper for Kite instruments master.r,   N   r   )stripupperr(   r   getr   ranger   r   r)   r   instruments	Exceptionr#   r+   )
r   r.   r/   exnowtslast_errr$   r5   r   r   r   r   get_instruments*   s.   




zZerodhaClient.get_instrumentsc                 C   s
   | j  S )zReturn the Kite login URL)r   	login_url)r   r   r   r   generate_login_urlD   s   
z ZerodhaClient.generate_login_urlrequest_tokenc              
   C   sb   z| j j|| jd}|d | _| j | j td |W S  ty0 } ztd |d}~ww )z'Exchange request_token for access_token)r>   r   r	   zZerodha session establishedz"Failed to generate Zerodha sessionN)	r   generate_sessionr   r	   r   loggerinfor6   	exception)r   r>   session_datar   r   r   r   r?   H   s   


zZerodhaClient.generate_sessionrefresh_tokenc              
   C   s\   z| j |}|d | _| j | j td |W S  ty- } ztd |d}~ww )z+(Optional) If using refresh token mechanismr	   zAccess token refreshedzFailed to refresh access tokenN)r   rD   r	   r   r@   rA   r6   rB   )r   rD   rC   r   r   r   r   rD   W   s   


zZerodhaClient.refresh_tokenMARKETCNCDAYsymbolquantitytransaction_type
order_typeproductvaliditypricetrigger_pricedisclosed_quantitytagc                 C   s   z.| j j|||||||||	|
|d}dd | D }| j jdi |}td|  |W S  tyD } z
td|  |d}~ww )zPlace a market order)varietytradingsymbolr.   rJ   rI   rK   rL   rM   rN   rO   rP   rQ   c                 S   s   i | ]\}}|d ur||qS Nr   ).0kvr   r   r   
<dictcomp>   s    z-ZerodhaClient.place_order.<locals>.<dictcomp>zOrder placed successfully: zOrder placement failed for Nr   )r   VARIETY_REGULARitemsplace_orderr@   rA   r6   rB   )r   rH   rI   rJ   r.   rK   rL   rM   rN   rO   rP   rQ   payloadorder_idr   r   r   r   r[   c   s.   zZerodhaClient.place_orderc              
   C   4   z| j  W S  ty } ztd |d }~ww )NzFailed to fetch profile)r   profiler6   r@   rB   r   r   r   r   r   get_profile      
zZerodhaClient.get_profilec              
   C   r^   )NzError fetching holdings)r   holdingsr6   r@   rB   r`   r   r   r   get_holdings   rb   zZerodhaClient.get_holdingsc              
   C   r^   )NzError fetching positions)r   	positionsr6   r@   rB   r`   r   r   r   get_positions   rb   zZerodhaClient.get_positionsr]   c              
   C   s8   z| j j|dW S  ty } ztd |d }~ww )N)r]   zError fetching order history)r   order_historyr6   r@   rB   )r   r]   r   r   r   r   get_order_history   s   
zZerodhaClient.get_order_historyc              
   C   r^   )NzError fetching orders)r   ordersr6   r@   rB   r`   r   r   r   
get_orders   rb   zZerodhaClient.get_ordersc              
   C   s4   z| j  W S  ty } ztd |d}~ww )zReturn recent executed trades (Kite tradebook).

        Note: KiteConnect returns the user's trades for the day/session.
        zError fetching tradesN)r   tradesr6   r@   rB   r`   r   r   r   
get_trades   s   
zZerodhaClient.get_tradessegmentc              
   C   sZ   z|rt | r| jt | W S | j W S  ty, } ztd |d}~ww )zReturn available margins (account-level).

        KiteConnect:
        - margins() => all segments
        - margins(segment) => specific segment, e.g. "equity"
        zError fetching marginsN)r    r1   r   marginsr6   r@   rB   )r   rm   r   r   r   r   get_margins   s   
zZerodhaClient.get_marginsri   c              
   C   s6   z| j |W S  ty } ztd |d}~ww )zReturn per-order margin requirements.

        Input: list of order dicts for KiteConnect `order_margins`.
        This is read-only and does not place orders.
        zError fetching order marginsN)r   order_marginsr6   r@   rB   )r   ri   r   r   r   r   get_order_margins   s   
zZerodhaClient.get_order_marginssymbolsc                 C   s   d}t | jd D ]?}z| jdkrt| j | j|W   S  tyH } z|}|| jk r>| |r>| 	| W Y d}~q	t
d  d}~ww t
d |)z%symbols = ['NSE:RELIANCE', 'NSE:TCS']Nr0   r   zError fetching quotes)r4   r   r   r(   r)   r   quoter6   r#   r+   r@   rB   )r   rr   r:   r$   r   r   r   r   	get_quote   s"   



zZerodhaClient.get_quoteFinstrument_tokeninterval	from_dateto_date
continuousoic                 C   s   d}t | jd D ]b}z4| jdkrt| j | jj||||||d}	t|	}
|
j	s;t
|
d |
d< |
jddd |
W   S  tyk } z |}|| jk r^| |r^| | W Y d}~q	td|   d}~ww td|  |)	zFetch historical OHLC dataNr0   r   ru   rw   rx   rv   ry   rz   dateT)inplacez Error fetching historical data: )r4   r   r   r(   r)   r   historical_datapd	DataFrameemptyto_datetime	set_indexr6   r#   r+   r@   error)r   ru   rv   rw   rx   ry   rz   r:   r$   datadfr   r   r   r   get_historical_data   s:   




z!ZerodhaClient.get_historical_data)ry   rz   c                C   s   d}t | jd D ]L}z| jdkrt| j | jj||||||d}	|	p&g W   S  tyU }
 z |
}|| jk rH| |
rH| 	| W Y d}
~
q	t
d|
   d}
~
ww t
d|  |)zFetch historical data as raw Kite records with retry/throttle.

        This is used for intraday-only snapshots where the caller wants the
        raw list (and does its own trimming/caching).
        Nr0   r   r{   z#Error fetching historical records: )r4   r   r   r(   r)   r   r~   r6   r#   r+   r@   r   )r   ru   rv   rw   rx   ry   rz   r:   r$   r   r   r   r   r   get_historical_data_records  s2   

z)ZerodhaClient.get_historical_data_recordsrT   )r,   r-   )r,   rE   rF   rG   NNNN)FF)!__name__
__module____qualname__r    r   r   r6   boolr#   r   r+   r;   r=   dictr?   rD   r   r[   ra   listrd   rf   rh   rj   rl   ro   rq   rt   r   r   r   r   r   r   r   r   r   r      s    	

(

.
	)kiteconnectr   r   typingr   r   pandasr   loggingr   r(   r'   	getLoggerr@   setLevelINFOr   r   r   r   r   <module>   s    
