o
    ̿Si)                     @   s  d dl Z d dlZd dlmZmZ d dlmZmZmZmZ d dl	m
Z
 e eZeeddZeddZeed	d
ZdededefddZdedee fddZdeeeef  dedeeeef  fddZdeeeef  deeeef  fddZdeeeef  deeeef  deeeef  fddZdddded ed!ed"eeeeef   d#ee ddfd$d%Zdd&ded ed!ed'edeeeef  d#ee ddfd(d)Zded'edeeeef  fd*d+Zddd,d-e
d.eeef dee d/eee  deeef f
d0d1ZdS )2    N)datetime	timedelta)AnyDictListOptional)ZerodhaClient!ZERODHA_MAX_HISTORICAL_RANGE_DAYS2000STOCK_HISTORY_COLLECTIONstock_historySTOCK_HISTORY_KEEP_DAY365nowfrm_dtreturnc                 C   s8   t dtt}| | j|kr| tt d|d d S |S )z;Ensure (now - frm_dt) does not exceed Zerodha max interval.   days)maxintr	   r   r   )r   r   max_days r   ;/var/www/html/Trade-python/app/v1/services/stock_history.py_cap_from_date   s   r   vc                 C   s   | du rdS t | tr:|  }|sdS zt|dd  W S  ty9   t	|dkr6|dd  Y S Y dS w t | trE|   S dS )z/Normalize candle date to an ISO YYYY-MM-DD key.NZz+00:00
   )

isinstancestrstripr   fromisoformatreplacedate	isoformat	Exceptionlen)r   sr   r   r   _as_date_key   s    

r(   candleskeepc                 C   s"   | sg S |dkr
g S | | d  S )Nr   r   )r)   r*   r   r   r   _trim/   s
   r+   recordsc                 C   s   | sg S g }| D ]6}t |tsqt|d}|sq||d|d|d|dd}d|v r9|d|d< || q|jdd	 d
 |S )zNormalize Kite historical records into our storage shape.

    Input is the raw list from `kite.historical_data` (via `get_historical_data_records`).
    Output uses ISO `YYYY-MM-DD` strings for `date`.
    r#   openhighlowclose)r#   r-   r.   r/   r0   volumec                 S   s   t | dpdS )Nr#    )r   get)xr   r   r   <lambda>P   s    z$_normalize_records.<locals>.<lambda>)key)r   dictr(   r3   appendsort)r,   outrkrowr   r   r   _normalize_records6   s(   
r>   existingincomingc                    s   | s|sg S i  | pg D ]}t |tsqt|d}|sqt|}||d< | |< q|p.g D ]}t |ts7q/t|d}|sAq/t|}||d< | |< q/ fddt  D S )zYMerge two candle arrays, de-duplicating by YYYY-MM-DD `date` (keep incoming on conflict).r#   c                    s   g | ]} | qS r   r   ).0r<   r:   r   r   
<listcomp>k   s    z*_merge_candles_by_date.<locals>.<listcomp>)r   r7   r(   r3   sortedkeys)r?   r@   r;   r<   rrr   rB   r   _merge_candles_by_dateT   s,   



rG   )day
updated_atstock_idsymbolexchangerH   rI   c           
      C   s
  |pt  }t|t|pd  t|pd  |ddd}i }d|d< d|d< d|d< d|d	< d|d
< d|d< d|d< d|d< |durht|t}|r`||d< t|d pXi d|d< nd|d< d|d< |d|id}	|ru||	d< | t	 j
dt|i|	dd dS )zStore daily candles for a stock.

    Minimal persistence model:
    - one doc per stock_id
    - only `day` candles are stored
    - `day_last_date` is stored for quick freshness checks
    r2   NSEZERODHA   )rJ   rK   rL   rI   sourceschema_versionr)   	day_count
week_countmonth_countweekmonthweek_last_datemonth_last_dateNrH   r#   day_last_date
created_at)z$setz$setOnInsertz$unsetrJ   T)upsert)r   utcnowr   r    upperr+   r   r(   r3   r   
update_one)
dbrJ   rK   rL   rH   rI   
set_fieldsunset_fieldsday_trimmedupdater   r   r   upsert_stock_history_bundlen   s8   	
 re   )rI   	timeframec                 C   sB   t |pd  }|dkrt| |||||d d S td| )Nr2   rH   r`   rJ   rK   rL   rH   rI   zUnsupported timeframe: )r   r    lowerre   
ValueError)r`   rJ   rK   rL   rf   r)   rI   tfr   r   r   upsert_stock_history   s
   
rk   c                    sF   t |pd  }|dkrg S dttt tf  f fdd}| S )Nr2   rH   r   c                     s    t  dtipi } | d}t|tr|S | d}t|tr3|dp)g }t|tr1|S g S  t  tdddddpDi }|dpKg }t|trS|S g S )NrJ   rH   r)   )rJ   rf   r   r   )_idr)   )r   find_oner   r3   r   listr7   )docday_arrcandles_objnestedlegacyr)   r`   rJ   r   r   _get_day_only   s   



$z(get_stock_history.<locals>._get_day_only)r   r    rh   r   r   r   )r`   rJ   rf   rj   ru   r   rt   r   get_stock_history   s
    rv   )r   
timeframeszerodha_clientstockrw   c              
   C   s  |pt  }|p
dg}t|dpd}|d}|dpd  }|dp*d  }|r7|du s7|s=d	d
|dS d||g d}	dd |pJg D }
d|
v }| t dt|idddddpci }|d}t|t	s|d}t|t
rt|dt	r|d}ng }|d}d}t|tr| rz	t | }W n ty   d}Y nw |dur|}n|tdd }t||}|d}|d}zT|jt|d||d}t|}|s|sd	||ddigdW S t||}|sd	||ddigdW S d}|rt|t}|r|	d d |rt| |||||d |	W S  tyD } ztd|| d	||dt|igdW  Y d}~S d}~ww ) zgFetch daily candles from Zerodha and store them.

    Intraday candles must never be written here.
    rH   rJ   r2   instrument_tokenrK   rL   rM   NFmissing_stock_id_or_token)okreasonrK   T)r|   rK   rJ   updatedc                 S   s   h | ]
}t |  qS r   )r   r    rh   )rA   rj   r   r   r   	<setcomp>   s    z2refresh_stock_history_for_stock.<locals>.<setcomp>r   r   )rl   rH   rZ   r)   r)   rZ   i  r   z%Y-%m-%d)interval	from_dateto_dateerrorno_day_candles_returned)r|   rK   rJ   errorsmerge_produced_emptyr~   rg   z History refresh failed | %s | %s)r   r]   r   r3   r    r^   r   rm   r   rn   r7   r!   r%   r   r   strftimeget_historical_data_recordsr   r>   rG   r+   r   r8   re   loggerwarning)r`   rx   ry   r   rw   rJ   tokenrK   rL   resultswantwant_dayexisting_docexisting_dayrq   last_slast_dtr   frmtorawr@   mergedday_outer   r   r   refresh_stock_history_for_stock   sx   

&








	$r   )loggingosr   r   typingr   r   r   r   app.v1.services.zerodha.clientr   	getLogger__name__r   r   getenvr	   r   r   r   r   r(   r+   r>   rG   re   rk   rv   r   r   r   r   r   <module>   sv    
.*: 
D	
" 


