o
    ̿SiU                     @  sv  d dl mZ d dlmZ d dlmZ d dlZd dlmZmZm	Z	m
Z
mZ d dlmZ d dlmZmZ d dlmZ ed	Zeed
dZeddZdYddZdZddZd[ddZd\ddZd[dd Zd[d!d"Zd]d$d%Zd^d'd(Zd_d*d+Z ddd,d`d6d7Z!d8dd9dad>d?Z"dbdAdBZ#dcdEdFZ$dddIdJZ%eG dKdL dLZ&dedOdPZ'dfdQdRZ(	SdgdhdUdVZ)	8didjdWdXZ*dS )k    )annotations)	dataclass)datetimeN)AnyDictListOptionalTuple)ZoneInfo)confidence_ranknormalize_confidence)ist_date_strzAsia/KolkataALERTS_MIN_SCORE85INTRADAY_ALERTS_COLLECTIONintraday_alertsnamestrdefaultfloatreturnc                 C  s   t | }|d u st| dkrt|S z tt| }||ks,|tdtdfv r1t|W S t|W S  tyB   t| Y S w )N inf-inf)osgetenvr   stripr   	Exception)r   r   rawv r    4/var/www/html/Trade-python/app/v1/services/alerts.py
_env_float   s   


r"   r   r   Optional[float]c                 C  s8   z| d u s
t | trW d S t| W S  ty   Y d S w N
isinstanceboolr   r   r   r    r    r!   _safe_float!   s   
r)   c                 C  s   t | pd  S Nr   r   r   upperr(   r    r    r!   _norm_symbol*   s   r-   intc                 C  s   t | S r$   )r   r(   r    r    r!   _confidence_score.   s   r/   c                 C  s   t | pd  }|S r*   r+   )r   sr    r    r!   _normalize_source2   s   r1   c                 C  s0   t | pd  }|dkrdS |dkrdS |S )Nr   LONGBUYSHORTSELLr+   )r   dr    r    r!   _normalize_decision7   s   r7   Dict[str, Any]c                   C  s   t ddg dddgdS )Nr        @U@)MANUALGAINERLOSEREARLY_MOVERSr3   r5   	min_scoresources	decisions)r"   r    r    r    r!   _default_alert_settingsA   s   rB   user_idc                C  s  | d  dt|iddipi }t|dtr|dni }t }t|d}|d u r4t|d}|d u r:d}|d}t|trF|sK|d}d	d
 |pQg D }|s_t|dp]g }|d}t|trk|sp|d}dd
 |pvg D }|st|dpg }t|||dS )Nuser_settingsrC   _idr   alertsr?   r9   r@   c                 S      g | ]}t |d v rt |qS    r<   r;   r:   r=   r1   .0r0   r    r    r!   
<listcomp>X   s
    z+get_user_alert_settings.<locals>.<listcomp>rA   c                 S  rG      r3   r5   r7   rL   r6   r    r    r!   rM   c   s     r>   )	find_oner   r&   getdictrB   r)   listr   )dbrC   docrF   defaultsr?   r@   rA   r    r    r!   get_user_alert_settingsJ   s.    



rY   settingsc                C  sF  t | t|d}t|tr|ni }t|d}|d u r!|d}|d ur)t|nd}tdtdt|}|d}|d}t|t	rT|rTdd |D }d	d |D }|s[|d}|d
}|d
}	t|t	rz|rzdd |D }	dd |	D }	|	s|d
}	t|||	d}
| d j
dt|idt||
t didd |
S )NrC   r?   r9                 Y@r@   c                 S     g | ]}t |qS r    rJ   rK   r    r    r!   rM   w       z.update_user_alert_settings.<locals>.<listcomp>c                 S     g | ]}|d v r|qS rH   r    rK   r    r    r!   rM   x       rA   c                 S  r^   r    rP   rQ   r    r    r!   rM      r_   c                 S  r`   rN   r    rQ   r    r    r!   rM      ra   r>   rD   rC   $set)rC   rF   
updated_atTupsert)rY   r   r&   rT   r)   rS   r   maxminrU   
update_oner   utcnow)rV   rC   rZ   currentincomingr?   
sources_inr@   decisions_inrA   mergedr    r    r!   update_user_alert_settingsj   s8   







ro   )market_datasnapshot_timestampsnapshot_idstock_idsymbolsourceanalysisrp   Optional[Dict[str, Any]]rq   Optional[datetime]c                  s  |r|r|rt |tsdS t|dp|d}|dvrdS t|d}	|	du r,dS t|}t|}
|
dvr:dS t |trA|nt }t	|}dBdd dC fdd}dD fdd}dE fdd}||t
||
|t|d|d|ddt|	t
||t d
}zK |d|d< |d|d< t
|dpd   pd|d< t
|d!pd   pd|d!< t
|d"pd  pd|d"<  |d#}|du rt |tr |d#}|durzt||d#< W n ty   ||d#< Y nw ||d$p|d%|d$<  |d&p|d'|d&< ||d(p#|d)p,||d*|d(<  |d+}t |trA|d,nd}t |tsKi } |d-pV|d.}|du r_|}|durjt||d+< t |d/trx|d/ni } |d0p|d1}|dur|dur|d2krt|t| }||d3< |t| d4 |d5< t
|d6p|d7pd   pd|d6< |||}|r||d8< W n
 ty   Y nw z"| t }|jd9d:gd;d< |j||d=|d>t id?d@dA |W S  ty
   Y dS w )FzPersist a single materialized alert row (upsert by day+symbol).

    This is intentionally global (not per-user). Per-user filtering happens at read-time.
    NdecisionactionrO   scorerI   r   r   r   r#   c                 S  sb   z&| d u s
t | trW d S t| }||ks|tdtdfv r"W d S t|W S  ty0   Y d S w )Nr   r   r%   )r   fr    r    r!   	_as_float   s   
z6upsert_intraday_alert_from_snapshot.<locals>._as_floatOptional[Dict[str, float]]c                   s   t | tsd S  d| v r| dn| d} d| v r!| dn| d}|d u s/|d u r1d S |dks9|dkr;d S ||k rD||}}t|t|dS )Nlowlowerhighr,   r   )r   r   )r&   rT   rS   r   )r   r   r   r}   r    r!   _as_zone   s   
  
z5upsert_intraday_alert_from_snapshot.<locals>._as_zoneOptional[List[float]]c                   s  t | tr)g }| D ]} |}|d ur|dkr|t| q	|r'|d d S d S t | tr | dpB| dpB| dpB| d} | dpS| dpS| d	}g }|d urf|dkrf|t| |d uru|dkru|t| |r}|d d S d S d S )
Nr      target_1t1target1targettarget_2t2target2)r&   rU   appendr   rT   rS   )r   outxr|   r   r   out2r   r    r!   _as_targets   s$   

,"z8upsert_intraday_alert_from_snapshot.<locals>._as_targetsar8   mdrw   Optional[Dict[str, int]]c                   s  t | tsdS t| dpd  }|dvrdS i }t |tr7|dp'i dp6|dp1i dp6i }t |ts>i } |d} |d	} |d
} |d} |d} |d}	g }
t| dpqd  }|dv r|
||dkrdndk |dur|dur|
|dkr||kn||k  |dur|dur|
|dkr||kn||k  |dur|
|dkr|dkn|dk |	dur|
|dkr|	dkn|	dk  | d}t |tr|
t| dd |
D }|sdS tdd |D }t	|t	t
|dS )zCompute a compact X/Y confirmations summary for the UI.

        This is intentionally simple and defensive: only counts checks we can evaluate.
        Nry   r   rO   
indicators15minute5minuteema9ema21vwapclosersi	macd_histtrend>   BEARISHBULLISHr3   r   r   g     K@g     F@r\   entry_trigger_firedc                 S  s   g | ]	}t |tr|qS r    )r&   r'   rL   cr    r    r!   rM     s    zYupsert_intraday_alert_from_snapshot.<locals>._indicator_confirmations.<locals>.<listcomp>c                 s  s    | ]}|rd V  qdS )   Nr    r   r    r    r!   	<genexpr>  s    zXupsert_intraday_alert_from_snapshot.<locals>._indicator_confirmations.<locals>.<genexpr>)	confirmedtotal)r&   rT   r   rS   r   r,   r   r'   sumr.   len)r   r   r6   indr   r   r   r   r   r   checksr   fired	evaluatedr   r   r    r!   _indicator_confirmations   sH   

,


zEupsert_intraday_alert_from_snapshot.<locals>._indicator_confirmations
confidencedecision_probabilityr   r{   )
ist_datert   rs   ru   ry   r   r{   rr   snapshot_tsrc   confidence_pctr   r   setuptrend_labelinstrument_token
entry_zoneentry_engine_entry_zoneexec_slentry_engine_exec_slexec_targetsentry_engine_exec_targetstargetscurrent_pricequote
last_priceltpohlcr   previous_closer   changer]   
change_pctsignal_stateentry_engine_signal_stateindicators_confirmed)r   r   )rt   r   ix_intraday_alerts_day_symbol)r   )r   rt   
created_at)rb   z$setOnInsertTrd   r   r   r   r#   )r   r   r   r~   )r   r   r   r   )r   r8   r   rw   r   r   )r&   rT   r7   rS   r)   r-   r1   r   ri   r   r   r   r   r   r,   r.   r   r   create_indexrh   )rV   rr   rs   rt   ru   rv   rp   rq   ry   r{   srcnowr   r   r   r   rW   tokr   r   r   r   
prev_closechgconfscolr    r   r!   #upsert_intraday_alert_from_snapshot   s   
8""

 2
r   
   )limitist_daycurrent_userr   r   Optional[str]c                C  s   t |pi d}t| |d}|pd pt }t|dpd}t|dp(g }t|dp1g }	|dt|id	}
|rFd
t|i|
d< |	rPd
t|	i|
d< | t 	|
ddi
ddgt|}t|}d||dt|i|dS )NrE   r[   r   r?   r\   r@   rA   z$gte)r   r{   $inru   ry   r   )r{   )r   r   oktop_signals)statusdayrZ   countsr   )r   rS   rY   r   r   r   setrU   r   findsortr   r.   r   )rV   r   r   r   rC   rZ   r   r?   allowed_sourcesallowed_decisionsqcurrowsr    r    r!   %get_materialized_top_signals_for_userh  s2   



r   tsc                 C  s<   t | tsd S | }|jd u r|jtdd}|tdS )NUTC)tzinfoz	%H:%M IST)r&   r   r   replacer
   
astimezoneISTstrftime)r   dtr    r    r!   _dt_to_ist_hm  s   

r   stocksnapc                 C  s  | dpi }t|tsi }| dp| dpd}t| dp$| d| d| dd	}t| d}| d
}t|trK| dpI| d}n| d}| d}	t|	trqzt|	dd}	W n t	yp   d }	Y nw | d}
t|
tr|
 dnd }t|tsi }| dp| dp| dpt| dt
tfr| dnd }| dpt| d| d| | d| dpd| d|d urt| nd|||| d|t|	tr|	 nd t|	trt|	nd |d}| d}|dv rd nd!|d"< |S )#Nrv   ry   rz   HOLDr   confidence_levelr   r{   r   r   entry_priceentry	timestampZz+00:00rp   r   r   r   r   priceanalysis_idrE   rs   r   exchangeNSEr   	stop_loss)r   rs   rt   r   r   r   ry   r   r{   r   r   r   r   time_istr   r3   r5   zEntry SignalMonitorsignal_label)rS   r&   rT   r   r)   r   r   fromisoformatr   r   r.   r   r,   	isoformatr   )rt   r   r   rv   ry   r   r{   r   r   r   r   r   r   r   decr    r    r!   _extract_from_analysis  sf   








 
r  prevcurrc                 C  s   | sdS g }|  d| dkr!|d|  d d| d  |  d| dkr<|d|  d d| d  dD ]}|  || |krY| |d urY|| d q>|rad	|S d
S )NNewry   z	decision u   →r   zconfidence )r   r   z updatedz; -)rS   r   join)r	  r
  partskeyr    r    r!   _what_changed  s   """r  c                   @  s   e Zd ZU ded< ded< dS )Universe	List[str]	stock_idsr   ru   N)__name__
__module____qualname____annotations__r    r    r    r!   r    s   
 r  
account_idr  c                 C  sx   |dd}|rd|idddiiddidd ig|d< | d  |d	d
i}g }|D ]}|d	}|r9||vr9|| q'|S )NACTIVE)rC   r   r  z$existsFr   z$oruser_portfolio_itemsrs   r   )r   rS   r   )rV   rC   r  queryr   r   rowsidr    r    r!   _portfolio_stock_ids  s"   


r  c                 C  sV   | d  i ddiddg|}g }|D ]}|d}|r(||vr(|| q|S )Nlive_moversrs   r   )rankr   )last_updatedr   )r   r   r   rS   r   )rV   r   r   r   r  r  r    r    r!   _et_movers_stock_ids  s   $

r"     limit_moversc           
      C  s   t |d}|dpd}t | pd }t|dpddk}t| ||}|s/t|ddS t| |d	}g }|| D ]}	|	rH|	|vrH||	 q;t|d
dS )NrE   r  r   roler   r   	portfolio)r  ru   )r   zportfolio+et_movers)r   rS   r   r.   r  r  r"  r   )
rV   r   r$  rC   r  is_super_adminportfolio_ids	mover_idsrn   r  r    r    r!    resolve_universe_for_top_signals  s   
r*  c                 C  s  t | |}|jsd|jddig dS t| d dd|jiiddddddd	}d
d |D }t| d dd|jiidddddd}dd |D }g }|jD ]}	||	}
|
sZqPt|
d}|sdqPt| d d|	idgd}|syqPt	||
|d }t
|dkrt	||
|d nd }t|||d< ||	pi }|d|d< |d|d< t|dpd }t|d}|d}t|ttfot|ttk}|dv r|r|| qPd"dd }|j|d! |d | }d|jdt
|i|dS )#Nr   r   r   )r   ru   r   r   stocksrs   r   r   )rE   rs   rt   r   r   r   c                 S  "   i | ]}| d r| d |qS rs   rS   rK   r    r    r!   
<dictcomp>=     " z+get_top_signals_service.<locals>.<dictcomp>r  )rE   rs   r   
mover_typer!  c                 S  r,  r-  r.  )rL   rr    r    r!   r/  E  r0  rt   stock_analysis_snapshots)r   r   r   what_changedr   r1  ry   r   r   r{   r  r  r8   r   Tuple[int, int, str]c                 S  sH   t | d}| d}t|trt|nd}| dpd}| ||fS )Nr   r   i'  r   r   )r/   rS   r&   r.   )r  conf_valr   rank_valr   r    r    r!   sort_keyg  s
   
z)get_top_signals_service.<locals>.sort_key)r  )r  r8   r   r5  )r*  r  ru   rU   r   rS   r-   r   r   r  r   r  r   r,   r/   r&   r.   r   r   r   )rV   r   r   unir+  by_id	live_rows
live_by_id
candidatesr  r   rt   snapsr
  r	  livery   confr{   score_okr8  topr    r    r!   get_top_signals_service)  sj   


$ 



rC  )r   r   r   r   r   r   r   )r   r   r   r   )r   r   r   r.   )r   r8   )rC   r   r   r8   )rC   r   rZ   r8   r   r8   )rr   r   rs   r   rt   r   ru   r   rv   r8   rp   rw   rq   rx   r   rw   )r   r8   r   r.   r   r   r   r8   )r   rx   r   r   )rt   r   r   r8   r   r8   r   r8   )r	  rw   r
  r8   r   r   )rC   r   r  r   r   r  )r   r.   r   r  )r#  )r   r8   r$  r.   r   r  )r   )r   r8   r   r.   r   r8   )+
__future__r   dataclassesr   r   r   typingr   r   r   r   r	   zoneinfor
   app.v1.utils.confidencer   r   "app.v1.services.intraday_watchlistr   r   r   r   r   r   r"   r)   r-   r/   r1   r7   rB   rY   ro   r   r   r   r  r  r  r  r"  r*  rC  r    r    r    r!   <module>   sL    


	





	
 + `
)
	
@

