
    \jb                        S r SSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
rSSKJr  SSKJrJr  SrSrSrS\R(                  4S	 jrS
\R(                  S\S\\   S\S\\   4
S jrS\4S jr\S:X  a  \R:                  " \" 5       5        gg)u  
Backtest storico delle tre fasce dei pronostici del giorno.

Stessa meccanica walk-forward di backtest.py (refit settimanale, zero
look-ahead), ma per ogni partita: griglia punteggi DC -> riscalata alle
probabilità implicite del mercato -> selezione delle tre fasce -> esito reale.

Verifica la promessa di calibrazione: la fascia "sicuro" (p dichiarata
0.70-0.88) vince davvero in quella banda? Idem per le altre.

Uso:
    python scripts/backtest_picks.py
    N)settle)candidates_from_grid
pick_tiersgŏ1w-!_?gffffff?i!  returnc                 t   [         R                  " U R                  U R                  U R                  U R
                  SS9n[        R                  " SU5      nUR                  5         [        R                  " US   5      US'   S H  n[        R                  " X#   SS9X#'   M     [        R                  " US   R                  5       S	[        -
  US
   -  [        US   -  -   US
   5      US'   [        R                  " US   R                  5       S	[        -
  US   -  [        US   -  -   US   5      US'   U$ )N	tigertips)hostportuserpassworddatabasea-  
        SELECT l.code AS league, m.season, m.match_date AS date,
               h.name AS home, a.name AS away,
               m.home_goals AS hg, m.away_goals AS ag,
               m.imp_prob_home AS mkt_h, m.imp_prob_draw AS mkt_d,
               m.imp_prob_away AS mkt_a,
               m.home_xg AS xg_h, m.away_xg AS xg_a
        FROM matches m
        JOIN leagues l ON l.id = m.league_id
        JOIN teams h ON h.id = m.home_team_id
        JOIN teams a ON a.id = m.away_team_id
        WHERE m.result IS NOT NULL
        ORDER BY m.match_date
    date)mkt_hmkt_dmkt_axg_hxg_acoerce)errorsr      hghg_tr   agag_t)pymysqlconnectr	   r
   r   r   pdread_sqlcloseto_datetime
to_numericnpwherenotnaALPHA)argsconndfcs       1C:\wamp64\www\Tigertips\scripts\backtest_picks.pyload_matchesr+   "   s   ??						$(MMKID	  

B 	JJL6
+BvJ8beH5 9"V***,u94052f:3EEr$xQBvJ"V***,u94052f:3EEr$xQBvJI    r(   leagueeval_seasons
refit_daysc           
      R   X S   U:H     R                  SS9nUS   R                  U5      nUR                  5       (       d  / $ [        UR                  US4   R                  5       5      nUS   US   p/ n	Su  p[        R                  " 5       nXx::  Ga  U[        R                  " US	9-   nXDS   U:  US   U[        R                  " [        S	9-
  :  -     nXEUS   U:  -  US   U:  -     nUR                  (       a  UnMt  [        [        US
   5      [        US   5      -  5      n[        U5       VVs0 s H	  u  nnUU_M     nnnX~S   -
  R                  R                  R                  5       n[         R"                  " US
   R%                  U5      R                  5       US   R%                  U5      R                  5       US   R                  5       US   R                  5       [&        R(                  " [*        * U-  5      UUU:X  a  U
OS S9nUR-                  5       UpUR/                  SS9 GH6  n[         R0                  " UUR2                  5      u  nn[         R0                  " UUR4                  5      u  nn[         R6                  " UUUUU5      n[        R8                  " UR:                  5      (       a8  [         R<                  " UUR:                  UR>                  UR@                  45      n[C        [E        U5      5      RG                  5        HM  u  nn[I        US   US   US   URJ                  URL                  S.5      nU	RO                  UUUS   US.5        MO     GM9     UnXx::  a  GM  [Q        SU S[        R                  " 5       U-
  S S35        U	$ s  snnf )Nr-   T)dropseasonr   r   )NN)dayshomeawayr   r   )x0F)indexmarket	selectionline)r9   r:   r;   r   r   p)r-   tierr<   outcome  z: z.0fs))reset_indexisinanysortedlocuniquetimer   	TimedeltaTRAIN_MAX_DAYSemptyset	enumeratedtr4   to_numpydcfitmapr"   expXIparams_vector
itertuplesteam_paramsr5   r6   score_matrixr$   r   rescale_to_1x2r   r   r   r   itemsr   r   r   appendprint)r(   r-   r.   r/   data	eval_mask
eval_dateswindow_start	last_daterowswarm
prev_teamst0
window_endtraintodoteamsitidxdays_agomodelratt_hdfn_hatt_adfn_agridr=   candr>   s                                  r*   backtest_leagueru   >   sU   lf$%11t1<DX##L1I==??	F!23::<=J(mZ^)D!D	B

#!BLLj$AA
6l\16llR\\~5V&VVX Yf!=>&\J.0 1::%Ls5=)Cf,>>? )% 01 01q!t 01 =04499BBDuV}((-668V}((-668V}--/v1G1G1IvvrcHn-u"':"5$4	A
 !..0%ju-A>>%8LE5>>%8LE5??5%uEDxx  ((!''/JK()=d)CDJJL
d DN/3K/@*.v,add!$$"P Q vt$s)(/1 2	 M . "? 
#@ 
Bvhbr)#.a
01K/ 2s   7N#c                     [         R                  " SS9n U R                  SSSS/S9  U R                  S[        S	S
9  [        R
                  " U 5        U R                  5       n[        U5      n[        US   R                  5       5      n[        SU SUR                   35        / nU H3  nUR                  [        X%UR                  UR                  5      5        M5     [        R                   " U5      nXfS   R#                  SS/5         n[        S[%        U5       S35        [        SS SS SS SS 35        S Hd  nXfS   U:H     n[%        U5      (       d  M  [        US [%        U5      S US   R'                  5       S US   S:H  R'                  5       S 35        Mf     [        S 5        XfS   S!:H     nUR)                  S5       H8  u  pY[        S"US# S$U	S   S:H  R'                  5       S% S&[%        U	5       35        M:     g')(NzBacktest delle fasce pronostici)descriptionz--eval-seasons+z2024/25z2025/26)nargsdefaultz--refit-days   )typerz   r-   zBacktest fasce su z, stagioni r>   winlossz
=== Verifica fasce (z pick regolate) ===fasciaz<14pickz>7zp dichiarataz>14zvinte davveroz>15)sicuroequilibratoazzardor=   r<   z>14.1%z>15.1%z
Per lega (fascia sicuro):r   r?   z<5 z.1%z su r   )argparseArgumentParseradd_argumentintconfigadd_db_args
parse_argsr+   rD   rF   r[   r.   extendru   r/   r   	DataFramerB   lenmeangroupby)
parserr&   r(   leaguesra   lgbtr=   ggrps
             r*   mainr   n   s   $$1RSF
(i=ST
S!<
vD	d	BR\((*+G	wi{43D3D2E
FGDOBD,=,=tOP 	d	B	yMv/	0B	"3r7)+>
?@	XcN6"+nS%9/#9N
OP4&zT!"q66T#Js1vbk!C&++-)?	le+113F;= > 5 

'(
f:!"A99X&2b'C	Ne399;C@SXJOP 'r,   __main__)__doc__r   sysrG   numpyr"   pandasr   r   r   dixon_colesrO   score_tipstersr   daily_picksr   r   rS   r%   rI   r   r+   strlistr   dictru   r   __name__exit r,   r*   <module>r      s     
       ! 8",, 8- -c -c - #-(,T
-`c @ zHHTV r,   