a
    ) —j|&  ã                   @   sÈ   d Z ddlZddlZddlmZ ej deeeƒj	ƒ¡ ej
jddd� ddlmZmZmZmZ ddlmZmZmZmZmZmZmZmZmZ eeƒZd	d
„ Zdd„ Zddd„Zdd„ ZedkrÄeƒ  dS )a!  
Midnight job - resolves previous day's pending bets via API-Football
and updates bankroll. Runs daily at midnight via Task Scheduler.

Also reconciles auto_trade_log.json against Kalshi fills (Phase 3): flags
auto-placed orders that never filled, and Kalshi fills that have no log entry.
é    N)ÚPathzutf-8Úreplace)ÚencodingÚerrors)ÚdatetimeÚdateÚ	timedeltaÚtimezone)	Úresolve_pending_betsÚload_bankrollÚload_kalshi_bankrollÚload_poly_bankrollÚ
build_htmlÚ
send_emailÚload_historyÚsave_historyÚAUTO_TRADE_LOGc                	   C   s0   zt  t ¡ ¡W S  ttfy*   g  Y S 0 d S )N)ÚjsonÚloadsÚAUTO_LOGÚ	read_textÚFileNotFoundErrorÚ
ValueError© r   r   úmain/resolve_bets.pyÚ_load_auto_log   s    r   c                 C   s   t  tj| dd�¡ d S )Né   )Úindent)r   Z
write_textr   Údumps)Úlogr   r   r   Ú_save_auto_log   s    r    é0   c                 C   s|  t ƒ }|sdS zddl}W n4 tyN } ztd|› �ƒ W Y d}~dS d}~0 0 tt tj¡t	| d�  
¡ ƒ}i }�zfd}d|dœ}|r�||d< |jd|d	�}t| d
g ¡p®g ƒ}	|sòz(|	|jdd|ddœd	� d
¡pØg 7 }	W n tyð   Y n0 t|ƒ}|	|d
< | d
g ¡D ]´}
|
 d¡}|�s&�q| |dd|
 d¡dœ¡}t|
 d|
 dd¡¡�pZdƒ}|
 d¡dk�r†t|
 dd¡�p€dƒ}nt|
 dd¡�p˜dƒ}|d  |7  < |d  || 7  < �q| d¡}|sz�qØqzW n6 t�y } ztd|› �ƒ W Y d}~dS d}~0 0 dd„ |D ƒ}g }g }|D ]´}| d¡}|�sD�q,| |¡}
|
�s¶z2t |d  dd¡¡}t tj¡|  ¡ d }W n t�yž   d}Y n0 |dk�rÞ| |¡ n(|
d |d < t|
d d!ƒ|d"< | |¡ �q,t|ƒ d#d„ |D ƒ}g }| ¡ D ]:\}}
||v �r�q|
 d¡|v �r| d|i|
¥¡ �qg }|D ]t}| d$| d%d&¡› d'| d(d&¡› d)|d › d)| dd&¡› d*| d+d&¡› d,| d d¡d-›d.| d"d¡d/›d0�¡ �qH|D ]T}| d$| d%d&¡› d'| d(d&¡› d)|d › d)| dd&¡› d*| d+d&¡› d1�¡ �qÂ|D ]4}
| d2|
d › d)|
d d-›d.|
d d/›d3�¡ �qd4}|�rnd5d4 |¡ d6 }||||d7œS )8a{  
    Walk auto_trade_log.json, ask Kalshi for fills, and produce a report.

    Returns dict {orphan_logs, orphan_fills, filled, partial, html} or None
    if no auto-trade activity. orphan_logs = placed but never filled;
    orphan_fills = Kalshi fills whose order_id is not in our log.
    Also persists fill counts back onto each log entry (filled_count, filled_dollars).
    Nr   z'  [RECON] kalshi_trader import failed: )ZhourséÈ   )ÚlimitÚmin_tsÚcursorz/portfolio/fills)ÚparamsZfillsé   )r#   r$   Z
subaccountÚorder_idg        Úticker)ÚcountÚdollarsr)   Zcount_fpr*   ZsideZyesZyes_price_dollarsZno_price_dollarsr+   z!  [RECON] fetching fills failed: c                 S   s    h | ]}|  d ¡r|  d ¡’qS )r(   ©Úget©Ú.0Úer   r   r   Ú	<setcomp>`   ó    z(reconcile_auto_orders.<locals>.<setcomp>Z	placed_atÚZz+00:00i  iç  Zfilled_counté   Zfilled_dollarsc                 S   s    h | ]}|  d ¡r|  d ¡’qS )r)   r,   r.   r   r   r   r1   {   r2   z<tr><td>Úhomeú?z vs Zawayz	</td><td>z @ Zprice_centsz
c</td><td>z.1fz
</td><td>$z.2fz/</td><td style='color:#2d7d2d'>FILLED</td></tr>zJc</td><td>0</td><td>$0.00</td><td style='color:#cc3333'>UNFILLED</td></tr>z:<tr><td colspan='2'><i>DRIFT: fill not in log</i></td><td>z/</td><td style='color:#cc6600'>ORPHAN</td></tr>Ú a  <h3>Auto-trade reconciliation</h3><table border='1' cellpadding='4' cellspacing='0' style='border-collapse:collapse;font-size:12px'><tr style='background:#222;color:white'><th>Match</th><th>Ticker</th><th>Placed</th><th>Filled qty</th><th>Filled $</th><th>Status</th></tr>z</table>)ÚfilledÚorphan_logsÚorphan_fillsÚhtml)r   Zkalshi_traderÚ	ExceptionÚprintÚintr   Únowr	   Zutcr   Z	timestampZ_getÚlistr-   ÚdictÚ
setdefaultÚfloatZfromisoformatr   Ztotal_secondsÚappendÚroundr    ÚitemsÚjoin)Zlookback_hoursr   Zktr0   Z	cutoff_tsZfills_by_orderr%   r&   ZrespZ_rowsÚfZoidÚdZqtyZpxZ
logged_idsr9   r8   ZplacedZage_hZlogged_tickersr:   Zrowsr;   r   r   r   Úreconcile_auto_orders!   sê    	
ÿÿþþ







"ÿ
þ
þýü"ÿ
þ
þÿÿþûûürJ   c                  C   s�  t  ¡  d¡} td| › d�ƒ tƒ  tƒ }tƒ }tƒ }tƒ }dd„ |D ƒ}tdt	|ƒ› d�ƒ t
dd	„ |D ƒƒ}t
d
d	„ |D ƒƒ}t	|ƒ| | }t
dd	„ |D ƒƒ}	t
dd	„ |D ƒƒ}
t
dd	„ |D ƒƒ}|�r|rÞd|› d�nd}td|› d|› d|› d|	d›d|
d›d|d›�ƒ td|d›�ƒ td|d›�ƒ d }zBtƒ }|�rxtdt	|d ƒ› dt	|d ƒ› dt	|d  ƒ› �ƒ W n4 t�y® } ztd!|› �ƒ W Y d }~n
d }~0 0 |�r„t ¡ td"d#�  d¡}d}|�rð|d �sì|d  �rðd$}d%|› d&|› d'|› d(|› d)|d›d*|d›�}tg ||||d+�}|�rT| d,¡�rT| d-|d, d- ¡}t||ƒ�r„td.ƒ |D ]}d/|d0< �qlt|ƒ td1ƒ d S )2Nz%Y-%m-%dz
=== Nightly Bet Resolution - z ===c                 S   s   g | ]}|  d ¡s|‘qS )Úemailed_nightlyr,   )r/   Úhr   r   r   Ú
<listcomp>·   r2   zmain.<locals>.<listcomp>zResolved (unreported): z betsc                 s   s   | ]}|  d ¡rdV  qdS )Zwonr'   Nr,   ©r/   Úrr   r   r   Ú	<genexpr>¹   r2   zmain.<locals>.<genexpr>c                 s   s   | ]}|  d ¡rdV  qdS )Zvoidedr'   Nr,   rN   r   r   r   rP   º   r2   c                 s   s   | ]}|  d d¡V  qdS )Zpnlr   Nr,   rN   r   r   r   rP   ¼   r2   c                 s   s(   | ] }|  d ¡dur|  d d¡V  qdS )Z
kalshi_pnlNr   r,   rN   r   r   r   rP   ½   r2   c                 s   s(   | ] }|  d ¡dur|  d d¡V  qdS )Zpoly_pnlNr   r,   rN   r   r   r   rP   ¾   r2   z  (z void)r7   z  zW / ÚLz  |  Net P&L: $z+.2fz  Kalshi: $z	  Poly: $z  Kalshi Bankroll: $z,.2fz  Poly Bankroll:   $z  [RECON] filled=r8   z
 unfilled=r9   z orphan_fills=r:   z  [RECON] failed: r'   )Zdaysz [RECON-ALERT]ú[zW/zL]z NIGHTLY RESULTS - z  |  Kalshi $z  Poly $)Úkalshi_bankrollÚresolvedr;   z</body>z  Email sent.TrK   zDone.)r   r?   Ústrftimer=   r
   r   r   r   r   ÚlenÚsumrJ   r<   r   Útodayr   r   r-   r   r   r   )rX   ZbankrollrS   Zpoly_bankrollÚhistoryrT   ZwinsZvoidsZlossesZnetZk_netZp_netZvoid_strZreconr0   Z	yesterdayZsubject_extraZsubjectr;   rL   r   r   r   Úmain©   sd    2
ÿ
þ$ÿÿrZ   Ú__main__)r!   ) Ú__doc__Úsysr   Úpathlibr   ÚpathÚinsertÚstrÚ__file__ÚparentÚstdoutÚreconfigurer   r   r   r	   Zdaily_signalsr
   r   r   r   r   r   r   r   r   r   r   r    rJ   rZ   Ú__name__r   r   r   r   Ú<module>   s   ,
 	>