
    ˨j                         S r SSKJr  SSKrSSS.rSS jrS rSS	 jrSS
 jrSS jr	S r
SS jrSS jrSS jrSS jrSS jr  SS jrg)u   
scanner_common.py — สูตรอินดิเคเตอร์และ pattern กลาง ใช้ร่วมกันทุกสแกนเนอร์
    )datetimeN)   r   )r      )USTHc                    U R                  5       nUR                  US:  S5      R                  US9R                  5       nUR                  US:  S5      * R                  US9R                  5       nX4S-   -  nSSSU-   -  -
  $ )Nr   )windowg&.>d      )diffwhererollingmean)seriesperioddeltagainlossrss         $/home/kit001/stock/scanner_common.pycalculate_rsir      s    KKMEKK	1%..f.=BBDD[[A&&//v/>CCED		B#R.!!    c                    U b  U R                   (       a  U S 4$  U R                  n[        USS 5      nUb  [        R                  " U5      O[        R                  " 5       nUS   R                  5       nXTR                  5       :w  a  U S 4$ [        R                  US5      u  pgUR                  UR                  4Xg4:  nU(       a  U S 4$ U R                  S S SU SUS SUS S34$ ! [         a    U S 4s $ f = f)	Ntz)   ;   u(   ตัดแท่งวันที่ u7    ทิ้ง (ตลาดยังไม่ปิด 02d:uS   ) -> ใช้แท่งที่ปิดแล้วล่าสุดแทน)emptyindexgetattrr   nowdateMARKET_CLOSEgethourminuteiloc	Exception)	dfmarketidxr   r#   	last_dateclose_hclose_malready_closeds	            r   drop_incomplete_last_barr2      s    	zRXX4xhhS$%"$.hll2hllnGLLN	
"t8O'++FH=((CJJ/G3EEt8Owws|6ykAxsm1WSM)|~
 	
  4xs   A0C' >C' 
C' 'C87C8c                 B    U S   R                  XS9R                  5       $ )NHigh)r	   min_periods)r   max)r+   r	   r5   s      r   rolling_highr7   .   s#    f:VEIIKKr   c                     U S   R                  S5      R                  U5      R                  5       nU S   U:  U S   U:  -  R                  S5      $ )NLowr   CloseF)shiftr   minfillna)r+   lookbackprev_lows      r   detect_liquidity_sweepr@   2   sP    %yq!))(3779HY!bkH&<=EEeLLr   c                 2   U S   U S   -
  R                  5       nU S   U S   -
  nU SS/   R                  SS9U S   -
  nU S   U SS/   R                  SS9-
  nUS:  XAU-  :  -  USU-  :  -  US	U-  :*  -  U S   U S   S
U-  -   :  -  R                  S5      $ )Nr:   Openr4   r9   r   )axisr   g?gffffff?g      ?F)absr<   r6   r=   )r+   	wick_multbodyrng
lower_wick
upper_wicks         r   detect_hammerrJ   7   s    wK"V*$))+D
V*r%y
 CVW%&***2RY>JFb&'!2377Q7??J 
qT))	+#	% #	% g;ES3Y..		0
 fUmr   c                     U S   U S   :  U S   R                  S5      U S   R                  S5      :  -  U S   U S   R                  S5      :  -  U S   U S   R                  S5      :*  -  R                  S5      $ )Nr:   rB   r   F)r;   r=   )r+   s    r   detect_bullish_engulfingrL   F   s    	Gr&z	!g;Q"V*"2"21"55	7g;"V***1--	/ f:G**1--	/ fUmr   c                 0    [        X5      [        U 5      -  $ )N)rJ   rL   )r+   rE   s     r   detect_pa_reversalrN   O   s    '*B2*FFFr   c                     U b  [        U 5      US-   :  a  gU S   R                  US-   * S R                  5       nU S   R                  S   nUS::  a  g[        U5      U[        U5      -  :  $ )u{   ตรวจจับ Volume Spike: Volume วันนี้ > threshold x เฉลี่ย window วันก่อนr   FVolumer   r   lenr)   r   float)r+   r	   	thresholdavg_vol
latest_vols        r   detect_volume_spikerW   S   su    	zSWvz)l&1*b1668GH""2&J!|y5>999r   c                     U b  [        U 5      US-   :  a  gU S   R                  US-   * S R                  5       nU S   R                  S   nUS::  a  g[        U5      [        U5      -  $ )um   คำนวณ ratio ของ Volume ล่าสุด vs เฉลี่ย (ใช้แสดงผล)r         ?rP   r   r   rQ   )r+   r	   rU   rV   s       r   detect_volume_ratiorZ   ^   sp    	zSWvz)l&1*b1668GH""2&J!|uW~--r   c                    U b  [        U 5      US-   :  a  gU S   R                  n[        U S   US9R                  n[        U5      S-
  n[        SXR-
  5      nXV::  a  gU[	        [
        R                  " X6U 5      R                  5       5      -   nX7   nXG   n	US   n
US   n[
        R                  " U	5      (       d  [
        R                  " U5      (       a  gX:  =(       a    X:  $ )uL  
ตรวจจับ RSI Bullish Divergence:
- Price ทำ Lower Low (ราคาต่ำกว่าจุดต่ำสุดก่อนหน้า)
- แต่ RSI ทำ Higher Low (RSI ไม่ได้ต่ำกว่าเดิม)
→ ขาลงอ่อนแรง มีโอกาสกลับตัว
   Fr:   )r   r   r   )	rR   valuesr   r6   intpdSeriesidxminisna)r+   
rsi_periodr>   closes
rsi_series	check_endcheck_startprev_low_idxprev_low_priceprev_low_rsicurrent_pricecurrent_rsis               r   detect_rsi_bullish_divergencerm   i   s     
zSWx!|+[Fr'{:>EEJ FaIa-.KRYYv)/L%M%T%T%V!WWL)N+L 2JMR.K	ww| 4 4 )Hk.HHr   c                 .    US:X  d  U S:w  a  U$ US:X  a  gg)NoffBEARblockc       )regime
base_scoremodes      r   regime_min_scorerx      s#    u}&(wr   c
                 Z   US::  a  SUS S3n
O1US::  a  SUS S3n
O#US::  a  SUS S3n
OUS	::  a  SUS S
3n
OSUS S3n
/ nU(       a  UR                  S5        U(       a  UR                  S5        U(       a  UR                  S5        U(       a  UR                  SU	S S35        U(       a  SR                  U5      OSn/ nU(       a  UR                  S5        U(       a  SR                  U5      OSnUS:  a  SnOUS:X  a  SnOUS:X  a  SnOSnU SU
 SU 3nU(       a  USU 3-  nU$ )um  
สร้างข้อความวิเคราะห์แบบ rule-based (ไม่ใช้ AI)
ใช้ค่า RSI / drawdown / สัญญาณที่คำนวณได้จริง มาประกอบเป็นคำอธิบาย
ผลลัพธ์คงที่ทุกครั้งที่รัน (deterministic)
r   zRSI z.0fuF    ต่ำมาก (oversold) เข้าโซนของถูก(   uD    เริ่มต่ำ มีโอกาสกลับตัว2   u;    ปานกลาง ยังไม่สุดทางF   u    ปกติu0    สูง (overbought) ระวังย่อu'   กวาดสภาพคล่องu!   แท่งกลับตัวu   ยืนเหนือ EMA9u   🔥 Volume z.1fz	x (spike)z + u?   ยังไม่มีสัญญาณกลับตัวu9   📈 RSI Divergence — ขาลงอ่อนแรงz |     u<   ✨ สัญญาณครบ 4 ด้าน (Prime Setup)rs   u0   ✨ สัญญาณ 3/4 แข็งแรง   u0   ✨ สัญญาณ 2/4 น่าสนใจu7   ○ รอสัญญาณเพิ่มเติมz: )appendjoin)drawdownrsisweeppaemascore	news_textvolume_spikersi_divergence	vol_ratiorsi_txtsigssig_txtextras	extra_txtheadresults                    r   make_verdictr      s[    byS	!gh	S	!ef	S	!\]	S	/S	!QR D=>	78
34l9S/;<"&ejj,mG FQR&,

6""I zM	!A	!AHvRyG9-FC	{##Mr   )   )   r   )r\   )g      ?)   g       @)r   )r   r   )r   	raise_bar)r}   FFrY   )__doc__r   pandasr_   r%   r   r2   r7   r@   rJ   rL   rN   rW   rZ   rm   rx   r   rt   r   r   <module>r      sl      
"0LM
G:.ID BDEH2r   