a
    ŠË?j  ã                   @   s¬   d 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g d¢Z	dd„ Z
d	d
„ Zdd„ Zdd„ Zdd„ ZeedœZdd„ Zdd„ Zdd„ Zdd„ Zedkr¨eƒ  dS )a¾  
Does the de-vig correction + band shift carry over to POLYMARKET?  Read-only.

Same study as Kalshi (research/devig_live_rerun.py + devig_band_sweep.py) but on the
Poly backfill (poly_backfill/*_polybackfill.csv, 815 fixtures w/ poly prices, 23 leagues,
2026-04-18..06-18). Poly is MID-ONLY: single poly_{side}_price, no bid/ask -> a "bet" is
priced at that mid (matches the +17.4% mid-only backtest). Shares the SAME raw Pinnacle
odds (pin_home/draw/away), so we recompute pin_fair under each de-vig identically.

Selection (NON-look-ahead): first pre-KO snapshot whose mid-CLV = (pin_fair - poly_mid)/
pin_fair is in band; both-sides dedupe to higher-CLV side; bet at that snapshot's poly mid;
settle by ftr. Reports n, WR, implied(mid) WR, flat ROIturn, win-rate-vs-implied z.
Part 1: mult vs power at the current [0.05,0.12) band. Part 2: band sweep under power
with a 60/40 temporal split (in-sample band selection -> trust the split, not headline p).
é    N)Údatetime)ÚdefaultdictzE:\soccer\poly_backfill)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\devig_poly_study.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 ©ç      ð?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                    sŒ   dd„ | D ƒ}d\}}t dƒD ]4}|| d ‰ t‡ fdd„|D ƒƒdkrNˆ }qˆ }q|| d ‰ ‡ fd	d„|D ƒ}t|ƒ‰‡fd
d„|D ƒS )Nc                 S   s   g | ]}d | ‘qS r   r   r!   r   r   r   r#   '   r$   zfair_power.<locals>.<listcomp>)ç      à?g      $@é<   é   c                 3   s   | ]}|ˆ  V  qd S r   r   r%   ©Úkr   r   Ú	<genexpr>+   r$   zfair_power.<locals>.<genexpr>r    c                    s   g | ]}|ˆ  ‘qS r   r   r%   r-   r   r   r#   .   r$   c                    s   g | ]}|ˆ  ‘qS r   r   )r"   Zpir&   r   r   r#   /   r$   )Úranger'   )r(   r   ÚloÚhiÚ_Úpr   )r.   r	   r   Ú
fair_power&   s     r5   ©ZmultÚpowerc               
   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 ]h\\}}}}}	|s°qštd	d
„ |	D ƒdd„ d�}
|
sÐqšt|	ƒ}|d u râqš| t|||dd
„ |
D ƒd�¡ qš|jdd„ d� |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_fixtures.<locals>.<listcomp>c                 S   s   | d S ©Nr   r   ©Útr   r   r   Ú<lambda>>   r$   zload_fixtures.<locals>.<lambda>©Úkeyc                 S   s   g | ]\}}|‘qS r   r   )r"   r3   r   r   r   r   r#   B   r$   )Úgdr:   r   Úprec                 S   s   | d S ©NrC   r   r   r   r   r   r@   C   r$   )r   ÚlistÚglobÚosÚpathÚjoinÚDIRÚopenÚcsvZ
DictReaderr   ÚappendÚitemsÚsortedr   ÚdictÚsort)ZfixturesrI   Zfhr   ÚpreppedrC   r:   r;   r<   r   rD   r   r   r   r   Úload_fixtures2   s*    ÿÿ&þ
"rT   c              	   C   sš  t | }g }| D �]r}g }dD �]0\}}	|d D �]}
t|
 d¡ƒt|
 d¡ƒt|
 d¡ƒ  }}}d |||fv s0|dkr0|dkr0|dksŒq0t|
 d|› d�¡ƒ}|d u s0d	|  k r¾dk sÂq0 q0||||fƒ|	 }|rä|| | nd }|d u s0||  k�r|k �sq0 q0|d
 dk�r$|dk�p8|d
 dk�o8|dk}| |||f¡  qq0q|rt|dd„ d�\}}}| t|d ||d�¡ q|jdd„ d� |S )N))r;   r   )r<   r,   rD   Zpin_homeZpin_drawZpin_awayé   Zpoly_Z_pricer   r   r   r;   r   r<   c                 S   s   | d S r=   r   r>   r   r   r   r@   V   r$   zselect.<locals>.<lambda>rA   rC   )rC   ÚpriceÚwonc                 S   s   | d S rE   r   )Úbr   r   r   r@   X   r$   )Ú_DEVIGr   r   rN   ÚmaxrQ   rR   )rS   Zdevigr1   r2   ÚfnÚbetsZfxZcandsZsideZsidxr   ZphZpd_ZpaZmidZpfZclvrW   r   r   r   ÚselectF   s&    
.( $.r]   c                 C   sº   t | ƒ}|sd S tdd„ | D ƒƒ}tdd„ | D ƒƒ}tdd„ | D ƒƒ}tdd„ | D ƒƒ}|dkrr|| t |¡ nd}dt |t d	¡ ¡ }t||| d
 || d
 || d
 ||d�S )Nc                 s   s   | ]}|d  V  qdS )rW   Nr   ©r"   rX   r   r   r   r/   ^   r$   zstat.<locals>.<genexpr>c                 s   s.   | ]&}|d  r"d|d  |d  ndV  qdS )rW   rU   rV   g      ð¿Nr   r^   r   r   r   r/   _   r$   c                 s   s   | ]}|d  V  qdS )rV   Nr   r^   r   r   r   r/   `   r$   c                 s   s"   | ]}|d  d|d    V  qdS )rV   rU   Nr   r^   r   r   r   r/   `   r$   r   g        r*   r,   éd   )ÚnÚwrÚiwrÚroiÚzr4   )Úlenr'   ÚmathZsqrtZerfcrQ   )r\   r`   ZwinsZnetZmuÚvarrd   r4   r   r   r   Ústat[   s    $rh   c                  C   s&  t ƒ } tdt| ƒ› d�ƒ tdƒ dD ]r}tt| |ddƒƒ}|r&td|d›d	|d
 d›d|d d›d|d d›d|d d›d|d d›d|d d›�ƒ q&tdƒ 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&�ƒ |D �]\}}t| d'||ƒ}t|ƒ}|�s2td(|d)›d*|d)›d+�ƒ qðtt|ƒd, ƒ}t|d |… ƒt||d … ƒ }}	d(|d)›d*|d)›d-|d
 d›d|d d.›d|d d/›d|d d0›d|d d1›d|d d2›d3�}
|�r|	�r|
d4|d d›d5|d d›d6|	d d›d5|	d d›d7�	7 }
t|
ƒ qðtd8ƒ td9ƒ d S ):NzLoaded z& Poly fixtures with pre-KO snapshots.
zFPART 1 -- current band [0.05,0.12), mult vs power de-vig (mid-priced):r6   çš™™™™™©?ç¸…ëQ¸¾?z  Z5sz  n=r`   Z4dz  WR=ra   z4.1fz%  impl=rb   z%  ROIturn=rc   z+6.1fz%  z=rd   z+.2fz  p=r4   z.3fz6
PART 2 -- band sweep under POWER de-vig (mid-priced):))ç{®Gáz”?ri   )g¸…ëQ¸ž?çìQ¸…ë±?)ri   rj   )ri   çš™™™™™É?)rl   g333333Ã?)rl   rm   )çš™™™™™¹?rm   )rn   ç333333Ó?)rj   ro   )ri   r    )rk   r    ZbandZ14sú z>4zWR%z>5zimpl%z>6zROIturn%z>9z#  | 60/40  trainROI(z)   testROI(z)r7   z  [z.2fú,z)  (no bets)g333333ã?z)  z5.1fz6.1fz+9.1fz+6.2fz6.3fz  | ztr:z%(zz) te:ú)zP
Note: Poly is mid-only (no ask-tax). Band selection is in-sample over 11 bands;z&trust the 60/40 split over headline p.)rT   Úprintre   rh   r]   Úint)rS   Zdvr	   Zbandsr1   r2   r\   ZcutZtrZteÚliner   r   r   Úmaine   sF    0ÿÿÿ
B"6ÿÿÿ:
rv   Ú__main__)Ú__doc__rM   rG   rH   rf   r   Úcollectionsr   rK   r   r   r   r   r)   r5   rY   rT   r]   rh   rv   Ú__name__r   r   r   r   Ú<module>   s"    


