
    Ջi}                     
   U d 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	Z	ddl
Z
ddlmZ ddlmZmZmZ ddlmZ ddlmZ  e        ej*                  j-                  dd	      Zej*                  j-                  d
d	      ZdZdad ZdedededefdZdedefdZ G d d      Z g Z!ee    e"d<   g Z#ee   e"d<   dZ$da%e&dz  e"d<   d Z'd Z(d Z) e       Z*e*jW                  d      defd       Z,d  Z-e.d!k(  r e-        yy)"u  
Mentions Dashboard — FastAPI backend + React frontend
Up to 4 single mention market orderbooks with trading controls.
YES bids (green, bottom) / YES asks derived from NO bids (red, top).

Usage:
    python dashboard.py
    python dashboard.py --port 8080
    N)Path)load_dotenv)FastAPI	WebSocketWebSocketDisconnectHTMLResponse)StaticFilesKALSHI_MOM_API_KEY KALSHI_MOM_API_SECRETz-https://api.elections.kalshi.com/trade-api/v2c                  ^   t         } | sy 	 ddlm} ddlm} t
        j                  j                  |       rt        | d      j                         n| }|j                  t        |t              r|j                         n|d  |             S # t        $ r}t        d|        Y d }~y d }~ww xY w)Nr   )serialization)default_backendr)passwordbackendzKey load failed: )KALSHI_API_SECRETcryptography.hazmat.primitivesr   cryptography.hazmat.backendsr   ospathisfileopenreadload_pem_private_key
isinstancestrencode	Exceptionprint)secretr   r   key_dataes        dashboard.py_load_private_keyr&   (   s    F
@@/1ww~~f/E4$))+611!+Hc!:HOO?#4 2 
 	
  !!%&s   A?B 	B,B''B,	timestampmethodr   returnc           	         t         syddlm} ddlm} |j                  d      d   }| |z   dz   |z   }t         j                  |j                         |j                  |j                  |j                               |j                  j                        |j                               }t        j                  |      j                         S )Nr   r   )hashes)padding?z/trade-api/v2)mgfsalt_length)_private_keyr   r+   )cryptography.hazmat.primitives.asymmetricr,   splitsignr   PSSMGF1SHA256DIGEST_LENGTHbase64	b64encodedecode)r'   r(   r   r+   r,   
path_cleanmsgsigs           r%   _sign_requestr>   9   s    5AC#J
f

.
;C




V]]_5!(!:!: 	 	<	C C ''))    sidec                     | D cg c]:  \  }}t        t        t        |      dz              t        t        |            d< c}}S c c}}w )Nd   pricesize)introundfloat)r@   pss      r%   	_parse_obrK   M   s:    UYZTQPQc%a3/0#eAh-HZZZs   ?A	c            	       d   e Zd ZdZ	 d%dedededefdZdefdZd	e	j                  fd
Zd&deded	efdZd Zdededed	edz  fdZded	efdZd Zdeded	edz  fdZdefdZded	edz  fdZd Zd	efdZd	ee   fdZd	efdZd Zd Zded	edz  fd Zded	edz  fd!Zd	efd"Zd#efd$Z y)'MentionsMarketManagerzIManages one single mentions market: orderbook display + YES-side trading.slot_idx	market_idrefresh_ratecontract_incrementc                 &   || _         || _        || _        || _        d| _        |r|j                  d      d   nd| _        g | _        g | _        d | _	        d| _
        d | _        d | _        d| _        d | _        d d d| _        d d d| _        ddd| _        ddd| _        d d d| _        d | _        d | _        d d d| _        d d d| _        ddd| _        d d d| _        d| _        d| _        d| _        d| _        d | _        d | _        g | _         y )NT-r-   r   yesnoF)!rN   rO   rP   rQ   runningr2   labelraw_yes_bidsraw_no_bidsbest_yesbest_yes_size
second_yesbest_nobest_no_size	second_no	order_idslast_pricescurrent_incrementscycle_start_restingcached_restingcached_position_yescached_position_nocached_queue_positionsfill_pricesbump_activebump_targetactivepausedstoppingone_side_firstactive_side_http	log_lines)selfrN   rO   rP   rQ   s        r%   __init__zMentionsMarketManager.__init__T   s<    "("41:Y__S)"-
 )+') %)"#&*#'!"%) 9=D0I<@4M:;12E;<A3F =A5N/3 .2EIQU=V#<@4M49,G:>d2K #'+37
$&r?   r<   c                    t        j                  d      }d| d| j                  dz    d| }| j                  j	                  |       t        | j                        dkD  r| j                  dd  | _        t        |d	       y )
Nz%H:%M:%S[z] [S   z] 2   iT)flush)timestrftimerN   rs   appendlenr!   )rt   r<   tslines       r%   _logzMentionsMarketManager._log   sq    ]]:&2$d4==1,-Ru5d#t~~#!^^CD1DNd$r?   r)   c                    K   | j                   | j                   j                  r/t        j                  t        j                  d            | _         | j                   S w)N   totaltimeout)rr   closedaiohttpClientSessionClientTimeoutrt   s    r%   	_get_httpzMentionsMarketManager._get_http   sD     ::!2!2 ..w7L7LST7UVDJzzs   AA Nr(   endpointc                 8  K   t          | }t        t        t        j                         dz              }t	        |||      }t
        ||dd}	 | j                          d {   }|dk(  r|j                  ||      4 d {   }	|	j                  dk\  rT|	j                          d {   }
| j                  | d| d|	j                   d|
d d	         i cd d d       d {    S |	j                          d {   cd d d       d {    S |d
k(  r|j                  |||      4 d {   }	|	j                  dk\  rT|	j                          d {   }
| j                  | d| d|	j                   d|
d d	         i cd d d       d {    S |	j                          d {   cd d d       d {    S |dk(  r|j                  ||      4 d {   }	|	j                  dk\  rT|	j                          d {   }
| j                  | d| d|	j                   d|
d d	         i cd d d       d {    S |	j                          d {   cd d d       d {    S y 7 7 7 7 7 ~7 q# 1 d {  7  sw Y   y xY w7 f7 B7 
7 7 # 1 d {  7  sw Y   y xY w7 7 7 |7 e7 W# 1 d {  7  sw Y   y xY w# t        j                  $ r i cY S t         $ r }| j                  d|        i cY d }~S d }~ww xY ww)N  application/jsonzKALSHI-ACCESS-KEYzKALSHI-ACCESS-SIGNATUREzKALSHI-ACCESS-TIMESTAMPzContent-TypeGETheadersi   z: HTTP P   POST)jsonr   DELETEzRequest error: )KALSHI_API_BASEr   rF   r{   r>   KALSHI_API_KEYr   getstatustextr   r   postdeleteasyncioTimeoutErrorr    )rt   r(   r   dataurlr'   r=   r   sessionrespbodyr$   s               r%   _requestzMentionsMarketManager._request   s     !(,DIIK$./0	Ivx8!/'*'0.	
	 NN,,G";;sG;< - -{{c)%)YY[0		VHAhZwt{{m1TRUSUYK"XY!	- - -
 "&,- - - 6!"<<$<H - -D{{c)%)YY[0		VHAhZwt{{m1TRUSUYK"XY!	- - -
 "&,- - - 8#">>#w>? - -4{{c)%)YY[0		VHAhZwt{{m1TRUSUYK"XY!	- - -
 "&,- - - $ --0-
 -- - - --0-
 -- - - --0-
 -- - - - ## 	I 	IIs+,I	s4  ALK "I0# K I3K #J*I6+.JK %I9&K *L+J>I<?JK I?K LK 1J2K 5#J$J.J$K JK LJ$,J -J$0K <J"=K LK J9K "#KJ;.K4K  J=K LKJ?KK )K*K .L0K 3K 6J9K <J?K JJ	JK LK J$K  J$"K $J6*J-+J62K 5L6K ;K=K ?KK K	K
KK LK L-L/L7LLLLLc                 d  K   | j                  dd| j                   d      | j                  dd| j                   d      | j                  dd| j                   d      | j                  dd| j                         g}t        j                  |d	d
i d {   }|d   }|r)t	        |t
              s|j                  di       }t        |j                  dg             }t        |d d
      d d }|| _	        |r8|d   d   | _
        |d   d   | _        t        |      dkD  r|d   d   nd | _        nd | _
        d| _        d | _        t        |j                  dg             }t        |d d
      d d }|| _        |r8|d   d   | _        |d   d   | _        t        |      dkD  r|d   d   nd | _        nd | _        d| _        d | _        |d   }	|	rJt	        |	t
              s:|	j                  dg       }
dD ]#  t%        fd|
D              | j&                  <   % |d   }|rt	        |t
              sd| _        d| _        |j                  dg       D ]h  }|j                  d      | j                  k(  s"t-        t/        |j                  dd                  }|dkD  r|| _        n|dk  rt1        |      | _         n d d d| _        |d   }|rt	        |t
              s|j                  d      }|rt	        |t4              r|D ]  }|j                  d       | j                  k(  s"|j                  d!      }dD ]f  | j6                     s|| j6                     k(  s&t-        t/        |j                  d"|j                  d#d                        | j2                  <   h  y y y y y 7 w)$Nr   z	/markets/z
/orderbookz/portfolio/orders?ticker=z&status=restingz/portfolio/positions?ticker=z&count_filter=positionz1/portfolio/orders/queue_positions?market_tickers=return_exceptionsTr   orderbook_fpyes_dollarsc                     | d   S NrD    xs    r%   <lambda>z/MentionsMarketManager.refresh.<locals>.<lambda>   s
    !G* r?   keyreverse   rD   rE   rx   
no_dollarsc                     | d   S r   r   r   s    r%   r   z/MentionsMarketManager.refresh.<locals>.<lambda>   s
    '
 r?   ordersrU   c              3      K   | ]L  }|j                  d       k(  r6t        t        |j                  d|j                  dd                         N yw)r@   remaining_count_fpcount_fp0N)r   rF   rH   ).0or@   s     r%   	<genexpr>z0MentionsMarketManager.refresh.<locals>.<genexpr>   sI      0quuV}'< aee$8!%%
C:PQRS0s   AA   market_positionstickerposition_fpr   r   queue_positionsmarket_tickerorder_idqueue_position_fpqueue_position)r   rO   r   gatherr   r    r   rK   sortedrZ   r\   r]   r~   r^   r[   r_   r`   ra   sumrf   rg   rh   rF   rH   absri   listrb   )rt   tasksresultsob_dataob
yes_levels
yes_sorted	no_levels	no_sortedorders_datar   pos_datapospv
queue_dataqpsqpoidr@   s                     @r%   refreshzMentionsMarketManager.refresh   s    MM%9T^^,<J!GHMM%#<T^^<LO!\]MM%#??OOe!fgMM%#TUYUcUcTd!ef	
  FFF !*:gy9^R0B"266-#<=J
0DdSTVUVWJ *D *1g 6%/]6%:"<?
Oa<O*Q-"8UY $%&""&!"&&r":;Iy.BDQRTSTUI(D(|G4$-aL$8!:=i.1:L1g!6RV#$%!!% ajz+yA __Xr2F% ,/ 0#0 -##D) 1:Jx;'(D$&'D#||$6; 778$6U377=##>?@BAv350a25b'/ /3$&?#QZ
jY?..!23Cz#t, aBvvo.$..@ ffZ0$1 aD#~~d3t~~d?S8SDG$&FF+>GWY\@]$^I` Ea ; ;D Aaa -s @:s Gs-   BN0N-GN09B0N0*%N0N0#AN0r@   rD   countc                 R  K   d| j                   d|ddd|ddd| j                    d	| d	t        t        j                         d
z         | dt        t        |dz              i}| j	                  dd|       d {   }|r!|j                  di       j                  d      S d S 7 )w)Nr   r@   actionbuyr   typelimitclient_order_idrS   r   _pricerB   r   z/portfolio/ordersorderr   )rO   rF   r{   rG   r   r   )rt   r@   rD   r   
order_dataresults         r%   place_orderz!MentionsMarketManager.place_order  s     dnnD(EUFG$..!14&#diikD>P:Q9RSfFOSus{!34

 }}V-@*MM:@vzz'2&**:6JdJ Ns   A9B';B%<*B'c                    K   | j                   |   }|r(| j                  dd|        d {   }t        |      S y7 w)Nr   z/portfolio/orders/F)rb   r   bool)rt   r@   r   r   s       r%   cancel_orderz"MentionsMarketManager.cancel_order  sE     nnT"==5Gu3MNNF< Os   *?=?c                 \  K   g }d}dD ]U  }| j                   |   s|j                  | j                  |             d | j                   |<   d | j                  |<   |dz  }W |rt	        j
                  |ddi d {    |r| j                  d| d       y | j                  d       y 7 .w)	Nr   rU   rx   r   Tz
Cancelled z orderszNo open orders)rb   r}   r   rc   r   r   r   )rt   r   r   r@   s       r%   cancel_all_ordersz'MentionsMarketManager.cancel_all_orders  s     ! 	D~~d#T..t45'+t$)-  &
	 ..%@4@@@II
5'12II&'	 As   B,AB,;B*</B,	new_pricec                 T  K   | j                   |   }| j                  }|rk| j                  |   xs d}|dk(  ry | j                  |       d {    t	        j
                  d       d {    | j                  |||       d {   }n%| j                  ||| j                         d {   }|rM|| j                   |<   || j                  |<   | j                  |   |r|n| j                  z   | j                  |<   |S |rd | j                   |<   d | j                  |<   y 7 7 7 7 zw)Nr   皙?)
rb   rQ   rf   r   r   sleepr   rc   rd   re   )rt   r@   r   old_oidresting_beforenew_oids         r%   modify_orderz"MentionsMarketManager.modify_order%  s%    ..&00!006;!N"##D)))--$$$ ,,T9nMMG ,,T9d>U>UVVG#*DNN4 %.DT"-1-D-DT-J")t/F/F.HD$$T*N#'DNN4 %)DT" *$MVsI   AD(D D(*D"+D(D$%D(+D&,A5D("D($D(&D(c                     |dk(  r#| j                   | j                  | j                  fS | j                  | j                  | j
                  fS )NrV   )r\   r]   r^   r_   r`   ra   )rt   r@   s     r%   _get_bid_infoz#MentionsMarketManager._get_bid_info@  s?    5===$"4"4dooEE<<!2!2DNNBBr?   c                 B   | j                  |      \  }}}|y |dz  }| j                  |   }| j                  |   xs d}|}|t        |dz        nd }	||kD  r|n||nd }
| j                  j                  |d      r| j                  |   |
|
dz   | j                  |<   | j                  |   }|W|
F|
|k\  rAd| j                  |<   d | j                  |<   | j                  |j                          d       nt        |d      dz  S |	||	kD  r|S ||kD  r|S ||dz  S |S )NrB   r   Frx   z bump disabled - outbidc   )
r   rc   rf   rG   rk   r   rl   r   uppermin)rt   r@   best	best_sizesecond	bid_pricecurrent_priceour_resting	bid_centscurrent_centsothers_best_centstarget_centss               r%   check_target_pricez(MentionsMarketManager.check_target_priceF  sq   "&"4"4T":i<3J	((.))$/41	6C6Omc12UY)2[)@I(Fd 	 e,%-2C2O):Q)>  &++D1L'$05F,5V-2D$$T*-1D$$T*II.EFG|R0366 $])B{"C<r?   c                    dD ]  }| j                   |   }|| j                  |   |z
  }|dk  r-|}|| j                  |   kD  sB|| j                  |   z
  }|dkD  sZ|| j                  |<   | j                  |   | j                  |<   | j                  |j                          d| d| d| j                   d       || j                  k\  sd| j                  |<   d | j                  |<    y )NrU   r   z: +z	 fill (C:/)F)
rf   re   rd   rc   rj   r   r   rQ   rk   rl   )rt   r@   restingexpectedfills	new_fillss         r%   check_fillsz!MentionsMarketManager.check_fillsk  s   ! 	6D))$/G//5?H1}Et..t44!D$;$;D$AA	q=49D++D1-1-=-=d-CD$$T*IIc)IeWAdNeNeMffghi 7 7716((.15((.!	6r?   c                       j                   r2 j                  r& j                   j                      j                  k\  S t	         fddD              S )Nc              3   V   K   | ]   }j                   |   j                  k\   " y wN)rd   rQ   )r   rJ   rt   s     r%   r   z4MentionsMarketManager.both_filled.<locals>.<genexpr>  s'     `Q4**1-1H1HH`s   &)rU   )rp   rq   rd   rQ   allr   s   `r%   both_filledz!MentionsMarketManager.both_filled~  sH    4#3#3**4+;+;<@W@WWW`R_```r?   c                 T    | j                   r| j                  r| j                  gS ddgS )NrV   rW   )rp   rq   r   s    r%   _active_sidesz#MentionsMarketManager._active_sides  s,    4#3#3$$%%t}r?   c           	      ,  K   d}| j                         D ]  }| j                  |      \  }}}||dz  }| j                  ||| j                         d {   }|rj|| j                  |<   || j
                  |<   | j                  | j                  |<   | j                  |j                          d| j                   d|d       | j                  |j                          d       d}| j                  |j                          d       d} |S 7 w)	NTrB   z	: Placed z @ $.2fz: Failed to place orderFz: No bid available)	r  r   r   rQ   rb   rc   re   r   r   )rt   successr@   r   _r  r   s          r%   initialize_ordersz'MentionsMarketManager.initialize_orders  s    &&( 	 D++D1JD!Q 3J	 ,,T9d>U>UVV+.DNN4(-6D$$T*595L5LD,,T2IIi8O8O7PPTU^_bTcdeII.EFG#G		TZZ\N*<=>	    Ws   ADDB>Dc                 v  K   | j                   r| j                  }|dk(  rdnd| _        d| j                  | j                  <   d | j                  | j                  <   d| j                  | j                  <   d | j
                  | j                  <   | j                  |j                          d| j                  j                                 nT| j                  d       dD ]>  }d| j                  |<   d | j                  |<   d| j                  |<   d | j
                  |<   @ | j                          d {    y 7 w)NrV   rW   r   Fz filled - switching to zBoth sides filled - new cyclerU   )	rp   rq   rd   rj   rk   rl   r   r   r  )rt   old_sider@   s      r%   start_new_cyclez%MentionsMarketManager.start_new_cycle  s#    ''H'/5'8teD89D##D$4$4515DT--.16DT--.15DT--.II)**A$BRBRBXBXBZA[\]II56% .01''-)-  &).  &)-  &	.
 $$&&&s   D/D91D72D9c                   K   | j                         D ]  }| j                  |   | j                  k\  r | j                  |      }|4| j                  |   }|t        |dz        t        |dz        k(  rc|}| j                  ||       d {   }|s|||kD  rdnd}| j                  |   rdnd}| j                  | d|j                          d|dd	|d|         y 7 Ww)
NrB   u   ↑u   ↓z [BUMP]r   r   z: $r  z -> $)
r  rd   rQ   r
  rc   rG   r   rk   r   r   )rt   r@   target
last_price	old_pricer   	directionbump_strs           r%   update_ordersz#MentionsMarketManager.update_orders  s    &&( 	fD&&t,0G0GG,,T2F~))$/J%%*=zTWGWAX*X"I --dF;;G90%+i%7EU	(,(8(8(>9B		YKqc)CfUX\ZbYcde	f <s   BC'C%C'C'AC'c                 x    | j                   |   }| j                  |   xs d}||dkD  rt        |dz        |dS y )Nr   rB   )price_levelquantity)rc   rf   rG   )rt   r@   lpr  s       r%   _resting_annotationz)MentionsMarketManager._resting_annotation  sH    d#%%d+0q>gk#(c?HHr?   c                 j    | j                   |   }| j                  |   }||t        |dz        |dS y )NrB   )r*  position)rc   ri   rG   )rt   r@   r,  r   s       r%   _queue_annotationz'MentionsMarketManager._queue_annotation  sA    d#((.>bn#(c?CCr?   c                 ^   | j                   D cg c]  }d|d   z
  |d   d }}t        |d d      }i d| j                  d	| j                  d
| j                  d| j
                  d| j                  d| j                  d| j                  d| j                  d| j                  d| j                  d| j                  d|d| j                  d   d| j                  d   d| j                  d   d| j                  d   d| j                  | j                   | j"                  d   | j"                  d   | j$                  d   | j$                  d   | j'                  d      | j'                  d      | j)                  d      | j)                  d      | j*                  dd  d
S c c}w )NrB   rD   rE   rC   c                     | d   S r   r   r   s    r%   r   z/MentionsMarketManager.to_dict.<locals>.<lambda>  s
    7 r?   Tr   rN   rO   rY   rP   rQ   rm   rn   ro   rp   rq   yes_bidsyes_asksresting_yesrV   
resting_norW   	queue_yesqueue_noposition_yesi)
position_nofill_yesfill_nobump_yesbump_noresting_order_yesresting_order_noqueue_position_yesqueue_position_nologs)r[   r   rN   rO   rY   rP   rQ   rm   rn   ro   rp   rq   rZ   rf   ri   rg   rh   rd   rk   r-  r0  rs   )rt   nbr4  yes_asks_sorteds       r%   to_dictzMentionsMarketManager.to_dict  s
   OSO_O_`cBwK/FD`` /CTR


 TZZ
 D--	

 !$"9"9
 dkk
 dkk
 
 d11
 4++
 ))
 
 4..u5
 $--d3
 44U;
  33D9!
" D44#
$  22//6..t4((/''-!%!9!9%!@ $ 8 8 >"&"8"8"?!%!7!7!=NN34(7
 	
 as   F*cmdc                 T
  K   |j                         j                         }|dk(  r| j                  r| j                  s| j	                  d       y d| _        d| _        d| _        d| _        d | _        dD ]>  }d| j                  |<   d | j                  |<   d| j                  |<   d | j                  |<   @ | j                          d {    | j                          d {    | j	                  d| j                   d       y |d	k(  r| j                  s| j	                  d
       y | j                   | _        | j                  r*| j	                  d       | j                          d {    y | j	                  d       dD ]   }d| j                  |<   d | j                  |<   " | j                          d {    | j                          d {    y |dk(  r| j                          d {    y |dk(  rd| _        | j	                  d       y |dk(  ra| j                  d    | j                  d<   | j                  d   sd | j                  d<   | j	                  d| j                  d   rdnd        y |dk(  ra| j                  d    | j                  d<   | j                  d   sd | j                  d<   | j	                  d| j                  d   rdnd        y |dk(  s|dk(  r| j                  r| j                  s| j	                  d       y |dk(  rdnd}d| _        d| _        d| _        d| _        || _        dD ]>  }d| j                  |<   d | j                  |<   d| j                  |<   d | j                  |<   @ | j                          d {    | j                          d {    | j	                  d|j                          d| j                   d       y |dk(  rD| j                  r| j                          d {    d| _        d| _        | j	                  d       y |j#                  d      rJ	 t%        |j'                  d      d          }d |cxk  rd!k  r n n|| _        | j	                  d"|        y y y |j#                  d#      rJ	 t-        |j'                  d      d          }d$|cxk  rd%k  r n y || _        | j	                  d&| d'       y y y 7 7 7 7 37 7 7 `7 K7 # t(        t*        f$ r Y y w xY w# t(        t*        f$ r Y y w xY ww)(NGzAlready runningTFrU   r   zJOIN BID started (xr  RzNot active - use G to startPAUSEDRESUMEDNSzStopping after current cycle...1rV   z	YES bump ONOFF2rW   zNO bump OSF_YESOSF_NOzONE-SIDE-FIRST started on z (xXRemovedzSET_INCREMENT::rx      zContract increment: z	SET_RATE:r   
   zRefresh rate: zx/sec)r   striprm   rn   r   ro   rp   rq   rd   rj   rk   rl   r   r  rQ   r   rX   
startswithrF   r2   
ValueError
IndexErrorrH   rP   )rt   rG  r@   
start_sidevals        r%   handle_commandz$MentionsMarketManager.handle_command  s    iik!#:{{4;;		+,DKDK!DM"'D#D% .01''-)-  &).  &)-  &	.
 ,,.  ((***II+D,C,C+DAFGCZ;;		78"kk/DK{{		(#,,...		)$) 2D45D++D1-1D$$T*2 lln$$,,...CZ((***CZ DMII78CZ*.*:*:5*A&ADU###E**.  'II	$*:*:5*A$u!MNOCZ)-)9)9$)?%?DT"##D))-  &II)9)9$)?U KLMI{{4;;		+,"%"2JDKDK!DM"&D)D% .01''-)-  &).  &)-  &	.
 ,,.  ((***II2:3C3C3E2Fc$JaJaIbbcdeCZ{{,,...DK DLIIi ^^,-#))C.+,>r>.1D+II 4SE:; " ^^K(CIIcN1-.###(+D%IIse59: $ )U !* / %. +B !*
 / 
+  
+ s   CT(	S$
T(!S'"B	T(+S*,AT(:S-;T(S0T(0S31F%T(S6T(.S9/AT(S<	5T(?AS> T(*T T(T !T('T(*T(-T(0T(3T(6T(9T(<T(>TT(TT(T%"T($T%%T()      ?r   r  )!__name__
__module____qualname____doc__rF   r   rH   ru   r   r   r   r   dictr   r   r   r   r   r   r   r   r
  r  r  r   r  r  r!  r(  r-  r0  rF  r`  r   r?   r%   rM   rM   Q   sz   S GH*' *' *'$*'@C*'X   !6!6 
%S %C %t %RIaZ	Kc 	K% 	K 	Kd
 	Ks t ( s u t 6C# C!s !ut| !J6&aT atCy 
 ('&f& t c dTk  
  
Hb br?   rM   markets
ws_clientsg      ?cached_balancec                    K   i } 	 t        j                          }t        D ]S  }|j                  s|j                  dkD  rd|j                  z  nd}| j	                  |j
                  d      }||z
  |k  rV|| |j
                  <   	 |j                          d {    |j                  r|j                  s|j                          |j                  ra|j                         r8|j                  d       |j                          d {    d|_        d|_
        nZ|j                          d {    nA|j                         r|j                          d {    n|j                          d {    V t#        j$                  d       d {    7 7 7 l7 E7 .# t         $ r}|j                  d|        Y d }~d }~ww xY w7 ;w)Nr   ra  g      @zCycle complete - stoppedFzLoop error: g?)r{   rg  rX   rP   r   rN   r   rm   rn   r  ro   r  r   r   r(  r!  r    r   r   )last_refreshnowmintervallastr$   s         r%   refresh_looprp  i  s~    %'L
iik 	+A99/0~~/AsQ^^+sH##AJJ2DTzH$'*L$+iik!!88AHHMMOzz==?FF#=>"#"5"5"777',AH).AJ"#//"333//111oo////	+4 mmD!!!9  " 8 41/ +aS)**+!s   BGF FA,F F&F -F.(F FF /F0F 4GGGF F F F F  	G)G=GGGc                    K   t        j                  t        j                  d            4 d{   } 	 	 d}t        t	        t        j
                         dz              }t        |d|      }t        ||dd	}| j                  t         | |
      4 d{   }|j                  dk(  r-|j                          d{   }|j                  dd      dz  addd      d{    t        j                  d       d{    7 7 p7 K7 (# 1 d{  7  sw Y   8xY w# t        $ r Y Fw xY w7 1# 1 d{  7  sw Y   yxY ww)z'Fetch account balance every 10 seconds.r   r   r   Nz/portfolio/balancer   r   r   r   r      balancer   rB   r   )r   r   r   r   rF   r{   r>   r   r   r   r   r   ri  r    r   r   )r   r   r'   r=   r   r   r   s          r%   balance_looprt    sF     $$W-B-B-KL # #PW/DIIK$$6 78	#Iuh?)7/2/8$6	 #;;/):8*'Ew;W F F[_{{c)%)YY[0)-)Q)?#)EF F --"""# #F0F F F F  "%# # #s   /ED	ED7A"D&DD&#DDDD&&D'D&+D7D5D7	ED&DD&D#	DD#	D&&	D2/D71D22D77E	=E >E	Ec                    K   	 t         rt        D  cg c]  } | j                  s| j                         ! c} t        d}t        j                  |      }g }t         D ]  }	 |j                  |       d {     |D ]  }t         j                  |        t        j                  t               d {    c c} w 7 I# t        $ r |j                  |       Y w xY w7 ,w)N)rg  rs  )rh  rg  rX   rF  ri  r   dumps	send_textr    r}   remover   r   WS_PUSH_INTERVAL)rm  statepayloaddeadwss        r%   ws_broadcast_loopr~    s     
18FAAIIAIIKF)E jj'GD  $$,,w///$
  &!!"%&mm,---  G 0  $KKO$ 	.sV   C#B:B:*C#!C5B?6C::C#4C!5
C#?CCC#CC#z/wsr}  c                 n  K   | j                          d {    t        j                  |        	 	 | j                          d {   }	 t	        j
                  |      }|j                  dd      }|dk(  r|j                  dd      j                         }t        |j                  dd            }t        |j                  dd            }|r_t        t              d	k  rLt        t        t              |t        d
t        d|            t        dt        d|                  t        j                         j                  dj                           n|dk(  rt        |j                  dd            dcxk  rt        t              k  rn nt           }|j"                  r|j%                          d {    d|_        t        j)                         t+        t              D ]  \  }|_         n-|dk(  rt        |j                  dd            dcxk  rt        t              k  rn nt           j                  d       t/        j0                         }	|	j3                  d fd       d {   }
|
dk(  rj5                  d       d {    n|
dk(  rj5                  d       d {    nhj                  d       nVt        |j                  dd            dcxk  rt        t              k  r#n n t           j5                  |       d {    7 7 7 v7 7 7 |7 # t        j6                  t8        f$ r Y .w xY w# t:        $ r Y nw xY w	 | t        v rt        j=                  |        y y # | t        v rt        j=                  |        w w xY ww)NrG  r   
ADD_MARKETrO   rP   ra  rQ   r      r   rY  rx   rX  )rN   rO   rP   rQ   zAdded: REMOVE_MARKETrN   rT   r   FOz2One-side-first: which side first? (y/n in console)c                  z    t        d dz    dj                   d      j                         j                         S )Nz[Srx   r   z] Start with YES or NO? (y/n): )inputrY   rZ  lower)idxrm  s   r%   r   z$websocket_endpoint.<locals>.<lambda>  sd    %RTUXYZUZT[[\]^]d]d\e  fE  QF  KG  KM  KM  KO  KU  KU  KW r?   yrS  nrT  zCancelled - enter y or n)acceptrh  r}   receive_textr   loadsr   rZ  rH   rF   r~   rg  rM   maxr   r   rY   rm   r   rX   pop	enumeraterN   r   get_event_looprun_in_executorr`  JSONDecodeErrorr\  r   rx  )r}  r   r<   rG  midrateinceviloopchoicer  rm  s              @@r%   websocket_endpointr    s    
))+b6"**D.jj&ggeR(,&''+r288:C !=>Dcgg&:A>?Cs7|a/1%(\S),S#b$-)@/21c"cl/C
  q)	23O+cggj"56CC.#g,.$S\99"$"6"6"888%*
C($-g$6 +DAq)*AJ+CZcggj!45CC.#g,.#CLST&557'+';';D  CW  (X  "X!S="#"2"29"===#s]"#"2"28"<<<FF#=> cggj!45CC.#g,.%cl99#>>>]   +, 9 "X=< ?((*5  b! 2b! s   N5L3N5M# L6M# E6M L9CM L<M $L>%M M A(M ,M-M 1M# 3N56M# 9M <M >M  M M M M# M  M# #	M/,N .M//N 3N5 N22N5c                     t        j                  d      } | j                  dt        dd       | j	                         }t               at        dd        t        d	       t        d        t        rt        d
       nt        d       t        d|j                          t        d d       t        j                  d      d        }t        t              j                  dz  dz  j                         rOt        j                  dt               fd       }t        j#                  dt%        t'                    d       nt        j                  d      d        }t)        j*                  t        d|j                  d       y )NzMentions Dashboard)descriptionz--porti  zServer port (default: 8080))r   defaulthelp
z2==================================================z  MENTIONS DASHBOARDz  Kalshi:  API key loadedzB  Kalshi:  No key (set KALSHI_MOM_API_KEY + KALSHI_MOM_API_SECRET)z  Server:  http://localhost:startupc                     K   t        j                  t                      t        j                  t                      t        j                  t	                      y wr  )r   create_taskrp  rt  r~  r   r?   r%   start_bgzmain.<locals>.start_bg  s8     LN+LN+-/0s   AAzdashboard-uidistr  )response_classc                  2   K    dz  j                         S w)Nz
index.html)	read_text)
static_dirs   r%   serve_indexzmain.<locals>.serve_index  s     -88::s   )	directorystatic)namec                      K   t        d      S w)NzK<h1>Dashboard UI not built</h1><p>Run: cd dashboard-ui && npm run build</p>r   r   r?   r%   serve_fallbackzmain.<locals>.serve_fallback  s      mnns   z0.0.0.0warning)hostport	log_level)argparseArgumentParseradd_argumentrF   
parse_argsr&   r0   r!   r  appon_eventr   __file__parentexistsr   r	   mountr
   r   uvicornrun)parserargsr  r  r  r  s        @r%   mainr    sL   $$1EFF
sD?\]D$&L	Bvh-	 "	VH)+RT	(
45	VHB-\\)1 1 h&&7&@J	\	2	; 
3	; 			#{S_=H	M		o 
	o KK)$))yIr?   __main__)/re  r  r   r8   r   r   r{   pathlibr   r   r  dotenvr   fastapir   r   r   fastapi.responsesr	   fastapi.staticfilesr
   environr   r   r   r   r0   r&   r   r>   r   rK   rM   rg  __annotations__rh  ry  ri  rH   rp  rt  r~  r  	websocketr  r  rb  r   r?   r%   <module>r     sH       	      ; ; * +   4b9JJNN#:B? A"*S *# *S *S *([D [T [G G\ (*#	$ ) 
DO   # #"B#0.. i u9" 9" 9"@%JP zF r?   