a
    Çéiò&  ã                   @   sn  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 e d¡ dZdZdZdd	„ Zeefd
d„Zedƒ e d¡Zg ZeD ]jZzXejedd�Zej e¡ d¡d ed< ej e¡ dd¡ d¡d ed< e e¡ W qŠ   Y qŠ0 qŠejedd�Zejg d¢d�Zej ed ddd�ed< ejdgd� !d¡j"dd�Zed j#j$ %dd„ ¡ed < d!d"„ Z&ed  %e&¡ed < e 'd#d$„ e (¡ D ƒ¡Z)e)dd…df e)dd…df e)dd…d%f   ed&< ed'< ed(< ed) ded&   ded&   ed*< ed+ ded'   ded'   ed,< ed- ded(   ded(   ed.< ed/ƒ �zJe d0¡Z*e  e*d1 ¡e*d1< d2d$„ e*j+D ƒZ,e*e*d3 dk g d4¢e,   -¡ Z.g d4¢d5d$„ e,D ƒ e._+e*e*d3 dk d6ge,   -¡ Z/d6gd7d$„ e,D ƒ e/_+e.j0e/d6d8�Z1d9d$„ e,D ƒd:d$„ e,D ƒ Z2e3d;d$„ e,D ƒd<d$„ e,D ƒƒD ]*\Z4Z5e1e4 e1e5  e1d=e4d%d…  < �q,d>d$„ e,D ƒZ6e2e6 Z7dZ8ed?e9e1ƒd@›dAe9e7ƒ› dB�ƒ W n8 e:�yÌ Z; zedCe;› �ƒ dDZ8W Y dZ;[;n
dZ;[;0 0 e8�ršddl<Z<ddl=Z=dEdF„ Z>e1dG  %e>¡e1dH< e1dI  %e>¡e1dJ< edK  %e>¡edH< edL  %e>¡edJ< ed j# ?dM¡edN< e1d1 j# ?dM¡e1dN< e1j0eg dO¢ g dP¢dQdR�Z@e@je7d�Z@ed?e9e@ƒd@›dS�ƒ g dT¢ZAe8�r:edUƒ g ZBeAD �]ZCe@e@dV eCk  je7d�ZDe@e@dV eCk je7d�ZEe9eDƒdWk �s¸e9eEƒdXk �r�q¸eDe7 jFeEe7 jF ZGZHdYD ]š\ZIZJeDdZ eIk KeL¡jFZMe	d[d\d]d^d_d`�ZNeeNdadbdc�ZOeO PeGeM¡ eO QeH¡dd…df ZReSeE (¡ ƒD ],\ZT\ZUZVeB d6eVd6 ddeIdeeReT i¡ �q’�q(edfeC› dg�ƒ �q¸e WeB¡ZXeXjYd6dddedhdi� "¡ ZZdeZj+_[eZj\djdkdldmœdn�ZZe@j0eZd6dQdR�Z]ed?e9e]ƒd@›do�ƒ edpƒ dqZ^ee^ _drdsdtdudvdwdx¡ƒ edyƒ dzd{„ Z`eed d|k Zad}D ]R\ZIZbZcZdd~D ]>Zeeaeaeb eek Zfe`deI› d€eed� d‚›dƒ�efecedeId ƒ �q”�q„eƒ  e8�rjd„D ]d\ZIZgZcZdd…D ]PZee]e]eg eek Zfe9efƒd†k �r�qøe`d‡eId › dˆeed‰›dŠ�efecedeId ƒ �qø�qèeƒ  d‹D ]l\ZIZgZbZcZddŒD ]VZhe]e]eg ehke]eb d�k@  Zfe9efƒd†k �rœ�qje`dŽeI› d�ehd‰›�efecedeId ƒ �qj�qXeƒ  ed�ƒ d‘D ]�\ZIZgZcZde]eg de]ec   e]d’eId › �< d“D ]ZZee]e]d’eId › � eek Zfe9efƒd†k �r:�q
e`d”eI› d€eed� d‚›dƒ�efecegeId ƒ �q
�qØdS )•a'  
Grid search: RF model predictions x outcomes x filter types x thresholds.
Compares:
  1. Pure CLV (Pinnacle closing)
  2. RF pA >= threshold + CLV > 5%  (current)
  3. RF pA >= threshold only (no CLV gate)
  4. RF implied edge vs B365 (model p > 1/B365 by X%)
Across Home, Draw, Away outcomes.
é    N)ÚRandomForestClassifier)ÚCalibratedClassifierCVÚignoreg     @�@g      Ð?c                 C   s:   d|  d|  d|  }d|  | d| | d| | fS )Né   © )ÚhÚdÚaZovr   r   ú$E:\soccer\misc\archive\model_grid.pyÚremove_margin   s    r   c                 C   sZ  t }|}d}g }	|  ¡ D ]²\}
}|| }|| d }|dkrVt|| d|  | dƒnd}t|| |ƒ}|d |k}|r||nd}t||| |  dƒ}t||ƒ}t||| | ƒ}|	 t || ¡¡ |}qt| ƒdk rä|d|dfS t| d  ¡ | d  ¡  jd d	ƒ}|t  d|  d }t 	|	¡dk�rJt 
|	¡t 	|	¡ t d
¡ nd}||||fS )Nr   r   ÚFTRg      ð¿g{®Gáz„?é   ÚDateim  gš™™™™™¹?éü   )ÚSTARTÚiterrowsÚmaxÚminÚappendÚnpÚlogÚlenZdaysZstdÚmeanZsqrt)Zbets_dfÚodds_colÚp_colÚresultZkmZmaxpctÚbrZpeakZmax_ddZlog_retsÚ_ÚrowÚpÚbZkfZfracZwonZpnl_unitZbr_newZyrsÚcagrZsharper   r   r
   Úkelly_compound   s$    &
$2r"   zLoading odds...zE:/soccer/league_data/*.csvz	utf-8-sig)Úencodingr   Údivz.csvÚ r   Z
season_strT)Zignore_index)ÚB365HÚB365DÚB365AÚPSCHÚPSCDÚPSCAr   r   )Zsubsetr   Zcoerce)ZdayfirstÚerrors)Zdropc                 C   s(   t jt d jj| k jd dkr$| S | S )Nr   r   )ÚoddsZlocÚdtÚyearÚindex)Úyr   r   r
   Ú<lambda>:   ó    r2   Ú	season_yrc                 C   s*   zdt | d d… ƒ W S    Y dS 0 d S )NiÐ  r   r   )Úint©Úsr   r   r
   Úss_to_yr<   s    r8   c                 C   s"   g | ]\}}t |j|j|jƒ‘qS r   )r   r)   r*   r+   )Ú.0r   Úrr   r   r
   Ú
<listcomp>B   r3   r;   r   Úpin_pHÚpin_pDÚpin_pAr&   Úedge_Hr'   Úedge_Dr(   Úedge_AzLoading features...z$E:/soccer/raw_api/match_features.csvÚdatec                 C   s    g | ]}d |v sd|v r|‘qS )Z_w5Z_w10r   ©r9   Úcr   r   r
   r;   M   r3   Zis_home)Ú
fixture_idrB   r$   ÚseasonÚ	home_teamÚ	away_teamc                 C   s   g | ]}d |› �‘qS ©Zh_r   rC   r   r   r
   r;   O   r3   rE   c                 C   s   g | ]}d |› �‘qS ©Za_r   rC   r   r   r
   r;   Q   r3   )Úonc                 C   s   g | ]}d |› �‘qS rI   r   rC   r   r   r
   r;   S   r3   c                 C   s   g | ]}d |› �‘qS rJ   r   rC   r   r   r
   r;   S   r3   c                 C   s   g | ]}d |› �‘qS rI   r   rC   r   r   r
   r;   T   r3   c                 C   s   g | ]}d |› �‘qS rJ   r   rC   r   r   r
   r;   T   r3   Údiff_c                 C   s   g | ]}d | ‘qS )rL   r   rC   r   r   r
   r;   V   r3   z  ú,z
 matches, z	 featuresz  No features: Fc                 C   sN   t | ƒ ¡  ¡ } t d| ¡ dd¡ d¡} t dd| ¡ ¡ } t dd| ¡ ¡ S )NZNFKDÚasciir   z1\b(fc|afc|sc|cf|cd|sd|ss|us|uc|rc|ac|as|sv|1\.)\br%   z\s+ú )	ÚstrÚlowerÚstripÚunicodedataZ	normalizeÚencodeÚdecodeÚreÚsubr6   r   r   r
   Únorma   s    rX   rG   Úh_normrH   Úa_normZHomeTeamZAwayTeamz%Y-%m-%dÚdate_str)r[   r$   rY   rZ   r&   r'   r(   r<   r=   r>   r?   r@   rA   r   r   r4   )r[   r$   rY   rZ   Úinner)rK   Zhowz merged)iå  iæ  iç  iè  ié  z#
Walk-forward training (H, D, A)...rF   iô  é2   ))ÚHZpH)ÚDZpD)ÚAZpAr   éÈ   é
   é   é*   éÿÿÿÿ)Zn_estimatorsZ	max_depthZmin_samples_leafZrandom_stateZn_jobsé   Zisotonic)ZcvÚmethodÚoutcomeZmodel_pz	  Season z: doneÚfirst)r0   ÚcolumnsÚvaluesZaggfuncÚmodel_pHÚmodel_pDÚmodel_pA)r^   r_   r`   )rj   z rows with model predictionsz
=== Strategy Comparison ===z+{:<32} {:>5} {:>5} {:>8} {:>10} {:>7} {:>7}ZStrategyZBetszWR%ZAvgOddszFinal BRZCAGRZSharpezR----------------------------------------------------------------------------------c           
   
   C   sh   t |ƒdk rd S |d |k ¡ d }t||||ƒ\}}}}	td | t |ƒ|||  ¡ ||d |	¡ƒ d S )Né   r   éd   z>{:<32} {:>5} {:>4.0f}% {:>8.2f} {:>10,.0f} {:>+6.0f}% {:>7.2f})r   r   r"   ÚprintÚformat)
ÚnameZbetsr   r   r   Úwrr   r!   ZddZshr   r   r
   Úshow›   s    ÿru   z
2021-07-01))ÚAwayrA   r(   r>   )ÚHomer?   r&   r<   )ÚDrawr@   r'   r=   )çš™™™™™©?ç{®Gáz´?z	Pure CLV z >rp   z.0fú%))rv   rn   r(   r>   )rw   rl   r&   r<   )rx   rm   r'   r=   )ç333333Ó?çffffffÖ?gš™™™™™Ù?ro   zRF pz>=z.2fz only))rv   rn   rA   r(   r>   )rw   rl   r?   r&   r<   )rx   rm   r@   r'   r=   )r|   r}   ry   zRF+CLV z p>=z*--- RF implied edge (model p > 1/B365) ---))rv   rn   r(   rn   )rw   rl   r&   rl   )rx   rm   r'   rm   Zrf_edge_)g{®Gáz”?ry   rz   zRF edge )iÚ__doc__ZpandasZpdZnumpyr   ZglobÚosÚwarningsZsklearn.ensembler   Zsklearn.calibrationr   Úfilterwarningsr   ZKMZMAXPCTr   r"   rq   ÚfilesZdfsÚfZread_csvr   ÚpathÚbasenameÚsplitÚreplacer   Úconcatr-   ZdropnaZto_datetimeZsort_valuesZreset_indexr.   r/   Zapplyr8   Zarrayr   ÚresZfeatrj   Zw_colsÚcopyZhfZafÚmergeZmatchesZ	feat_colsÚzipZhcZacZ	diff_colsZX_colsZHAS_FEATURESr   Ú	ExceptionÚerS   rV   rX   ÚstrftimeZmergedZOOS_SEASONSZ	all_predsZtest_yrZtrainÚtestrk   ZX_trZX_terh   ZlabelZastyper5   Zy_trZrfZcalZfitZpredict_probaZprobaÚ	enumerateÚir   r   Z	DataFrameZpred_dfZpivot_tableZ	pred_widers   ÚrenameZmerged2Zhdrrr   ru   ZoosZecZocZpcZthreshrW   ZmcZpa_tr   r   r   r
   Ú<module>   s   	(

"@$$$
 &$$
ü
ÿÿ
ÿ
00*"