o
    ii$                     @   s   d Z ddlZddlZ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mZ dd	l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 ee Z!G dd dZ"dS )u  
实时信号扫描器

M1核心：每小时扫描所有币种，检测新信号并推送

架构:
1. 每小时整点触发
2. 拉取最新K线 → 聚合 → 跑信号管线
3. 新信号 → 过滤 → 仓位计算 → Telegram推送
4. 记录到数据库
    N)DictListOptional)datetimetimezone   )COINSget_coin)settings)generate_long_signalsSignal)find_short_signals)SignalFiltercalc_trend_60d)calc_positioncalc_effective_equity)Database)TelegramNotifierc                
   @   s   e Zd ZdZ		ddedededee fdd	Zd
d Z	dd Z
dedefddZdeeeeejf f dee fddZdeeeeejf f dee fddZdS )LiveScanneru   
    实时信号扫描器

    用法:
        scanner = LiveScanner(db, notifier, balance=1000)
        new_signals = scanner.scan_all(all_tf_data)
         @@Ndbnotifierbalancemonth_start_balancec                 C   s8   || _ || _|| _|p|| _t | _t | _|   d S N)	r   r   r   r   r   signal_filtersetknown_signal_keys_restore_state)selfr   r   r   r    r     /opt/langlang_ai/live/scanner.py__init__'   s   
zLiveScanner.__init__c                 C   s   | j dd}t|| j_| j dddk| j_| j dd}|r&t|| _| j dd}|r4t|| _t	
d| jd	d
| jj d| jj  dS )u!   从数据库恢复过滤器状态consecutive_losses0	paused_4h1r    r   zState restored: balance=$z,.0fz, consecutive_losses=z, paused_4h=N)r   	get_stateintr   r#   r%   floatr   r   loggerinfo)r   consecbalmsbr    r    r!   r   9   s   

zLiveScanner._restore_statec                 C   s\   | j dt| jj | j d| jjrdnd | j dt| j | j dt| j dS )u   保存状态到数据库r#   r%   r&   r$   r   r   N)r   	set_statestrr   r#   r%   r   r   )r   r    r    r!   _save_stateK   s   zLiveScanner._save_statesigreturnc                 C   s&   |j  d|j d|j d|j  S )u*   生成信号唯一标识（用于去重）_)coin	directionsignal_type
entry_time	isoformat)r   r3   r    r    r!   _signal_keyR   s   &zLiveScanner._signal_keyall_tf_datac                    s  t tjd}td|  g }g }| D ]\}}|tvr"qt| }z)t	||d |d |d }|
| |D ]}	|	jdkrM|	jdv rM||	j q;W n tyl }
 ztd| d	|
  W Y d
}
~
nd
}
~
ww |jrzt||d }|
| W q ty }
 ztd| d	|
  W Y d
}
~
qd
}
~
ww q|jdd d tjjddtjdd   fdd|D }tdt| dt| d g }|di }|d}|D ](}| |}|| jv rq| j| ||ji }|d}|d
u s|jrqt|d j|d |j}d}|d
ur'|js't|d j|d |j}| j ||||\}}}t!| j"| j#}t$|j}|rXt%||j&|j|j|j'|d |ddd}n	dddd |j'd!}i d"|jd#|j(d$|jd%t)|jd&|j*d'|j+d(|j&d)|j,d*|j-d+|j.d,|j/d-|j0d.|j1d/|d0|d1|rd2ndd3||d4d|d4d|d5d|j'|ddd6}| j23|}|r|d7s|| td8|j d9|j( d9|j d:|j*d;d<|j+d;
 qt4d=|j d9|j d>|  q| 5  |S )?u   
        扫描所有币种，返回新信号列表

        Args:
            all_tf_data: {symbol: {'1H': df, '4H': df, '1D': df}}
        Returns:
            List of signal dicts (已通过过滤，包含仓位建议)
        z%Y-%m-%d %H:%M UTCzScanning all coins at 1H4H1DBTCUSDT)u   日线u   共振zLong signal error z: NzShort signal error c                 S   s   | j S r   r9   )sr    r    r!   <lambda>   s    z&LiveScanner.scan_all.<locals>.<lambda>)keyUTC)tz   )hoursc                    s   g | ]	}|j  kr|qS r    rA   ).0rB   cutoffr    r!   
<listcomp>   s    z(LiveScanner.scan_all.<locals>.<listcomp>zFound z total signals, z in last 24hclose	timestampg        position_multcross_resonanceF)equitysl_distancer6   r8   leveragerO   rP   r   T)marginnotionalposition_pctskiprS   r6   r7   r8   r9   entry_price	stop_lossrR   box_highbox_lowbox_width_pctbox_duration_barsvolume_ratioentry_methodbtc_trend_60dcoin_trend_60dfilter_passed   filter_reasonrV   rU   )suggested_position_pctrV   rU   rS   rP   rW   zNEW SIGNAL:  z @ $z,.2fz, SL=$z
Filtered: z - )6r   nowr   utcstrftimer+   r,   itemsr   r   extendr6   r8   appendr9   	Exceptionerrorallow_shortr   sortpd	Timestamp	Timedeltalengetr;   r   addemptyr   valuesr   check_signalr   r   r   r	   r   rR   rS   r7   r1   rX   rY   rZ   r[   r\   r]   r^   r_   r   save_signaldebugr2   )r   r<   	scan_timeall_signalsbtc_daily_breakout_timessymboltf_datacfg	long_sigsrB   e
short_sigsrecent_signalsnew_signalsbtc_tfbtc_1dr3   rD   coin_1d
coin_trend	btc_trendpassedreasonadjustmentseffective_equitypossignal_dict	signal_idr    rJ   r!   scan_allV   s  
""










	





"zLiveScanner.scan_allc                 C   s   g }| di }| d}| D ]9\}}|tvrq| d}|du s&|jr'q|d jd }|d jd }	t|d j|d |	}
||||
dd q|S )	u6   
        获取所有币种当前状态概览
        r@   r?   NrM   rN   F)r6   price	trend_60dhas_active_box)ru   rj   r   rw   ilocr   rx   rl   )r   r<   status_listr   r   r   r   df_1dr   rg   trendr    r    r!   get_coins_status   s&   


zLiveScanner.get_coins_status)r   N)__name__
__module____qualname____doc__r   r   r*   r   r"   r   r2   r   r1   r;   r   rq   	DataFramer   dictr   r   r    r    r    r!   r      s6    

 r   )#r   loggingpandasrq   typingr   r   r   r   r   config.coinsr   r	   configr
   Score.pipeliner   r   core.shortsr   core.filtersr   r   core.positionr   r   data.databaser   notify.telegram_botr   	getLoggerr   r+   r   r    r    r    r!   <module>   s    
