a
    Dß?j5  ã                   @   s¦   d Z ddlZddlZddlZddlZddlmZmZ ddlmZ dZ	d\Z
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edkr¢eƒ  dS )aü  
Is the Kalshi market wising up?  Measure the Kalshi-vs-Pinnacle price GAP over
calendar time, on ALL fixtures (not just settled bets) -- a far higher-n signal
than win/loss P&L.

For each fixture take the LAST pre-KO Kalshi snapshot (its "closing" line, the
fairest comparison to Pinnacle's close). For the bettable home/away sides compute
  pin_fair  = multiplicative de-vig of (pin_home,pin_draw,pin_away)   [live default]
  kalshi_mid
  gap       = kalshi_mid - pin_fair          (signed; <0 means Kalshi cheap = +CLV)
  |gap|     = mispricing magnitude
  CLV       = (pin_fair - kalshi_mid)/pin_fair

CONVERGENCE (market wising up) => |gap| shrinks and mean CLV -> 0 over time.

CONFOUND: league mix shifts over the season (Apr = European majors, Jun = thin
summer leagues w/ structurally bigger gaps), so a raw time trend can be pure mix.
We therefore ALSO report the trend WITHIN each league that spans several weeks,
which removes the mix. Edge-relevant view = longshot sides pin_fair in [0.05,0.40].
Read-only.
é    N)ÚdatetimeÚdate)ÚdefaultdictzE:\soccer\live_data)çš™™™™™©?gš™™™™™Ù?)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_pin_convergence.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                    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)ÚoÚrr   r   r   Ú	fair_mult%   s    r   c                 C   sH   zt  | d¡ ¡ }W n ty(   Y d S 0 | ¡ \}}}|› d|d›�S )Nz%Y-%m-%dz-WZ02d)r   r   r   r	   Zisocalendar)ÚgdÚdÚyÚwÚ_r   r   r   Úisoweek'   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 �]X\\}}}}}	|s²qšd
d„ |	D ƒ}
|
sÆqšt|
dd„ d�\}}t| 
d¡ƒt| 
d¡ƒt| 
d¡ƒ  }}}d	|||fv sš|dkrš|dkrš|dk�s2qšt|||fƒ}t|ƒ}dD ]¦\}}t| 
d|› d�¡ƒ}|d	u �sLd|  k �rŒdk �s’n �qL|| }| t|||||||| t|| ƒ|�rÎ|| | nd	t|  k�oätk n  d�
¡ �qLqš|S )zMReturn list of dicts: one per (fixture, side) at the closing pre-KO snapshot.z*.csvÚ zutf-8)ÚnewlineÚencodingZ	game_dateÚleagueÚhomeÚawayNc                 S   s>   g | ]6}|  d ¡pd ¡ dkrt|d ƒrt|d ƒ|f‘qS )Zstatusr"   ZPREZ	timestamp)ÚgetÚupperr   ©r   r   r   r   r   r   7   s   "ÿzload_sides.<locals>.<listcomp>c                 S   s   | d S )Nr   r   )Útr   r   r   Ú<lambda>:   r   zload_sides.<locals>.<lambda>©ÚkeyZpin_homeZpin_drawZpin_awayé   ))r&   r   )r'   é   Zkalshi_Z_midr   )
Úwkr   r%   ÚsideÚpfÚmidÚgapÚagapÚclvÚlongshot)r   ÚlistÚglobÚosÚpathÚjoinÚDIRÚopenÚcsvZ
DictReaderr(   ÚappendÚitemsÚmaxr   r   r!   ÚdictÚabsÚLOÚHI)Zfixturesr<   Zfhr   Úoutr   r%   r&   r'   ÚrowsZprer    ZphZpd_ZpaZfairr1   r2   Zsidxr4   r3   r   r   r   Ú
load_sides,   s:    ÿÿ&.*(ýrJ   c                 C   sž   t | ƒ}|sd S tdd„ | D ƒƒ| }tdd„ | D ƒƒ| }dd„ | D ƒ}|r^t|ƒt |ƒ ntdƒ}tdd„ | D ƒƒ| }t||d |d |d |d d	�S )
Nc                 s   s   | ]}|d  V  qdS ©r6   Nr   r*   r   r   r   Ú	<genexpr>L   r   zsumm.<locals>.<genexpr>c                 s   s   | ]}|d  V  qdS )r5   Nr   r*   r   r   r   rL   M   r   c                 S   s    g | ]}|d  dur|d  ‘qS )r7   Nr   r*   r   r   r   r   N   r   zsumm.<locals>.<listcomp>Únanc                 s   s*   | ]"}|d  dur|d  dkrdV  qdS )r7   Nr   r/   r   r*   r   r   r   rL   P   r   éd   )Únr6   r5   r7   Úfpos)Úlenr   r   rD   )rI   rO   r6   r5   Zclvsr7   rP   r   r   r   ÚsummI   s    rR   c                    s¬   t | ƒ}|dk rtdƒS t| ƒ| t|ƒ|  ‰ ‰t‡ ‡fdd„t| |ƒD ƒƒ}t t‡ fdd„| D ƒƒ¡}t t‡fdd„|D ƒƒ¡}|dkr¤|dkr¤|||  S tdƒS )Né   rM   c                 3   s"   | ]\}}|ˆ  |ˆ  V  qd S r   r   ©r   r   r   ©ÚmxÚmyr   r   rL   W   r   zcorr.<locals>.<genexpr>c                 3   s   | ]}|ˆ  d  V  qdS ©r0   Nr   r   ©rV   r   r   rL   X   r   c                 3   s   | ]}|ˆ  d  V  qdS rX   r   )r   r   )rW   r   r   rL   X   r   r   )rQ   r   r   ÚzipÚmathZsqrt)ÚxsÚysrO   ZcovZsxZsyr   rU   r   ÚcorrS   s    8r^   c                     s<  t ƒ } dd„ | D ƒ}tdt| ƒ› dt› dt› dt|ƒ› d�	ƒ ttƒ}|D ]}||d   |¡ qJtd	ƒ td
dd›ddd›ddd›ddd›ddd›ddd›ddd›d�ƒ t|ƒ}g }t	|ƒD ]Ö\}}|| }t
|ƒ}	ttƒ}
|D ]}|
|d   d7  < qäd dd„ t|
 ¡ dd„ d �d d!… D ƒ¡}td
|d›d|	d" d#›d|	d$ d%›d|	d& d'›d|	d( d)›d|	d* d+›d,t|
ƒd-›d
|› �ƒ | ||	f¡ qÀtd.td/d„ |D ƒd0d„ |D ƒƒd1›�ƒ td2td3d„ |D ƒd4d„ |D ƒƒd1›�ƒ td5ƒ td6ƒ td
d7d8›ddd›dd9d:›dd;d<›dd=d<›dd>d?›dd@d›�ƒ ttƒ}|D ]}||d   |¡ �qHdAdB„ t	|ƒD ƒ‰g }t| ¡ ƒD �]P\}}ttƒ}|D ]}||d   |¡ �qšt|ƒdCk �s„t|ƒdDk �rÔ�q„t‡fdEd„| ¡ D ƒƒ}dFd„ |D ƒ}dGd„ |D ƒ}t|ƒ}t|ƒ| ‰ t|ƒ| ‰t‡ fdHd„|D ƒƒ}|�rht‡ ‡fdId„t||ƒD ƒƒ| ntdJƒ}t||ƒ}| |¡ td
|d8›dt|ƒd#›dt|ƒdK›d|dL dM›d|dN dM›d|dO›d|dP›�ƒ �q„|�r8tdQd„ |D ƒƒ}tdRt|ƒ› dS|› dTt|ƒ| › dUt|ƒt|ƒdV  d1›dW�	ƒ tdXƒ d S )YNc                 S   s   g | ]}|d  r|‘qS )r8   r   r*   r   r   r   r   ]   r   zmain.<locals>.<listcomp>zclosing-snapshot sides total=z, longshot[ú,z)=Ú
r1   zIWeekly longshot Kalshi-vs-Pinnacle gap (RAW -- confounded by league mix):z  ZweekZ9sú ZnSidesz>6z|gap|ppz>8Zgap_ppz>7zmeanCLV%z>9z%CLV>=5ZnLgz>4z  topLeaguesr%   r/   c                 s   s    | ]\}}|› d |› �V  qdS )ú:Nr   )r   ÚlÚcr   r   r   rL   l   r   zmain.<locals>.<genexpr>c                 S   s
   | d  S )Nr/   r   )Zkvr   r   r   r,   l   r   zmain.<locals>.<lambda>r-   é   rO   Z6dr6   z8.2fr5   z+7.2fr7   z+9.2frP   z7.1fz% Z4dz
  corr(week_index, |gap|)   = c                 S   s   g | ]\}}|‘qS r   r   ©r   Úir    r   r   r   r   p   r   c                 S   s   g | ]\}}|d  ‘qS )r6   r   ©r   r    r   r   r   r   r   p   r   z+.2fz  corr(week_index, meanCLV) = c                 S   s   g | ]\}}|‘qS r   r   rf   r   r   r   r   q   r   c                 S   s   g | ]\}}|d  ‘qS )r7   r   rh   r   r   r   r   q   r   zL  (positive |gap| corr => WIDENING; negative => converging. Mix-confounded.)zH
Within-league |gap| trend (mix-controlled): leagues spanning >=3 weeks:ÚlgZ6sÚweeksz>5z
|gap|firstz>10z	|gap|lastzslope_pp/wkz>12r^   c                 S   s   i | ]\}}||“qS r   r   )r   rg   r1   r   r   r   Ú
<dictcomp>{   r   zmain.<locals>.<dictcomp>rS   é   c                 3   s&   | ]\}}ˆ | t |ƒd  fV  qdS rK   )rR   )r   r1   Zrs)Úwk_to_ir   r   rL   �   r   c                 S   s   g | ]}|d  ‘qS )r   r   ©r   Úpr   r   r   r   ‚   r   c                 S   s   g | ]}|d  ‘qS )r/   r   rn   r   r   r   r   ‚   r   c                 3   s   | ]}|ˆ  d  V  qdS rX   r   r   rY   r   r   rL   …   r   c                 3   s"   | ]\}}|ˆ  |ˆ  V  qd S r   r   rT   rU   r   r   rL   †   r   rM   Z5dr   z10.2féÿÿÿÿz+12.2fz+6.2fc                 s   s   | ]}|d krdV  qdS )r   r/   Nr   )r   r   r   r   r   rL   Œ   r   z
  within-league slopes: z
 leagues, z widening / z converging, median slope = r0   z pp/weekzh  (consistent NEGATIVE within-league slopes = market wising up; mixed/near-zero = no convergence signal))rJ   ÚprintrQ   rF   rG   r   r9   rA   ÚsortedÚ	enumeraterR   Úintr=   rB   r^   r   rZ   r   )ZsidesZlsZbywr   rj   Úidxrg   r1   rI   r   ZlgcÚtopZbylgZtrendsri   ZwkrowsZptsr\   r]   rO   ZdenZsloperd   Úposr   )rV   rW   rm   r   Úmain[   s~    *,ÿÿ
,<ÿÿÿ**,ÿÿ  0

<ÿÿ
ÿþ
rx   Ú__main__)Ú__doc__r@   r:   r;   r[   r   r   Úcollectionsr   r>   rF   rG   r   r   r   r   r!   rJ   rR   r^   rx   Ú__name__r   r   r   r   Ú<module>   s     
8