a
    HËAjƒ  ã                   @   sº   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mZ ddlmZ dZ	dZ
dZg d¢Zd	d
„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zedkr¶eƒ  dS )a_  
Full audit of EVERY soccer league shared between Kalshi and Poly.

Poly-covered = league_map.json poly_tag != null (25 leagues). For each, measure from
poly_backfill how much Kalshi AND Poly actually price it, then the unique/overlap
[0.05,0.12) bet behavior. Columns:
  cov   : data presence -> 'BOTH' if fixtures have both kalshi & poly PRE prices,
          'K-only'/'P-only' if only one book quoted, '-' if no data in window
  fix   : resolved fixtures seen in backfill
  kPx   : fixtures with >=1 Kalshi PRE price
  pPx   : fixtures with >=1 Poly  PRE price
  both  : fixtures with BOTH (the shared opportunity set)
  uN/uROI : unique bets + ROIturn (one book fires)   [K@ask, P@est-ask]
  oN/oROI : overlap bets + ROIturn (both fire; Kalshi side @ ask)
Per-league n is small => ROI is noisy; this is a COVERAGE map, not a per-league edge
claim. Read-only.
é    N)Údatetime)ÚdefaultdictzE:\soccer\poly_backfillzE:\soccer\data\league_map.json)çš™™™™™©?g¸…ëQ¸¾?)z%Y-%m-%d %H:%M:%Sz%m/%d/%Y %H:%Mz%m/%d/%Y %H:%M:%Sz%Y-%m-%d %H:%Mc              
   C   s8   t D ].}zt | |¡W   S  ttfy0   Y q0 qd S ©N)Ú_FMTSr   ÚstrptimeÚ
ValueErrorÚ	TypeError)ÚsÚf© r   ú.E:\soccer\research\kalshi_poly_shared_audit.pyÚ_pts   s    r   c              	   C   s(   z
t | ƒW S  ttfy"   Y d S 0 d S r   )Úfloatr	   r   )Úxr   r   r   Ú_f   s    r   c                 C   s8   t | ƒD ]*}| d¡pd ¡  ¡ }|dv r|  S qd S )NÚftrÚ )ÚHÚDÚA)ÚreversedÚgetÚupperÚstrip)ÚrowsÚrÚvr   r   r   Ú_result"   s    r   c                    s(   dd„ | D ƒ}t |ƒ‰ ‡ fdd„|D ƒS )Nc                 S   s   g | ]}d | ‘qS )g      ð?r   )Ú.0r   r   r   r   Ú
<listcomp>(   ó    zfair_mult.<locals>.<listcomp>c                    s   g | ]}|ˆ  ‘qS r   r   )r   Zri©r
   r   r   r    (   r!   )Úsum)Úor   r   r"   r   Ú	fair_mult'   s    r%   c                 C   s(   | dk rdS | dk rdS | dk r$dS dS )Nr   gú~j¼t“h?g      Ð?g{®Gázt?gffffffÖ?gš™™™™™™?g{®Gáz”?r   )Úmidr   r   r   Úhalf_spread)   s    r'   c               
   C   s
  t tƒ} t tj td¡¡D ]p}t|ddd��N}t 	|¡D ]2}| | 
d¡| 
d¡| 
d¡| 
d¡f  |¡ q:W d   ƒ q1 s‚0    Y  qg }|  ¡ D ]j\}}|\}}}	}
|s´qštd	d
„ |D ƒdd„ d�}|sÔqšt|ƒ}|d u ræqš| t||dd
„ |D ƒd�¡ qš|S )Nz*_polybackfill.csvr   zutf-8)ÚnewlineÚencodingZ	game_dateÚleagueÚhomeÚawayc                 S   s>   g | ]6}|  d ¡pd ¡ dkrt|d ƒrt|d ƒ|f‘qS )Zstatusr   ZPREZ	timestamp)r   r   r   ©r   r   r   r   r   r    :   s   "ÿzload.<locals>.<listcomp>c                 S   s   | d S )Nr   r   )Útr   r   r   Ú<lambda><   r!   zload.<locals>.<lambda>©Úkeyc                 S   s   g | ]\}}|‘qS r   r   )r   Ú_r   r   r   r   r    @   r!   )r*   r   Úpre)r   ÚlistÚglobÚosÚpathÚjoinÚDIRÚopenÚcsvZ
DictReaderr   ÚappendÚitemsÚsortedr   Údict)Zfixturesr7   Zfhr   Úfxr1   r   Úgdr*   r+   r,   r3   r   r   r   r   Úload/   s*    ÿÿ&þ
 rB   c                 C   sx   | d D ]j}dD ]`}|dkr2t | d|› d�¡ƒnt | d|› d�¡ƒ}|d urd|  k rdd	k rn q  d
S qqdS )Nr3   )r+   r,   ÚkalshiÚkalshi_Ú_midÚpoly_Ú_pricer   é   TF)r   r   )r@   Úbookr   Úsider   r   r   r   Ú	has_priceC   s
    4,rK   c              	   C   sØ  g }dD �]²\}}| d D �]ž}t | d¡ƒt | d¡ƒt | d¡ƒ  }}}d |||fv s|dkr|dkr|dksvq|dkr¬t | d|› d	�¡ƒ}	t | d|› d
�¡ƒ}
n.t | d|› d�¡ƒ}	|	d urÖ|	t|	ƒ nd }
|	d u s|
d u sd|	  k �r dk rn qd|
  k �rdk �s q qt|||fƒ| }|�rD||	 | nd }|d u std |  k�rptd k �stq q| d dk�rŒ|dk�p | d dk�o |dk}| t|
||d�¡  qqq|�rÔt|dd„ d�S d S )N))r+   r   )r,   é   r3   Zpin_homeZpin_drawZpin_awayrH   rC   rD   rE   Z_askrF   rG   r   r   r   r+   r   r,   )ÚpxÚwonÚclvc                 S   s   | d S )NrO   r   )Údr   r   r   r/   Z   r!   zfire.<locals>.<lambda>r0   )r   r   r'   r%   ÚBANDr<   r?   Úmax)r@   rI   ZcandsrJ   Zsidxr   ZphZpd_Zpar&   rM   ZpfrO   rN   r   r   r   ÚfireJ   s    .(..F,.rS   c                 C   sR   t | ƒ}|sd S tdd„ | D ƒƒ}tdd„ | D ƒƒ}t||| d || d d�S )Nc                 s   s   | ]}|d  V  qdS )rN   Nr   ©r   Úbr   r   r   Ú	<genexpr>_   r!   zroi.<locals>.<genexpr>c                 s   s.   | ]&}|d  r"d|d  |d  ndV  qdS )rN   rH   rM   g      ð¿Nr   rT   r   r   r   rV   `   r!   éd   )ÚnÚwrÚroi)Úlenr#   r?   )ZbetsrX   ZwinsZnetr   r   r   rZ   \   s
    rZ   c                  C   sZ  t  ttƒ¡} dd„ |  ¡ D ƒ}tƒ }ttƒ}|D ]}||d   |¡ q2g }| ¡ D �]\}}| |g ¡}t	dd„ |D ƒƒ}	t	dd„ |D ƒƒ}
t	dd„ |D ƒƒ}g g  }}|D ]l}t
|dƒr°t
|d	ƒsÊq°t|dƒ}t|d	ƒ}|rò|rò| |¡ q°|�r
|�s
| |¡ q°|r°|s°| |¡ q°|�r(d
n|	�r2dn|
�r<dnd}| t|| dd¡|t|ƒ|	|
|t|ƒt|ƒd�	¡ qV|jdd„ d� tdt|ƒ› d�ƒ t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,  }}|�r*|d- nd*}|�r<|d- nd*}||7 }||7 }|�rb|d. d/›nd0}|�rx|d. d/›nd0}td|d d›d|d d d1… d›d|d d›d|d d2›d|d3 d2›d|d4 d2›d|d! d5›d#|d6›d|› d#|d6›d|› �ƒ �qtd7t	d8d„ |D ƒƒ› d9t|ƒ› �ƒ td:td;d„ |D ƒƒ› �ƒ td<|› d=|› �ƒ d S )>Nc                 S   s*   i | ]"\}}t |tƒr| d ¡r||“qS )Zpoly_tag)Ú
isinstancer?   r   )r   Úcr   r   r   r   Ú
<dictcomp>e   s   ÿzmain.<locals>.<dictcomp>r*   c                 s   s   | ]}t |d ƒrdV  qdS )rC   rH   N©rK   ©r   r   r   r   r   rV   n   r!   zmain.<locals>.<genexpr>c                 s   s   | ]}t |d ƒrdV  qdS )ÚpolyrH   Nr_   r`   r   r   r   rV   o   r!   c                 s   s&   | ]}t |d ƒrt |dƒrdV  qdS )rC   ra   rH   Nr_   r`   r   r   r   rV   p   r!   rC   ra   ÚBOTHzK-onlyzP-onlyú-Únamer   )	Úcoderd   ÚcovÚfixÚkpxÚppxÚbothÚur$   c                 S   s   | d  | d fS )Nrj   re   r   )r   r   r   r   r/   |   r!   zmain.<locals>.<lambda>r0   z(Poly-covered (shared-eligible) leagues: Ú
z  re   Z5sú Z18srf   Z6srg   z>4ZkPxZpPxrj   z>5z | ZuNz>3zuROI%z>7ZoNzoROI%r   rk   r$   rX   rZ   z+7.1fz      -é   Z4drh   ri   Z5dZ3dz#
  shared-data leagues (cov=BOTH): c                 s   s   | ]}|d  dkrdV  qdS )rf   rb   rH   Nr   r-   r   r   r   rV   ˆ   r!   ú/z1  Poly-covered but NO backfill data this window: c                 s   s"   | ]}|d  dkr|d V  qdS )rf   rc   re   Nr   r-   r   r   r   rV   Š   r!   z&  totals over shared fixtures: unique=z
  overlap=)ÚjsonrB   r:   ÚLMAPr=   r   r4   r<   r   r#   rK   rS   r?   r[   rZ   ÚsortÚprintr>   )ZlmZpoly_leaguesr@   Zbyr   r   re   r   Zlgfxrh   ri   rj   ZuniqZoverÚkÚprf   ZtuÚtor   rk   r$   ZunZonZurZorrr   r   r   Úmainc   sr    
"ÿ
<ÿÿÿÿ4Hÿÿÿÿÿÿ&ÿrw   Ú__main__)Ú__doc__r;   r5   r6   rp   Zmathr   Úcollectionsr   r9   rq   rQ   r   r   r   r   r%   r'   rB   rK   rS   rZ   rw   Ú__name__r   r   r   r   Ú<module>   s&   (*