o
    �ý¨jv2 ã                	   @   sô  U d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	m
Z
 d dl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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"m#Z# d dl$m%Z%m$Z$m&Z&m'Z'm(Z(m)Z)m*Z* d dl+m+Z+ d dl,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z; e <e=¡Z>e j? @dd¡ZAe j? @dd¡ZBdZCeDeBƒ E¡ aFdaGdd„ e j? @dd¡ Hd¡D ƒZIeBràeI JeDeBƒ E¡ ¡ dZKd÷deDdeLdeLdeLfdd„ZMeMdd d!d"�ZNeMd#d$d d"�ZOeMd%eOd& eOd! d"�ZPeMd'd d!d"�ZQeƒ ZRd aSd(ZTd)ZUd*ZVd+ZWd,ZXd-ZYd.ZZd/Z[d0Z\d1Z]eMd2d dd"�Z^d3d4iZ_h d5£Z`d6Zadabeced dB eed7< d afegeed8< d ahegeed9< daieddB eed:< dajeced dB eed;< d akegeed<< i aledeDedf eed=< deDfd>d?„ZmdødAeDddfdBdC„ZndeDfdDdE„ZodeceD fdFdG„ZpdHeDdeqfdIdJ„ZrdKedB deqfdLdM„ZsdNdO„ ZtdPdQ„ Zudeced fdRdS„Zvi awedeLeced f eedT< d axdayejzdB eedU< deLfdVdW„Z{dXeDdeDfdYdZ„Z|dXeDdeDfd[d\„Z}d]egdeDfd^d_„Z~d]egdeDfd`da„Zd]egdbeDdeDfdcdd„Z€deeDdeqfdfdg„Z�dXeDdeqfdhdi„Z‚djeddeqfdkdl„ZƒdmeDdeDdB fdndo„Z„dejzfdpdq„Z…dreceD dedeDegf fdsdt„Z†deced fdudv„Z‡dXeDdegdB fdwdx„ZˆdyeDdeceD fdzd{„Z‰d|eceD dedeDegf fd}d~„ZŠdyeDdeced fdd€„Z‹dyeDdeced fd�d‚„ZŒdyeDdeced fdƒd„„Z�d…eDdeddB fd†d‡„ZŽdXeDdeddB fdˆd‰„Z�d|eceD dedeDedf fdŠd‹„Z�dŒeDdeDdB fd�dŽ„Z‘deddB fd�d�„Z’dXeDdeddB fd‘d’„Z“d…eDdeddB fd“d”„Z”dXeDdeddB fd•d–„Z•d—Z–d˜Z—d™Z˜dKeddfdšd›„Z™dKedœejšfd�dž„Z›dKedœejšfdŸd „ZœdKedœejšfd¡d¢„Z�dKedœejšfd£d¤„ZždKedœejšfd¥d¦„ZŸdKedœejšfd§d¨„Z dKedœejšfd©dª„Z¡defd«d¬„Z¢d­eDdefd®d¯„Z£dKedœejšfd°d±„Z¤	²	dùdKed­eDd³eDd´eqfdµd¶„Z¥dKedœejšfd·d¸„Z¦dKedœejšfd¹dº„Z§dKedœejšfd»d¼„Z¨dKedœejšfd½d¾„Z©d¿eddeDfdÀdÁ„ZªdKedœejšfdÂdÃ„Z«dKedœejšfdÄdÅ„Z¬dKedœejšfdÆdÇ„Z­dKedœejšfdÈdÉ„Z®dKedœejšfdÊdË„Z¯dKedœejšfdÌdÍ„Z°dKedœejšfdÎdÏ„Z±dKedœejšfdÐdÑ„Z²dKedœejšfdÒdÓ„Z³dKedœejšfdÔdÕ„Z´dKedœejšfdÖd×„ZµdefdØdÙ„Z¶dÚeddfdÛdÜ„Z·dÝeddfdÞdß„Z¸dÝefdàdá„Z¹	dúdÝedeeDdâeqdeqfdãdä„ZºdÝedåeddeqfdædç„Z»dÝefdèdé„Z¼dÝefdêdë„Z½dÝefdìdí„Z¾dÝefdîdï„Z¿dÝefdðdñ„ZÀdòdó„ ZÁdûdÝedôeDdHeDdB fdõdö„ZÂdS )üé    N)Úwraps)Úunescape)ÚBytesIO)Ú
BotCommandÚInlineKeyboardButtonÚInlineKeyboardMarkupÚUpdate)ÚNetworkErrorÚTelegramError)ÚApplicationÚCallbackQueryHandlerÚCommandHandlerÚContextTypes)ÚdatetimeÚ	timedelta)ÚUpbitTraderÚreconstruct_virtual_account)Úrun_backtestÚformat_backtest_result)Ú
APP_LABELSÚapp_master_serviceÚapp_stat_categoriesÚformat_app_event_messageÚformat_app_stats_messageÚ	list_appsÚresolve_app_key)Úofficial_mail_service)Úsave_sessionÚsave_alertsÚclear_positionsÚload_sessionÚload_positionsÚload_alertsÚsave_bot_stateÚload_bot_stateÚhas_app_event_deliveryÚmark_app_event_deliveredÚcreate_notification_inviteÚconsume_notification_inviteÚsave_notification_subscriberÚload_notification_subscribersÚdelete_notification_subscriberÚTELEGRAM_BOT_TOKENÚ ÚTELEGRAM_CHAT_IDÚdefault_chat_idFc                 C   s   h | ]
}|  ¡ r|  ¡ ’qS © )Ústrip©Ú.0Úitemr0   r0   ú0/var/www/back/telegram_server/telegram_module.pyÚ	<setcomp>6   s    ýÿr6   ÚTELEGRAM_ALLOWED_CHAT_IDSú,Úapp_event_last_checked_até   ÚnameÚfallbackÚminimumÚreturnc              	   C   s6   zt |ttj | |¡ƒƒW S  ttfy   | Y S w ©N)ÚmaxÚintÚosÚenvironÚgetÚ	TypeErrorÚ
ValueError)r;   r<   r=   r0   r0   r5   Ú_positive_int_envA   s
   ÿrG   ÚAPP_MASTER_EVENT_POLL_SECONDSé
   é   )r=   ÚTELEGRAM_LONG_POLL_SECONDSé   ÚTELEGRAM_LONG_POLL_READ_TIMEOUTé   ÚTELEGRAM_CONNECT_TIMEOUTz+https://api.binance.com/api/v3/ticker/pricez+https://api.binance.com/api/v3/exchangeInfoz#https://api.upbit.com/v1/market/allzhttps://api.upbit.com/v1/tickerz3https://www.kebhana.com/cms/rate/wpfxd651_01i_01.doi,  z2https://query1.finance.yahoo.com/v1/finance/searchz:https://query1.finance.yahoo.com/v8/finance/chart/{symbol}z.https://kind.krx.co.kr/corpgeneral/corpList.doi`T  ÚALERT_POLL_SECONDSz
User-AgentzMozilla/5.0>   ÚASEÚNCMÚNGMÚNMSÚNYQÚPCX)ú.KSú.KQÚ_upbit_markets_cacheÚ_upbit_cache_timeÚ_rate_limit_untilÚ_hana_usd_krw_cacheÚ_krx_stocks_cacheÚ_krx_stocks_cache_timeÚ_notification_subscribersc                 C   s   | d u rdS t | ƒ ¡ S )Nr-   )Ústrr1   ©Úvaluer0   r0   r5   Ú_normalize_chat_idw   s   rc   ÚruntimeÚsourcec                 C   s:   t | ƒ}|sd S t|krt d|› d|› �¡ |adad S )NzDefault chat_id updated from ú: F)rc   Ú_runtime_chat_idÚloggerÚinfoÚ_missing_chat_id_warned)Úchat_idre   Ú
normalizedr0   r0   r5   Ú_set_default_chat_id}   s   rm   c                  C   s.   t tptƒ} | rda| S tst d¡ dadS )NFzLNo default chat_id set yet. Send any bot command once to bind notifications.Tr-   )rc   rg   ÚDEFAULT_CHAT_IDrj   rh   Úwarning©rk   r0   r0   r5   Ú_get_default_chat_idˆ   s   
rq   c                  C   sD   g } t ƒ }|r|  |¡ tD ]}t|ƒ}|r|| vr|  |¡ q| S r?   )rq   Úappendr_   rc   )ÚtargetsÚowner_chat_idrk   rl   r0   r0   r5   Ú%_get_operational_notification_targets”   s   

€ru   rk   c                 C   s&   t r| t v S ttp
tƒ}| p| |kS r?   )Ú_configured_allowed_chat_idsrc   rg   rn   )rk   Úcurrent_chat_idr0   r0   r5   Ú_is_authorized_chat    s   rx   Úupdatec                 Ã   sd   �| r| j sdS t| j jƒ}|sdS t|ƒst d|¡ dS |tkr0t|dd� tt	|ƒI d H  dS )NFz6Rejected Telegram command from unauthorized chat_id=%sztelegram command©re   T)
Úeffective_chatrc   Úidrx   rh   ro   rg   rm   r#   ÚCHAT_ID_STATE_KEY©ry   rk   r0   r0   r5   Ú_remember_chat_context§   s   €
r   c                    s$   t ˆ ƒdtdtjf‡ fdd„ƒ}|S )Nry   Úcontextc                 “   s\   �t | ƒI d H s&| jr| jjddd�I d H  d S | jr$| j d¡I d H  d S ˆ | |ƒI d H S )Nu,   ì�´ ë´‡ì�„ ì‚¬ìš©í•  ê¶Œí•œì�´ ì—†ìŠµë‹ˆë‹¤.T)Ú
show_alert)r   Úcallback_queryÚanswerÚeffective_messageÚ
reply_text©ry   r€   ©Úhandlerr0   r5   Úwrapped·   s   €þþz#_bind_chat_context.<locals>.wrapped)r   r   r   ÚDEFAULT_TYPE)rˆ   r‰   r0   r‡   r5   Ú_bind_chat_context¶   s   r‹   c           	   
   Ã   sÔ   �ddl }|  ¡ }|tk rt| }t d|d›d�¡ dS z| I dH W S  tyi } z:t|ƒ ¡ }d|v s9d|v rdddl}| d|¡}|rLt	| 
d	¡ƒnd
}|  ¡ | at d|› d�¡ W Y d}~dS ‚ d}~ww )u=   í…”ë ˆê·¸ëž¨ API í˜¸ì¶œ ëž˜í�¼ - 429 ë°œìƒ� ì‹œ ìž�ë�™ ëŒ€ê¸°r   NzRate limit active, skipping (z.0fzs remaining)zflood controlÚ429zretry in (\d+)r:   é<   zTelegram 429 - waiting Ús)Útimer[   rh   ro   Ú	Exceptionr`   ÚlowerÚreÚsearchrA   Úgroup)	Úcoror�   ÚnowÚwaitÚeÚerr_strr’   ÚmatchÚ
retry_secsr0   r0   r5   Ú_safe_telegram_callÇ   s*   €€örœ   c               
   Ã   sþ   �ddl } |   ¡ }tr|t dk rtS tƒ I dH }zG|jtddid�4 I dH š-}|jdkrJ| ¡ I dH }dd	„ |D ƒa|atW  d  ƒI dH  W S W d  ƒI dH  n1 I dH sZw   Y  W n tyz } zt	 
d
|› �¡ W Y d}~nd}~ww tp~g S )u3   ì—…ë¹„íŠ¸ KRW ë§ˆì¼“ ì½”ì�¸ ëª©ë¡� (ìº�ì‹œ 1ì‹œê°„)r   Ni  Ú
is_detailsÚfalse©ÚparamséÈ   c                 S   s   g | ]}|d    d¡r|‘qS )ÚmarketúKRW-)Ú
startswith)r3   Úmr0   r0   r5   Ú
<listcomp>ì   s
    ÿÿz&_get_upbit_markets.<locals>.<listcomp>zError fetching upbit markets: )r�   rY   rZ   Ú_get_sessionrD   ÚUPBIT_MARKET_URLÚstatusÚjsonr�   rh   Úerror)r�   r–   ÚsessionÚrespÚdatar˜   r0   r0   r5   Ú_get_upbit_marketsß   s0   €
ÿù(ÿ€€ÿr¯   Ú_alertsÚ_http_sessionc                   C   s   t d7 a t S )Nr:   )Ú_alert_id_counterr0   r0   r0   r5   Ú_next_alert_idü   s   r³   Úsymbolc                 C   sX   |   ¡  ¡ }| d¡r|dd … }| d¡r|d d… }t d|¡r*| dd¡d }|S )	Nr£   é   ÚUSDTéüÿÿÿú\d{6}\.(KS|KQ)Ú.r:   r   )Úupperr1   r¤   Úendswithr’   Ú	fullmatchÚsplit)r´   Úassetr0   r0   r5   Ú_normalize_asset_code  s   

r¿   c                 C   s   t | ƒ› d�S )Nr¶   )r¿   ©r´   r0   r0   r5   Ú_normalize_symbol  s   rÁ   rb   c                 C   sP   t | ƒ}|dkr| d›d�S |dkr| d›d�S |dkr"| d›d�S | d›d�S )	Néd   ú,.0fõ   ì›�r:   ú,.2fgš™™™™™¹?ú,.4fz,.6f)Úabs)rb   Ú	abs_valuer0   r0   r5   Ú_format_krw  s   rÉ   c                 C   s   d| d›�S )Nú$rÆ   r0   ra   r0   r0   r5   Ú_format_usd  s   rË   Úunitc                 C   s   |dkrt | ƒS t| ƒS )NÚKRW)rÉ   rË   )rb   rÌ   r0   r0   r5   Ú_format_price_by_unit   s   rÎ   Útextc                 C   s   t dd„ | D ƒƒS )Nc                 s   s(   � | ]}d |  kodkn  V  qdS )u   ê°€u   íž£Nr0   ©r3   Úchr0   r0   r5   Ú	<genexpr>'  s   €& z#_contains_hangul.<locals>.<genexpr>)Úany)rÏ   r0   r0   r5   Ú_contains_hangul&  s   rÔ   c                 C   s   |   d¡p	|  d¡S )Nr£   r¶   )r¤   r»   rÀ   r0   r0   r5   Ú_is_crypto_symbol*  s   rÕ   r4   c                 C   sP   |   d¡dkr	dS t|   d¡pdƒ ¡ }t|   d¡pdƒ ¡ }| t¡p'|tv S )NÚ	quoteTypeÚEQUITYFr´   r-   Úexchange)rD   r`   rº   r»   ÚYAHOO_SUPPORTED_KR_SUFFIXESÚYAHOO_SUPPORTED_US_EXCHANGES)r4   r´   rØ   r0   r0   r5   Ú_is_supported_stock_quote_item.  s
   rÛ   r¢   c                 C   s   | dv rdS | dkrdS d S )N>   õ   ìœ ê°€ì¦�ê¶Œõ   ìœ ê°€õ	   ì½”ìŠ¤í”¼rW   u	   ì½”ìŠ¤ë‹¥rX   r0   )r¢   r0   r0   r5   Ú_market_to_yahoo_suffix6  s
   rß   c                   Ã   s   �t d u st jrt ¡ a t S r?   )r±   ÚclosedÚaiohttpÚClientSessionr0   r0   r0   r5   r§   >  s   €r§   Úmarketsc           
      Ã   s$  �| si S t ƒ I d H }i }d}tdt| ƒ|ƒD ]x}| ||| … }zC|jtdd |¡id�4 I d H š&}|jdkrN| ¡ I d H }|D ]}t|d ƒ||d < qAW d   ƒI d H  n1 I d H s^w   Y  W n t	y~ }	 zt
 d	|	› �¡ W Y d }	~	nd }	~	ww || t| ƒk r�t d
¡I d H  q|S )Né2   r   rã   r8   rŸ   r¡   Útrade_pricer¢   zError fetching upbit prices: gš™™™™™©?)r§   ÚrangeÚlenrD   ÚUPBIT_TICKER_URLÚjoinr©   rª   Úfloatr�   rh   r«   ÚasyncioÚsleep)
rã   r¬   ÚpricesÚ
chunk_sizeÚiÚchunkr­   r®   r4   r˜   r0   r0   r5   Ú_get_upbit_pricesE  s:   €þ
€(ù€€ÿ€rñ   c               
   Ã   s¾  �t   ¡ } tr| t tk rtS tƒ I d H }zE|jtdddœtd�4 I d H š)}|jdkr:tp.g W  d   ƒI d H  W S |j	ddd�I d H }W d   ƒI d H  n1 I d H sTw   Y  W n t
yx } zt d	|› �¡ tpmg W  Y d }~S d }~ww t d
|tj¡}|s‡tp†g S g }|dd … D ]I}t d|tj¡}t|ƒdk r q�dd„ |D ƒ}	|	d }
|	d }|	d }t d|¡sºq�t|ƒ}|sÁq�|dkrÇdn|}| |› |› �||
||dœ¡ q�|a| a|S )NÚdownloadÚ13)ÚmethodÚ
searchType©r    Úheadersr¡   zeuc-krÚignore©ÚencodingÚerrorszError fetching KRX stock list: z<tr>(.*?)</tr>r:   z<t[dh][^>]*>(.*?)</t[dh]>é   c                 S   s*   g | ]}t t d d|¡ dd¡ ¡ ƒ‘qS )z<[^>]+>r-   z&nbsp;ú )r   r’   ÚsubÚreplacer1   )r3   Úcellr0   r0   r5   r¦   z  s    ÿÿz#_get_krx_stocks.<locals>.<listcomp>r   é   ú\d{6}rÝ   rÞ   )r´   Údisplay_symbolÚcompany_namer¢   Úcode)r�   r]   r^   ÚKRX_STOCK_CACHE_SECONDSr§   rD   ÚKRX_CORP_LIST_URLÚYAHOO_REQUEST_HEADERSr©   rÏ   r�   rh   r«   r’   ÚfindallÚSrç   r¼   rß   rr   )r–   r¬   r­   Úhtmlr˜   ÚrowsÚstocksÚrowÚcellsÚvaluesr  r¢   r  ÚsuffixÚmarket_labelr0   r0   r5   Ú_get_krx_stocks]  sl   €ý
ú(ù€€þþ
ûÿ
r  c              
   Ã   sÖ   �t ƒ I d H }zE|jtd| id�4 I d H š*}|jdkr3| ¡ I d H }t|d ƒW  d   ƒI d H  W S W d   ƒI d H  W d S 1 I d H sEw   Y  W d S  tyj } zt d| › d|› �¡ W Y d }~d S d }~ww )Nr´   rŸ   r¡   ÚpricezError fetching price for rf   )	r§   rD   ÚBINANCE_TICKER_URLr©   rª   rê   r�   rh   r«   )r´   r¬   r­   r®   r˜   r0   r0   r5   Ú
_get_price–  s$   €

ýÿúþ €þr  Úkeywordc              
   ƒ   s0  �t ƒ I dH }zu|jtddid�4 I dH šZ}|jdkrc| ¡ I dH }ˆ  ¡ ‰ g }|d D ]}|d dkrG|d	 d
krG|d }ˆ |v rG| |¡ q,|j‡ fdd„d� |dd… W  d  ƒI dH  W S W d  ƒI dH  W g S 1 I dH suw   Y  W g S  ty— } zt	 
d|› �¡ W Y d}~g S d}~ww )u,   ë°”ì�´ë‚¸ìŠ¤ì—�ì„œ USDT ë§ˆì¼“ ì‹¬ë³¼ ê²€ìƒ‰NÚpermissionsÚSPOTrŸ   r¡   ÚsymbolsÚ
quoteAssetr¶   r©   ÚTRADINGÚ	baseAssetc                    s   | ˆ kt | ƒ| fS r?   ©rç   )Úx©r  r0   r5   Ú<lambda>°  s    z!_search_symbols.<locals>.<lambda>©ÚkeyrL   zError searching symbols: )r§   rD   ÚBINANCE_EXCHANGE_URLr©   rª   rº   rr   Úsortr�   rh   r«   )r  r¬   r­   r®   ÚresultsrŽ   Úbaser˜   r0   r   r5   Ú_search_symbols¢  s6   €

€
õÿòþ€þr(  r  c              
   Ã   sú   �| si S t ƒ I d H }i }zTt | ¡}|jtd|id�4 I d H š4}|jdkr<| ¡ I d H }|D ]}t|d ƒ||d < q/W d   ƒI d H  W |S W d   ƒI d H  W |S 1 I d H sZw   Y  W |S  ty| } zt 	d|› �¡ W Y d }~|S d }~ww )Nr  rŸ   r¡   r  r´   zError fetching prices: )
r§   rª   ÚdumpsrD   r  r©   rê   r�   rh   r«   )r  r¬   rí   Úsymbols_paramr­   r®   r4   r˜   r0   r0   r5   Ú_get_prices·  s2   €

ýÿüýùþ€þr+  c           	      Ã   sÐ   �t ƒ I d H }|sg S |  ¡ } |  ¡ }g }|D ]=}|d }|d }| |ks1||ks1| |v s1||v rT| |kp8||k}| | ¡pB| |¡}| |rIdnd|rNdnd||f¡ q|jdd„ d� dd	„ |d d
… D ƒS )Nr  r  r   r:   c                 S   ó   | d d… S ©Nrü   r0   ©r4   r0   r0   r5   r!  ä  ó    z$_search_krx_stocks.<locals>.<lambda>r"  c                 S   ó   g | ]}|d  ‘qS ©rü   r0   r2   r0   r0   r5   r¦   å  ó    z&_search_krx_stocks.<locals>.<listcomp>é   )r  r1   rº   r¤   rr   r%  )	r  r  Úkeyword_upperÚmatchesÚstockr  r  ÚexactÚprefixr0   r0   r5   Ú_search_krx_stocksÈ  s4   €

üÿ€	r9  c                 Ã   sì  �|   ¡ } | rt| ƒrg S tƒ I d H }z?|jtd| itd�4 I d H š$}|jdkr5g W  d   ƒI d H  W S | ¡ I d H }W d   ƒI d H  n1 I d H sLw   Y  W n tyn } zt	 
d|› �¡ g W  Y d }~S d }~ww |  ¡ }g }tƒ }| dg ¡D ]d}t|ƒs…q~t| d¡pŒdƒ ¡ }	|	r–|	|v r—q~| |	¡ t|	ƒ}
| d¡p«| d	¡p«|	}| d
¡p·| d¡p·d}||	kp¿||
k}|	 |¡pÉ|
 |¡}| |rÐdnd|rÕdndt|	ƒ|	|
||dœf¡ q~|jdd„ d� dd„ |d d… D ƒS )NÚqrö   r¡   zError searching stocks: Úquotesr´   r-   ÚlongnameÚ	shortnameÚexchDisprØ   r   r:   ©r´   r  r  r¢   c                 S   r,  r-  r0   r.  r0   r0   r5   r!    r/  z&_search_yahoo_stocks.<locals>.<lambda>r"  c                 S   r0  r1  r0   r2   r0   r0   r5   r¦     r2  z(_search_yahoo_stocks.<locals>.<listcomp>r3  )r1   rÔ   r§   rD   ÚYAHOO_FINANCE_SEARCH_URLr  r©   rª   r�   rh   r«   rº   ÚsetrÛ   r`   Úaddr¿   r¤   rr   rç   r%  )r  r¬   r­   r®   r˜   r4  r&  Úseenr4   r´   r  r  r¢   r7  r8  r0   r0   r5   Ú_search_yahoo_stocksè  sf   €ý
ú(ù€€þ


üüÿrD  c                 Ã   s®   �g }t ƒ }t| ƒstdd„ | D ƒƒr0t| ƒI d H D ]}|d |v r#q| |d ¡ | |¡ qt| ƒsQt| ƒI d H D ]}|d |v rDq;| |d ¡ | |¡ q;|d d… S )Nc                 s   s   � | ]}|  ¡ V  qd S r?   )ÚisdigitrÐ   r0   r0   r5   rÒ      ó   € z!_search_stocks.<locals>.<genexpr>r´   r3  )rA  rÔ   rÓ   r9  rB  rr   rD  )r  r&  rC  r4   r0   r0   r5   Ú_search_stocks  s    €rG  Úqueryc                 ƒ   s^  �ˆ   ¡ ‰ ˆ  ¡ ‰t dˆ¡rˆˆ dd¡d d ddœS t dˆ¡rBtˆƒI d H }|D ]}|d ˆkr7|  S q+t|ƒdkrB|d S tˆ ƒrhtˆ ƒI d H }‡ fd	d
„|D ƒ}|r\|d S t|ƒdkrf|d S d S t ddˆ¡}t d|¡r~|t	|ƒd d dœS t
ˆ ƒI d H }‡fdd
„|D ƒ}|r”|d S ‡fdd
„|D ƒ}|r£|d S t|ƒdkr­|d S d S )Nr¸   r¹   r:   r   ÚKorear?  r  r  c                    s   g | ]
}|d  ˆ kr|‘qS )r  r0   r2   )rH  r0   r5   r¦   G  ó    z,_resolve_stock_candidate.<locals>.<listcomp>z\s+r-   z[A-Z0-9.\-]{1,15}c                    s(   g | ]}|d  ˆ ks|d ˆ kr|‘qS )r´   r  r0   r2   ©Úquery_upperr0   r5   r¦   X  s
    ÿc                    s*   g | ]}t | d ¡pdƒ ¡ ˆ kr|‘qS )r  r-   )r`   rD   rº   r2   rK  r0   r5   r¦   ^  s
    ÿ)r1   rº   r’   r¼   r½   r9  rç   rÔ   rþ   r¿   rD  )rH  Úkrx_matchesr4   Úexact_name_matchesÚdirect_symbolÚyahoo_matchesÚexact_symbol_matchesr0   )rH  rL  r5   Ú_resolve_stock_candidate1  s\   €üÿü
ÿ
ÿrR  c           	   
   Ã   s¶  �t ƒ I d H }zD|jtj| d�dddœtd�4 I d H š$}|jdkr.	 W d   ƒI d H  W d S | ¡ I d H }W d   ƒI d H  n1 I d H sEw   Y  W n tyi } zt 	d| › d|› �¡ W Y d }~d S d }~ww | d	¡ppi  d
¡pug }|szd S |d  d¡p‚i }t
| d¡pŠdƒ ¡ dkr’d S | d¡}|d u r | d¡}|d u r¦d S t
| d¡p­| ƒ ¡ }|t|ƒ| d¡pÀ| d¡pÀ|t
| d¡pÇdƒ ¡ t|ƒ| d¡pØ| d¡pØddœS )NrÀ   Ú1dÚ5d)Úintervalræ   rö   r¡   zError fetching stock quote for rf   ÚchartÚresultr   ÚmetaÚinstrumentTyper-   r×   ÚregularMarketPriceÚchartPreviousCloser´   ÚlongNameÚ	shortNameÚcurrencyÚfullExchangeNameÚexchangeName)r´   r  r  r^  r  r¢   )r§   rD   ÚYAHOO_FINANCE_CHART_URLÚformatr  r©   rª   r�   rh   r«   r`   rº   r¿   rê   )	r´   r¬   r­   r®   r˜   rW  rX  r  Úresolved_symbolr0   r0   r5   Ú_get_stock_quotei  sN   €
ý
ú(ù€€þ

úrd  c                 Ã   sx   �| si S t jdd„ | D ƒddiŽI d H }i }t| |ƒD ]\}}t|tƒr1t d|› d|› �¡ q|d ur9|||< q|S )Nc                 S   s   g | ]}t |ƒ‘qS r0   )rd  )r3   r´   r0   r0   r5   r¦   ”  r2  z%_get_stock_quotes.<locals>.<listcomp>Úreturn_exceptionsTz Error resolving stock quote for rf   )rë   ÚgatherÚzipÚ
isinstancer�   rh   r«   )r  r&  r;  r´   r4   r0   r0   r5   Ú_get_stock_quotes�  s"   €ÿþ
€ri  Ú
asset_codec                 Ã   s:   �d| › �}t ƒ I d H }|D ]}|d |kr|  S qd S )Nr£   r¢   )r¯   )rj  r¢   rã   r4   r0   r0   r5   Ú_find_upbit_market¡  s   €
ÿrk  c               
   Ã   sÄ  �t  ¡ } tr| td   ¡ }|tk rtS tƒ I d H }d|  d¡d|  d¡ddœ}z?|jt|d�4 I d H š'}|j	d	krH	 W d   ƒI d H  W d S |j
d
dd�I d H }W d   ƒI d H  n1 I d H sbw   Y  W n tyƒ } zt d|› �¡ W Y d }~d S d }~ww t d|tj¡}|s�d S t d| d¡¡}t|ƒdk r¡d S zt|d  dd¡ƒ}	W n
 ty·   Y d S w d }
d }t d|tj¡}|rØ| d¡› d| d¡› �}
| d¡}|	|
|d| dœatS )NÚ
fetched_atÚUSDz%Y-%m-%dÚ3z%Y%m%dÚ1)ÚcurCdÚtmpInqStrDtÚpbldDvCdÚinqStrDtÚ	inqKindCd)r®   r¡   úutf-8rø   rù   z#Error fetching Hana exchange rate: u-   <tr>\s*<td class=\"tc\">.*?ë¯¸êµ­ USD.*?</tr>z)<td class="txtAr">([\d,]+(?:\.\d+)?)</td>r   é   é   r8   r-   u€   ê³ ì‹œì�¼ì‹œ.*?(\d{4}ë…„\d{2}ì›”\d{2}ì�¼)\s*</strong>\s*<strong>(\d{2}ì‹œ\d{2}ë¶„\d{2}ì´ˆ)\s*</strong>\s*<strong>\((\d+)íšŒì°¨\)r:   rý   r  rü   u   í•˜ë‚˜ì�€í–‰ ë§¤ë§¤ê¸°ì¤€ìœ¨)ÚrateÚpublished_atÚsequencere   rl  )r   r–   r\   Útotal_secondsÚHANA_EXCHANGE_CACHE_SECONDSr§   ÚstrftimeÚpostÚHANA_EXCHANGE_QUERY_URLr©   rÏ   r�   rh   r«   r’   r“   r
  r	  r”   rç   rê   rÿ   rF   )r–   Úager¬   Úbodyr­   r  r˜   Ú	row_matchÚnumeric_cellsÚdeal_base_ratery  rz  Úpublished_matchr0   r0   r5   Ú_get_hana_usd_krw_rateª  sl   €û
þ(ý€€þÿý
ûr†  c           	      Ã   sÆ   �t | ƒ}t|ƒI d H }|r(t|gƒI d H }| |¡}|d ur(||d|dddœS t|ƒ}t|ƒI d H }|d u r9d S tƒ I d H }|d u rEd S ||d  }||d|dd||d |d | d	¡| d
¡dœS )NrÍ   u   ì—…ë¹„íŠ¸ KRW ë§ˆì¼“Ú
direct_krw)r¾   r´   Ú
price_unitÚcurrent_pricere   Údisplay_moderx  u+   Binance USDT x í•˜ë‚˜ì�€í–‰ ë§¤ë§¤ê¸°ì¤€ìœ¨Úconverted_krwre   ry  rz  )r¾   r´   rˆ  r‰  re   rŠ  Ú	usd_priceÚusd_krw_rateÚrate_sourceÚrate_published_atÚrate_sequence)r¿   rk  rñ   rD   rÁ   r  r†  )	r´   r¾   Úupbit_marketÚupbit_pricesÚupbit_priceÚbinance_symbolrŒ  Úfx_infoÚ	krw_pricer0   r0   r5   Ú_get_crypto_price_infoæ  sD   €
ú	õr—  c                 Ã   s$  �t | ƒI d H }|d u rd S t|d ƒI d H }|d u rd S | d¡p%|d }| d¡p.|d }| d¡p7|d }|d dkrRd|||d d|d d	|› � ¡ d
dœS |d dkrZd S tƒ I d H }|d u rfd S |d |d  }d|||d d|d	|› d� ¡ d|d |d |d | d¡| d¡dœS )Nr´   r  r  r¢   r^  rÍ   r6  r  zYahoo Finance r‡  )Ú
asset_typer¾   Údisplay_namer´   rˆ  r‰  re   rŠ  rm  rx  u    x í•˜ë‚˜ì�€í–‰ ë§¤ë§¤ê¸°ì¤€ìœ¨r‹  re   ry  rz  )r˜  r¾   r™  r´   rˆ  r‰  re   rŠ  rŒ  r�  rŽ  r�  r�  )rR  rd  rD   r1   r†  )rH  Ú	candidateÚquoter  r™  r¢   r•  r–  r0   r0   r5   Ú_get_stock_price_info  sP   €øórœ  c                 Ã   s2   �t | ƒI d H }|d urd|d< |S t| ƒI d H S )NÚcryptor˜  )r—  rœ  )r´   Úcrypto_price_infor0   r0   r5   Ú_get_price_infoB  s   €rŸ  u  ìš´ì˜� ê´€ë¦¬ & ì½”ì�¸ ìž�ë�™ë§¤ë§¤ ë´‡

[ì•± ê´€ë¦¬]
/apps - ê´€ë¦¬ ì•± ì„ íƒ� ë°� í†µê³„ ì¡°íšŒ
/stats [ì•±] - ì•± í†µê³„ ë°”ë¡œ ì¡°íšŒ

[ì•Œë¦¼]
/price <ì‹¬ë³¼> - ì½”ì�¸/ì£¼ì‹� ê°€ê²© ì¡°íšŒ (ê¸°ë³¸ ì›�í™”)
/coins <í‚¤ì›Œë“œ> - ì½”ì�¸ ê²€ìƒ‰
/stocks <í‚¤ì›Œë“œ> - ì£¼ì‹� ê²€ìƒ‰
/alert_above <ì‹¬ë³¼> <ê°€ê²©> - ì½”ì�¸/ì£¼ì‹� ì�´ìƒ� ì•Œë¦¼ (ì›�í™”)
/alert_below <ì‹¬ë³¼> <ê°€ê²©> - ì½”ì�¸/ì£¼ì‹� ì�´í•˜ ì•Œë¦¼ (ì›�í™”)
/alerts - ì•Œë¦¼ ëª©ë¡�
/remove <ë²ˆí˜¸> - ì•Œë¦¼ í•´ì œ
/remove_all - ì „ì²´ í•´ì œ

[ìš´ì˜� ì•Œë¦¼ ê³µìœ ]
/notify_invite - ë³´ì¡° ìˆ˜ì‹  ê³„ì • ì´ˆëŒ€ ì½”ë“œ ë°œê¸‰
/notify_join <ì´ˆëŒ€ì½”ë“œ> - ë³´ì¡° ê³„ì • ìš´ì˜� ì•Œë¦¼ ê°€ìž…
/notify_list - ìš´ì˜� ì•Œë¦¼ ìˆ˜ì‹  ê³„ì • ëª©ë¡�
/notify_remove <chat_id> - ë³´ì¡° ìˆ˜ì‹  ê³„ì • ì œê±°
/notify_leave - ë³´ì¡° ê³„ì • ìš´ì˜� ì•Œë¦¼ êµ¬ë�… í•´ì œ

[ìž�ë�™ë§¤ë§¤]
/auto_start <íˆ¬ìž�ê¸ˆ> [ê°€ìƒ�|ë³µë¦¬] - ì‹œìž‘
/auto_stop - ì¤‘ì§€ (ì „ëŸ‰ ë§¤ë�„)
/auto_status - í˜„í™©
/balance - ìž”ê³ 

[ë°±í…ŒìŠ¤íŠ¸]
/backtest <ì½”ì�¸> [ì�¼ìˆ˜] - ì „ëžµ ì‹œë®¬ë ˆì�´ì…˜ (ì˜ˆ: /backtest BTC 30)u  ìš´ì˜� ì•Œë¦¼ ìˆ˜ì‹  ê³„ì •

ê²°ì œ ì™„ë£ŒÂ·ë¬¸ì�˜Â·ë�„ë©”ì�¸ ì§€ì›� ë“±ì�˜ ìš´ì˜� ì•Œë¦¼ì�„ ë°›ìŠµë‹ˆë‹¤.
íŠ¸ë ˆì�´ë”© ëª…ë ¹, ê±°ëž˜ ì•Œë¦¼, ìž”ê³  ì •ë³´ëŠ” ì£¼ ê³„ì • ì „ìš©ìž…ë‹ˆë‹¤.

/notify_leave - ìš´ì˜� ì•Œë¦¼ êµ¬ë�… í•´ì œ
/start ë˜�ëŠ” /help - ì�´ ë�„ì›€ë§� í™•ì�¸u¸   ìš´ì˜� ì•Œë¦¼ì�„ ë°›ìœ¼ë ¤ë©´ ì£¼ ê³„ì •ì—�ì„œ ë°œê¸‰í•œ ì´ˆëŒ€ ì½”ë“œê°€ í•„ìš”í•©ë‹ˆë‹¤.
/notify_join <ì´ˆëŒ€ì½”ë“œ> - ìš´ì˜� ì•Œë¦¼ ê°€ìž…
/start ë˜�ëŠ” /help - ì�´ ë�„ì›€ë§� í™•ì�¸c                 Ã   sf   �t | ƒI d H r| j t¡I d H  d S t| jjƒ}|tv r(| j t¡I d H  d S | j t	¡I d H  d S r?   )
r   Úmessager…   Ú	HELP_TEXTrc   r{   r|   r_   ÚSUBSCRIBER_HELP_TEXTÚINVITE_HELP_TEXTr~   r0   r0   r5   Ú_reply_role_helpx  s   €r¤  r€   c                 Ã   ó   �t | ƒI d H  d S r?   ©r¤  r†   r0   r0   r5   Ú	cmd_start…  ó   €r§  c                 Ã   r¥  r?   r¦  r†   r0   r0   r5   Úcmd_help‰  r¨  r©  c                 Ã   s^   �t | jjƒ}t d¡ ¡ }t | d¡¡ 	¡ }t
||ƒI d H  | j d|› d�¡I d H  d S )Né   Úasciiu�   ìš´ì˜� ì•Œë¦¼ ì´ˆëŒ€ ì½”ë“œê°€ ìƒ�ì„±ë�˜ì—ˆìŠµë‹ˆë‹¤.

ë�™ìƒ� ê³„ì •ì—�ì„œ ì�´ ë´‡ê³¼ì�˜ ê°œì�¸ ì±„íŒ…ì�„ ì—´ê³  ì•„ëž˜ ëª…ë ¹ì�„ ë³´ë‚´ì„¸ìš”.
/notify_join uŸ   

ìœ íš¨ì‹œê°„: 15ë¶„ / 1íšŒë§Œ ì‚¬ìš© ê°€ëŠ¥
ë³´ì¡° ê³„ì •ì�€ ê²°ì œÂ·ë¬¸ì�˜ ë“± ìš´ì˜� ì•Œë¦¼ë§Œ ë°›ìœ¼ë©° íŠ¸ë ˆì�´ë”© ëª…ë ¹ì�€ ì‚¬ìš©í•  ìˆ˜ ì—†ìŠµë‹ˆë‹¤.)rc   r{   r|   ÚsecretsÚ	token_hexrº   ÚhashlibÚsha256ÚencodeÚ	hexdigestr'   r   r…   )ry   r€   rt   r  Ú
token_hashr0   r0   r5   Úcmd_notify_invite�  s   €þÿr³  c                 Ã   s’  �| j }|r|jdkr| j d¡I d H  d S t|jƒ}|tƒ kr+| j d¡I d H  d S |js9| j d¡I d H  d S |jd  	¡  
¡ }t | d¡¡ ¡ }t|ƒI d H s^| j d¡I d H  d S | j}|rf|jndd d	… }|rx|jrx|jd d	… nd }t|||ƒI d H  |||d
œt|< | j d¡I d H  tƒ }	|	rÇ|r d|› �n|}
z|jj|	d|
› d|› d�d�I d H  W d S  tyÆ   t d¡ Y d S w d S )NÚprivateuC   ê°œì�¸ ì±„íŒ…ì—�ì„œë§Œ ìš´ì˜� ì•Œë¦¼ì�„ êµ¬ë�…í•  ìˆ˜ ìžˆìŠµë‹ˆë‹¤.uA   ì£¼ ê³„ì •ì�€ ì�´ë¯¸ ëª¨ë“  ìš´ì˜� ì•Œë¦¼ì�„ ë°›ê³  ìžˆìŠµë‹ˆë‹¤.u&   ì‚¬ìš©ë²•: /notify_join <ì´ˆëŒ€ì½”ë“œ>r   ru  u>   ì´ˆëŒ€ ì½”ë“œê°€ ì˜¬ë°”ë¥´ì§€ ì•Šê±°ë‚˜ ë§Œë£Œë�˜ì—ˆìŠµë‹ˆë‹¤.u   ë³´ì¡° ìˆ˜ì‹  ê³„ì •rÂ   )rk   r™  ÚusernameuÝ   ìš´ì˜� ì•Œë¦¼ êµ¬ë�…ì�´ ì™„ë£Œë�˜ì—ˆìŠµë‹ˆë‹¤.
ê²°ì œ ì™„ë£ŒÂ·ë¬¸ì�˜Â·ë�„ë©”ì�¸ ì§€ì›� ë“±ì�˜ ì•Œë¦¼ì�„ í•¨ê»˜ ë°›ìŠµë‹ˆë‹¤.
íŠ¸ë ˆì�´ë”© ëª…ë ¹ê³¼ ê±°ëž˜ ì•Œë¦¼ì�€ ì£¼ ê³„ì • ì „ìš©ìž…ë‹ˆë‹¤.
êµ¬ë�… í•´ì œ: /notify_leaveú@u$   ìš´ì˜� ì•Œë¦¼ ìˆ˜ì‹  ê³„ì • ì¶”ê°€: ú (ú)©rk   rÏ   z+Failed to notify owner about new subscriber)r{   Útyper„   r…   rc   r|   rq   r   Úargsr1   rº   r®  r¯  r°  r±  r(   Úeffective_userÚ	full_namerµ  r)   r_   ÚbotÚsend_messager�   rh   Ú	exception)ry   r€   Úchatrk   r  r²  Úuserr™  rµ  rt   Úaccountr0   r0   r5   Úcmd_notify_join›  sP   €


ý
ÿþÿùrÄ  c                 Ã   sx   �t | jjƒ}|tƒ kr| j d¡I d H  d S t|ƒI d H }t |d ¡ |r1| j d¡I d H  d S | j d¡I d H  d S )Nu:   ì£¼ ê³„ì •ì�˜ ìš´ì˜� ì•Œë¦¼ì�€ í•´ì œí•  ìˆ˜ ì—†ìŠµë‹ˆë‹¤.u+   ìš´ì˜� ì•Œë¦¼ êµ¬ë�…ì�„ í•´ì œí–ˆìŠµë‹ˆë‹¤.u9   í˜„ìž¬ ìš´ì˜� ì•Œë¦¼ì�„ êµ¬ë�…í•˜ê³  ìžˆì§€ ì•ŠìŠµë‹ˆë‹¤.)	rc   r{   r|   rq   r   r…   r+   r_   Úpop©ry   r€   rk   Úremovedr0   r0   r5   Úcmd_notify_leaveË  s   €
rÈ  c                 Ã   s¢   �t s| j d¡I d H  d S dtt ƒ› d�g}t  ¡ D ]"}| d¡}|r)d|› �n| dd¡}| d|› d	|d
 › d�¡ q| d¡ | j d |¡¡I d H  d S )Nu6   ì¶”ê°€ë�œ ìš´ì˜� ì•Œë¦¼ ìˆ˜ì‹  ê³„ì •ì�´ ì—†ìŠµë‹ˆë‹¤.u   [ìš´ì˜� ì•Œë¦¼ ìˆ˜ì‹  ê³„ì •] u   ê°œrµ  r¶  r™  u   ì�´ë¦„ ì—†ì�Œz- r·  rk   r¸  u!   
ì œê±°: /notify_remove <chat_id>Ú
)r_   r   r…   rç   r  rD   rr   ré   )ry   r€   ÚlinesÚ
subscriberrµ  r;   r0   r0   r5   Úcmd_notify_listØ  s   €

rÌ  c                 Ã   s|   �|j s| j d¡I d H  d S t|j d ƒ}t|ƒI d H }t |d ¡ |r3| j d|› �¡I d H  d S | j d¡I d H  d S )Nu#   ì‚¬ìš©ë²•: /notify_remove <chat_id>r   u3   ìš´ì˜� ì•Œë¦¼ ìˆ˜ì‹  ê³„ì •ì�„ ì œê±°í–ˆìŠµë‹ˆë‹¤: u>   í•´ë‹¹ ìš´ì˜� ì•Œë¦¼ ìˆ˜ì‹  ê³„ì •ì�„ ì°¾ì�„ ìˆ˜ ì—†ìŠµë‹ˆë‹¤.)r»  r   r…   rc   r+   r_   rÅ  rÆ  r0   r0   r5   Úcmd_notify_removeå  s   €rÍ  c                     s6   dd„ t ƒ D ƒ‰ ‡ fdd„tdtˆ ƒdƒD ƒ} t| ƒS )Nc                 S   s&   g | ]}t |d  d|d › �d�‘qS )Úlabelzam:app:r#  ©Úcallback_data©r   )r3   Úappr0   r0   r5   r¦   ó  s    ÿÿz&_app_list_keyboard.<locals>.<listcomp>c                    ó   g | ]
}ˆ ||d  … ‘qS ©r  r0   ©r3   Úindex©Úbuttonsr0   r5   r¦   ÷  rJ  r   r  )r   ræ   rç   r   )r  r0   r×  r5   Ú_app_list_keyboardò  s
   þrÙ  Úapp_keyc                    sP   ‡ fdd„t ˆ ƒD ƒ‰‡fdd„tdtˆƒdƒD ƒ}| tddd�g¡ t|ƒS )	Nc                    s(   g | ]\}}t |d ˆ › d|› �d�‘qS )zam:stat:ú:rÏ  rÑ  )r3   ÚcategoryrÎ  )rÚ  r0   r5   r¦   ü  s    ÿÿz'_app_stats_keyboard.<locals>.<listcomp>c                    rÓ  rÔ  r0   rÕ  )Úcategory_buttonsr0   r5   r¦      s    ÿÿr   r  u   ë‹¤ë¥¸ ì•± ì„ íƒ�úam:listrÏ  )r   ræ   rç   rr   r   r   )rÚ  r  r0   )rÚ  rÝ  r5   Ú_app_stats_keyboardû  s   
þ
þrß  c                 Ã   s*   �| j jdttƒ› d�tƒ d�I d H  d S )Nõ   í˜„ìž¬ ê´€ë¦¬ ì¤‘ì�¸ ì•±ì�€ õ9   ê°œìž…ë‹ˆë‹¤.
í†µê³„ë¥¼ í™•ì�¸í•  ì•±ì�„ ì„ íƒ�í•˜ì„¸ìš”.©Úreply_markup)r   r…   rç   r   rÙ  r†   r0   r0   r5   Úcmd_apps  s
   €þrä  ÚoverviewrÜ  Úeditc                 Ã   sf   �t  ||¡I d H }t|||ƒ}t|ƒ}|r&| jr&| jj||d�I d H  d S | jj||d�I d H  d S )Nrâ  )r   Ústatsr   rß  r‚   Úedit_message_textr„   r…   )ry   rÚ  rÜ  ræ  r®   rÏ   Úkeyboardr0   r0   r5   Ú_send_app_stats  s   €
rê  c                 Ã   s�   �|j st| |ƒI d H  d S td |j ¡ƒ}|s#| j d¡I d H  d S zt| |ƒI d H  W d S  tyG   t 	d|¡ | j d¡I d H  Y d S w )Nrý   uO   ì•±ì�„ ì°¾ì�„ ìˆ˜ ì—†ìŠµë‹ˆë‹¤. /apps ì—�ì„œ ê´€ë¦¬ ì•±ì�„ ì„ íƒ�í•´ ì£¼ì„¸ìš”.z#App Master stats command failed: %suR   ì•± í†µê³„ë¥¼ ë¶ˆëŸ¬ì˜¤ì§€ ëª»í–ˆìŠµë‹ˆë‹¤. ìž ì‹œ í›„ ë‹¤ì‹œ ì‹œë�„í•´ ì£¼ì„¸ìš”.)
r»  rä  r   ré   r   r…   rê  r�   rh   rÀ  )ry   r€   rÚ  r0   r0   r5   Ú	cmd_stats  s    €
ÿþrë  c                 Ã   sj  �| j }| ¡ I d H  t|jpdƒ}z‡|dkr+|jdttƒ› d�tƒ d�I d H  W d S | d¡}t|ƒdkrY|d d… d	d
gkrYt	|d ƒ}|sLt
dƒ‚t| |dd�I d H  W d S t|ƒdkr–|d d… d	dgkr–t	|d ƒ}|d }dd„ t|pzdƒD ƒ}|r„||vrˆt
dƒ‚t| ||dd�I d H  W d S t
dƒ‚ ty´   t d|¡ |jdtƒ d�I d H  Y d S w )Nr-   rÞ  rà  rá  râ  rÛ  rü   r  ÚamrÒ  u!   ì§€ì›�í•˜ì§€ ì•ŠëŠ” ì•±ìž…ë‹ˆë‹¤.T)ræ  rµ   Ústatc                 S   s   h | ]}|d  ’qS )r   r0   r2   r0   r0   r5   r6   I  r2  z-handle_app_master_callback.<locals>.<setcomp>u$   ì§€ì›�í•˜ì§€ ì•ŠëŠ” í†µê³„ìž…ë‹ˆë‹¤.u$   ì§€ì›�í•˜ì§€ ì•ŠëŠ” ë©”ë‰´ìž…ë‹ˆë‹¤.zApp Master callback failed: %suG   ì•± í†µê³„ë¥¼ ë¶ˆëŸ¬ì˜¤ì§€ ëª»í–ˆìŠµë‹ˆë‹¤. ë‹¤ì‹œ ì„ íƒ�í•´ ì£¼ì„¸ìš”.)r‚   rƒ   r`   r®   rè  rç   r   rÙ  r½   r   rF   rê  r   r�   rh   rÀ  )ry   r€   rH  ÚcallbackÚpartsrÚ  rÜ  Úallowed_categoriesr0   r0   r5   Úhandle_app_master_callback/  sD   €þ
  þþrñ  c              	   Ã   s>  �|j s| j d¡I d H  d S d |j ¡}tƒ I d H }|s(| j d¡I d H  d S | ¡ }g }|D ],}|d  dd¡}| dd¡}| dd¡}	||v sT||v sT||	 ¡ v r\| |||	f¡ q0|sn| j d	|› d
�¡I d H  d S |d d… }d	|› d�g}
|D ]\}}}|
 d|› d|› d|› �¡ q}| j d |
¡¡I d H  d S )NuY   ì‚¬ìš©ë²•: /coins <í‚¤ì›Œë“œ>
ì˜ˆ: /coins ë¹„íŠ¸ì½”ì�¸
ì˜ˆ: /coins íŠ¸ë¡ 
ì˜ˆ: /coins BTCrý   u,   ì½”ì�¸ ëª©ë¡�ì�„ ê°€ì ¸ì˜¬ ìˆ˜ ì—†ìŠµë‹ˆë‹¤.r¢   r£   r-   Úkorean_nameÚenglish_nameú'u+   ' ê´€ë ¨ ì½”ì�¸ì�„ ì°¾ì�„ ìˆ˜ ì—†ìŠµë‹ˆë‹¤.r3  u(   ' ê²€ìƒ‰ ê²°ê³¼ (ì—…ë¹„íŠ¸ KRW ë§ˆì¼“):
ú  ú | rÉ  )	r»  r   r…   ré   r¯   rº   rÿ   rD   rr   )ry   r€   r  rã   r4  r&  r¥   r´   Úkr_nameÚen_namerÊ  ÚkrÚenr0   r0   r5   Ú	cmd_coinsX  s8   €€rû  c           	   	   Ã   sì   �|j s| j d¡I d H  d S d |j ¡ ¡ }t|ƒI d H }|s/| j d|› d�¡I d H  d S d|› d�g}|d d… D ]+}| d¡pHt|d ƒ}| d	¡pQ|d }| d
¡pXd}| d|› d|› d|› �¡ q<| j d |¡¡I d H  d S )Nu^   ì‚¬ìš©ë²•: /stocks <í‚¤ì›Œë“œ>
ì˜ˆ: /stocks ì‚¼ì„±ì „ìž�
ì˜ˆ: /stocks AAPL
ì˜ˆ: /stocks 005930rý   rô  u+   ' ê´€ë ¨ ì£¼ì‹�ì�„ ì°¾ì�„ ìˆ˜ ì—†ìŠµë‹ˆë‹¤.u   ' ì£¼ì‹� ê²€ìƒ‰ ê²°ê³¼:
r3  r  r´   r  r¢   ú-rõ  rö  rÉ  )	r»  r   r…   ré   r1   rG  rD   r¿   rr   )	ry   r€   r  r&  rÊ  r4   r´   r;   r¢   r0   r0   r5   Ú
cmd_stocksy  s    €rý  Ú
price_infoc                 C   sD   t |  d¡pdƒ ¡ }| d }|r | ¡ | ¡ kr |› d|› �S |S )Nr™  r-   r¾   rö  )r`   rD   r1   rº   )rþ  r™  r¾   r0   r0   r5   Ú_format_price_title�  s
   rÿ  c                 Ã   s  �|j s| j d¡I d H  d S t|j d ƒI d H }|d u r/| j d|j d › d�¡I d H  d S t|ƒ}|› dt|d ƒ› �d|d › �g}|d	 d
kr~| dt|d ƒ› d|d d›d�¡ | d¡r~| d¡}|rpd|› d�nd}| d|d › |› �¡ | j d 	|¡¡I d H  d S )NuT   ì‚¬ìš©ë²•: /price <ì‹¬ë³¼>
ì˜ˆ: /price BTC
ì˜ˆ: /price ì‚¼ì„±ì „ìž�
ì˜ˆ: /price AAPLr   rô  õ_   ' ê°€ê²©ì�„ ê°€ì ¸ì˜¬ ìˆ˜ ì—†ê±°ë‚˜ ì›�í™” í™˜ì‚°ìš© ê³ ì‹œí™˜ìœ¨ ì¡°íšŒì—� ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤.z (KRW): r‰  õ   ê¸°ì¤€: re   rŠ  r‹  õ   í™˜ì‚°ì‹�: rŒ  ú x r�  rÅ   rÄ   r�  r�  r·  õ   íšŒì°¨)r-   u   ê³ ì‹œì‹œê°�: rÉ  )
r»  r   r…   rŸ  rÿ  rÉ   rr   rË   rD   ré   )ry   r€   rþ  ÚdisplayrÊ  ÚseqÚseq_textr0   r0   r5   Ú	cmd_price•  s.   €
ÿþÿ

r  c                 Ã   óp  �t |jƒdk r| j d¡I d H  d S t|jd ƒI d H }z	t|jd ƒ}W n ty9   | j d¡I d H  Y d S w |d u rP| j d|jd › d�¡I d H  d S | jj}t	ƒ }t
 |g ¡ ||d |d	d
dœ¡ tt
ƒI d H  t|ƒ}d|› d�|› dt|ƒ› d�dt|d ƒ› �d|d › �g}|d dkrª| dt|d ƒ› d|d d›d�¡ | j d |¡¡I d H  d S )Nr  uo   ì‚¬ìš©ë²•: /alert_above <ì‹¬ë³¼> <ê°€ê²©>
ì˜ˆ: /alert_above BTC 100000000
ì˜ˆ: /alert_above ì‚¼ì„±ì „ìž� 300000r   r:   õ'   ê°€ê²©ì�€ ìˆ«ìž�ë¡œ ìž…ë ¥í•´ì£¼ì„¸ìš”.rô  r   r´   ÚaboverÍ   ©r|   r´   Útarget_priceÚ	directionrˆ  õ	   [ì•Œë¦¼ #õ   ] ì„¤ì • ì™„ë£Œrý   u    ì�´ìƒ� ë�„ë‹¬ ì‹œ ì•Œë¦¼õ   í˜„ìž¬ ê°€ê²©: r‰  r  re   rŠ  r‹  r  rŒ  r  r�  rÅ   rÄ   rÉ  ©rç   r»  r   r…   rŸ  rê   rF   r{   r|   r³   r°   Ú
setdefaultrr   r   rÿ  rÉ   rË   ré   ©ry   r€   rþ  r  rk   Úalert_idr  rÊ  r0   r0   r5   Úcmd_alert_above²  óN   €þ
ÿû
üÿÿr  c                 Ã   r	  )Nr  uf   ì‚¬ìš©ë²•: /alert_below <ì‹¬ë³¼> <ê°€ê²©>
ì˜ˆ: /alert_below BTC 90000000
ì˜ˆ: /alert_below AAPL 450000r   r:   r
  rô  r   r´   ÚbelowrÍ   r  r  r  rý   u    ì�´í•˜ ë�„ë‹¬ ì‹œ ì•Œë¦¼r  r‰  r  re   rŠ  r‹  r  rŒ  r  r�  rÅ   rÄ   rÉ  r  r  r0   r0   r5   Úcmd_alert_belowà  r  r  c           
      Ã   s¼   �| j j}t |g ¡}|s| j d¡I d H  d S dg}|D ]2}|d dkr'dnd}t|d ƒ}| dd	¡}t|d
 |ƒ}	| d|d › d|› d|	› d|› �¡ q| j d 	|¡¡I d H  d S )Nu!   ì„¤ì •ë�œ ì•Œë¦¼ì�´ ì—†ìŠµë‹ˆë‹¤.u   ì„¤ì •ë�œ ì•Œë¦¼ ëª©ë¡�:
r  r  õ   ì�´ìƒ�õ   ì�´í•˜r´   rˆ  rm  r  ú#r|   rö  rý   rÉ  )
r{   r|   r°   rD   r   r…   r¿   rÎ   rr   ré   )
ry   r€   rk   Úuser_alertsrÊ  Úalertr  r¾   rˆ  Útarget_textr0   r0   r5   Ú
cmd_alerts  s    €ÿr   c                 Ã   s*  �|j s| j d¡I d H  d S z	t|j d ƒ}W n ty+   | j d¡I d H  Y d S w | jj}t |g ¡}t	|ƒD ]K\}}|d |kr…| 
|¡}ttƒI d H  |d dkrXdnd}t|d	 ƒ}	| d
d¡}
t|d |
ƒ}| j d|› d|	› d|› d|› �¡I d H   d S q:| j d|› d�¡I d H  d S )Nu0   ì‚¬ìš©ë²•: /remove <ì•Œë¦¼ë²ˆí˜¸>
ì˜ˆ: /remove 1r   u.   ì•Œë¦¼ ë²ˆí˜¸ëŠ” ìˆ«ìž�ë¡œ ìž…ë ¥í•´ì£¼ì„¸ìš”.r|   r  r  r  r  r´   rˆ  rm  r  u   ì•Œë¦¼ #u    í•´ì œ ì™„ë£Œ
rý   u   ë¥¼ ì°¾ì�„ ìˆ˜ ì—†ìŠµë‹ˆë‹¤.)r»  r   r…   rA   rF   r{   r|   r°   rD   Ú	enumeraterÅ  r   r¿   rÎ   )ry   r€   r  rk   r  rï   r  rÇ  r  r¾   rˆ  r  r0   r0   r5   Ú
cmd_remove#  s@   €þ
ÿÿÿ
ÿõr"  c                 Ã   sN   �| j j}tt |g ¡ƒ}g t|< ttƒI d H  | j d|› d�¡I d H  d S )Nu!   ëª¨ë“  ì•Œë¦¼ í•´ì œ ì™„ë£Œ (ì´� u   ê°œ))r{   r|   rç   r°   rD   r   r   r…   )ry   r€   rk   Úcountr0   r0   r5   Úcmd_remove_allB  s   €r$  c           	      Ã   s  �t jr| j d¡I d H  d S |js| j d¡I d H  d S z	t|jd ƒ}W n ty9   | j d¡I d H  Y d S w |dk rI| j d¡I d H  d S dd„ |jd	d … D ƒ}td
d„ |D ƒƒ}tdd„ |D ƒƒ}|rwdt _t	|ƒt _
t j ¡  n2dt _t  ¡ s‰| j d¡I d H  d S t  d¡I d H }||k r©| j d|d›d|d›d�¡I d H  d S |t _|t _dt _dt _t j ¡  t j ¡  dt _t ¡  d¡t _t  ¡  tt ƒI d H  tƒ I d H  |râd}d}n|réd}d}nd}d}| j d|› d|d›d|› dt j› d �	¡I d H  d S )!Nu3   ì�´ë¯¸ ì‹¤í–‰ ì¤‘ìž…ë‹ˆë‹¤.
/auto_status ë¡œ í™•ì�¸uã   ì‚¬ìš©ë²•: /auto_start <íˆ¬ìž�ê¸ˆ> [ì˜µì…˜]
ì˜ˆ: /auto_start 500000
ì˜ˆ: /auto_start 100000 ê°€ìƒ�
ì˜ˆ: /auto_start 500000 ë³µë¦¬

ì˜µì…˜:
  ê°€ìƒ� - ì‹¤ì œ ì£¼ë¬¸ ì—†ì�´ ê°€ìƒ�ë¨¸ë‹ˆë¡œ í…ŒìŠ¤íŠ¸
  ë³µë¦¬ - ìˆ˜ì�µê¸ˆ ìž¬íˆ¬ìž�r   u*   íˆ¬ìž�ê¸ˆì�€ ìˆ«ìž�ë¡œ ìž…ë ¥í•´ì£¼ì„¸ìš”.iPÃ  u'   ìµœì†Œ íˆ¬ìž�ê¸ˆì�€ 50,000ì›�ìž…ë‹ˆë‹¤.c                 S   s   g | ]}|  ¡ ‘qS r0   )r‘   ©r3   Úar0   r0   r5   r¦   h  r2  z"cmd_auto_start.<locals>.<listcomp>r:   c                 s   ó   � | ]}|d v V  qdS ))õ   ê°€ìƒ�Úpaperu	   í…ŒìŠ¤íŠ¸u   ì‹œë®¬Nr0   ©r3   Úor0   r0   r5   rÒ   i  rF  z!cmd_auto_start.<locals>.<genexpr>c                 s   r'  ))õ   ë³µë¦¬ÚcompoundNr0   r*  r0   r0   r5   rÒ   j  rF  TFu   UPBIT_ACCESS_KEY / UPBIT_SECRET_KEY í™˜ê²½ë³€ìˆ˜ê°€ ì„¤ì •ë�˜ì§€ ì•Šì•˜ìŠµë‹ˆë‹¤.
ê°€ìƒ� ëª¨ë“œ: /auto_start <íˆ¬ìž�ê¸ˆ> ê°€ìƒ�rÍ   u   ìž”ê³  ë¶€ì¡±
ë³´ìœ : rÃ   u   ì›� / í•„ìš”: rÄ   ç        z%Y-%m-%d %H:%M:%Su    [ê°€ìƒ�ë¨¸ë‹ˆ ëª¨ë“œ]u,   ëª¨ë“œ: ê°€ìƒ�ë¨¸ë‹ˆ (ì‹¤ì œ ì£¼ë¬¸ ì—†ì�Œ)
u    [ë³µë¦¬ ëª¨ë“œ]u&   ë³µë¦¬: ìˆ˜ì�µê¸ˆ ìž¬íˆ¬ìž� í™œì„±í™”
r-   u   ìž�ë�™ë§¤ë§¤ ì‹œìž‘!u   

ì´� íˆ¬ìž�ê¸ˆ: õ   ì›�
u   ìµœëŒ€ uc  ì¢…ëª© (ì‹œê·¸ë„� ê°•ë�„ë³„ ë�™ì � ë°°ë¶„)
ì¢…ëª©ì„ ì •: KRW ì „ì²´ ì¢…ëª© ìŠ¤ìº” + ê±°ëž˜ëŒ€ê¸ˆìˆœ ìš°ì„  ë¶„ì„�
ìŠ¤ìº”ê°„ê²©: 15ë¶„

ì „ëžµ: ë©”ì�´ì € ì¶”ì„¸ + ì•ŒíŠ¸ ë�ŒíŒŒ + ì‹¤ì‹œê°„ í˜¸ê°€/ì²´ê²° ìˆ˜ê¸‰
  ë©”ì�´ì €: ëˆŒë¦¼ëª© ì¶”ì„¸ ìž¬ê°œë§Œ ì„ ë³„
  ì•ŒíŠ¸: ê±°ëž˜ëŸ‰ ë�™ë°˜ ê³ ì � ë�ŒíŒŒë§Œ ì„ ë³„
  ì¶”ì„¸í•„í„°: ë©”ì�´ì € BTCìƒ�ìŠ¹ í•„ìˆ˜ / ì•ŒíŠ¸ BTCìœ„í—˜ ì �ìˆ˜ ë°˜ì˜�
  ê³µí†µí•„í„°: ê°œë³„ì�¼ë´‰ up + ì „ëžµë³„ ì�¼ë´‰ATR ë²”ìœ„
  ë¦¬ìŠ¤í�¬ê´€ë¦¬: ì „ëžµë³„ ì�µì ˆ/ì†�ì ˆ + ì†�ì ˆ í›„ ìž¬ì§„ìž… ì¿¨ë‹¤ìš´

ëª©í‘œ/ì†�ì ˆ: ë©”ì�´ì €ëŠ” ê¸¸ê²Œ, ì•ŒíŠ¸ëŠ” ë¹ ë¥´ê²Œ ê´€ë¦¬
ë§¤ìˆ˜ í›„ë³´ ìŠ¤ìº” ì¤‘...)ÚtraderÚrunningr   r…   r»  rA   rF   rÓ   Ú
paper_moderê   Ú_virtual_krwÚ_virtual_coinsÚclearÚis_configuredÚget_balanceÚtotal_budgetr-  Útotal_realizedÚtotal_tradesÚ	positionsÚ
_cooldownsr   r–   r}  Ú
started_atÚrequest_immediate_rescanr   r   Ú	max_coins)	ry   r€   ÚbudgetÚoptionsr)  r-  ÚkrwÚ
mode_labelÚ	mode_liner0   r0   r5   Úcmd_auto_startL  sz   €
ÿ	þ
$

ÿþýÿrE  c                 Ã   s(  �t js| j d¡I d H  d S t j}dt _t  ¡ I d H }tt ƒI d H  tƒ I d H  |r-dnd}|› d�}|r^|dt jd›d�7 }|d	t j	d›d�7 }t jt j	 t j	 d
 }|d|d›d�7 }|dt j
d›d�7 }|dt j› d�7 }|r||dd |¡ 7 }|r‰dt _dt _t j ¡  | j |¡I d H  d S )Nu+   ìž�ë�™ë§¤ë§¤ê°€ ì‹¤í–‰ ì¤‘ì�´ ì•„ë‹™ë‹ˆë‹¤.Fu   ê°€ìƒ�ë§¤ë§¤u   ìž�ë�™ë§¤ë§¤u    ì¤‘ì§€
u   ìµœì¢… ê°€ìƒ�ìž”ê³ : rÃ   r/  u   ì´ˆê¸° íˆ¬ìž�ê¸ˆ: rÂ   u   ì´�ìˆ˜ì�µë¥ : z+.2fz%
õ   ëˆ„ì �ìˆ˜ì�µ: ú+,.0fu   ì´�ê±°ëž˜: õ   íšŒ
u   
ë§¤ë�„ ê²°ê³¼:
rÉ  r.  )r0  r1  r   r…   r2  Úforce_sell_allr   r   r3  r8  r9  r:  ré   r4  r5  )ry   r€   Ú	was_paperr&  rÎ  ÚmsgÚtotal_returnr0   r0   r5   Úcmd_auto_stop£  s2   €

rM  c                 Ã   sD   �t  ¡ s| j d¡I d H  d S t  ¡ I d H }| j |¡I d H  d S )Nõ2   ì—…ë¹„íŠ¸ API í‚¤ê°€ ì„¤ì •ë�˜ì§€ ì•Šì•˜ìŠµë‹ˆë‹¤.)r0  r6  r   r…   Úget_status_text)ry   r€   rÏ   r0   r0   r5   Úcmd_auto_statusÃ  s   €rP  c              
   Ã   s4  �|j s| j d¡I d H  d S |j d  ¡ }| d¡s d|› �n|}d}t|j ƒdkrPzt|j d ƒ}tdt|dƒƒ}W n t	yO   | j d¡I d H  Y d S w | j |› d	|› d
�¡I d H  zt
||d�I d H }t|ƒ}| j |¡I d H  W d S  ty™ } z| j dt|ƒ› �¡I d H  W Y d }~d S d }~ww )Nu_   ì‚¬ìš©ë²•: /backtest <ì½”ì�¸> [ì�¼ìˆ˜]
ì˜ˆ: /backtest BTC 30
ì˜ˆ: /backtest ETH 7
ê¸°ë³¸: 30ì�¼r   r£   rL   r:   rü   rÂ   u/   ì�¼ìˆ˜ëŠ” ìˆ«ìž�ë¡œ ìž…ë ¥í•´ì£¼ì„¸ìš”. (3~100)rý   u.   ì�¼ ë°±í…ŒìŠ¤íŠ¸ ì‹¤í–‰ ì¤‘... (1~2ë¶„ ì†Œìš”))Údaysu   ë°±í…ŒìŠ¤íŠ¸ ì˜¤ë¥˜: )r»  r   r…   rº   r¤   rç   rA   r@   ÚminrF   r   r   r�   r`   )ry   r€   ÚcoinÚtickerrQ  rW  rÏ   r˜   r0   r0   r5   Úcmd_backtestÌ  s4   €
ÿþ*€ÿrU  c           	   
   Ã   s  �t  ¡ s| j d¡I d H  d S t  ¡ I d H }|s$| j d¡I d H  d S dg}|D ]O}| dd¡}t| dd¡ƒ}t| dd¡ƒ}t| d	d¡ƒ}|| dkrPq)|d
kre| d|| d›d|d›d�¡ q)| d|› d|| d›d|d›d�¡ q)| j d |¡¡I d H  d S )NrN  u)   ìž”ê³  ì¡°íšŒ ì‹¤íŒ¨ ë˜�ëŠ” ìž”ê³  ì—†ì�Œu   [ì—…ë¹„íŠ¸ ìž”ê³ ]
r^  r-   Úbalancer   ÚlockedÚavg_buy_pricerÍ   z  KRW: rÃ   u   ì›� (ê°€ìš©: r¸  rõ  rf   z.8fu
    (í�‰ë‹¨: u   ì›�)rÉ  )	r0  r6  r   r…   Úget_balancesrD   rê   rr   ré   )	ry   r€   ÚbalancesrÊ  Úbr^  ÚbalrW  Ú	avg_pricer0   r0   r5   Úcmd_balanceì  s0   €"ÿÿr^  c                  C   sà  t  ¡  t¡ t¡ t¡ ¡ } |  	t
dtƒ¡ |  	t
dtƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
d	ttƒƒ¡ |  	t
d
ttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dtƒ¡ |  	t
dtƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dttƒƒ¡ |  	t
dtt ƒƒ¡ |  	t
dtt!ƒƒ¡ |  	t"tt#ƒdd�¡ | S )NÚstartÚhelpÚappsrç  Úcoinsr  r  Úalert_aboveÚalert_belowÚalertsÚremoveÚ
remove_allÚnotify_inviteÚnotify_listÚnotify_removeÚnotify_joinÚnotify_leaveÚ
auto_startÚ	auto_stopÚauto_statusrV  Úbacktestz^am:)Úpattern)$r   ÚbuilderÚtokenÚ	BOT_TOKENÚget_updates_connect_timeoutrO   Úget_updates_read_timeoutrM   ÚbuildÚadd_handlerr   r§  r©  r‹   rä  rë  rû  rý  r  r  r  r   r"  r$  r³  rÌ  rÍ  rÄ  rÈ  rE  rM  rP  r^  rU  r   rñ  )rÒ  r0   r0   r5   Ú
create_bot  sF   ûþÿry  r«   c                 C   s8   t | tƒrt d| ¡ d S tjdt| ƒ| | jfd� d S )NzCTelegram polling connection interrupted; retrying automatically: %sz!Unexpected Telegram polling error)Úexc_info)rh  r	   rh   ro   r«   rº  Ú__traceback__)r«   r0   r0   r5   Ú_handle_polling_error7  s   
þ
þr|  Úbot_appc                 Ã   s   �| j jtdtd�I d H  d S )Néÿÿÿÿ)ÚtimeoutÚbootstrap_retriesÚerror_callback)ÚupdaterÚstart_pollingrK   r|  ©r}  r0   r0   r5   Ústart_bot_pollingE  s   €ýr…  c                 Ã   sp   �| j  tddƒtddƒtddƒtddƒtd	d
ƒtddƒtddƒtddƒtddƒtddƒtddƒg¡I d H  d S )Nra  u   ê´€ë¦¬ ì•± ì„ íƒ� ë°� í†µê³„rç  u   ì•± í†µê³„ ë°”ë¡œ ì¡°íšŒr  u   ì£¼ì‹� ê²€ìƒ‰r  u   ì½”ì�¸/ì£¼ì‹� ê°€ê²© ì¡°íšŒre  u   ê°€ê²© ì•Œë¦¼ ëª©ë¡�rh  u"   ìš´ì˜� ì•Œë¦¼ ìˆ˜ì‹  ê³„ì • ì´ˆëŒ€ri  u"   ìš´ì˜� ì•Œë¦¼ ìˆ˜ì‹  ê³„ì • ëª©ë¡�rl  u   ìš´ì˜� ì•Œë¦¼ êµ¬ë�… í•´ì œro  u   ìž�ë�™ë§¤ë§¤ í˜„í™©rV  u   ì—…ë¹„íŠ¸ ìž”ê³ r`  u   ì „ì²´ ëª…ë ¹ì–´ ì•ˆë‚´)r¾  Úset_my_commandsr   r„  r0   r0   r5   Úconfigure_bot_commandsM  s   €õÿr‡  Údisable_web_page_previewc           	   	   Ã   s²   �t ƒ }|sdS tƒ }d}d}|D ]A}z)t| jj|||d�ƒI d H }|d u r/||kr-W  n&W qd}||kr;d}td7 aW q tyR   t d|¡ ||krPY  nY qw |rW|S |S )NF)rk   rÏ   rˆ  Tr:   z+Operational notification failed: chat_id=%s)	ru   rq   rœ   r¾  r¿  Ú_send_counterr�   rh   rÀ  )	r}  rÏ   rˆ  rs   rt   Úowner_deliveredÚany_deliveredrk   rW  r0   r0   r5   Ú_broadcast_operational_messagea  s@   €ý
ÿ€ÿþrŒ  Úeventc                 Ã   s   �t | t|ƒdd�I d H S )NT)rˆ  )rŒ  r   )r}  r�  r0   r0   r5   Ú_send_app_event‡  s   €ýrŽ  c           	   
   ƒ   s¾  �t tƒI d H }|r"zt |¡}W n( ty!   t ¡ I d H }Y nw t ¡ I d H tdd� }tt|j	dd�ƒI d H  t
 d|t¡ 	 z}t ¡ I d H ‰ |ttd� }t t |ˆ ¡t |ˆ ¡¡I d H \}}tg |¢|¢‡ fdd„d	�}d}|D ]7}t|d
 ƒI d H r‚qvzt| |ƒI d H s�d}W  nt|ƒI d H  W qv ty­   t
 d| d
¡¡ d}Y  nw |r¾ˆ }tt|j	dd�ƒI d H  W n tjyÈ   ‚  tyÕ   t
 d¡ Y nw t t¡I d H  qB)NrL   )Úsecondsrý   )Úsepz7App Master event monitor started from %s (interval=%ss)Tc                    s    |   d¡pˆ t|   d¡pdƒfS )NÚ
event_timeÚ	event_keyr-   )rD   r`   )r�  ©Úend_atr0   r5   r!  ª  s   þz0start_app_master_event_monitor.<locals>.<lambda>r"  r’  Fz!App event notification failed: %sz%App Master event monitor cycle failed)r$   ÚAPP_EVENT_CHECKPOINT_STATE_KEYr   ÚfromisoformatrF   r   Údatabase_nowr   r#   Ú	isoformatrh   ri   ÚAPP_EVENT_POLL_SECONDSrë   rf  Úfetch_eventsr   Úsortedr%   rŽ  r&   r�   rÀ  rD   ÚCancelledErrorrì   )	r}  Úcheckpoint_valueÚ
checkpointÚquery_startÚ
app_eventsÚofficial_mail_eventsÚeventsÚall_deliveredr�  r0   r“  r5   Ústart_app_master_event_monitor�  st   €ÿý

þ

þþú

þ€ÿÔr¤  c                 ƒ   sP  �	 �z÷t ƒ }t ƒ }t ƒ }d}t ¡ D ]:}|D ]5‰ ˆ d }| d¡r(| |¡ q| d¡r=| |¡ ˆ  dd¡dkr<d}q| |¡ ˆ  dd¡dkrLd}qq|sU|sU|�rùtt|ƒƒI d	H }t	t|ƒƒI d	H }t
t|ƒƒI d	H }	|rxtƒ I d	H nd	}
g }t ¡ D ]¸\}}|D ]±‰ ˆ d }ˆ  dd¡}d	}t|ƒ}d}| d¡r¥| |¡}nb| d¡rÇ| |¡}|d	urÆ|dkrÄ|
d	urÃ||
d
  }d}nC|}n@|	 |¡}|d	u�r| d¡p×|}|d dkrã|d }n$|d dkrü|dkrü|
d	urü|d |
d
  }d}n|d |k�r|d }|d	u �rq†ˆ d dk�r|ˆ d k�p'ˆ d dk�o'|ˆ d k}|�r7| |ˆ |||
||f¡ q†q€|D ]½\}‰ }}}
}}ˆ d dk�rMdnd}t||ƒ}tˆ d |ƒ}d}|dk�r¤|�r¤|
d	u�r¤|
d
 d›d�}|
 d¡�rš|
 d¡}|�r†d|› d�nd}d|
d › d|› d|
d › |› �}n
d|
d › d|› �}z"t| jj|dˆ d  › d!|› d"|› d#|› d|› |› �d$�ƒI d	H  W n t�yä } zt d%|› d"|› �¡ W Y d	}~nd	}~ww |tv �r÷‡ fd&d'„t| D ƒt|< �q;W n$ tj�y   ‚  t�y } zt d(|› �¡ W Y d	}~nd	}~ww t t¡I d	H  q))up   10ì´ˆ ê¸°ë³¸ ê°„ê²©ìœ¼ë¡œ ê°€ê²©ì�„ í™•ì�¸í•˜ê³  ì¡°ê±´ ì¶©ì¡± ì‹œ ì•Œë¦¼ ì „ì†¡ í›„ í•´ë‹¹ ì•Œë¦¼ ìž�ë�™ í•´ì œTFr´   r£   r¶   rˆ  rm  rÍ   Nrx  r  r^  r  r  r  r  r  r  r  r-   rÅ   rÄ   ry  rz  r·  r  u   
ê¸°ì¤€í™˜ìœ¨: re   rý   ú / r  r|   u
   ] ë�„ë‹¬!
rf   u	   
ì„¤ì •: r¹  zError sending alert to c                    s    g | ]}|d  ˆ d  kr|‘qS )r|   r0   r%  ©r  r0   r5   r¦   6  s     z'start_alert_checker.<locals>.<listcomp>zAlert checker error: )rA  r°   r  r¤   rB  r»   rD   rñ   Úlistr+  ri  r†  Úitemsr¿   rr   rÎ   rœ   r¾  r¿  r�   rh   r«   rë   rœ  rì   rP   )r}  Úupbit_symbolsÚbinance_symbolsÚstock_symbolsÚneeds_krw_fxr  r´   r’  Úbinance_pricesÚstock_quotesÚusd_krw_infoÚ	triggeredrk   rˆ  r‰  r  Úused_fxrŒ  r›  Úhitr  Úcurrent_textr  Úfx_lineÚ	rate_textr  r  r˜   r0   r¦  r5   Ústart_alert_checkerÏ  sà   €


€
€õ


€€



þÿ€Ú+

$ÿÿþþýýÿ"€ÿ
€€ÿ”r¶  c              
   ƒ   s’   �d	dt dtdB f‡ fdd„}	 ztjrt |¡I dH  W n" tjy&   ‚  ty? } zt 	d|› �¡ W Y d}~nd}~ww t 
d¡I dH  q)
u(   2ì´ˆë§ˆë‹¤ ìž�ë�™ë§¤ë§¤ ì‚¬ì�´í�´ ì‹¤í–‰NrÏ   Úphotoc              
   “   s¨   �t ƒ }|sd S z0|rtˆ jj||| d d… d�ƒI d H }ntˆ jj|| d�ƒI d H }|d ur6td7 aW d S W d S  tyS } zt d|› �¡ W Y d }~d S d }~ww )Ni   )rk   r·  Úcaptionr¹  r:   zTrade notification error: )	rq   rœ   r¾  Ú
send_photor¿  r‰  r�   rh   r«   )rÏ   r·  rk   rW  r˜   r„  r0   r5   Úsend_fnD  s&   €ÿ
ÿÿ€ÿz"start_auto_trader.<locals>.send_fnTzAuto trader error: r  r?   )r`   r   r0  r1  Úexecute_cyclerë   rœ  r�   rh   r«   rì   )r}  rº  r˜   r0   r„  r5   Ústart_auto_trader@  s   €€€ÿør¼  c           	      Ã   sŠ  �t ƒ }d}d}	 �zt ƒ }||kr3|r-|r-z| jj||d�I dH  W n	 ty,   Y nw |}d}t}tjrù|sBt d¡I dH  W qt 	¡ I dH }|rÝt|krlt}|rlz| jj||d�I dH  W n	 tyi   Y nw d}|r»zt
| jj|||d�ƒI dH }W n— tyº } z0dt|ƒ ¡ vr°zt
| jj||d�ƒI dH }|r¡|jnd}W n ty¯   d}Y nw W Y d}~n`d}~ww zt
| jj||d�ƒI dH }|rÎ|jnd}W nD tyÜ   d}Y n:w |røz| jj||d�I dH  W n	 tyõ   Y nw d}n|�rz| jj||d�I dH  W n
 t�y   Y nw d}W n$ tj�y!   ‚  t�y; } zt d	|› �¡ W Y d}~nd}~ww t d¡I dH  q	)
uG   5ì´ˆë§ˆë‹¤ ë³´ìœ  í�¬ì§€ì…˜ ì‹¤ì‹œê°„ í˜„í™© - í•­ìƒ� ë§¨ ì•„ëž˜ ìœ ì§€Nr   T)rk   Ú
message_idrJ   )rk   r½  rÏ   znot modifiedr¹  zMonitor error: )rq   r¾  Údelete_messager�   r‰  r0  r1  rë   rì   Úget_monitor_textrœ   rè  r`   r‘   r¿  r½  rœ  rh   r«   )	r}  rk   Úmsg_idÚlast_counterrw   rÏ   rW  r˜   rK  r0   r0   r5   Ústart_position_monitorb  sÂ   €ÿÿÿÿýÿÿ
ÿÿ€÷ÿ
ÿÿÿÿ€ÿÿ€€ÿ«rÂ  c                 Ã   sZ  �t tƒI dH }|rt|dd� tƒ I dH }dd„ |D ƒatr't dttƒ¡ tƒ I dH \}}|r[t	 
|¡ |at dtdd	„ | ¡ D ƒƒ› d
�¡ tƒ s[tt| ¡ ƒƒ}t|dd� tƒ I dH }|�r§| d¡�r©| d¡}|du }dt_|d t_t| dd¡ƒt_| dd¡t_| dd¡t_| d¡t_|p�t|ƒt_tj ¡  tj ¡  t  ¡  t!ƒ I dH }	|	D ]%}
|
d |
d |
d |
 d¡|
 d¡|
 d¡|
d |
d dœtj|
d < qµtjrêt"||	tj#ƒ\t_$t_ndt_$|röt%tƒI dH  t dtj› d ttjƒ› d!tj› d"tj› d#tj$› �
¡ tƒ }|�r«g }tj�r"| &d$¡ tj�r+| &d%¡ |�r7d&d' '|¡› d(�nd)}tj�rEd*tj$d+›d,�nd)}|�rLd-nd)}d)}tj�rcd.d/ 'd0d	„ tj ¡ D ƒ¡ }z'| j(j)|d1|› d2tjd+›d,|› d3tjd4›d5tj› d6|› |› �d7�I dH  W dS  t*�y¦ } zt +d8|› �¡ W Y d}~dS d}~ww dS dS dS )9uM   ì„œë²„ ìž¬ì‹œìž‘ ì‹œ DBì—�ì„œ íŠ¸ë ˆì�´ë”© ì„¸ì…˜ + í�¬ì§€ì…˜ + ì•Œë¦¼ ë³µì›�NÚdbrz   c                 S   s.   i | ]}t |d  ƒi |¥d t |d  ƒi¥“qS rp   )rc   )r3   r  r0   r0   r5   Ú
<dictcomp>É  s    üÿþÿz!restore_state.<locals>.<dictcomp>z0Restored %s operational notification subscribersz	Restored c                 s   s   � | ]}t |ƒV  qd S r?   r  )r3   Úvr0   r0   r5   rÒ   Û  rF  z restore_state.<locals>.<genexpr>z alertsre  r1  r2  Tr8  r-  r   r9  r.  r:  r=  rT  rS  r©   Ú	buy_priceÚ
buy_volumeÚ	bought_atÚtarget_profitÚ	stop_loss)rT  rS  r©   rÆ  rÇ  rÈ  rÉ  rÊ  z!Restored trading session: budget=z, positions=z, compound=z, paper=z, virtual_krw=r(  r,  z [r¥  ú]r-   u   ê°€ìƒ�ìž”ê³ : rÃ   r/  uX   ê¸°ì¡´ ì„¸ì…˜ ëª¨ë“œ ì •ë³´ê°€ ì—†ì–´ ì•ˆì „í•˜ê²Œ ê°€ìƒ� ëª¨ë“œë¡œ ë³µêµ¬í–ˆìŠµë‹ˆë‹¤.
u   
ë³´ìœ  í�¬ì§€ì…˜:
rÉ  c                 s   s0   � | ]}d |d › d|  dd¡d›d�V  qdS )rõ  rS  rf   rÆ  r   rÃ   rÄ   N)rD   )r3   Úpr0   r0   r5   rÒ   #  s
   € ÿ
ÿu-   ì„œë²„ ìž¬ì‹œìž‘ - íŠ¸ë ˆì�´ë”© ìž�ë�™ ë³µì›�u   
íˆ¬ìž�ê¸ˆ: rF  rG  u   ì›�
ê±°ëž˜íšŸìˆ˜: rH  r¹  zRestore notification error: ),r$   r}   rm   r*   r_   rh   ri   rç   r"   r°   ry   r²   Úsumr  rq   ÚnextÚiterÚkeysr    rD   r0  r1  r8  Úboolr-  r9  r:  r=  r2  r;  r5  r4  r>  r!   r   ÚFEE_RATEr3  r   rr   ré   r¾  r¿  r�   r«   )r}  Úsaved_chat_idÚsubscriber_rowsÚalerts_dataÚmax_idÚfirst_chat_idr¬   Úsaved_paper_modeÚlegacy_paper_recoveryr;  Úposrk   Úmode_labelsÚmodeÚbalance_infoÚrecovery_infoÚpos_infor˜   r0   r0   r5   Úrestore_stateÀ  sØ   €ûþ
$



øÿ
ÿÿþþÿ

ÿþÿþ
þÿþýüûúý€ÿ®0rà  c                   Ã   s&   �t rt jst  ¡ I d H  d S d S d S r?   )r±   rà   Úcloser0   r0   r0   r5   Ústop_alert_checker8  s   €
ÿrâ  rK  c                 Ã   sD   �t |ƒ}|r| jj||d�I d H  d S t| |ƒI d H s tdƒ‚d S )Nr¹  uC   ìš´ì˜� ì•Œë¦¼ì�„ ì „ì†¡í•  chat_idê°€ ì§€ì •ë�˜ì§€ ì•Šì•˜ìŠµë‹ˆë‹¤.)rc   r¾  r¿  rŒ  rF   )r}  rK  rk   Útargetr0   r0   r5   r¿  >  s   €ÿr¿  )r:   )rd   )rå  F)Fr?   )ÃrB   rª   rë   r®  Úloggingrá   r’   r¬  r�   Ú	functoolsr   r  r   Úior   Útelegramr   r   r   r   Útelegram.errorr	   r
   Útelegram.extr   r   r   r   r   r   Úupbit_traderr   r   rp  r   r   r   r   r   r   r   r   r   r   Úpersistencer   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   Ú	getLoggerÚ__name__rh   rC   rD   rt  rn   r}   r`   r1   rg   rj   r½   rv   rB  r•  rA   rG   r™  rK   rM   rO   r0  r‰  r  r$  r¨   rè   r  r|  r@  ra  r  r  rP   r  rÚ   rÙ   rY   r§  ÚdictÚ__annotations__rZ   rê   r[   r\   r]   r^   r_   rc   rm   rq   ru   rÑ  rx   r   r‹   rœ   r¯   r°   r²   r±   râ   r³   r¿   rÁ   rÉ   rË   rÎ   rÔ   rÕ   rÛ   rß   r§   rñ   r  r  r(  r+  r9  rD  rG  rR  rd  ri  rk  r†  r—  rœ  rŸ  r¡  r¢  r£  r¤  rŠ   r§  r©  r³  rÄ  rÈ  rÌ  rÍ  rÙ  rß  rä  rê  rë  rñ  rû  rý  rÿ  r  r  r  r   r"  r$  rE  rM  rP  rU  r^  ry  r|  r…  r‡  rŒ  rŽ  r¤  r¶  r¼  rÂ  rà  râ  r¿  r0   r0   r0   r5   Ú<module>   st  
 $	D
þýýýý9 48'	<*2ÿÿ	ÿ0	
üÿþý
üÿ
þ)!..
W 	 !*ýÿþý
ü&@q"^x 