o
    SLNi<                  
   @   s  d dl Z d dlZ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 d dlmZmZmZmZ d dlmZmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ eeZ dZ!e"e#ddZ$e"e#ddZ%e"e#ddZ&e"e#ddZ'e"e#ddZ(e"e#ddZ)e * Z+de"de"de"de"fddZ,d0de-d e-de
ee-ef  fd!d"Z.de	e- fd#d$Z/d%e	e- d&ede0fd'd(Z1d1d)d*Z2d1d+d,Z3d2d-e
e" ddfd.d/Z4dS )3    N)datetime	timedelta)AnyDictListOptional)get_mongo_db)_get_global_user_id_get_global_account_id_get_global_zerodha_client_is_market_hours_ist)fetch_equity_index_symbolsshould_refresh_by_ttl)analyze_symbol_service)fetch_market_data) process_signal_and_market_update)normalize_confidence)score_market_datazNIFTY 50NIFTY50_REFRESH_MINUTES60NIFTY50_CRAWL_TTL_HOURS24NIFTY50_FRESHNESS_MINUTESNIFTY50_MAX_ANALYSES50NIFTY50_GPT_TOP_N25 NIFTY50_FEATURES_REFRESH_MINUTES10vlohireturnc                 C   s4   zt | } W n ty   | Y S w t|t|| S N)int	Exceptionmaxmin)r   r    r!    r(   @/var/www/html/Trade-python/app/v1/background/nifty50_intraday.py
_clamp_int+   s   r*   NSEsymbolexchangec                 C   s  |pd   }|sdS |pd   }t }| d ||dp*| d d|i}|sE||dd|d}| d |}i |d	|ji}|d
set|d	}| d 	d	|d	 idd
|ii ||d
< | d dt
| ddd|dddddddddd}	|	r|	dr|	d|	dp||	d|	d|	d|	d|	dp||d}
| d 	d	|d	 iddd |
 D i |dd |
 D  |S ) z@DB-only ensure for `stocks` + best-effort instrument enrichment. Nr+   stocks)r,   r-   r,   T)r,   r-   sector	is_active
created_at_idstock_id$setzerodha_instruments^$i)z$regexz$options)tradingsymbolr-   r      )r3   instrument_tokenr:   namesegment	tick_sizelot_sizer-   r<   r:   r=   r>   r?   r@   r-   )r<   r:   r=   r>   r?   r@   r-   instrument_updated_atc                 S      i | ]\}}|d ur||qS r#   r(   .0kr   r(   r(   r)   
<dictcomp>g       z*_ensure_stock_identity.<locals>.<dictcomp>c                 S   rB   r#   r(   rC   r(   r(   r)   rF   h   rG   )stripupperr   utcnowfind_one
insert_oneinserted_idgetstr
update_onereescapeitemsupdate)dbr,   r-   symnowstock	stock_docinsertedsidinstpatchr(   r(   r)   _ensure_stock_identity3   sX   &
 *
r^   c              	   C   s:  t  }ttdd}| d dti}t|tr|dnd }t|tr?t|dt	r?t
|||ds?dd	 |dp<g D S tt}|s`t|tr^t|dt	r^d
d	 |dp[g D S g S |D ]}zt| | W qb tyz   td| Y qbw | d jdtit||d|dd|iddd tdt|| |S )Nr;   i  index_constituentsindex
fetched_atsymbols)	ttl_hoursnow_utcc                 S   (   g | ]}t | rt |  qS r(   rO   rH   rI   rD   sr(   r(   r)   
<listcomp>z      ( z3_refresh_constituents_if_needed.<locals>.<listcomp>c                 S   re   r(   rf   rg   r(   r(   r)   ri      rj   z/[NIFTY50] Failed ensuring stock identity for %snseindia)r`   rb   ra   sourcerc   r2   )r5   z$setOnInsertT)upsertz:[NIFTY50] Constituents refreshed | symbols=%d ttl_hours=%d)r   rJ   r*   CRAWL_TTL_HOURSrK   _INDEX_NAME
isinstancedictrN   listr   r   r^   r%   logger	exceptionrP   infolen)rU   rW   rc   docra   rb   rV   r(   r(   r)   _refresh_constituents_if_neededm   sF   
rx   	stock_idscutoffc                 C   s`   |st  S z| d dd|id|id}dd |pg D W S  ty/   td t   Y S w )	Nstock_analysis_snapshotsr4   $in$gter4   	timestampc                 S   s   h | ]}|rt |qS r(   )rO   rD   xr(   r(   r)   	<setcomp>   s    z-_latest_snapshot_stock_ids.<locals>.<setcomp>z.[NIFTY50] Failed to compute fresh snapshot ids)setdistinctr%   rs   rt   )rU   ry   rz   idsr(   r(   r)   _latest_snapshot_stock_ids   s   

r   c           %         s  t  sddlm}m}m} td| ||  d S t| }|s'td d S t| }|s4t	d d S t
| }|sAt	d d S t| }t| d dd	|iid
d
d
d}dd |D }	g }
|D ]}|	|}|slqb|ddu rtqb|
| qb|
std d S ttd
d}t t|d }g }|
D ]}t|d}|dpd  }|r|sqi }zI| d j|d|idddgdd
d
d
dd}|rt|dtr|dpi }n|rt|dtr|dpi d|dpi dd }W n ty   i }Y nw |rt|tr|ds<|ds<zt||g d!| dd"}W n ty;   td#| i }Y nw t|}|||t|d$pLd%|d&t|d'pYd%d( q|sitd) d S |j d*d+ d,d- tt!d
d.}|d | }tt"d
d/}t t|d }d0d1 |D }t#| ||d2  fd3d1|D }|std4| d S tt$d
d5}|d | }d}|D ],}t|d}|dpd  }|r|sݐqzt%| ||g d6d7d8|d,d9}W n ty } ztd:|| W Y d }~qd }~ww t|tr|d;nd }t|tr#|r#|d nd } t&t|tr1|d<nd t|tr=|d=nd t|trI|d>nd d?}!t|trW|!|d<< |t |d@|!|dA|dB|dCpu|dDpu| |dEdF|t|tr|dnd t|tr|dnd dG}"d }#z| d '|"}$t|$j(}#W n ty   tdH| Y nw zt)| |||||t|tr|dnd dFdI|#|"dJdK W n ty   tdL| Y nw |d
7 }qtdM|t*| d S )NNr   backend_market_windowformat_windowlocal_time_str:[NIFTY50] Backend skipped due to time | now=%s | window=%sz-[NIFTY50] No constituents available; skippingz;[NIFTY50] Skipping cycle: global Zerodha client unavailablez*[NIFTY50] Global user_id missing; skippingr/   r,   r|   r;   )r4   r,   r1   c                 S   s.   i | ]}| d r| dpd  |qS )r4   r,   r.   )rN   rH   rI   rg   r(   r(   r)   rF      s   . z&_run_nifty50_cycle.<locals>.<dictcomp>r1   Fz&[NIFTY50] No eligible stocks; skipping<   )minutesr4   r.   r{   r}   r~   )r   )r3   r   )r3   market_datafeaturesr   )sort
projectionr   r   
indicators
strategies)r   r   )5minute15minuteday)zerodha_clientr,   
timeframesrU   include_quotez'[NIFTY50] Feature compute failed for %sopportunity        	directionquality)r4   r,   scorer   r   z"[NIFTY50] No scored rows; skippingc                 S   s$   t | dpdt | dpdfS )Nr   r   r   )floatrN   )r   r(   r(   r)   <lambda>     $ z$_run_nifty50_cycle.<locals>.<lambda>T)keyreverse2     c                 S   s$   g | ]}| d rt| d qS r4   )rN   rO   r   r(   r(   r)   ri     r   z&_run_nifty50_cycle.<locals>.<listcomp>)rz   c                    s"   g | ]}t |d  vr|qS r   )rO   rN   r   	fresh_idsr(   r)   ri     s   " z3[NIFTY50] Top ranked all fresh (<=%d min); skippingi  )r   r   30minuter   weekmonthzgeneral intraday analysisnifty50)rU   r   r,   r   questioncontextuser_idinclude_market_dataz$[NIFTY50] Analysis failed for %s: %stargets
confidencedecision_probabilityr   )r   r   decisionentry_price	stop_lossprice_targettarget	rationaleNIFTY50)r4   r   r   r   entryr   r   reasonrl   analysisr   r   z4[NIFTY50] Failed to persist analysis snapshot for %s60minuter   )rU   r   
account_idr4   r,   r   r   rl   preferred_timeframesnapshot_idsnapshot_timestampz0[NIFTY50] Paper trading simulation failed for %sz/[NIFTY50] Cycle finished | analyzed=%d stale=%d)+r   app.v1.utils.market_timer   r   r   rs   ru   rx   r   errorr	   r
   rr   findrN   appendr*   r   r   rJ   r   rO   rH   rI   rK   rp   rq   r%   r   rt   r   r   r   r   FRESHNESS_MINUTESr   MAX_ANALYSES_PER_CYCLEr   r   rL   rM   r   rv   )%rU   r   r   r   rb   r   r   r   r/   	by_symboleligiblerV   rowfeatures_refreshfeat_cutoffscored_rowsrr[   mdsnaprh   top_nrankedfreshness_minutesrz   eligible_ids
to_analyzemax_per_cycleanalyzedr   er   primary_targetconfsnapshot_docr   insr(   r   r)   _run_nifty50_cycle   s@  


$

*
>




r   c                  C   sz   t  } t| }zt| W z|   W d S  ty%   tjddd Y d S w z|   W w  ty<   tjddd Y w w )Nz$[NIFTY50] Error closing DB generatorT)exc_info)r   nextr   closer%   rs   debug)db_genrU   r(   r(   r)   _run_nifty50_cycle_syncn  s   
r   interval_secondsc              	      s,  t dI dH  ttdd}t| tr| dkr| n|d }td| 	 t sFddl	m
}m}m} td	| ||  t |I dH  q$t rXtd
 t |I dH  q$t4 I dH $ z
t tI dH  W n tyw   td Y nw W d  I dH  n1 I dH sw   Y  t |I dH  q%)a@  Background loop for NIFTY50 constituents.

    - Refreshes constituents list on a TTL (daily/weekly) via NSE API
    - Runs analysis only during IST market hours
    - Writes snapshots to `stock_analysis_snapshots` with source="NIFTY50"

    IMPORTANT: API endpoints must remain DB-only; this loop does Zerodha/GPT.
       Nr   r   r   z0[NIFTY50] Background loop started (interval=%ss)Tr   r   z:[NIFTY50] Previous cycle still running; skipping this tickz#[NIFTY50] Unexpected error in cycle)asynciosleepr*   REFRESH_MINUTESrp   r$   rs   ru   r   r   r   r   r   _NIFTY50_LOCKlocked	to_threadr   r%   rt   )r   refresh_minutesintervalr   r   r   r(   r(   r)   nifty50_intraday_loopz  s:   

(r   )r+   )r"   Nr#   )5r   loggingosrQ   r   r   typingr   r   r   r   app.db.databaser   !app.v1.background.global_intradayr	   r
   r   r   app.v1.libraries.nse_indicesr   r   app.v1.services.teGPTr   r   app.v1.services.paper_tradingr   app.v1.utils.confidencer   app.v1.utils.symbol_rankingr   	getLogger__name__rs   ro   r$   getenvr   rn   r   r   r   r   Lockr   r*   rO   r^   rx   r   r   r   r   r   r(   r(   r(   r)   <module>   s>    
$:0
 
D