o
    hB                     @   s  d dl mZmZmZ d dl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mZ d dlmZmZmZmZmZ d dlmZ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"Z"d dl#Z#ej$j%j&ej'd e Z(e()ej* e(j+edgddgdgd dd Z,e(-dee,fde.de.de.de.de.defddZ/d dl mZ d dlmZmZ d dl	m0Z0 e(1ded ed!ed!edee,fde.de.de.de.d"eee.  defd#d$Z2e(1d%ee,fdefd&d'Z3e(1d(ed!ee,fd)e.defd*d+Z4dDd-d.Z5dDd/d0Z6dDd1d2Z7d3d4 Z8dDd5d6Z9dEd8d9Z:d:d; Z;e(1d<ed!ee,fde.de.de.d=e.d>ee. defd?d@Z<e(1dAdBdC Z=dS )F    )FastAPIDependsQuery)ListOptional)datetime	timedelta)and_)Session)modelsdatabase)fetch_kpi_dataparse_dotnet_dategenerate_date_rangefind_continuous_rangesstore_kpi_response)
InstrumentKPIKPIValue)SessionLocal)CORSMiddleware)admin_routes)	KPIFilterN)bind*T)allow_originsallow_credentialsallow_methodsallow_headersc                  c   s*    t  } z
| V  W |   d S |   w N)r   r   closedb r#   +/var/www/html/stock_analysis/be/app/main.pyget_db   s
   r%   z/fetch-kpis/token	frequencysymbol
start_dateend_dater"   c              
   C   s  dd | tj D }| ddidd |D |||dd|ddid	d
dgd}t| |}td t| |d d }	dd |	d D }
|	d d d d d }| tjj|d }|sttj|d}|	| |
  || |	d D ]m}|d }|d d d }|d d d}| tjj|d }|stj|d}|	| |
  || t|
|D ].\}}|d u rq| tjj|j|j||d }|stj|j|j||||d}|	| qqx|
  ddiS )Nc                 S      g | ]}|j qS r#   code.0kr#   r#   r$   
<listcomp>(       zfetch_kpis.<locals>.<listcomp>RequestAllMetadataTc                 S      g | ]	}|d didqS 
ReturnNameTValue
Propertiesr#   r/   r-   r#   r#   r$   r1   .          StartEnd	FrequencyKindr6   r7    	DataTypesDater   Tag
TokenValuer9   DataRequestsz<=============== Response from DataStream API ===============DataResponsesr   c                 S   s   g | ]}t |qS r#   )r   r/   dr#   r#   r$   r1   B       DatesDataTypeValuesSymbolValuesSymbolr(   DataTyper8   Currencyr,   )instrument_idkpi_idr'   date)rU   rV   r'   rW   valuecurrencymessagezKPI data fetched and stored.)queryr   r   allr   printr   	filter_byfirstaddcommitrefreshgetzipr   id)r&   r'   r(   r)   r*   r"   	kpi_codesbodyresponsedatadatesinstrument_symbol
instrumententrykpi_codevaluesrY   kpirW   rX   existingkpi_valr#   r#   r$   
fetch_kpis%   s~   





rs   )r   )funcz/kpis/Q.kpisc              	      s  t d}t|d }t|d }|rTdd  t D td fdd|D }	td|	 |	D ]}
 tj	|
d	
 sN t|
|
d
 q8   ndd  t D }	 tj	| d
 }|st| d} |     |  fdd|	D } tjtj|jktj|ktj|tj|ktj|ktjttjt|k }dd |D td t|||}td| tfdd|D }td| |rt||}td| |D ]/\}}|ddidd |	D | | |dd| ddidddgd}t||}t  | qi }|	D ]D}
 tj	|
d	
 }|s4q" ttj|jktj|jktj|ktj|ktj|k!tj }dd |D ||j"pd|j#< q"| |t$|t$||d S )!NDATASTREAM_API_TOKENz%Y-%m-%dc                 S   s   i | ]
}|j p	|j|jqS r#   )namer-   r.   r#   r#   r$   
<dictcomp>       zget_kpis.<locals>.<dictcomp>zName to Code Mapping:c                    s   g | ]}  ||qS r#   )rc   )r/   rx   )name_code_mapr#   r$   r1          zget_kpis.<locals>.<listcomp>zKPI Codes to Fetch:r,   r-   rx   c                 S   r+   r#   r,   r.   r#   r#   r$   r1      r2   rR   c                    s@   g | ]}  tjj|d  dur  tjj|d  qS )r,   N)r[   r   re   r^   scalarr:   r!   r#   r$   r1      s    c                 S   s   h | ]}|d  qS )r   r#   rK   r#   r#   r$   	<setcomp>   rM   zget_kpis.<locals>.<setcomp>zExisting Dates in DB:zFull Date Range:c                    s   g | ]}| vr|qS r#   r#   rK   )existing_datesr#   r$   r1      r|   zMissing Dates:zChunks:r3   Tc                 S   r4   r5   r#   r:   r#   r#   r$   r1      r;   r<   r=   r6   r7   rB   rC   rG   c                 S   s"   g | ]}t |j|j|jd qS ))rW   rX   rY   )strrW   rX   rY   )r/   rr#   r#   r$   r1      s    )r(   r'   r)   r*   rv   )%osgetenvr   strptimerW   r[   r   r\   r]   r^   r_   r`   ra   r   rb   r   filterrU   re   r'   rV   in_group_byhavingrt   countlenr   sortedr   	isoformatr   r   order_byrx   r-   r   )r(   r'   r)   r*   rv   r"   r&   startendrf   r-   rl   kpi_idsdb_dates
full_rangemissing_dateschunkschunk_start	chunk_endrg   rh   kpi_datarp   recordsr#   )r"   r   r{   r$   get_kpisu   s   
	








"









r   z/kpi-options/c                 C   s   |  t }dd |D S )Nc                 S   s    g | ]}|j |jp|j d qS )r}   r}   r.   r#   r#   r$   r1      s     z#get_kpi_options.<locals>.<listcomp>)r[   r   r\   )r"   rv   r#   r#   r$   get_kpi_options   s   r   z/symbol-search/r[   c                 C   s8   | ttjd|  dd }dd |D S )N%
   c                 S   s   g | ]	}|j |jd qS )r(   rx   r   r/   ir#   r#   r$   r1      r;   z!symbol_search.<locals>.<listcomp>)r[   r   r   r(   ilikelimitr\   )r[   r"   resultsr#   r#   r$   symbol_search   s   r   positivec                 C   s   dd | D }t ||k rdS |dkrt||||S |dkr#t||S |dkr.t||||S |dkr8t|||S |dkrBt|||S dS )	Nc                 S   s   g | ]
}|j d ur|j qS r   )rX   )r/   vr#   r#   r$   r1      rz   z)check_trend_condition.<locals>.<listcomp>Fconsecutive_growthnegative_to_positive
yoy_growthpost_transition_growthabsolute_threshold)r   check_consecutive_growthcheck_negative_to_positivecheck_yoy_growthcheck_post_transition_growthcheck_absolute_threshold)ro   
trend_typequarters	threshold	direction	data_listr#   r#   r$   check_trend_condition   s   
r   c                    s4   |dkrt  fdd| D S t  fdd| D S )Nr   c                 3   s     | ]}|d uo| kV  qd S r   r#   r/   rX   r   r#   r$   	<genexpr>      z+check_absolute_threshold.<locals>.<genexpr>c                 3   s     | ]}|d uo| kV  qd S r   r#   r   r   r#   r$   r     r   )any)r   r   r   r#   r   r$   r     s   r   c                    sx   t | k rdS dd t| | dd  D |dkr!fdd nfdd t fd	d
tt  d D S )NFc                 S   s<   g | ]\}}|d ur|d ur|dkr|| t | d qS )Nr   d   )abs)r/   prevcurrr#   r#   r$   r1     s    z,check_consecutive_growth.<locals>.<listcomp>r<   negativec                    s
   |   kS r   r#   gr   r#   r$   <lambda>%  s   
 z*check_consecutive_growth.<locals>.<lambda>c                    s   |  kS r   r#   r   r   r#   r$   r   '  s    c                 3   s6    | ]}t  fd d|| d  D V  qdS )c                 3   s    | ]} |V  qd S r   r#   )r/   r   )comparer#   r$   r   *  s    z5check_consecutive_growth.<locals>.<genexpr>.<genexpr>r<   N)r\   r   )r   growth_listr   r#   r$   r   )  s
    $
z+check_consecutive_growth.<locals>.<genexpr>   )r   rd   r   range)r   r   r   r   r#   )r   r   r   r   r$   r     s   r   c                 C   s   t | |k rdS tt | | d D ]+}| |||  }|d }tdd |d | D r=tdd ||d  D r= dS qdS )NFr<   r   c                 s   s     | ]}|d uo|dk V  qd S Nr   r#   r/   xr#   r#   r$   r   6  r   z-check_negative_to_positive.<locals>.<genexpr>c                 s   s     | ]}|d uo|dkV  qd S r   r#   r   r#   r#   r$   r   6  s    
T)r   r   r   r\   )r   r   r   segmenthalfr#   r#   r$   r   /  s   "
r   c                 C   s   t | |d k r
dS d}tdt | D ]P}| | d urc| |d  d urc| |d  dkrc| | | |d   t| |d   d }|dkrM|| krM|d7 }n|dkrZ||krZ|d7 }nd}||krc dS qdS )N   Fr   r   r   r<   T)r   r   r   )r   r   r   r   r   r   growthr#   r#   r$   r   =  s   ,(

r   r   c                 C   s   t t| | d D ]i}| | d urs| | dk rs| |d  d urs| |d  dkrsd}t |d |d | D ]8}| | d u sM| |d  d u sM| |d  dkrQd} n| | | |d   t| |d   d }||k rmd} nq5|rs dS q
dS )Nr<   r   TFr   )r   r   r   )r   quarters_afterr   r   	growth_okjr   r#   r#   r$   r   Q  s    8,(r   c                 C   s   |  tjj|d }|sdS |  tjtjj|ktjj|j	ktjj
|ktjj|ktjj|ktjj  }|rCt|dk rEdS |d}	t|dd}
t|dd}|dd	}t||	|
||}|rvt|d
d d}d|fS dS )z&Apply trend logic for advanced filtersr,   )FNr   trendr   r   r   r   r   c                 S   s   | j S r   )rW   )r   r#   r#   r$   r   z  s    z'apply_advanced_filter.<locals>.<lambda>)keyT)r[   r   r   r^   r_   r   r   rU   rV   re   r'   rW   r   ascr\   r   rc   intfloatr   max)r"   rU   rn   filter_datar'   r)   r*   rp   ro   r   r   r   r   passedlatest_valuer#   r#   r$   apply_advanced_filterb  s.   




r   z/filter-stocks/logical_operatorfiltersc              
   C   sf  dd |D }t d| |tj }g }|D ]}	g }
d}|D ]}|d }d|v rLt||	j||| ||\}}|rK|d7 }|
||jt	|j
d q!|d	 }t|d
 }|tjj|d }|seq!|tjtjj|	jktjj|jktjj| ktjj
|ktjj
|k}|dkr|tjj|k}nG|dkr|tjj|k}n9|dkr|tjj|k }n+|dkr|tjj|k}n|dkr|tjj|k}n|dkr|tjj|k}nq!|tjj
  }|r|d7 }|
||jt	|j
d q!| dkr|t|kr||	j|
d q| dkr)|dkr)||	j|
d qt d| d|iS )Nc                 S   s   g | ]}t |qS r#   )jsonloads)r/   fr#   r#   r$   r1     s    z%filter_stocks_get.<locals>.<listcomp>zlogical_operator ===>r   rn   r   r<   )rn   rX   rW   operatorrX   r,   gtgteltlteeqneAND)r(   
kpi_valuesORmatching_resultssymbols)r]   r[   r   r   r\   r   re   appendrX   r   rW   r   r   r^   r_   r   r   rU   rV   r'   r   descupperr   r(   )r'   r)   r*   r   r   r"   parsed_filtersinstrumentsr   rl   instrument_kpi_datafilter_pass_countr   rn   r   kpi_value_objr   rX   rp   kpi_values_queryr#   r#   r$   filter_stocks_get  s   





	

r   z/routesc                   C   s   dd t jD S )Nc                 S   r+   r#   )path)r/   router#   r#   r$   r1     r2   zlist_routes.<locals>.<listcomp>)approutesr#   r#   r#   r$   list_routes  s   r   )r   )r   r   )>fastapir   r   r   typingr   r   r   r   
sqlalchemyr	   sqlalchemy.ormr
   app.dbr   r   app.utils.datastream_apir   r   r   r   r   app.db.modelsr   r   r   app.db.databaser   fastapi.middleware.corsr   app.apir   app.schemasr   r   r   Basemetadata
create_allenginer   include_routerrouteradd_middlewarer%   postr   rs   rt   rc   r   r   r   r   r   r   r   r   r   r   r   r   r#   r#   r#   r$   <module>   s    ,J
r"





X