a
    ¨Í.j:  ã                	   @   s  d 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Z	d\Z
ZZg d¢Zd	Zd
d„ Zdd„ ZeeƒZe ej ed¡¡D ]tZeeddd��RZe e¡D ]6Ze d¡e d¡e d¡e d¡fZee  e¡ q W d  ƒ q‚1 sì0    Y  q‚g d¢Zdd„ Zdd„ Zdd„ dD ƒZedd„ ƒZ ee!ƒZ"eeƒZ#d d!„ Z$e %¡ D �]N\ZZ&e\Z'Z(Z)Z*ee&ƒZ+e+du �rv�qJe,d"d#„ e&D ƒed$�Z-e-�s–�qJdZ.e/e-ƒD ]l\Z0Zd%D ]P\Z1Z2Z3ee e2¡ƒZ4e4du�r®ee4  k�rèe	k �r®n ne0e1e3fZ. �q �q®e.�r¢ �q�q¢e.�s�qJe.\Z5Z1Z3ee-e5 ƒZ6ee-e5  e3¡ƒZ7ee-e5  e1d&k�rZd'nd(¡ƒZ8ee8e7ƒZ9e9�sv�qJe$e1e+e7e9ƒ\Z:Z;ed) e e( d) fD ]FZ<e<d*  d+7  < e<d,  e;7  < e<d-  e97  < e<d!  e:7  < �qœe=eg d.¢ƒD �]¢\Z>Z?e6 @¡ e>d/  ZAd0\ZBZCe-e5d+ d… D ]2ZeeƒZDeD�r$eD @¡ eAk�r$eeD ZBZC �qX�q$eBdu �rze"e?d1   d+7  < �qòeeB e1d&k�rŽd2nd3¡ƒZEeEdu �sºeeE  k�r¸e	k �sÎn e"e?  d+7  < �qòe#e?  eCe6  F¡ d/ ¡ eeB e3¡ƒZGeeB e1d&k�r
d'nd(¡ƒZHeeHeGƒZIeI�s&�qòe$e1e+eGeIƒ\Z:Z;ee? e e( e? fD ]FZ<e<d*  d+7  < e<d,  e;7  < e<d-  eI7  < e<d!  e:7  < �qL�qò�qJd4d5„ ZJeKd6ƒ eKd7ƒ eKd8eLe ej ed¡¡ƒ› d9eMd:d;„ e %¡ D ƒƒ› �ƒ eKd6ƒ eKd<ƒ d=D ]\Z?ZNeKeJeNee? ƒƒ �qddlOZPeKd>e"d? › d@e"dA › dBe"dC › �ƒ eKdDe"dE › d@e"dF › dBe"dG › �ƒ eKdHdI dJd;„ d.D ƒ¡ ƒ eKdKƒ e,e  %¡ dLd„ d$�ZQeQD ]P\Z(ZReRd) d* dMk �rÎ�q°eKdNe(› �ƒ d=D ]\Z?ZNeKeJeNeRe? ƒƒ �qà�q°dS )OaÝ  
Read-only study: does requiring the Kalshi edge to PERSIST 15/30/60 min after it
first appears improve realized (paper) profit vs entering immediately?

Mechanism under test (user, 2026-06-14): our Pinnacle feed is stale, so an edge
measured as Pin_fair - Kalshi can be illusory in fast markets (Kalshi already
moved). If the edge is still open N minutes later, it's more likely a real,
durable mispricing rather than feed lag.

Replays each fixture's 15-min snapshots from E:/soccer/live_data/*.csv.
Signal gate matches live_monitor exactly: 0.05 <= Kalshi CLV < 0.12, Kelly 0.25x
off the ask. Outcome from the FT score in the same CSV. Non-compounding $1000
bankroll so stakes are comparable across strategies. NOTHING is traded.
é    N)Údatetime)ÚdefaultdictzE:\soccer\live_data)gš™™™™™©?g¸…ëQ¸¾?)ç      Ð?r   g     @�@)é   é   é<   é	   c              	   C   s(   z
t | ƒW S  ttfy"   Y d S 0 d S )N)ÚfloatÚ	TypeErrorÚ
ValueError)Úx© r   úE:\soccer\analyze_kalshi_lag.pyÚf   s    r   c                 C   sp   | r|rd|  k rdk s"n d S d| }|d }| | d|   | }|dkrRd S t tt|t tƒt dƒdƒS )Nr   é   é   g      ð?)ÚmaxÚroundÚminÚ
KELLY_MULTÚMAX_BET_PCTÚBANKROLL)ZpfÚaskZoddsÚbÚfrr   r   r   Úkelly_stake   s
    "r   z*.csvÚ zutf-8)ÚnewlineÚencodingZ	game_dateÚleagueÚhomeÚaway)z%Y-%m-%d %H:%M:%Sz%m/%d/%Y %H:%Mz%m/%d/%Y %H:%M:%Sz%Y-%m-%d %H:%Mc              	   C   sB   |   d¡pd}tD ]*}zt ||¡W   S  ty:   Y q0 qd S )NÚ	timestampr   )ÚgetÚ_FMTSr   Ústrptimer   )ÚrÚsZfmtr   r   r   Úparse_ts-   s
    r(   c                 C   s®   t | ƒD ]*}| d¡pd ¡  ¡ }|dv r|  S qt | ƒD ]l}| d¡pLd ¡ }t| d¡ƒt| d¡ƒ }}|dv r<|dur<|dur<||kr”d	n||kr d
nd  S q<dS )z@Final H/D/A: prefer the 'ftr' column, else derive from FT goals.Úftrr   )ÚHÚDÚAÚstatusZ
home_goalsZ
away_goals)ZFTZAETZPENNr*   r,   r+   )Úreversedr#   ÚupperÚstripr   )Úrowsr&   r)   ÚstZhgZagr   r   r   Úresult4   s    "r3   c                 C   s   i | ]}|d d dddœ“qS ©r   g        )ÚnÚwinÚstakeÚpnlr   ©Ú.0Úkr   r   r   Ú
<dictcomp>A   ó    r<   ©Ú	immediateÚp15Úp30Úp60c                   C   s   dd„ dD ƒS )Nc                 S   s   i | ]}|d d dddœ“qS r4   r   r9   r   r   r   r<   B   s   ÿz<lambda>.<locals>.<dictcomp>r>   r   r   r   r   r   Ú<lambda>B   s   ÿrC   c                 C   s>   | dkr|dkp| dko|dk}|r4|d| d  n| |fS )Nr,   r*   r   r   )ÚsideÚresr   r7   Zwonr   r   r   r8   G   s     r8   c                 C   s2   g | ]*}|  d ¡pd ¡ dkrt|ƒdur|‘qS )r-   r   ZPREN)r#   r/   r(   )r:   r&   r   r   r   Ú
<listcomp>O   s   ÿrF   )Úkey))r,   Úclv_kalshi_awayZkalshi_away_ask)r*   Úclv_kalshi_homeZkalshi_home_askr,   Zpin_fair_awayZpin_fair_homer?   r5   r   r6   r7   )r@   rA   rB   r   )NNZ_noobsrH   rI   c                 C   sŒ   |d dkrd| d›d�S |d r6|d |d  d nd}d| d›d	|d d
›d|d |d  d d›d|d d›d|d d›d|d›d�S )Nr5   r   ú  Z11z n=0r7   r8   éd   z n=Z3dz  win=r6   z4.1fz
%  stake=$z7.2fz  pnl=z+8.2fz  ROI=z+6.1fú%r   )ÚlabelÚaZroir   r   r   Úline   s     .ÿÿÿrO   zN==============================================================================zQKALSHI EDGE-PERSISTENCE STUDY  (entry only if edge still in [5%,12%) after N min)zsnapshot files: z   fixtures w/ result: c                 c   s   | ]\}}t |ƒrd V  qdS )r   N)r3   )r:   r;   Úvr   r   r   Ú	<genexpr>ˆ   r=   rQ   z
OVERALL))r?   r?   )r@   zpersist 15m)rA   zpersist 30m)rB   zpersist 60mzG
  dropped by filter (edge CLOSED -> the fakes we want to avoid):  15m=r@   z  30m=rA   z  60m=rB   z5  un-confirmable (no later snapshot before KO):  15m=Z	p15_noobsZ	p30_noobsZ	p60_noobsz?  median ACTUAL gap used (snapshots are ~hourly far from KO):  rJ   c                 c   s<   | ]4}t | r*|› d t t | ¡d›d�n|› d�V  qdS )ú=z.0fr   z=naN)Úactual_gapsÚ_stZmedian)r:   r5   r   r   r   rQ   “   s   ÿz$
PER LEAGUE (immediate -> persist60)c                 C   s   | d d d  S )Nr   r?   r5   r   )Zkvr   r   r   rC   —   r=   é   z
 )SÚ__doc__ZcsvZglobÚosr   Úcollectionsr   ZLIVE_DIRZ	THRESH_LOZ	THRESH_HIr   r   r   ZDELAYSZTOLr   r   ÚlistZfixturesÚpathÚjoinÚopenZfhZ
DictReaderr&   r#   rG   Úappendr$   r(   r3   ZstratZ	by_leagueÚintZskipped_closedrS   r8   Úitemsr1   Úgdr   r    r!   rE   ÚsortedZpreÚfirstÚ	enumerateÚirD   ZclvkZaskkZclvZi0Zt0Zask0ZpfkZst0ÚpÚwZaccÚzipÚdÚnamer"   ÚtargetZcandZcand_tsZtsZclv_nowZtotal_secondsZaskdZpfdZstdrO   ÚprintÚlenÚsumrM   Z
statisticsrT   Zrows_lZaccsr   r   r   r   Ú<module>   sÐ   
$0ÿ
&

2

D
$*

Lÿÿÿÿÿÿ
ÿÿ