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Zdd„ Zdd„ Z	d	d
„ Z
dd„ Zde	fde
fdefgZddddœZdd„ Zdd„ Zedkr”eƒ  dS )a—  
Which de-vig method gives the best-calibrated 'true' probability from Pinnacle's
1X2 closing odds (PSH/PSD/PSA)?  Read-only calibration study, no betting.

The live pipeline uses plain MULTIPLICATIVE de-vig (live_monitor.py:442-443,627-630):
    p_i = (1/o_i) / sum_j(1/o_j)
which is known to over-state longshot probabilities (it spreads the book's vig
proportionally, but real vig sits disproportionately on longshots). Our CLV edge
lives in the longshot tail, so a biased fair there would distort every CLV number.

Compare three de-vig methods against ACTUAL results:
  multiplicative : p_i = r_i / sum(r),                r_i = 1/o_i
  power          : p_i = r_i^k,  k chosen so sum(p)=1 (shrinks longshots more)
  shin           : insider-trader model, solve z so sum(p)=1 (favorite-longshot fix)

Scoring (lower=better): log-loss & Brier vs realized FTR (which outcome happened).
Plus a calibration table BY PREDICTED-PROB BIN, with the longshot bins (p<0.25)
broken out -- that is the slice our strategy actually bets. If multiplicative
over-states longshots, its predicted prob in those bins will exceed the empirical
win frequency, and Shin/power should be closer.
é    N)ÚdefaultdictzE:\soccer\league_datac              	   C   s8   zt | ƒ}|dkr|nd W S  ttfy2   Y d S 0 d S )Nç      ð?)ÚfloatÚ	TypeErrorÚ
ValueError)ÚxÚv© r	   ú'E:\soccer\research\devig_calibration.pyÚ_f   s
    r   c                    s(   dd„ | D ƒ}t |ƒ‰ ‡ fdd„|D ƒS )Nc                 S   s   g | ]}d | ‘qS ©r   r	   ©Ú.0r   r	   r	   r
   Ú
<listcomp>$   ó    zdv_mult.<locals>.<listcomp>c                    s   g | ]}|ˆ  ‘qS r	   r	   ©r   Zri©Úsr	   r
   r   %   r   ©Úsum)ÚoÚrr	   r   r
   Údv_mult#   s    r   c                    s�   dd„ | D ƒ}d\}}t dƒD ]8}|| d ‰ t‡ fdd„|D ƒƒ‰ˆdkrRˆ }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dv_power.<locals>.<listcomp>)ç      à?g      $@é<   é   c                 3   s   | ]}|ˆ  V  qd S ©Nr	   r   ©Úkr	   r
   Ú	<genexpr>-   r   zdv_power.<locals>.<genexpr>r   c                    s   g | ]}|ˆ  ‘qS r	   r	   r   r   r	   r
   r   1   r   c                    s   g | ]}|ˆ  ‘qS r	   r	   ©r   Zpir   r	   r
   r   2   r   )Úranger   )r   r   ÚloÚhiÚ_Úpr	   )r   r   r
   Údv_power'   s    r&   c                    s–   dd„ | D ƒ‰t ˆƒ‰ ‡ ‡fdd„}d\}}tdƒD ]&}|| d ‰|ˆƒdkrVˆ}q4ˆ}q4|| 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   5   r   zdv_shin.<locals>.<listcomp>c                    s   t ‡‡ fdd„ˆD ƒƒS )Nc                 3   sD   | ]<}t  ˆˆ d dˆ  | | ˆ   ¡ˆ ddˆ   V  qdS )é   é   r   N©ÚmathZsqrtr   ©ÚBÚzr	   r
   r   7   r   z(dv_shin.<locals>.psum.<locals>.<genexpr>r   ©r-   )r,   r   r.   r
   Úpsum6   s    zdv_shin.<locals>.psum)ç        g®Gáz®ï?r   r   r   c                    sB   g | ]:}t  ˆˆ d dˆ  | | ˆ   ¡ˆ ddˆ   ‘qS )r'   r(   r   r)   r   r+   r	   r
   r   ?   r   c                    s   g | ]}|ˆ  ‘qS r	   r	   r    r   r	   r
   r   A   r   )r   r!   )r   r/   r"   r#   r$   r%   r	   )r,   r   r   r-   r
   Údv_shin4   s    r1   ÚmultiplicativeÚpowerÚshinr(   r   ©ÚHÚDÚAc               	   C   sÐ   g } t   tj td¡¡D ]²}t|ddd���}t |¡D ]t}| d¡pFd 	¡  
¡ }|dvrZq6t| d¡ƒt| d¡ƒt| d	¡ƒ  }}}d |||fv r˜q6|  ||||f¡ q6W d   ƒ q1 sÀ0    Y  q| S )
Nz*.csvÚ zlatin-1)ÚnewlineÚencodingZFTRr5   ZPSHZPSDZPSA)ÚglobÚosÚpathÚjoinÚDIRÚopenÚcsvZ
DictReaderÚgetÚstripÚupperr   Úappend)Úrowsr>   Zfhr   ÚftrÚohÚodÚoar	   r	   r
   ÚloadF   s    
.4rL   c                     s¾  t ƒ } tdt| ƒ› d�ƒ tdd„ | D ƒƒt| ƒ }td|d›d|d d	 d
›d�ƒ tdƒ i }tD ]¾\}}d }}| D ]\\}}}	}
||||	fƒ‰t|
 ‰|t tˆˆ dƒ¡ 7 }|t‡‡fdd„t	dƒD ƒƒ7 }qz|t| ƒ |t| ƒ f||< td|d›d|t| ƒ d›d|t| ƒ d›�ƒ qfg d¢}tdƒ tdƒ dd„ tD ƒ}| D ]h\}}}	}
t|
 ‰tD ]L\}}||||	fƒ‰t	dƒD ]*}||  
ˆ| |ˆk�r¦dndf¡ �q†�qh�qPt	t|ƒd ƒD �]@}|| ||d   ‰‰ i }tD ]x\}}‡ ‡fdd„|| D ƒ}t|ƒ}|�r2tdd„ |D ƒƒ| nd}|�rRtd d„ |D ƒƒ| nd}|||f||< �qî|d! d }ˆ d"k�r‚d#n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)›|› �ƒ �qÊtd/ƒ tD ]ž\}}d0d„ || D ƒ}t|ƒ}td1d„ |D ƒƒ| }td2d„ |D ƒƒ| }|| }td|d›d3|d(›d4|d›d5|d›d6|d7›d|dk�rªd8nd9› d:�ƒ �qd S );NzLoaded z( matches with Pinnacle closing 1X2 odds
c                 s   s.   | ]&\}}}}d | d |  d |  V  qdS )r(   Nr	   )r   rI   rJ   rK   r$   r	   r	   r
   r   U   r   zmain.<locals>.<genexpr>zmean Pinnacle overround = z.4fz  (r(   éd   z.2fz% vig)
z1OVERALL fit vs realized outcome (lower = better):r0   gê-�™—q=c                 3   s*   | ]"}ˆ | |ˆkrd nd d V  qdS )r   r0   r   Nr	   )r   r   )r%   Úyr	   r
   r   `   r   é   z   Z14sz	 logloss=z.5fz  brier=)
r0   gš™™™™™©?gš™™™™™¹?g333333Ã?gš™™™™™É?ç      Ð?gffffffÖ?r   gffffffæ?g)\�Âõ(ð?z@
CALIBRATION by predicted-prob bin (pooled over H/D/A outcomes):zX   bin            n      mult_pred  mult_emp |  shin_pred  shin_emp |  pow_pred  pow_empc                 S   s   i | ]\}}|g “qS r	   r	   )r   Únamer$   r	   r	   r
   Ú
<dictcomp>i   r   zmain.<locals>.<dictcomp>r   c                    s0   g | ](\}}ˆ|  kr ˆ k rn q||f‘qS r	   r	   ©r   ÚppÚhh)r#   r"   r	   r
   r   t   r   zmain.<locals>.<listcomp>c                 s   s   | ]\}}|V  qd S r   r	   ©r   rT   r$   r	   r	   r
   r   v   r   r   c                 s   s   | ]\}}|V  qd S r   r	   ©r   r$   rU   r	   r	   r
   r   w   r   r2   rP   z <- LONGSHOTr9   z   [ú,z)  Z6dz7.3fz  r   z  | r4   r3   z?
LONGSHOT TAIL (predicted p<0.25, the slice the strategy bets):c                 S   s    g | ]\}}|d k r||f‘qS )rP   r	   rS   r	   r	   r
   r   ‚   r   c                 s   s   | ]\}}|V  qd S r   r	   rV   r	   r	   r
   r   „   r   c                 s   s   | ]\}}|V  qd S r   r	   rW   r	   r	   r
   r   …   r   z n=z  mean_pred=z  emp_freq=z  bias(pred-emp)=z+.4fZOVERZunderz-states))rL   ÚprintÚlenr   ÚMETHODSÚIDXr*   ÚlogÚmaxr!   rF   )rG   ZbooksumZstatsrQ   ÚfnZllÚbrrI   rJ   rK   rH   ZedgesZpredsr   ÚiZcellsr$   ZselÚnZpmZemÚtagZbiasr	   )r#   r"   r%   rN   r
   ÚmainR   st    ""20  <ÿÿþþþ$ÿÿrd   Ú__main__)Ú__doc__rB   r<   r=   r*   Úcollectionsr   r@   r   r   r&   r1   r[   r\   rL   rd   Ú__name__r	   r	   r	   r
   Ú<module>   s    8