
    @jC                       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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 ddlmZmZ ddlmZ ddlmZmZ ddlmZmZ dd	lmZ dd
lmZ  ed      Zedz  dz  Zedz  Z edz  Z!edz  Z"edz  Z#edz  Z$dZ%dZ& e'ejP                  jS                  dd            Z*dZ+edz  Z,e,dz  Z-d Z. e.        ejP                  jS                  dd      Z/ejP                  jS                  dd      Z0 e1h d      Z2 ed      Z3d  Z4dqd!Z5d" Z6d# Z7d$ Z8d% Z9d& Z:d' Z;d( Z<d) Z=d* Z>d+ Z?d, Z@d- ZAd. ZBd/ ZCd0 ZDd1 ZEd2 ZFd3 ZGdrd4ZHdsd5ZId6 ZJd7 ZKd8d8d9d:hd;ZLd< ZM e1h d=      ZNd>ZOd? ZPdrd@ZQdA ZRdB ZSdC ZTdD ZUdE ZVdF ZW e' eXdG      j!                  dHdIdJddd eXdG      j"                  j                  K      j                         dLz        Z[dM Z\dN Z]dO Z^dP Z_dtdQZ`dR Zah dSZbdT ZcdU ZddV ZedW ZfdX ZgdY ZhdZ Zid[ Zjd\ Zkd] Zld^ Zmdud_Zndud`ZodvdaZpdvdbZqdc Zrdd ZsdwdeZtdxdfZudydgZvdh Zwdi Zxdj Zydk Zzdl Z{ G dm dne      Z|do Z}e~dpk(  r e}        yy)zu   
v2_stats_dashboard.py — Stats Dashboard 2° account (port 5511, Basic Auth)
NO template engine: tutto render server-side in Python (niente {{}} / {% %} nel template).
    N)BytesParser)defaultdatetimetimezone)Path)BaseHTTPRequestHandler
HTTPServer)urlparseparse_qs)defaultdict)ZoneInfoz /opt/charter-live/live_deploy_v2logszwebhook_queue.dbzv2_stats_trade_policy.json#v2_classification_review_queue.json!v2_classification_review_evidencez+v2_classification_certification_audit.jsonlv2_stats_policy_backupsi  P i  @ V2_STATS_PORT5511z0.0.0.0zv2_stats_dashboard.logc                  t   t         dz  } | j                         r	 | j                         j                         D ]  }|j	                         }|j                  d      sd|vr)|j                  dd      \  }}|j	                         }|j	                         j	                  d      j	                  d      }|dk(  r3t        j                  j                  d      s|t        j                  d<   |dk(  st        j                  j                  d      r|t        j                  d<    y y # t        $ r Y y w xY w)	Nz.v2_stats_creds#=   "'V2_STATS_USERV2_STATS_PASS)ROOTexists	read_text
splitlinesstrip
startswithsplitosenvironget	Exception)
creds_filelinekvs       [/opt/charter-live/backups/duration_by_strategy_asset_20260829T154513Z/v2_stats_dashboard.py_load_auth_from_envfiler-   (   s    ))J	",,.99; 
4zz|??3'3d?zz#q)1GGIGGIOOC(..s3'

0O23BJJ//)"**..2Q23BJJ/
4   		s   CD+ 4D+ D+ +	D76D7r   mattia_v2_statsr    >   classifyexclude_testneeds_reviewexclude_operationalzEurope/Romec                 l   | yt        |       j                         }|sy|j                         rBt        |      dk\  r4	 t	        |      }t        j                  |dz  t        j                        S 	 t        j                  |j                  dd            S # t        $ r Y yw xY w# t        $ r Y yw xY w)zBybit V5 closed-pnl restituisce createdAt/updatedTime in MILLISECONDI come stringa
    (es. "1785856148609"). Accetta anche ISO 8601 ("2026-08-05T20:39:31Z") o None/"".
    Ritorna datetime (UTC) oppure None se non parsabile.
    N
        @@tzZ+00:00)strr!   isdigitlenintr   fromtimestampr   utcr'   fromisoformatreplace)tssmss      r,   _parse_bybit_tsrF   G   s    
 
zBAyy{s1v|	QB))"v+(,,GG%%aiiX&>??	  		
  s#   2B 3$B' 	B$#B$'	B32B3c                 @    t        |       }|y|j                  |      S )zTRitorna una stringa formattata (UTC) per ts Bybit (ms o ISO). None se non parsabile.r/   )rF   strftime)rC   fmtdts      r,   _fmt_bybit_tsrK   _   s#    		B	z;;s    c                 f    t        |       }|y|j                  t              j                  d      S )Nz--z%d/%m/%Y %H:%M)rF   
astimezoneREVIEW_TIMEZONErH   )rC   rJ   s     r,   _fmt_review_tsrP   g   s/    		B	z==)223CDDrL   c                 p   t        j                  t        j                        j	                         j                         }d| d|  }t        |d       	 t        j                  dd       t        t        dd      5 }|j                  |d	z          d d d        y # 1 sw Y   y xY w# t        $ r Y y w xY w)
N[z] T)flushparentsexist_okautf-8encoding
)r   nowr   r@   rN   	isoformatprintLOG_DIRmkdiropenLOG_FILEwriter'   )msgrC   r)   fs       r,   logrf   n   s    	hll	#	.	.	0	:	:	<Brd"SE?D	$ddT2(C'2 	!aGGD4K 	! 	! 	! s0   )B) ?BB) B&"B) &B) )	B54B5c                      t         j                         sg S 	 t        j                  t         j	                  d            } t        | t              r| S g S # t        $ r}t        d|        g cY d }~S d }~ww xY w)N	utf-8-sigrY   zreview queue read err: )	REVIEW_QUEUE_PATHr   jsonloadsr   
isinstancelistr'   rf   )dataexcs     r,   _load_review_queuerp   z   sn    ##%	zz+55{5KL!$-t525 %cU+,	s#   :A A 	A8A3-A83A8c                    t         j                  dt         j                   dt        j                  d       d      }	 |j                  t        j                  | dd      d       t        j                  |d	       t        j                  |t                |j                         r|j                  d
       yy# |j                         r|j                  d
       w w xY w)zBScrittura atomica: la coda non modifica mai la policy certificata..   .tmpF   ensure_asciiindentrX   rY     T
missing_okN)ri   	with_namenamesecrets	token_hex
write_textrj   dumpsr$   chmodrB   r   unlink)itemstmps     r,   _save_review_queuer      s    

%
%
""#1W%6%6q%9$:$?C	(JJu5; 	 	
 	e


3)*::<JJ$J' 3::<JJ$J' s   AB< <%C!c                      t         j                         si S t        j                  t         j	                  d            } t        | t              st        d      | S )Nrh   rY   zPolicy statistiche non valida)STATS_POLICY_PATHr   rj   rk   r   rl   dict
ValueError)rn   s    r,   _load_raw_stats_trade_policyr      sK    ##%	::'11;1GHDdD!899KrL   c                    t         j                  dd       t        j                  t         d       t        j                         rxt        j                  t        j                        j                  d      }t         d| dz  }|j                  t        j                                t        j                  |d       t        j                  dt        j                   dt        j                   d	       d
      }	 |j#                  t%        j&                  | dd      d       t        j                  |d       t        j(                  |t               |j+                  d       y# |j+                  d       w xY w)z@Backup e sostituzione atomica. Non modifica DB webhook o ordini.TrT     z%Y%m%d_%H%M%S_%fv2_stats_trade_policy_z.jsonry   rr   rs   rt   Fru   rv   rX   rY   rz   N)STATS_POLICY_BACKUP_DIRr`   r$   r   r   r   r   r\   r   r@   rH   write_bytes
read_bytesr|   r}   r~   r   r   rj   r   rB   r   )rn   stampbackupr   s       r,   _save_raw_stats_trade_policyr      s   !!$!>HH$e,!X\\*334FG(-CE7%+PP,779:


%
%
""#1W%6%6q%9$:$?C$tzz$U1EPWX
e


3)*

d
#

d
#s   <AE( (E<c                    t        |       } | j                  dt        j                  t        j
                        j                                t        j                  t        t              t        j                  t        j                  z  t        j                  z  d      }t        j                  |dd      5 }|j                  t!        j"                  | dd      d	z          d d d        y # 1 sw Y   y xY w)
N	timestampry   rW   rX   rY   F),:)rw   
separatorsr[   )r   
setdefaultr   r\   r   r@   r]   r$   ra   r;   CERTIFICATION_AUDIT_PATHO_WRONLYO_CREATO_APPENDfdopenrc   rj   r   )eventfdhandles      r,   _append_certification_auditr      s    KE	[(,,x||"<"F"F"HI	$%
bjj 2;;.
B
 
2sW	- ZTZZEjQTXXYZ Z Zs   9+C--C6c                 @   | j                  d      rM|j                  dd      }t        |d      }|j                         D ci c]  \  }}||r|d   nd c}}d fS | j                  d	      st	        d
      t        t              j                  d| j                  dd      z   dz   |z         }|j                         st	        d      i }d }|j                         D ]  }	|	j                  dd      }
|
s|	j                  d      xs d}|	j                         }|r=|
dk7  s|t	        d      t        |      t        |	j                         xs d      |d}~|	j!                         xs d}|j                  |d      |t        |
      <    ||fS c c}}w )Nz!application/x-www-form-urlencodedrX   stricterrorsT)keep_blank_valuesr/   zmultipart/form-dataz Formato richiesta non supportato)policys   Content-Type: asciis   
MIME-Version: 1.0

zUpload multipart non validor}   zcontent-disposition)header)decoderL   evidence_filezAllegato non valido)original_namecontent_typern   )r"   r   r   r   r   r   email_policy
parsebytesencodeis_multipart
iter_parts	get_paramget_payloadget_filenamer;   get_content_typeget_content_charset)r   bodyrawvalueskeyvaluemessageform
attachmentpartr}   payloadfilenamecharsets                 r,   _parse_review_formr      s   BCkk'(k3#6BH,,.QJC%U2YR/QSWWW""#89;<<.99L///II
*	+-1	2G !677DJ""$ G~~f-B~C""$"/63$$&&**@ !677!$X #D$9$9$;$Ar BJ ..0;GG%nnWXnFDTO!G" = Rs   Fc                 l   | r| j                  d      sy | d   }t        |      t        kD  rt        d      |j	                  d      rd\  }}nF|j	                  d      rd\  }}n/t        |      dk\  r|d d d	k(  r|d
d dk(  rd\  }}nt        d      t        | j                  d      xs d      j                         }||dfvrt        d      t        t        | j                  d      xs d            j                  d d ||t        |      t        j                  |      j                         |dS )Nrn   z&Screenshot troppo grande: massimo 4 MBs   PNG

)	image/png.pngs   )
image/jpeg.jpg      s   RIFF   s   WEBP)
image/webp.webpz4Formato screenshot non valido: usare PNG, JPG o WEBPr   r/   zapplication/octet-streamz;Il tipo dichiarato dello screenshot non corrisponde al filer   
screenshot   )r   r   	extensionsizesha256rn   )r&   r=   MAX_EVIDENCE_BYTESr   r"   r;   lowerr   r}   hashlibr   	hexdigest)r   rn   detected_typer   declared_types        r,   _validate_review_attachmentr      s2   Z^^F3fD
4y%%ABB+,#6 y		)#7 y	TbT"1X0T!BZ75J#8 yOPP
~6<"=CCEM],FGGVWWc*.."A"Q\RSXXY]Z]^%D	..&002 rL   c                 X   t         j                  dd       t        j                  t         d       |  |d    }t         |z  }t        j                  t        |      t        j                  t        j                  z  t        j                  z  d      }	 t        j                  |d      5 }|j                  |d          d d d        |j                         D ci c]  \  }}|dk7  s|| }}}||d	<   ||fS # 1 sw Y   ;xY w# t        $ r |j                  d        w xY wc c}}w )
NTrT   r   r   ry   wbrn   rz   stored_name)REVIEW_EVIDENCE_DIRr`   r$   r   ra   r;   r   r   O_EXCLr   rc   r'   r   r   )	proposal_idr   r   targetr   r   r   r   metadatas	            r,   _save_review_attachmentr      s   dT:HH %( M*["9!:;K ;.F	VbkkBJJ6BE	JBYYr4  	-FLLF+,	-
 .8-=-=-?QzsE3&=U
QHQ)H]V	- 	- & Rs0   D +C: D D&)D&:D?D D#c                  8   t               D  ch c]  } | j                  d      dk(  rl| j                  d      dk(  rXt        | j                  d      xs d      j                         r,t        | j                  d      xs d      j                          c} S c c} w )Nstatuspendingactioncertification_rejectedorder_idr/   )rp   r&   r;   r!   items    r,   _rejected_order_idsr     s     '(88H*HHX"::$*+113	 	DHHZ &B'--/  s   BBc                    t        t              }| j                  di       j                  |g       D ]2  }t        |j                  d            }|t        v s&||xx   dz  cc<   4 t        t        |j                         d             S )Nasset_trade_detailsstrategyr   c                     | d    | d   fS )Nr   r    r   s    r,   <lambda>z._strategy_history_for_symbol.<locals>.<lambda>   s    $q'478K rL   r   )r   r>   r&   _canonical_strategyVALID_CLOSED_TRADE_STRATEGIESr   sortedr   )rn   symbolcountsrowr   s        r,   _strategy_history_for_symbolr     s{    Fxx-r266vrB "&swwz':;448!" v||~+KLMMrL   c           
         t               }g }| j                  dg       D ]  }t        |j                  d      xs d      j                         }|r||v r7t	        |      }t        |j                  d      xs d      j                         }t        | |      }t        t        |            }d}	d}
g }|rt        t        |            }	t        |j                               }||	   }t        |      dk(  r
||	k(  rdnd}
n||d	z  kD  rd}
nd}
|j                  d
dj                  d |j!                         D              z          |t"        v rA|j                  d|j                                 |	s|}	d}
n||	k7  rd}
|j                  d       |	s|j                  d       |j%                  d|	|
dj                  |      t'        |      d       |j                  |        |S )z2Genera suggerimenti, mai attribuzioni automatiche.unclassified_tradesr   r/   r   LOWr   HIGHMEDIUMru   zstorico asset: , c              3   L   K   | ]  \  }}|j                          d |   yw)r   Nupper).0r}   counts      r,   	<genexpr>z,_certification_candidates.<locals>.<genexpr><  s*      9.9dE4::<.%)9s   "$zconfig attuale: zconflitto storico/configz.nessuna prova storica o configurazione univocaPENDING_CERTIFICATIONz; )anomaly_typeproposed_strategyproposal_confidenceproposal_evidenceproposal_alternatives)r   r&   r;   r!   r   r  r   r   get_strategy_for_symbolnextitersumr   r=   appendjoinr   r   updaterm   )rn   rejected
candidatesr   r   r   r   history
configuredproposed
confidencereasonstotal	top_counts                 r,   _certification_candidatesr   #  s   "$HJxx-r2 ) swwz*0b17798x/CyTXXh'-2.446.tV<()@)HI

DM*H()E)I7|q '1X'=V8
UQY&%
"
NN,tyy 9=D]]_9 0   66NN-j.>.>.@-ABC%%
x'"
9:NNKL3!)#-!%7!3%)']
 	 	$S) T rL   c                     t               }g }| j                  dg       D ]W  }t        |j                  d      xs d      j                         }|s2||v s7t	        |      }d|d<   |j                  |       Y |S )zESolo casi rifiutati: i nuovi trade restano nella coda certificazioni.r   r   r/   PROPOSTA_RIFIUTATAr  )r   r&   r;   r!   r   r  )rn   r  r  r   r   r   s         r,   _review_candidatesr#  T  s~    "$HJxx-r2 $swwz*0b1779H,9D#7D d#$ rL   c                     t        |xs d      j                         }| j                  dg       D ]5  }t        |j                  d      xs d      j                         |k(  s3|c S  t        d      )Nr/   r   r   z1Trade non presente tra le classificazioni sospese)r;   r!   r&   r   )rn   r   r   s      r,   _current_unclassifiedr%  a  sk    8>r"((*Hxx-r2 swwz"(b)//1X=J H
IIrL   c                     t        j                  t        j                        j	                         }| D ]6  }|j                  d      dk(  s|j                  d      |k(  s-||d<   ||d<   8 | S )Nr   r   r   resolved_at)r   r\   r   r@   r]   r&   )queuer   r   r\   r   s        r,   _resolve_queue_for_orderr)  i  sg    
,,x||
$
.
.
0C &88H*txx
/Cx/O#DN"%D& LrL   c                   
 t        | j                  d      xs d      j                         
t        | j                  d            }|t        vrt        d      t        |
      }t        
fdt        |      D        d       }|t        d      t               }|j                  di       }|j                  di       }t        |j                  
            }|r||k7  rt        d	      ||
<   d
|
<   t        |       t        t               
d      }	t        |	       t        dt         
|j                  dd      |j                  dd      ||j                  dd      |j                  dd      d       t#        d
 d|        y )Nr   r/   r   #Strategia obbligatoria o non validac              3   L   K   | ]  }|j                  d       k(  s|  ywr   Nr&   r  r   r   s     r,   r	  z!_certify_trade.<locals>.<genexpr>y  "     [377:;NRZ;Z[   $$z*Caso gia rifiutato o non piu certificabilestrategy_by_closed_order_id(classification_source_by_closed_order_idz.Order ID gia certificato con strategia diversa!operator_certified_from_dashboard	certified	CERTIFIEDr   r  r  r  )r   operatorr   r   r  chosen_strategyr  evidenceztrade certified order=
 strategy=)r;   r&   r!   r   r   r   r%  r  r   r   r   r   r)  rp   r   r   	AUTH_USERrf   )r   rn   r   tradeproposalr   mappingsourcesexistingr(  r   s             @r,   _certify_traderA  r  s   488J'-2.446H"488J#78H44>??!$1E[1$7[H EFF)+F =rBG JBOG"7;;x#89HH(IJJ GH;GH ($%7%98[QEu))Hb)%\\*=rB#ll#8"=LL!4b9	! 	 
 
*XJ?@rL   c                 ~   t        | j                  d      xs d      j                         t        |      }t	               v rt        d      t        fdt        |      D        d       xs i }t               }|j                  dt        j                  t        j                        j                  d       dt        j                   d       t        j                  t        j                        j#                         d	d
dd|j                  dd      dt%        |      |j                  dd      |j                  dd      |j                  dd      dd       t'        |       t)        dt*        |j                  dd      |j                  dd      |j                  dd      d       t-        d        y )Nr   r/   z!Trade gia presente nelle anomaliec              3   L   K   | ]  }|j                  d       k(  s|  ywr-  r.  r/  s     r,   r	  z(_reject_certification.<locals>.<genexpr>  r0  r1  zreject-%Y%m%d%H%M%S-r   r   r   PROPOSTA_RIFIUTATA_DA_OPERATOREr  z'Da approfondire nella gestione anomalier  r  )r   r  r9  )r   
created_atr   r   r   reasonr9  notesr   trade_snapshotproposal_snapshotREJECTED_TO_ANOMALYr   )r   r7  r   r   r  r  z trade rejected to anomaly order=)r;   r&   r!   r%  r   r   r  r   rp   r  r   r\   r   r@   rH   r~   r   r]   r   r   r   r;  rf   )r   rn   r<  r=  r(  r   s        @r,   _reject_certificationrM    s   488J'-2.446H!$1E&((<==[1$7[  
   E	LL hll!;!D!D^!T UUVW^WhWhijWkVlmll8<<0::<*3LL!4b9:u+ %8"=",,'<bA %8"=
 " u&))Hb)%\\*=rBll#8"=!  
*8*56rL   c                    t        | j                  d      xs d      j                         t        | j                  d      xs d      j                         j                         t	        | j                  d            }t        | j                  d      xs d      j                         }t        | j                  d      xs d      j                         }t        | j                  d      xs d      j                         }t        |      D ci c]  }t        |j                  d            | }}|j                        }	|	t        d      t        vrt        d	      d
k(  r|t        vrt        d      d
k7  rd}|st        d      t        |      }
|s|
t        d      t               }t        fd|D              rt        d      dt        j                  t        j                        j!                  d       dt#        j$                  d       }|t        j                  t        j                        j'                         d|||||	j                  dd      |	j                  dd      |	j                  dd      |	j                  d|	j                  dd            |	j                  d|	j                  dd            |	j                  dd      |	j                  dd      |	j                  dd      |	j                  d |	j                  d!d            |	j                  d"d      |	j                  d#d      d$d%
}d }	 |
t)        ||
      \  }}||d&<   |j+                  |       t-        |       t3        d)|d*    d+ d, d-|xs d        |S c c}w # t.        $ r ||j1                  d'(        w xY w).Nr   r/   r   r   rH  r9  rI  z*Caso non presente tra le anomalie correntizAzione non validar0   r+  zMotivo obbligatorioz:Inserire una prova testuale oppure allegare uno screenshotc              3      K   | ]D  }|j                  d       dk(  xr* |j                  d      k(  xr |j                  d      k(   F yw)r   r   r   r   Nr.  )r  r   r   r   s     r,   r	  z*_create_review_proposal.<locals>.<genexpr>  sZ        	i' 	)HHZ H,	)HHX&(	)s   A
Az:Esiste gia una proposta pendente identica per questo tradezreview-rD  rE  r   r   r  r   sideclosed_sizeqtyr   avg_entry_priceentry_price
entry_timerG  
updated_atpnl_netpnlclassification_sourceoperational_reason)r  r   rP  rQ  rS  rU  rG  rV  rW  rY  rZ  )
r   rG  r   r   r   rH  r9  rI  r   rJ  evidence_attachmentTrz   zreview proposal saved id=r   z order=z action=r:  )r;   r&   r!   r   r   r#  r   REVIEW_ACTIONSr   r   rp   anyr   r\   r   r@   rH   r~   r   r]   r   r  r   r'   r   rf   )r   rn   r   r   rH  r9  rI  r   r  r<  validated_attachmentr(  r   r=  attachment_pathr   r   r   s                   @@r,   _create_review_proposalr`    s   488J'-2.446H(#)r*00288:F"488J#78H(#)r*002F488J'-2.446H!'R(..0E;Md;STC#cggj)*C/TJTNN8$E}EFF^#,--0M M>??.//6zB,4UVV E
  	  UVVHLL6??OPPQRYRcRcdeRfQghK"ll8<<0::<!IInb9ii"-IIfb) 99]EIIeQ4GH$yy):EIImUV<WX))L"5))L"5))L"5yyEIIeQ,?@%*YY/F%K"')),@""E
H0 O	+(?Ma(b%Ho.6H*+X5!
 
#H]$;#<GH: NHO#4	6 OC Ur  &""d"3s   "N!2N& &Oc                    d  t        |      j                  d      r|nd      }t        |       }t        |       }t	               }|D cg c]  }|j                  d      dk(  s| }	}d fd	dj                  fd|D              xs d}
dj                  fd	|D              }dj                  fd
|D              xs d}dj                  fdt        |	      D              xs d}|rd |       dnd}|rd |       dnd}|sdnd}d| d| | dt        |       d|
 dt        |       d| d| d| d| d         d| dt        |	       d| dS c c}w )!Nc                 J    t        j                  t        | | nd      d      S )Nr/   Tquote)htmlescaper;   r   s    r,   r   z)render_review_dashboard.<locals>.<lambda>
  s    C1B$KSWX rL   /r   r   r/   c                 V     dj                   fdt        t              D              S )Nr/   c           
   3   x   K   | ]1  }d  |       d|k(  rdnd d |j                                d 3 yw)z<option value='r   z	 selectedr/   >z	</option>Nr  )r  r   escselecteds     r,   r	  zDrender_review_dashboard.<locals>.strategy_options.<locals>.<genexpr>  sP      
  c(m_AX=QkWY-ZZ[8>>#$%Y0
s   7:)r  r   r   )rm  rl  s   `r,   strategy_optionsz1render_review_dashboard.<locals>.strategy_options  s)    ww 
 ##@A
 
 	
rL   c              3     K   | ]G  }d j                   t        |j                  d                   |j                  dd             |j                  dd             |j                  d|j                  dd                   t        |j                  d|j                  d	d                        d
z    |j                  dd             t	        |j                  dd            j                                |j                  dd             |j                  dd             |j                  dd            
       J yw)a-  <tr><td>{closed}</td><td><b>{symbol}</b></td><td>{side}</td><td>{qty}</td><td>{pnl}</td><td><span class='confidence {confidence_class}'>{confidence}</span></td><td>{evidence}</td><td><form class='inline certify-form' method='post'><input type='hidden' name='order_id' value='{order}'><select name='strategy' required>{options}</select><button type='submit'>Certifica</button></form><form class='inline reject-form' method='post'><input type='hidden' name='order_id' value='{order}'><button class='danger' type='submit'>No, anomalia</button></form></td></tr>rV  r   r/   rP  rQ  rR  r   rW  rX  z USDTr  r   r  r   r  )
closedr   rP  rR  rX  r  confidence_classr9  orderoptionsN)formatrP   r&   	_fmt_usdtr;   r   )r  r   rl  rn  s     r,   r	  z*render_review_dashboard.<locals>.<genexpr>  s+     !( '	V W]V\~cggl&;<=swwx,-SWWVR()CGGM3775!+<=>Icggi1BCDEO377#8%@A SWW-BE%J!K!Q!Q!ST!4b9:cggj"-.$SWW-@"%EF W] W
	
!s   EEzH<tr><td colspan='8' class='muted'>Nessun trade da certificare.</td></tr>c              3   X  K   | ]  }d j                   |j                  dd             |j                  dd             |j                  dd             |j                  dd             t        |j                  d|j                  dd                        	        y
w)zR<option value='{order}'>{kind} | {symbol} | {side} | {order} | {pnl} USDT</option>r   r/   r  r   rP  rW  rX  r   )rr  kindr   rP  rX  N)rt  r&   ru  r  r   rl  s     r,   r	  z*render_review_dashboard.<locals>.<genexpr>,  s      	   	]cccggj"-.SWW^R01swwx,-SWWVR()Icggi1BCDE 	d 	
	 s   B'B*c              3     K   | ]A  }d j                   |j                  dd             |j                  dd             |j                  dd             |j                  d|j                  dd                   |j                  d|j                  d	d                   t        |j                  d
      xs |j                  d                   t        |j                  d                   |j                  dd             t        |j                  d|j                  dd                        	       D yw)z<tr><td>{kind}</td><td>{symbol}</td><td>{side}</td><td>{qty}</td><td>{entry}</td><td>{opened}</td><td>{closed}</td><td class='mono'>{order}</td><td>{pnl}</td></tr>r  r/   r   rP  rQ  rR  r   rS  rT  rU  rG  rV  r   rW  rX  )	rw  r   rP  rR  entryopenedrp  rr  rX  N)rt  r&   rP   ru  rx  s     r,   r	  z*render_review_dashboard.<locals>.<genexpr>6  s      	;;A6SWW^R01swwx,-SWWVR()CGGM3775!+<=>cgg/1JKL~cggl&;&Tsww|?TUV~cggl&;<=cggj"-.Icggi1BCDE <B 
<
	
s   EEzI<tr><td colspan='9' class='muted'>Nessun caso anomalo corrente.</td></tr>c              3     K   | ]:  }d j                   |j                  dd             |j                  dd             |j                  dd             |j                  dd             |j                  di       j                  dd             |j                  dd             |j                  d	d             |j                  d
d            |j                  di       j                  d      r8dj                   |j                  di       j                  dd                  ndz          = yw)z<tr><td>{created}</td><td>{status}</td><td>{action}</td><td>{strategy}</td><td>{symbol}</td><td class='mono'>{order}</td><td>{reason}</td><td>{evidence}</td></tr>rG  r/   r   r   r   rJ  r   r   rH  r9  r[  r   zm<br><a class='evidence-link' href='review/evidence/{name}' target='_blank' rel='noopener'>Apri screenshot</a>)r}   )createdr   r   r   r   rr  rH  r9  N)rt  r&   )r  r   rl  s     r,   r	  z*render_review_dashboard.<locals>.<genexpr>F  sA     ( '	bbhbhr23txx"-.txx"-.*b12txx 0"599(BGHdhhz2./txx"-.DHHZ,-
 xx 5r:>>}M D  K  K *?!D!H!HXZ![\ K  TV ci c
	
s   EEzH<tr><td colspan='8' class='muted'>Nessuna proposta registrata.</td></tr>z<div class='ok'></div>z<div class='err'>z	 disabledaH  <!doctype html>
<html lang='it'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'>
<title>V2 Certificazioni e anomalie</title><style>
body{margin:0;background:#0d1117;color:#e6edf3;font-family:Arial,sans-serif}main{max-width:1500px;margin:auto;padding:20px}
h1{color:#58a6ff;font-size:25px}h2{font-size:17px;margin-top:0}.bar{display:flex;gap:10px;align-items:center;justify-content:space-between}
.panel{background:#161b22;border:1px solid #30363d;border-radius:6px;padding:16px;margin:14px 0}.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
label{display:block;color:#9fb3c8;font-size:12px;margin-bottom:5px}input,select,textarea{width:100%;box-sizing:border-box;background:#0d1117;color:#e6edf3;border:1px solid #3d4856;border-radius:4px;padding:9px}
textarea{min-height:76px;resize:vertical}button,.btn{display:inline-flex;align-items:center;background:#238636;color:white;border:0;border-radius:4px;padding:9px 13px;text-decoration:none;font-weight:700;cursor:pointer}button:disabled{opacity:.45;cursor:not-allowed}.btn.secondary{background:#1f6feb}
button.danger{background:#da3633}.inline{display:inline-flex;gap:6px;align-items:center;margin:2px 5px 2px 0}.inline select{width:190px}
.confidence{font-weight:700;padding:4px 7px;border-radius:4px}.confidence.high{background:#173c24;color:#56d364}.confidence.medium{background:#3b2e0b;color:#e3b341}.confidence.low{background:#3d1618;color:#ff7b72}
table{width:100%;border-collapse:collapse;font-size:12px}th,td{padding:8px;border-bottom:1px solid #30363d;text-align:left;vertical-align:top}th{color:#8fb2d9}.mono{font-family:Consolas,monospace;word-break:break-all}.muted{color:#8b949e}.ok{padding:10px;border:1px solid #2ea043;background:#102819;color:#56d364}.err{padding:10px;border:1px solid #f85149;background:#351315;color:#ff7b72}.notice{color:#d29922;font-size:13px}
@media(max-width:800px){.grid{grid-template-columns:1fr}.scroll{overflow:auto}}
</style></head><body><main>
<div class='bar'><h1>V2 Certificazioni e anomalie</h1><a id='mainDashboardLink' class='btn secondary' href='z'>Torna alla dashboard principale</a></div>
<p class='notice'>Il sistema propone l'abbinamento. Solo Certifica aggiorna la policy e i KPI; No sposta il caso nelle anomalie. Nessun effetto su ordini o posizioni.</p>
z,
<section class='panel'><h2>Da certificare (z)</h2><div class='scroll'><table><thead><tr><th>Chiusura</th><th>Asset</th><th>Side</th><th>Qty</th><th>Net</th><th>Confidenza</th><th>Prova proposta</th><th>Decisione</th></tr></thead><tbody>zL</tbody></table></div></section>
<section class='panel'><h2>Anomalie reali (z)</h2><div class='scroll'><table><thead><tr><th>Tipo</th><th>Asset</th><th>Side</th><th>Qty</th><th>Entry</th><th>Apertura (Roma)</th><th>Chiusura (Roma)</th><th>Order ID</th><th>Net</th></tr></thead><tbody>z</tbody></table></div></section>
<section class='panel'><h2>Risoluzione manuale anomalia</h2><form id='proposalForm' method='post' enctype='multipart/form-data'>
<div class='grid'><div><label>Caso anomalo</label><select name='order_id' requiredrk  zH</select></div>
<div><label>Azione</label><select name='action' requiredas  ><option value='classify'>Abbina a strategia</option><option value='exclude_test'>Escludi: test</option><option value='exclude_operational'>Escludi: anomalia operativa</option><option value='needs_review'>Richiede verifica</option></select></div>
<div><label>Strategia (obbligatoria solo per abbinamento)</label><select name='strategy'><option value=''>Seleziona</option>a<  </select></div>
<div><label>Motivo</label><input name='reason' maxlength='240' required placeholder='Motivo della decisione'></div>
<div><label>Prova / fonte testuale</label><input name='evidence' maxlength='500' placeholder='Alert TV, order ID, log, verifica manuale'></div>
<div><label>Screenshot (PNG, JPG o WEBP; massimo 4 MB)</label><input type='file' name='evidence_file' accept='image/png,image/jpeg,image/webp'></div>
<div><label>Note</label><textarea name='notes' maxlength='1200' placeholder='Dettagli aggiuntivi'></textarea></div></div>
<p><button type='submit'zt>Registra proposta</button></p></form></section>
<section class='panel'><div class='bar'><h2>Proposte da risolvere (aA  )</h2><a id='exportLink' class='btn secondary' href='export.json' download='v2_classification_review_queue.json'>Esporta audit JSON</a></div><div class='scroll'><table><thead><tr><th>Creata</th><th>Stato</th><th>Azione</th><th>Strategia</th><th>Asset</th><th>Order ID</th><th>Motivo</th><th>Prova</th></tr></thead><tbody>aE  </tbody></table></div></section>
<script>
const p=location.pathname.replace(/\/$/,'');
document.getElementById('proposalForm').action=p+'/proposals';
document.querySelectorAll('.certify-form').forEach((form)=>form.action=p+'/certify');
document.querySelectorAll('.reject-form').forEach((form)=>form.action=p+'/reject');
document.getElementById('exportLink').href=p+'/export.json';
const mainLink=document.getElementById('mainDashboardLink');
const publicMain=p.endsWith('/review')?p.slice(0,-7):'';
if(mainLink&&publicMain){mainLink.href=publicMain;}
</script></main></body></html>)r/   )	r;   r"   r   r#  rp   r&   r  reversedr=   )rn   r   errormain_urlsafe_main_urlcertifications	anomaliesr(  r   pending_queuecertification_rowscandidate_optionsanomaly_rows
queue_rowsmessage_html
error_htmldisabledrl  rn  s                    @@r,   render_review_dashboardr  	  sA   
XCCM$<$<S$AsKM.t4N"4(I E&+Odtxx/AY/NTOMO
  !( ")!  T* 
T+ ,  	  	  	 77    U 
U    ( ]+)  T* 
T+ , ?F%c'l^6:2L;@$SZL7bJ"+{Hm n{l{ |zl ,,/,?+@  AA  BT  AU U,,/	N+;  <K  LX  KY YSS[R\\]^o]p q99A
 C} ~N  ~P  }Q Q
 "
 #DDGDVCW  XY  Zd  Ye 
e7%" %"a Ps   E$(E$c                      	 t         j                  j                  dt        t                     ddlm}   |        }|j                         S # t        $ r}t        d|        g cY d }~S d }~ww xY w)Nr   BybitDemoClientzbybit positions err: )
syspathinsertr;   r   bybit_demo_clientr  fetch_positionsr'   rf   )r  ces      r,   get_bybit_positionsr    s\    3t9%5  "" #A3'(	s   A	A 	A/A*$A/*A/c                  ,   	 t         j                  j                  dt        t                     ddlm}   |        }|j                  ddddid      }|d	   d
   d   d   d   }t        |d         S # t        $ r}t        d|        Y d }~yd }~ww xY w)Nr   r  GETz/v5/account/wallet-balanceaccountTypeUNIFIEDTsignedresultrm   coinwalletBalancezbybit balance err:         )r  r  r  r;   r   r  r  _requestfloatr'   rf   )r  r  br  r  s        r,   get_bybit_balancer    s    
3t9%5JJu:%y1$  @{6"1%f-a0T/*++ !!%&s   A/A2 2	B;BBT))VIRTUALUSDT     p@)NEARUSDT33333@r  )symbols_qtysymbolsc                     t        | xs d      j                         j                         }|j                  d      r|d d }|j                  d      rdddddddd	d	d
ddd}|j	                  ||      S )Nr/   _closeivptr3
rettangolorettangolo_simplersi_swing_breakoutma_trailing	range_fibadxsupertrend_bosw)vptr_v3rettangolo_v2rettangolo_tv_simplerett_simplezrettangolo semplicezrsi swing breakoutzma trailingrangez	range fibadx_dmi_bb_volzsupertrend extensionszsupertrend bosw)r;   r!   r   endswithr&   )r   r   aliasess      r,   r   r     s    	rN  "((*E
..
"cr
 ..
" % 3*22$ !2,G ;;ue$$rL   >	   r  sqwr  r  r  r  r  r  r  unclassifiedc                     t               i g g i g i d} t        j                         s| S 	 t        j                  t        j                  d            }|j                  dg       D ch c]4  }t        |      j                         rt        |      j                         6 }}|j                  di       j                         D ci c]L  \  }}t        |      j                         r.t        |      r#t        |      j                         t        |      N }}}i }|j                  di       }t        |t              ry|j                         D ]f  \  }}	t        |xs d      j                         }|s&t        |	t              rt        |	      ||<   Edt        |	xs d      j                         i||<   h i }
|j                  d	i       j                         D ]  \  }}	t        |xs d      j                         j                         }|rt        |	t              sDt        |	j                  d
      xs d      j                         }t        |      t        d|        |t        |	j                  d      xs d      j                         dd|
|<    |||j                  dg       D cg c]  }t        |t              r| c}|j                  dg       D cg c]  }t        |t              r| c}||j                  dg       D cg c]4  }t        |t              r"t        |j                  d            t         v r|6 c}|
dS c c}w c c}}w c c}w c c}w c c}w # t"        $ r}t        d|        | cY d}~S d}~ww xY w)zBRegole storiche per orderId. Non modifica il DB operativo webhook.)excluded_closed_order_ids%operational_excluded_closed_order_idsexcluded_trade_fingerprints'operational_excluded_trade_fingerprintsr2  strategy_by_trade_fingerprintblocked_assetsrh   rY   r  r2  r  r/   rH  r  effective_fromNz9blocked asset policy ignored: invalid effective_from for blocked_assetnew_entries)r  rH  scoper  r  r  r   zstats trade policy err: )setr   r   rj   rk   r   r&   r;   r!   r   r   rl   r   r  rF   rf   r   r'   )emptyrn   r   excludedr   r   r>  operational_by_order_idraw_operational_idsruler  r   r  r   ro   s                  r,   _load_stats_trade_policyr    sn    &)U13')35'))+E ##%:zz+55{5KL "=rB
5z! J
 
 '+hh/Lb&Q&W&W&Y
"(8}""$)<X)F M!#6x#@@
 

 #%"hh'NPRS)40"5";";"= \$x~2.446dD)8<T
+H59A3tzr?CXCXCZ8[+H5\  HH%5r:@@B 	LFD2&,,.446FD$!7 *:!;!ArBHHJN~.6OPVxXY"0dhhx0CODJJL&&N6"	 *25L!%*G!L,dD) ,
 "&*SUW!X8dD) 8 ,3!%*I2!N.dD)'(<=A^^ .
 -#
 	
G


B,8
.  &se,-sa   =M% '9M %M% AMFM% -MM% M
5M% 9M M% M% %	N.N=NNc                 
   	 t        |       } t        |      }|dvr	 t        t        |            }nt	        dt        |      dz        }t        | |z
        |k  S # t        t        f$ r Y yw xY w# t        t        f$ r Y yw xY w)NFNr/   :0yE>ư>)r  	TypeErrorr   absmax)actualexpectedexplicit_tolerance	tolerances       r,   _fingerprint_float_equalr    s    v? +	E"456I c(md23	v !Y.. z" 
 :& 		s"   A A0 A-,A-0BBc                    d}t        fd|D              ryt        | j                  d      xs d      j                         j	                         t        d         j                         j	                         k7  ryt        | j                  d      xs d      j                         j	                         t        d         j                         j	                         k7  ryt        | j                  d      d         syt        | j                  d	      d
   j                  d            syj                  d      dvrt        | j                  d      d         syj                  d      dvr/t        | j                  d      d   j                  d            syj                  d      sj                  d      r	 t        t        | j                  d      xs | j                  d      xs d            }|syj                  d      rQt        t        j                  t        d         j                  dd            j                         dz        }||k  ryj                  d      rQt        t        j                  t        d         j                  dd            j                         dz        }||kD  ryyy# t        t        t        f$ r Y yw xY w)zLConfronta l'intero trade. Non consente mai una regola basata sul solo asset.)r   rP  rQ  rS  c              3   D   K   | ]  }j                  |      d v   yw)r  Nr.  )r  r   fingerprints     r,   r	  z-_matches_trade_fingerprint.<locals>.<genexpr>.  s     
B#;??3:-
Bs    Fr   r/   rP  
closedSizerQ  avgEntryPricerS  avg_entry_price_toleranceavg_exit_pricer  avgExitPrice
closed_pnl	closedPnlclosed_pnl_toleranceclosed_at_fromclosed_at_toupdatedTime	createdAtr   r9   r:     T)r]  r;   r&   r!   r  r  r>   r  r   rA   rB   r   r  r   OverflowError)closed_itemr  required	closed_msstart_msend_mss    `    r,   _matches_trade_fingerprintr  +  s   CH

B
BB
;??8$*+11399;sH@egeeg 
;??6"(b)//1779SF>egeeg #%{='A #(%&34
 '(
:C['5E)FD |$J6?W$L!./@
 '(KOON,K	E+//-"@"eKOOT_D`"edefgI/0**K(89:BB3QikD)
 x' ~.**K78@@hOikD)
 v%   :}5 		s    <K A!K *A!K K%$K%c                 F    |D cg c]  }t        | |      s| c}S c c}w N)r  )r  fingerprintsr   s      r,   _matching_fingerprintsr  f  s!    )[T-GUY-ZD[[[s   c                    | rt         j                         syd}	 t        j                  t               }|j	                  dt        |       f      j                         }|r|d   rt        |d         nd	 ||j                          S S # t        $ r.}t        d|  d|        Y d}~||j                          yyd}~ww xY w# ||j                          w w xY w)z@Usa esclusivamente la strategia registrata sullo stesso orderId.r/   NzGSELECT strategy FROM orders WHERE order_id = ? ORDER BY id DESC LIMIT 1r   z"strategy order lookup err orderId=: )DB_PATHr   sqlite3connectexecuter;   fetchoner   closer'   rf   )r   connr   ro   s       r,   _strategy_from_order_dbr  j  s    7>>+Dw'llU]
 (* 	 /2c!f"3q6*"D
 JJL 	  0
"SEBCJJL 	 JJL s*   AB	 		C B;#C ;C  C Cc                    t        | xs d      j                         } | st        dfS t        |j	                  |             }|t
        v r|dfS t        t        |             }|t
        v r|dfS |s|rt        dfS t        dfS )zFClassifica solo con prova univoca per orderId, mai in base al simbolo.r/   missing_order_idcertified_order_idexact_order_id_dbinvalid_strategy_for_order_idorder_id_not_registered)r;   r!   UNCLASSIFIED_STRATEGYr   r&   r   r  )r   certified_mappingr5  recordeds       r,   _strict_closed_trade_strategyr  ~  s    8>r"((*H$&888#$5$9$9($CDI11..."#:8#DEH00,,,H$&EEE ";;;rL   c           
      t   t        | j                  d      xs d      j                         }|rd}	 t        j                  dt
         dd      }t        j                  |_        |j                  d      j                         }|r!|j                  d	|f      j                         nd}	 ||j                          	 |t        | j                  d      xs d      j                         j                         }t        | j                  d      xs d      j                         j                         }|dk(  rdn|dk(  rdnd}	 t        t        | j                  d      xs d            }	t        | j                  d      xs d      }
t        t        |d   xs d            }t        |d   xs d      }t%        |d         }t'        |d         }t        |d   xs d      j                         j                         |k(  xr t        |d   xs d      j                         j                         |k(  xrW t        ||	z
        t)        d|	dz        k  xr7 t        ||
z
        t)        dt        |
      dz        k  xr |duxr |t*        v }|syt        |d   xs d      j                         d|t        |d   xs d      |d d!fS t
        j-                         sy"t        | j                  d      xs d      j                         j                         }t        | j                  d      xs d      j                         j                         }|dk(  rdn|dk(  rdnd}t%        | j                  d#      xs | j                  d$            }	 t        t        | j                  d      xs d            }t        | j                  d      xs d      }|r|r|
|dk  s|dk  ry&d}	 t        j                  dt
         dd      }t        j                  |_        |j                  d'||f      j/                         }	 ||j                          	 t)        d|dz        }t)        dt        |      dz        }g }|D ]+  }t        |d   xs d      j                         }t        |d*   xs d      j                         }|r|d+v rK|j1                         j3                  d,      rkt%        |d-         }|||kD  r	 t        t        |d   xs d            }t        |d.   xs d      }t        ||z
        |kD  rt        ||z
        |kD  rt'        |      }|t*        vr|j5                  |t        |d/   xs d      j                         |t        |d-   xs d      |d        . t7        |      d0k7  rdd1t7        |       fS |d   d2fS # t        $ r.}t        d
| d|        Y d}~||j                          yyd}~ww xY w# ||j                          w w xY w# t         t"        f$ r Y yw xY w# t         t"        f$ r Y y%w xY w# t        $ r.}t        d(| d|        Y d}~||j                          y)y)d}~ww xY w# ||j                          w w xY w# t         t"        f$ r Y 4w xY w)3zJTrova una sola entrata usando l'intera firma del trade, mai il solo asset.orderIdr/   Nzfile:z?mode=roT)urizUSELECT 1 FROM sqlite_master WHERE type='table' AND name='closed_trade_entry_evidence'zSELECT close_order_id, entry_order_id, symbol, open_side, qty, entry_price, strategy, opened_at, source FROM closed_trade_entry_evidence WHERE close_order_id = ?z(exact entry evidence lookup err orderId=r  )Nexact_entry_evidence_db_errorr   rP  SELLBUYr  r   r  rR  rT  )N$exact_entry_evidence_invalid_numeric	opened_atr   	open_sider  r  g|=g-C6
?)N'exact_entry_evidence_signature_mismatchentry_order_id)r  
request_idrU  entry_time_rawr   !exact_closed_order_entry_evidence)Nentry_db_missingr  r  )Nentry_signature_invalid)Nentry_signature_incompletezSELECT order_id, request_id, symbol, side, qty, price, strategy, created_at FROM orders WHERE UPPER(symbol) = ? AND UPPER(side) = ? ORDER BY id DESCz"entry lifecycle lookup err symbol=)Nentry_db_errorr   >   no_positionanti_dup_skiprender_blockedrender_short_blockedr  rG  pricer  r   entry_lifecycle_candidates_unique_entry_lifecycle)r;   r&   r!   r  r  r  Rowrow_factoryr  r   r'   rf   r  r  r  r  r  r   rF   r   r  r   r   fetchallr   r  r  r=   )r  close_order_id
exact_conntable_exists	exact_rowro   r   
close_sideexpected_open_side
closed_qtyclosed_entry
stored_qtystored_entryr  r   validr  close_dtrR  rT  r  rowsqty_toleranceprice_tolerancer  r   raw_strategyr   entry_dtrow_qty	row_prices                                  r,    _unique_entry_lifecycle_evidencer=    s   39r:@@BN
	# 5	)BMJ%,[[J"%--9 hj  ) #**L  !	
 hjd  %  " 28b9??AGGIF[__V4:;AACIIKJ*4*>j\aNaFgiD {|'D'I!JK
$[___%E%JK y'7'<1!=>
$Y}%=%BC (	+(>?I*9Z+@AHIh'-2.446<<>&H >	+.4"5;;=CCEI[[>
Z/0Cj4>O4PP> |34E3|CTW[C[8\\> T)	>
  ==  F"%i0@&A&GR"H"N"N"P '"%i&<&B"C$ 33 3 >>'*0b1779??AF[__V,2399;AACJ#v-Z5=P6VXI&F+//+*FH/%5:;<KOOO<AB h&6#(kUVFV1Dwix8dC";;||WY
 (*	 	 JJLcDj)M%[!1D!89OJ 3z?0b1779s:,"-3358 (
 
 ((2"3|#45x(2	%E
a01Gc'l/a0I w}-y;&'/9&|488&c,/526<<>"!#l"3"9r: 
 	1@ :!23z?2CDDDa=222Y  	9:>:J"SERS8%  " &		9 %  " & z* DCDD z" /./  &03%@A%JJL 	& JJL * :& 		s   A8W A2X( AX= -AY -Z$	XX0X XX X%(X:9X:=YY	Z	Z,Z Z		Z Z!$Z76Z7c                 @   t        | j                  d      xs d      j                         }|j                  di       j                  |      }|8t        |j                  d      xs d      j                         }t        dd|dd	S t	        | |j                  d
g             }|r;t        |d   j                  d      xs d      j                         }t        dd|dd	S t        ||d         \  }}t        |       \  }}	t        | j                  d      xs d      j                         j                         }
|j                  di       j                  |
      }|rit        |d         }t        | j                  d      xs | j                  d            }|,|||k\  r%|t        d|	 dddd	S |d   |k\  rt        ddd|d	S t	        | |j                  dg             }|D ch c]  }t        |j                  d             }}|t        v r||}}n|t        |      dk(  r@|j                         }t        |d   j                  d      xs d      j                         }n.t        |      dkD  r	t        d}}n||d   |	}}nt        | d|	 }}||dd|d	S c c}w ) zLClassifica il trade e applica il blocco all'ora di entrata, non di chiusura.r  r/   r  NrH  APPROVED_OPERATIONAL_EXCLUSION%operational_exclusion_closed_order_idT)r   sourceperformance_excludedrZ  entry_evidencer  r   #UNAUTHORIZED_ORDER_WITHOUT_TV_ALERT!operational_exclusion_fingerprintr2  r   r  r  r  r  zblocked_asset_entry_unverified:FrU  "blocked_entry_after_effective_fromBLOCKED_ASSET_ORDER_LEAKr  r   r   rA  certified_trade_fingerprintconflicting_trade_fingerprintsr   )r;   r&   r!   r
  r  r  r=  r  rF   r   r   r=   pop)r  r   r*  exact_operationalrH  operational_matchesexact_strategyexact_sourcerC  entry_sourcer   
block_ruleblocked_fromr5  fingerprint_matchesr   fingerprint_strategiesr   rA  s                      r,   _classify_closed_itemrT    s   39r:@@BN

#JBOSS $!!(+O/O

%' 	 .=$("("
 	
 1VZZ I2N "&&x0Y4Y

%' 	 .9$("("
 	
 $A,-$ NL $DK#P NL*0b1779??AF,b155f=J&z2B'CD"OOM*Jkook.J

 #)9X=U% 5 ?~N,1*,&*  l+|; 5B,0*D&4  1VZZ ?D ?R6:DHHZ01  66)<&	#	$	))--/"&&x0Q4Q

%' 	 
#	$q	(02R&		#)*5|&0\N!L>2R&  % ( %s   '!Jr     r   r   )tzinfor  c                    | j                  dd      }t        | j                  dd      xs d      }||ft        d   v r||ft        d   v ryt        | j                  dd      xs d      }|dk(  r#t        |d	z
        d
k  rt        |dz
        dk  ry|dk(  rt        |dz
        dk  ry|dk(  rt        |dz
        d
k  ryy)zCTrue se il trade chiuso Bybit corrisponde a un MIO test Pine-style.r   r/   r  r   r  Tr  r        ?r  r  {Gz?r  r  BTCUSDTZd;O?F)r&   r  MY_TEST_FILTERr  )r<  symrR  	avg_entrys       r,   is_mio_test_trader_  t  s    
))Hb
!C
		,*/a
0CSz^M22Sz^TaEb7beii38q9I
mIO 4t ;C&L@QTX@X
jSu-4
iCe,t3rL   c                     | j                  dd      }	 t        | j                  dd      xs d      }|dk(  rt	        |dz
        dk  ry	|d
k(  rt	        |dz
        dk  ry	y# t        t        f$ r Y yw xY w)u   True se la posizione aperta e' un MIO test Pine-style.
    FIX 2026-08-10 (Mattia): rimosso BTCUSDT 0.023 dal filtro perche' era una posizione reale
    del 2° account, non un test. Tenuto NEARUSDT 599.9 e VIRTUALUSDT 1500 (quei SI sono test).r   r/   r   r   Fr  r  rY  Tr  r  )r&   r  r  r   r  )posr]  r   s      r,   is_mio_test_positionrb    s     ''(B
CSWWVQ',1- jS.5
mD6M 2T 9 z" s   A" "A43A4c                  *   g } t               }|d   }|j                  dg       }|d   }	 t        j                  j	                  dt        t                     ddlm}  |       }t        t        d      j                  j                  t        d      j                  j                        j                         dz        }d}t         }	|	|k  rt#        |	|z   |      }
d	|	|
d
d}|j%                  dd|d      }|j                  d      xs i j                  dg       xs g }|D ]:  }|j                  dd      }t        |j                  d      xs d      j'                         }||v st)        ||      rSt+        ||      }|d   }|d   }|j                  d      xs i }t-        |j                  dd      xs d      }t-        |j                  dd      xs d      }t-        |j                  dd      xs d      }t-        |j                  dd      xs d      }t-        |j                  dd      xs d      }t-        |j                  dd      xs d      }t-        |j                  dd      xs d      xs ||z   }||z   }t/        ||z        }|dkD  r||z  dz  nd}|dkD  r||z  dz  nd}| j1                  i d|d |j                  d d      d!|d"|d#|d$|d%|d&|d'|d(|d)|d|d*|t2        k7  rd+nd,d-|d.|d.   d/|d/   d0|j                  d0d      |j                  d1d      ||j                  d2d      |j                  d3d      d4       = |
d5z   }	|	|k  r| S # t4        $ r} t7        d6|         | cY d7} ~ S d7} ~ ww xY w)8u  Legge TUTTI i trade chiusi da Bybit API (closed-pnl endpoint), filtra dal 1° agosto,
    esclude MIEI test Pine-style.
    FIX 08/08 (Mattia): NO cursor-based paging perche' bybit_demo_client._request calcola
    firma sul cursor RAW ma `requests.get` ri-encoda il `%3A` -> err 10004.
    Uso finestre di 1 giorno: ~5 trade/giorno, no rischio limite 50.
    FIX 12/08 (Mattia, REVISIONE FINALE #3): closed_trade.strategy = CLOSED_TRADES_STRATEGY_OVERRIDE
    (hardcoded, esplicito) per i simboli in cui il CSV NON riflette la SOURCE Pine TV al momento:
    - WIF: CSV dice rsi_swing ma Pine WIF = RETTANGOLO (Python/SL engine, non Pine RSI swing)
    - VIRTUAL: VPTR3 enabled=false ma Pine VIRTUAL = VPTR3 (aperti quando era attivo)
    - AEO: CSV dice rsi_swing ma Pine AEO = RSI swing SOLO con SL/TP (per Mattia lo conteggia RSI swing)
    Per TUTTI gli altri simboli: get_strategy_for_symbol (CSV con priorita').r  r  r2  r   r  r   r  i \&linear2   )category	startTimeendTimelimitr  z/v5/position/closed-pnlTr  r  rm   r   r/   r  r   rA  rC  r  r  r  r  openFeecloseFeetotalFeed   rP  rR  rT  
exit_pricerX  rW  	pnl_grossfeepnl_pct_grosspnl_pct_netclassification_status
classifiedr  rY  rB  rZ  r  r  r  r  )rU  r   rG  rV  r   zbybit closed trades err: N)r  r&   r  r  r  r;   r   r  r  r>   
__import__r   r\   r   r@   r   SINCE_DATE_MSminr  r!   r  rT  r  r  r  r
  r'   rf   )!outr   excluded_order_idsexcluded_fingerprintsstrategy_by_order_idr  r  now_ms	WINDOW_MScurrent_start
window_endparamsrr   itsym_rawr*  classificationstratattribution_sourcerC  qty_tentry_texit_tnet_pnlopen_fee	close_fee	total_fee	gross_pnlnotional_entryrq  rr  r  s!                                    r,   get_closed_trades_bybitr    s9    C%'F ;<"JJ'DbI!"?@J3t9%5Z
+4488J9O9X9X9\9\]ggilppq+	%f$]Y6?J$*%	F 

5";VD
QAUU8_*//;ArE 2&&2.!$RVVI%6%<"!=!C!C!E!%77;Q-< !6r6!B&z2%3H%="!/!3!34D!E!Kbff\15:; : ?a@rvvna8=A>{A 6 ;!< 	1!5!:;!"&&Q"7"<1=	!"&&Q"7"<1=W(YBV	#i/	!$Wu_!5FTWXFX^!;c!A^_BPSTBTw7#=Z[

 gBFF62. 5 "7	
 !& 7 w   9 $] ";  ,(-1F(FN  ,-?!" +N;Q,R#$ ).9M*N%& %n&8&89I2&N'( #1"4"45Er"J ."$&&b"9"$&&";/ 52f 'NM{ f$| 
 's+,
s$   MM/ -M/ /	N8NNNc                  X    t               } | D cg c]  }t        |      r| c}S c c}w )z>Legge posizioni aperte da Bybit, ESCLUDE MIEI test Pine-style.)r  rb  )r   ps     r,    get_open_positions_bybit_no_testr    s&    

C:!"6q"9A:::s   ''c                    g }t         j                         s|S 	 t        j                  t               }t        j                  |_        |j                         }|j                  d|| f       |j                         D ]  }|j                  t        |              |j                          |S # t        $ r}t        d|        Y d}~|S d}~ww xY w)uP   Carica ordini dal DB, filtrati per data >= since_date (default 1° agosto 2026).zSELECT order_id, symbol, side, qty, price, notional, strategy, created_at FROM orders WHERE created_at >= ? ORDER BY id DESC LIMIT ?zorders load err: N)r  r   r  r  r'  r(  cursorr  r)  r  r   r  r'   rf   )ri  
since_daterx  r  curr   r  s          r,   
get_ordersr    s    
C>>
%w'";;kkmI	

 <<> 	"CJJtCy!	"

 J  %s#$$J%s   BB- -	C6C

Cc                     t         j                         sdddddS 	 t        j                  t               } | j	                         }|j                  d       ddddd}|j                         D ]  \  }}|||<   |dxx   |z  cc<    | j                          |S # t        $ r}t        d|        dddddcY d }~S d }~ww xY w)Nr   )r   	completedfailedr  z2SELECT status, COUNT(*) FROM queue GROUP BY statusr  zqueue stats err: )
r  r   r  r  r  r  r)  r  r'   rf   )r  r  statsr   r  r  s         r,   get_queue_statsr    s    >>1AFFGw'kkmHIAQG \\^ 	$MFE!E&M'Ne#N	$ 	

 Gs#$1AFFGs   A<B 	C#B=7C=C>   $2cd6e92c-b82b-4814-808e-e23579f1a533$2d2e625b-d3b2-4d87-931a-9b378cf8db93$31a9c2fd-540e-45a5-b44f-fe2f8fdb4495$44e4a3ad-23ec-4b7f-b6f8-35778858e5bf$4c8a4478-377e-4b8c-b371-44c64090e26d$4cbb1304-8020-42bd-bcad-8e5d0f19caed$514f5553-6aa3-4148-8e1a-82961c47310b$5c53a9ef-dcab-469e-bbd1-3057fe2746d9$79969acc-3e4b-4101-91bc-69eede1ef6aa$7ed5cc82-3a99-4978-8ae3-c295e82f4609$8a53e7b1-c7d4-4e5a-b67b-4e4fbf4c0977$b426dc94-b72f-427b-b2f2-7e021f5da985$c60d098a-1ec5-4101-9e77-966f67f4f393$e45f561b-c4d8-4045-a2fe-581140fadac1$f79ab621-dc17-488e-950e-e984fc0d9e43c                    t        | j                  dd            }|t        v ry| j                  dd      }	 t        | j                  dd      xs d      }t        | j                  dd      xs d      }|d	k(  rt        |d
z
        dk  ry|dk(  r|dk\  ry|dk(  rt        |dz
        dk  ryy# t        t
        f$ r Y yw xY w)zpTrue se l'ordine e' un MIO test Pine-style (placeholder price=1.0, NEAR 599.9, o order_id in MY_TEST_ORDER_IDS).r   r/   Tr   rR  r   r$  Fr  rX  &.>r    rZ  r[  r  )r;   r&   MY_TEST_ORDER_IDSr  r  r   r  )ooidr]  rR  r$  s        r,   is_mio_testr  5  s    
aeeJ#
$C

%%"
CAEE%O(q)aeeGQ',1- mECK 04 7
jSCZ
iCe,t3 z" s   >B0 0CCc                 R   t        t              }t        | d       D ]d  }|j                  dd      }|s|j                  dd      }|dv r/|j                  dd      dk  rEt	        |      rQ||   j                  |       f g }|j                         D ]  \  }}g }|D ]~  }|j                  d	d      j                         }t        |j                  dd      xs d      }	t        |j                  d
d      xs d      }
|j                  dd      }|j                  dd      }|dk(  r)t        |
dz
        dk  }|j                  |	|
|||d       |dk(  s|s|	}|dkD  s|s|d   }t        ||d         }|
|d
   z
  |z  }|d
   dkD  r|
|d
   z
  |d
   z  dz  nd}|j                  dd      xs t        |      dkD  }|j                  |d||d
   |
|||d   |d   ||d       ||z  }|dxx   |z  cc<   |d   dk  r|j                  d       |dkD  s||r  |S )zMatcha buy+sell FIFO per symbol. Esclude trade che coinvolgono MIEI test Pine-style
    (placeholder price=1.0 o order_id in MY_TEST_ORDER_IDS).c                 &    | j                  dd      S )NrG  r/   r.  xs    r,   r   z$compute_trade_pnls.<locals>.<lambda>P  s    !%%b*A rL   r   r   r/   r   )r   r!  r/   NrR  r   rP  r$  r   rG  buyrX  r  )rR  r$  r   rC   placeholdersellrm  r  F   longrC   )r   rP  rR  rT  rn  rX  pnl_pctr   entry_tsexit_tswarn)r   rm   r   r&   r  r  r   r   r  r  rw  rJ  )orders	by_symbolr  r]  r  tradesords	open_buysrP  rR  r$  r  rC   r  qty_to_closer  matchedrX  r  r  s                       r,   compute_trade_pnlsr  L  sk    D!IF AB !eeHb!eeJ#<<55?aq>#a ! F__& )	T	 	)A55$**,DeQ,1-C!%%+0q1EEE*b)E|R(Bu}!%#+.5  u%WYju!vwI""Q&9#A,C!,E
;G 3w</7:CORSZ|^_O_G 4GDKefG77=%8MCL2<MDMM"%v&s7|SX"w$'
OTWY $#  !G+LJ')J5zT)!a(# #Q&9	))> MrL   c           
      .   t        |       }|dk(  rIi 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dt        |      dd|ddddddddS | D cg c]*  }|j                  d|j                  dd            dkD  s)|, }}| D cg c]*  }|j                  d|j                  dd            dk  s)|, }}t        d | D              }t        d | D              }t        d | D              }	t        d | D              }
t        t        d |D                    }d}|D ]%  }	 |t	        |j                  dd      xs d      z  }' ||	z
  }d}| D ]<  }t        |j                  d      xs |j                  d             }|3|||k  s;|}> |ldd!lm}m} |j                  |j                        }|j                  |j                        j                  d"      }||z
  }t        d#|j                  d#z         }nd}d}t        d$ |D              }t        d% |D              }|dk  r|t        |      z  }n
|dkD  rd&}nd}d}d}i d|dt        |      dt        |      d|rt        |      |z  d'z  ndd|d|d	|d
|	d|
d|d|d|r||z  ndd|r||z  ndd| rt        d( | D              ndd| rt        d) | D              nddt        |      d||||z   ||z   |||||d*S c c}w c c}w # t
        $ r Y w xY w)+zcCalcola KPI da trade chiusi Bybit (gia filtrati per data e test) + posizioni aperte (gia filtrate).r   n_tradeswinslosseswinrater  	total_pnltotal_pnl_nettotal_pnl_gross
total_feestotal_notionaltotal_lossespnl_realizedavg_pnlavg_pnl_gross
best_tradeworst_tradeopen_positionsunrealized_pnlr/   )balancetotal_pnl_with_unrealizedtotal_pnl_gross_with_unrealizedtrading_daysprofit_factorfirst_trade_datesharpe_ratiosortino_ratiorW  rX  c              3   `   K   | ]&  }|j                  d |j                  dd             ( ywrW  rX  r   Nr.  r  ts     r,   r	  z*compute_kpis_from_bybit.<locals>.<genexpr>  s%     Qaiua9Q   ,.c              3   @   K   | ]  }|j                  d d        yw)ro  r   Nr.  r  s     r,   r	  z*compute_kpis_from_bybit.<locals>.<genexpr>  s     GA!%%Q/G   c              3   @   K   | ]  }|j                  d d        yw)rp  r   Nr.  r  s     r,   r	  z*compute_kpis_from_bybit.<locals>.<genexpr>  s     <QUU5!_<r  c           
   3      K   | ]L  }t        t        |j                  d d      xs d      t        |j                  dd      xs d      z         N yw)rT  r   rR  N)r  r  r&   r  s     r,   r	  z*compute_kpis_from_bybit.<locals>.<genexpr>  sF     wdeU155#:#?a@5uVWI]\]C^^_ws   AAc              3   `   K   | ]&  }|j                  d |j                  dd             ( ywr  r.  r  s     r,   r	  z*compute_kpis_from_bybit.<locals>.<genexpr>  s%     M155AEE%O<Mr  unrealisedPnlNrV  rG  r   %Y-%m-%dr   c              3   `   K   | ]&  }|j                  d |j                  dd             ( ywr  r.  r  s     r,   r	  z*compute_kpis_from_bybit.<locals>.<genexpr>  s%     Haiua9Hr  c              3   `   K   | ]&  }|j                  d |j                  dd             ( ywr  r.  r  s     r,   r	  z*compute_kpis_from_bybit.<locals>.<genexpr>  s%     Kqy!%%q/:Kr  g(\X@rm  c              3   `   K   | ]&  }|j                  d |j                  dd             ( ywr  r.  r  s     r,   r	  z*compute_kpis_from_bybit.<locals>.<genexpr>  s%     S!%%	155?;Sr  c              3   `   K   | ]&  }|j                  d |j                  dd             ( ywr  r.  r  s     r,   r	  z*compute_kpis_from_bybit.<locals>.<genexpr>  s%     T155AEE%O<Tr  )r  r  r  r  r  r  r  r  )r=   r&   r  r  r  r'   rF   r   r   r\   r@   rN   rH   r  daysrw  )closed_trades	positionsr  nr  r  r  r  r  r  r  r  
unrealizedr  r  first_trade_dtrC   _dt_tznow_utcr  deltar  total_win_pnltotal_loss_pnlr  r  r  s                               r,   compute_kpis_from_bybitr    sn   MAAv

!1
&.
3<c

-s
 s
 %1#
 8H
 C	
 "0	

 s

 ,S
 #
  -c
 c)n
 /?
 S/2#
 	
 %N!iua(IA(MANDN&QA!%%	155?*Kq*PaQFQQ=QQMGGGO<m<<JwivwwN sMfMMNLJ 	%oq 9 >Q??J #Z/L N $QUU<0GAEE,4GH>%n)<!#	$
 !=''#''")44SWW=FFzR.(1ejj1n- H4HHMKFKKN%N(;;		 LMAD	 	#f+ 	ACIMC'3	
 	] 	 	? 	j 	. 	 	 	=1$s 	1,s 	WdcS]SSjm 	XesTmTTkn  	#i.!" 	*#$ %2Z%?+:Z+G$,&$&3 m OQ  		s*   *K=	K=*L>L/"L	LLc                    | s	g g g ddddS | j                  d        t        |t        d | D              z
  d      }g g g df\  }}}}| D ]h  }||d   z  }|j                  d      xs |j                  d	      xs d
}|j	                  |       |j	                  ||z          |j	                  |       j |r|d   nd}	d}
d}|D ]%  }||	kD  r|}	|	|z
  }||
kD  s|}
|	dkD  r||	z  dz  nd}' |||t        |       |
|dS )zCalcola equity curve da trade chiusi Bybit (gia filtrati).
    Ritorna anche max_dd_usdt e max_dd_pct (FIX 07/08 Mattia: drawdown real come Dash 5511).
    FIX 12/08 (Mattia): aggiunto cum_pnl (PnL cumulativo progressivo) per grafico equity.
    r   r  )datesequitycum_pnltrades_countmax_dd_usdt
max_dd_pctc                 R    | j                  d      xs | j                  d      xs dS NrV  rG  r/   r.  r  s    r,   r   z1compute_equity_curve_from_bybit.<locals>.<lambda>  s#    QUU<%8%UAEE,<O%USU rL   r   c              3   &   K   | ]	  }|d      ywrX  Nr   r  s     r,   r	  z2compute_equity_curve_from_bybit.<locals>.<genexpr>  s     &GAqx&G   rX  rV  rG  r/   rm  )sortr  r  r&   r  r=   )r  r  initial_equityr  r  r  cumr  rC   peakr  r  r+   dds                 r,   compute_equity_curve_from_bybitr    sE   
 rb!\_orssUV3&G&G#GGKN"$b"a-E67C qxUU< =AEE,$7=2Rns*+s 6!9ADKJ >t8DAXK.2Qh"t)c/AJ> &WcR_N`"* rL   c                    t        d       }| D ]  }|j                  dt              }|t        k(  r#|j                  d|j                  dd            }||   dxx   dz  cc<   |dkD  r||   dxx   dz  cc<   ||   dxx   |z  cc<   ||   d	xx   |j                  d	d      z  cc<   ||   d
xx   |j                  dd      z  cc<   ||   d   j                  |        g }|j	                         D ]  \  }}|d   r|d   |d   z  dz  nd}|d   }|d   }	|dk\  rt        |	      |z  t        fd|	D              |dz
  z  }
|
dkD  rt        j                  |
      nd}|dkD  r|z  nd}t        d |	D              }|dkD  rt        j                  ||z        nd}|dkD  r|z  nd}ndx}}|j                  |||d   ||d   |d	   |d
   ||d	        |j                  d d       |S )Nc                      dddddg dS )Nr   r  )r  r  rX  ro  feespnlsr   r   rL   r,   r   z0compute_by_strategy_from_bybit.<locals>.<lambda>  s    AcPS]`jl#m rL   r   rW  rX  r   r  r   r  ro  r  rp  r  rm  ru   c              3   .   K   | ]  }|z
  d z    yw)ru   Nr   )r  r  means     r,   r	  z1compute_by_strategy_from_bybit.<locals>.<genexpr>  s     4!q4xAo4   r  c              3   :   K   | ]  }t        d |      dz    yw)r  ru   N)rw  )r  r  s     r,   r	  z1compute_by_strategy_from_bybit.<locals>.<genexpr>  s     6As3{a'6s   )	r   r  r  r  rX  ro  r  sharpesortinoc                     | d   S NrX  r   r  s    r,   r   z0compute_by_strategy_from_bybit.<locals>.<lambda>&  
    1U8 rL   Tr   reverse)	r   r&   r
  r  r   r  mathsqrtr  )r  by_stratr  rD   pnl_nrx  dwrr  r  varstdr  ddsqr  r  r  s                   @r,   compute_by_strategy_from_bybitr+    s"   mnH *EE*34%%iua1CA19QK1$Ee#K AEE+q$99 FquuUA.F""5)* C  ;1+,S6ai!C& 3&qcFy6t9q=D4t44A>C$'!G$))C.C#&7TCZF666D(,q4!8$cB#%6dRisG""FW

1V9U8!K.!F)$: 	;;$ HH#TH2JrL   c                    t        d       }| D ]  }|j                  dd      }|s|j                  d|j                  dd            }||   dxx   dz  cc<   |dkD  r||   d	xx   dz  cc<   ||   dxx   |z  cc<   ||   d
xx   |j                  d
d      z  cc<   ||   dxx   |j                  dd      z  cc<   ||   dxx   |j                  dd      |j                  dd      z  z  cc<    g }|j                         D ]F  \  }}|d   r|d	   |d   z  dz  nd}|j                  ||d   |d	   ||d   |d
   |d   |d   d       H |j	                  d d       |S )Nc                      dddddddS )Nr   r  )r  r  rX  ro  r  volumer   r   rL   r,   r   z-compute_by_asset_from_bybit.<locals>.<lambda>+  s    AcPS]`lo#p rL   r   r/   rW  rX  r   r  r   r  ro  r  rp  r.  rR  rT  rm  )r   r  r  r  rX  ro  r  r.  c                     | d   S r  r   r  s    r,   r   z-compute_by_asset_from_bybit.<locals>.<lambda>=  r  rL   Tr   )r   r&   r   r  r  )r  by_assetr  rW   r%  rx  r&  r'  s           r,   compute_by_asset_from_bybitr1  *  s   pqH KEE(Biua1CA19QK1$Ee#K AEE+q$99 FquuUA.Hua1553J!JJK C  m1+,S6ai!C& 3&q

aafaiBU8!K.!F)_`ai_jl 	mm HH#TH2JrL   c                    t        t              }| D ]  }t        |j                  d      xs d      j	                         }|s3t        |j                  d      xs d      }|j                         dk(  rdn|j                         dk(  rdnd}t        |j                  d	            }t        |j                  d
      xs |j                  d            }||   j                  |r|j                         j                  d      nd|r|j                         j                  d      ndt        |j                  d      xs d      j	                         |t        |j                  d            t        |j                  d            t        |j                  d            t        |j                  d            t        |j                  d            t        |j                  d|j                  dd                  t        |j                  d      xs d      d        |j                         D ]  }|j                  d d        t        |      S )z<Movimenti certificati che compongono il saldo di ogni asset.r   r/   rP  r  LONGr  SHORTrE  rU  rV  rG  %Y-%m-%d %H:%Mr   rR  rT  rn  ro  rp  rW  rX  r   r   )r  	closed_atr   	directionrR  rz  exitgrossrp  netr   c                     | d   S Nr6  r   r   s    r,   r   z-compute_asset_trade_details.<locals>.<lambda>Z      #k"2 rL   Tr   )r   rm   r;   r&   r  r   rF   r  rN   rH   _safe_floatr   r  r   )	r  detailsr<  r   r.  r7  r{  rp  r6  s	            r,   compute_asset_trade_detailsrA  A  s   $G UYYx(.B/5576*0b1
(..0F:F:K[K[K]afKflo	 <!89 <!8!SEIIl<STKQ**,556FGWZKQ**,556FGWZEIIj17R8>>@"uyy/0 =!9:		, 78 ;!78uyy/0uyyEIIeQ4GHIEIIj17R8 
 	*   B		2D	AB=rL   c                    t        t              }| D ]	  }t        |j                  d      xs t              }|t        k(  r0t        |j                  d      xs d      }|j                         dk(  rdn|j                         dk(  rdnd}t        |j                  d	            }t        |j                  d
      xs |j                  d            }||   j                  |r|j                         j                  d      nd|r|j                         j                  d      ndt        |j                  d      xs d      j                         |t        |j                  d            t        |j                  d            t        |j                  d            t        |j                  d            t        |j                  d            t        |j                  d|j                  dd                  t        |j                  d      xs d      d        |j                         D ]  }|j                  d d        t        |      S )z@Movimenti certificati che compongono il saldo di ogni strategia.r   rP  r/   r  r3  r  r4  rE  rU  rV  rG  r5  r   rR  rT  rn  ro  rp  rW  rX  r   r   )r  r6  r   r7  rR  rz  r8  r9  rp  r:  r   c                     | d   S r<  r   r=  s    r,   r   z0compute_strategy_trade_details.<locals>.<lambda>w  r>  rL   Tr   )r   rm   r;   r&   r
  r   rF   r  rN   rH   r  r?  r   r  r   )	r  r@  r<  r   r.  r7  r{  rp  r6  s	            r,   compute_strategy_trade_detailsrD  ^  s   $G uyy,E0EF,,6*0b1
(..0F:F:K[K[K]afKflo	 <!89 <!8!SEIIl<ST  KQ**,556FGWZKQ**,556FGWZ%))H-34::<"uyy/0 =!9:		, 78 ;!78uyy/0uyyEIIeQ4GHIEIIj17R8"
 	*   B		2D	AB=rL   c                    t        d       }| D ]  }|j                  dd      }|j                  dt              }|r	|t        k(  r7|j                  d|j                  dd            }||f}||   dxx   d	z  cc<   |dkD  r||   d
xx   d	z  cc<   ||   dxx   |z  cc<   ||   dxx   |j                  dd      z  cc<   ||   dxx   |j                  dd      z  cc<    g }|j                         D ]F  \  \  }}}|d   r|d
   |d   z  dz  nd}	|j	                  |||d   |d
   |	|d   |d   |d   d       H |j                  d d       |S )a   FIX 11/08 (Mattia): aggrega per (symbol, strategy) per evitare abbinamenti errati
    tipo AEO RSI swing classificato come VPTR3, oppure WIF RSI swing classificato come RETTANGOLO.
    Ogni entry: {symbol, strategy, n, wins, winrate, pnl, pnl_gross, fees}.c                      ddddddS )Nr   r  )r  r  rX  ro  r  r   r   rL   r,   r   z6compute_by_asset_strategy_from_bybit.<locals>.<lambda>  s    a3SZ] ^ rL   r   r/   r   rW  rX  r   r  r   r  ro  r  rp  rm  )r   r   r  r  r  rX  ro  r  c                     | d   | d   fS )NrX  r  r   r  s    r,   r   z6compute_by_asset_strategy_from_bybit.<locals>.<lambda>  s    AeHaf- rL   Tr   )r   r&   r
  r   r  r  )
r  by_asr  rW   rD   r%  r   rx  r&  r'  s
             r,   $compute_by_asset_strategy_from_bybitrI  {  s    ^_E .EE(BEE*34A..iua1!fc
3119#Jv!#c
5U"c
;155a#88c
6aeeE1o-. C[[] V	A+,S6ai!C& 3&q

aQQsVQvY[]U8!K.!F)U 	VV HH-tH<JrL   c           
         t        d      D cg c]  }dgdz  
 }}t        d      D cg c]  }dgdz  
 }}t        d      D cg c]  }dgdz  
 }}t        d      D cg c]  }dgdz  
 }}t        d      D cg c]  }dgdz  
 }}g d}| D ]*  }t        |j                  d      xs |j                  d            }	|	4|	j                         }
t	        |j                  d|j                  d	d                  }|
j                         }|
j                  }||   |xx   t	        |j                  d
|            z  cc<   ||   |xx   t	        |j                  dd            z  cc<   ||   |xx   |z  cc<   |dkD  r||   |xx   dz  cc<   |dk  r||   |xx   dz  cc<   ||   |xx   dz  cc<   - |t        t        d            |||||dS c c}w c c}w c c}w c c}w c c}w )a>  Heatmap WIN/LOSS per giorno x ora. Ritorna matrix_w (vittorie) e matrix_l (loss).
    FIX 07/08: prima la heatmap mostrava solo il conteggio totale senza distinguere
    W da L. Adesso separa W (verde) e L (rosso) cosi' VIRTUAL che ha 1 loss -25.47
    a Ven 02 appare in rosso, non in verde come tutti gli altri.
       r      r  )LunMarMerGioVenSabDomrV  rG  rW  rX  ro  rp  r   )r  hoursmatrix_wmatrix_lmatrix_grossmatrix_fees
matrix_net)r  rF   r&   rN   r?  weekdayhourrm   )r  _rU  rV  rW  rX  rY  r  r  rJ   local_dtrX  d_idxr[  s                 r,   compute_heatmap_from_bybitr_    s    #((+Qb+H+"'(+Qb+H+(-a11SEBJ1L1',Qx0!C52:0K0&+Ah/3%"*/J/<D 'QUU<0GAEE,4GH:==?!%%	155?;<  "}}UD![{C1H%II!E4 KeQ$@@ 5$3&7UOD!Q&!1WUOD!Q&! UOD!Q&!%'( tE"IHRZ$[PZ 3 ,+10/s   GG"G'"G,>G1c                 4   t        d       }| D ]  }t        |j                  d      xs |j                  d            }|4|j                         j	                  d      }||   }|dxx   dz  cc<   |j                  d|j                  dd	            }|d	kD  r|d
xx   dz  cc<   |dxx   |j                  dd	      z  cc<   |dxx   |j                  dd	      z  cc<   |dxx   |z  cc<   |j                  dd      }|s||d   vs|d   j                  |        g }t        |j                         d      D ]U  }||   }|j                  ||d   |d
   |d   r|d
   |d   z  dz  nd	|d   |d   |d   dj                  |d         d       W |S )zIRaggruppa trade chiusi per giorno, calcola Gross/Fee/Net per ogni giorno.c                      dddddg dS )Nr   r  )r  r  ro  r  rW  r  r   r   rL   r,   r   z'compute_trades_by_day.<locals>.<lambda>  s    q!#s_boq!r rL   rV  rG  r  r  r   rW  rX  r   r  ro  r  rp  r   r/   r  Tr!  rm  r  )dater  r  r  ro  r  rW  r  )	r   rF   r&   rN   rH   r  r   keysr  )	r  by_dayr  rJ   day_keyr&  r%  r]  rx  s	            r,   compute_trades_by_dayrg    s   rsF %QUU<0GAEE,4GH:--/**:67O	#!iua119fINI	+!%%Q//	&	QUU5!_$		)eeHb!3a	l*iL$%  C&++-6 7O

3fI56sV&	AcF*S0;fI|yy9.	
 		 JrL   c                 H   ddl m }m}m} t        t              }| D ]  }t        |      r|j                  dd      }|j                  dd      xs dj                         }	 t        |j                  dd      xs d      }	t        |j                  dd      xs d      }
|	dk  s|
dk  r|dk7  r|j                  d	d      }|s|d
d }||   j                  ||	|
|d        	  |j                  |      j                         } |j                  |j                         j                         }|}||k  r+|j#                         }||vrg ||<   | |d      z  }||k  r+g }t%        |j'                         d      D ]\  }||   }|r3dj)                  |D cg c]  }|d    d|d   dd|d   dd c}      nd}|j                  |t+        |      |d       ^ |S # t        t        f$ r Y w xY w# t        $ r  |ddd      j                         }Y w xY wc c}w )a  FIX 07/08 v3: conta le APERTURE (entry Buy) per giorno, NON le posizioni ancora
    aperte. Un ordine Buy = un'apertura, anche se poi chiusa in piu' tranche.
    Esclude ordini 'no_pos' e 'anti_dup_skip' (qty=0 o price=0) E MIEI test (is_mio_test).
    FIX 07/08 v4 Mattia 14:40: escludi NEARUSDT 600 (test Pine) e popola con 0 i giorni
    dal since_date a oggi che non hanno entry (trasparenza).
    r   )r   r   	timedeltar   r/   rP  rR  r$  r  rG  Nr5   )r   rR  r$  rC   rU  r   r   )r  Trb  r   (,.0f@.4f)   —rc  r  r  )r   r   ri  r   rm   r  r&   r   r  r  r   r  rA   rc  r'   r\   r@   r]   r   rd  r  r=   )r  r  r   r   ri  re  r  r]  rP  rR  r$  rC   daystarttodayr  r&  rx  entriesr  symbols_strs                        r,   compute_entries_by_dayrv    sG    76F Rq>eeHb!fb!'R..0	eQ,1-C!%%+0q1E !8uz5=UU<$"gsc#RPQ%R(,&&&z2779 HLL&++-E
C
,MMOF?F1Iya  	 ,
 CfkkmT2 +krdii^e fYZAhK=1U8D/1W:cBRRS!T fgx}

W"
 	 JA :& 		  ,q!$))+, !gs*   ">G!' G7 H
!G43G47!HHc           	         t        t              }|D ]  }|j                  dd      }|j                  dd      xs dj                         }	 t	        |j                  dd      xs d      }t	        |j                  dd      xs d      }|dk  s|dk  r|dk(  s||   j                  |||j                  dd      d	        t        d
       }	| D ]  }
|
j                  dd      }t        |
j                  d            }t        |
j                  d            }|r|dk  rQ|j                  |g       }|sd}n+t        |d       }|j                  dd      xs ddd }|sd}|	|   dxx   dz  cc<   |	|   d   j                  | d|dd|dd        g }t        |	j                         d      D ]1  }|	|   }|j                  ||d   dj                  |d         d       3 |S # t
        t        f$ r Y w xY w)u  DEPRECATED dopo v3: contava le posizioni ANCORA APERTE per giorno di entry.
    Usava FIFO su DB orders, ma non vedeva le chiusure automatiche di Bybit TP/SL
    (es. WIF 10765 chiusa da TP ma DB diceva ancora aperto). Sostituita da
    compute_entries_by_day (aperture totali per giorno) che è piu' utile per Mattia.
    Mantenuta per retrocompatibilita' se Mattia la vuole di nuovo.
    r   r/   rP  rR  r   r$  r  rG  )rR  r$  rC   c                      dg dS )Nr   )r  r  r   r   rL   r,   r   z5compute_open_positions_by_entry_day.<locals>.<lambda>)  s    qR!8 rL   r   avgPricezN/Dc                 &    | j                  dd      S )NrC   r/   r.  r  s    r,   r   z5compute_open_positions_by_entry_day.<locals>.<lambda>4  s    quuT2 rL   r   rC   Nr5   r  r   r  rj  rk  rl  rm  rn  Trb  r  rp  )r   rm   r&   r   r  r  r   r  r?  r  r   rd  r  )bybit_positions	db_ordersr  buys_by_symbolr  r]  rP  rR  r$  re  ra  r   	avg_pricebuysrq  last_buyrx  r&  s                     r,   #compute_open_positions_by_entry_dayr    s+    !&N eeHb!fb!'R..0	eQ,1-C!%%+0q1E !8uz5=3&&UeeL"-(  89F Nggh#3776?+
 34	dai!!#r*C4%>?H<<b)/R"5CsCAsI%%RT{!Ic?!&LMN  CfkkmT2 3K

3yy9.
 	 JE :& 		s   >G--H ?H c                 
   t        |       }|D cg c]  }|j                  dd      dkD  s| }}|j                  d d       |d| }i }| D ]N  }|j                  dd      }|j                  d	|j                  dd            }	|	dk  s=||vs	|	||   k  sJ|	||<   P g }
|D ]=  }|j                  d      |v st        |      }||d      |d
<   |
j	                  |       ? |
j                  d        |
d| }||dS c c}w )a\  Top N best (asset con pnl > 0, ordinati per pnl desc) + Top N worst
    (asset che hanno ALMENO 1 singola loss, ordinati per worst_single_loss asc).

    FIX 07/08: prima il 'bad' richiedeva len(by_asset) > top_n, quindi con <= 5 asset
    il worst restava vuoto anche se c'erano loser.
    FIX 07/08 (2): il 'best' filtra solo asset con pnl > 0.
    FIX 07/08 (3): il 'worst' ora include asset che hanno almeno 1 singola loss,
    indipendentemente dal pnl aggregato. Cosi' VIRTUAL (pnl aggregato +18.47) compare
    perche' ha una loss singola da -25.47. Ordinato per worst_single_loss ascendente.
    rX  r   c                 &    | j                  dd      S )NrX  r   r.  r  s    r,   r   z,compute_top_bad_from_bybit.<locals>.<lambda>S  s    quuUA rL   Tr   Nr   r/   rW  worst_single_lossc                 &    | j                  dd      S )Nr  r   r.  r  s    r,   r   z,compute_top_bad_from_bybit.<locals>.<lambda>f  s    !%%(;Q"? rL   r   )topbad)r1  r&   r  r   r  )r  top_nr0  rW   winnersr  asset_worst_lossr  r]  rX  
worst_lista2r  s                r,   compute_top_bad_from_bybitr  E  s6    +=9H":QaeeE1o&9q:G:LL.L=
&5/C  ,eeHb!eeIquuUA/7**c4DS4I.I(+ %, J "55?..aB&6q{&CB"#b!	"
 OO?O@
Ve
Cs##- ;s
   D D c                    | D cg c]*  }|j                  d|j                  dd            dk  s)|, }}|j                  d        g }|d| D ]  }t        |j                  d      xs |j                  d            }|j                  |j                  d	d
      |j                  dd
      |j                  dd      |j                  dd      |j                  dd      |j                  d|j                  dd            |j                  dd      |j                  dd      |r|j	                  d      nd
d	        |S c c}w )zTop N peggiori trade SINGOLI (per pnl_net ascendente).
    FIX 07/08: serve perche' VIRTUAL aggregato e' +18.47 ma ha una singola loss -25.47
    che non comparirebbe mai in 'by_asset' worst. Mostra le singole chiusure peggiori.
    rW  rX  r   c                 F    | j                  d| j                  dd            S )NrW  rX  r   r.  r  s    r,   r   z+compute_top_single_losses.<locals>.<lambda>q  s    aeeIquuUA? rL   r   NrV  rG  r   r/   rP  rR  rT  rn  ro  rp  r5  )	r   rP  rR  rT  rn  rW  ro  rp  date_fmt)r&   r  rF   r  rH   )r  r  r  losersrx  rJ   s         r,   compute_top_single_lossesr  k  s$   
 'PA!%%	155?*Ka*OaPFP
KK?K@
CFU^ QUU<0GAEE,4GH

eeHb)EE&"%55?552%%a0uuYeQ8{A.55?9;$45

 
	 J! Qs
   *EEc           	         | j                         }t        dz  }t        dz  }t        dz  }t        dz  }ddl}ddd	d
dd}g }||||fD ]  }	|	j                         s	 t	        |	dd      5 }
|j                  |
      }|D ]  }|j                  d      s|d   j                         j                         |k(  s:t        |j                  dd            j                         dk(  sg|j                  dd      j                         j                         }|dk(  rd}|j                  |d      }|j                  ||f        	 ddd        |sy|j                  d d       |d   d   S # 1 sw Y   +xY w# t        $ r Y >w xY w)a  Replica la logica di sltp_engine.get_strategy_for_symbol per le 4 strategie v2.
    FIX 11/08 (Mattia): scorre TUTTI i CSV e ritorna lo strategy con priorita' piu' alta.
    Priorita': rsi_swing_breakout > rettangolo_simple > rettangolo > ma_trailing > vptr3.
    Necessario perche' WIFUSDT e' sia in rettangolo_assets.csv (strategy=rettangolo) che
    in RETTANGOLO_SIMPLE_ASSETS.csv (strategy=rsi_swing_breakout), e la versione specifica
    RSI swing deve avere priorita' sulla generica rettangolo.zVPTR_V3_ASSETS.csvzrettangolo_assets.csvzRETTANGOLO_SIMPLE_ASSETS.csvzMA_TRAILING_ASSETS.csvr   Nre  (   r     r5   )r  r  r  r  r  r  rX   rY   r   enabledtruer   r/   r  r  r  c                     | d   S )Nr   r   r  s    r,   r   z)get_strategy_for_symbol.<locals>.<lambda>  s
    !A$ rL   Tr   r   )r  r   csvr   ra   
DictReaderr&   r!   r;   r   r  r'   r  )r   r]  	vptr3_csvrett_csvrett_simple_csvma_csvcsvmodPRIORITYr  csv_pathre   readerr   rD   prios                  r,   r  r    s    ,,.C++I--H;;O,,F !H J/6B  	hg6 9!**1-! 	9C778, 8}**,224;swwy&9:@@BfL #
B 7 = = ? E E GA I~$+#+<<1#5D&--tQi8	99	$ OOO5a=%9 9  		s8   E;-AE/;,E/(AE/E;/E8	4E;;	FFc            	      ~   ddl } t        dz  }|j                         si S 	 t        |dd      5 } | j                  |      }|j                         D ci c]5  \  }}t        |t              s|j                         |j                         7 c}}cddd       S c c}}w # 1 sw Y   yxY w# t        $ r i cY S w xY w)aV  FIX 11/08 (Mattia): per le POSIZIONI LIVE, legge un mapping esplicito
    symbol -> strategy per gestire il mismatch tra CSV e SOURCE Pine.
    Caso tipico: WIF ha chart Pine TV = RSI swing MA le posizioni live sono state
    aperte da Python (SL/TP engine) con strategy=rettangolo. Il CSV dice rsi_swing
    ma la SOURCE reale e' Python/rettangolo. Stessa cosa per AERO (VPTR3 senza SL/TP).
    File: live_deploy_v2/position_strategy_override.json
    Formato: {"WIFUSDT": "rettangolo", "AEROUSDT": "vptr3"}
    Se il symbol non e' nel file, fallback a get_strategy_for_symbol (CSV con priorita').r   Nzposition_strategy_override.jsonr  rX   rY   )rj   r   r   ra   loadr   rl   r;   r  r   r'   )rj   r  re   rn   r*   r+   s         r,   get_position_strategy_overrider    s     33D;;=	$g. 	Y!499Q<D59ZZ\XTQZPQSVEWAGGIqwwy(X	Y 	YX	Y 	Y  	sF   B. &B"B.!BB"	B. B""B+'B. +B. .B<;B<c                 D    	 t        |       d| dS # t        $ r Y yw xY w)Nz,.re   z0.00r  r'   r+   decimalss     r,   ru  ru    s0    (2hZq.)*     	c                 D    	 t        |       d| dS # t        $ r Y yw xY w)Nrr   re   z0.0r  r  s     r,   _fmt_pctr    s0    (1XJa-() r  c                 D    	 | t        |       S |S # t        $ r |cY S w xY wr  r  )r+   r   s     r,   r?  r?    s.    =uQx5g5 s     c                 h   | syt        |       dk(  rt        | d         S t        |       dz
  t        |      z  }t        t        j                  |            }t        t        j
                  |            }||k(  rt        | |         S ||z
  }t        | |         d|z
  z  t        | |         |z  z   S )z<Percentile lineare deterministico, senza dipendenze esterne.r  r   r   rX  )r=   r  r>   r"  floorceil)sorted_values
percentilepositionr   r  weights         r,   _percentiler    s    
=Q]1%&&M"Q&%
*;;H

8$%E		(#$E~]5)**Fu%&#,7%e@T:UX^:^^^rL   c           
      "   	 t        dt        t        t        |                         }t        |d      \  }}t        |d      \  }}t        |d      \  }}|r| d| d| dS |r| d| dS |r| d	| d
S | d
S # t        t
        f$ r Y yw xY w)Nr   ro  iQ i  <   zg zh mzm rD   )r  r>   roundr  r  r   divmod)secondsr  r  	remainderrT  minutessecss          r,   _fmt_durationr    s    As5w012 UE*OD)i.E99b)MGTr%7)1--7)1%%"TF!$$V1: z" s   'A< <BBc                    g }t        t              }g }g }d}| D ]  }t        |j                  d            }t        |j                  d      xs |j                  d            }||||k  r|dz  }Z||z
  j	                         }	|j                  |	       t        |j                  d      xs d      }
||
   j                  |	       t        |j                  d|j                  d	d                  }|dkD  r|j                  |	       |dk  s|j                  |	        t        |      }d
 }g }t        |j                               D ]#  \  }
} ||      }|
|d<   |j                  |       % t        |      ||rt        |      t        |      z  ndt        |d      |r|d   nd|r|d   ndt        |d      t        |d      t        |d       ||       ||      |dS )zIDurata apertura->chiusura per tutti i trade classificati inclusi nei KPI.r   rU  rV  rG  r   r   unknownrW  rX  c                     t        |       } | sddddS t        |       t        |       t        |       z  t        | d      dS )Nr   r  )r  avg_secondsmedian_seconds      ?)r   r=   r  r  )r   s    r,   summaryz-compute_trade_duration_stats.<locals>.summary  sF    scJJ[v;V4)&$7
 	
rL   r  r  r         ?      ?g?)r  missingr  r  min_secondsmax_secondsp25_secondsp75_secondsp90_secondsr  r  by_strategy)r   rm   rF   r&   total_secondsr  r;   r?  r   r   r=   r  r  )r  samplesr  r  r  r  r<  r{  rp  durationr   rX  orderedr  
strategiesr   r   s                    r,   compute_trade_duration_statsr    s   Gd#KGFG $ <!89 <!8!SEIIl<ST>V^vqLGVO224x uyy,9	:H$$X.%))Iuyy/BCD7NN8$1WMM(#$  WoG
 J";#4#4#67  &v#Z$  W6=s7|c'l23%gt4%,wqz#&-wr{3"7D1"7D1"7D17#&/! rL   c                 FF   | d   }| d   }| d   }| d   }| j                  di       }| j                  di       }| j                  di       }| d   d	   }| d   d
   }	| d   }
| d   }| d   }| d   }| j                  dg       }| j                  dg       }t        t        |             }t        t        |             }|rg }|D ]  }|j                  d|j                  dd            }|dkD  rdn|dk  rd
nd}|j	                  d|j                  dd       d|j                  dd       d|j                  dd       d|j                  dd       d| dt        |       d        dt        |       d dj                  |      z   d!z   }nd"}|rg }|D ]  }|j                  d|j                  dd            }|j	                  d|j                  d#d       d|j                  dd       d|j                  dd       d|j                  d$d       d|j                  dd       d|j                  d%d       d&t        |       d        d't        |       d(dj                  |      z   d!z   }nd}d}d}|d)   dk\  rdnd
}|d*   dk\  rdnd
}|d+   dkD  rd,nd}|d-   dk\  rdnd
}|d.   dk\  rdnd
}|d/   d0k\  rdn|d/   d1k  rd
nd}|d2   dk\  rdnd
}|j                  d3d4      }|d5k\  rd} n|d6k\  rd} n
|d7k\  rd} nd
} |d8k  r|d9nd:}!|j                  d;d      }"|j                  d<d      }#|"rd=|" d>nd?}$d4}%d4}&d}'d}(d})d}*|d*   }+|d+   },d,}|d@   }-d
}.|dA   }/|/dk\  rdnd
}0|/|-z   |,z   }1|1dk\  rdnd
}2|j                  dBd      }3|j                  dCd      }4|4dkD  r|3|4z  }5|5d9}6|5d5k\  rd}7n|5d7k\  rd}7nd
}7nd:}6d}7|d-   }8|8dk\  rdnd
}9|/|8z   }:|:dk\  rdnd
};|j                  d<d      xs d}#t        |#dD      }<|j                  dEd      rt        |j                  dEd      |<z  dF      nd}=|j                  dGd      |<z  }>|:|<z  }?|?dk\  rdnd
}@dH}A|?|Az  dIz  }B|Bdk\  rdnd
}Cdj                  g dJt        |dK          dL|dE    dM|$ dN|# dO| dPt        |d/          dQ|dB    dR|dC    dS|7 dP|6 dT|  dP|! dU|2 dPt        |1       dV| dWt        |,       dXt        |-       dY|0 dPt        |/       dZ|9 dPt        |8       d[|; dPt        |:       d\| dPt        |d2          d]t        |d^          d_|d`    da|= dbt        |>       dc|C dPBd9dd@ dPt        |?       det        |df          dg|dh   d9di      }Ddj                  dj |j                  dg       D              }Edk|j                  dld       dm|j                  dnd       dot        |j                  dpd             dqt        |j                  drd             dst        |j                  dtd             dut        |j                  dvd             dwt        |j                  dxd             dut        |j                  dyd             dzt        |j                  d{d             d|t        |j                  d}i       j                  dpd             du|j                  d}i       j                  dld       d~t        |j                  di       j                  dpd             du|j                  di       j                  dld       d|E d}F|d   dkD  r|d   }G|d   }H|G}It        |I      dFk\  rt        I      t        |I      }K}Jt        |K|Jz
  d      }Ld\  }Md}Ng }Ot        |I      D ]Q  \  }P}QN|Pt        I      dDz
  z  MdF|Nz  z
  z  z   }R|Nz
  |QJz
  Lz  dF|Nz  z
  z  z
  }SOj	                  |Rdd|Sd       S dj                  O      }Td}UId   }V|Id   }W|V|Wz
  }X|Wdk7  rXt        W      z  dIz  nd}YXdk\  rdnd}Zd}[t        I      }\t        t        O|I            D ]  \  }]\  }^}_|^j                  d      \  }`}a|]t        H      k  rH]   nd}bd]dDz    }c|brL	 t!        b      }d|ddkD  rddz  }dddlm}em}f |ej'                  d|fj(                        }g|gj+                  d      }c_Id   z
  }h|Id   dk7  rht        Id         z  dIz  nd}idcj/                  dd      j/                  dd      z   dz   }j[d` da dZ d]dDz    d|j d_d9dhd9d|id9d|]dDz    d|c d|_d9dz  }[
 g }kdD ].  }lJ|lLz  z   }mNz
  |ldF|Nz  z
  z  z
  }nkj	                  |m|nf       0 d}od}pkD ]3  \  }m}npdN d|nddM|Nz
   d|ndd	z  }pod|NdFz
   d|ndz   dd|md9dz  }o5 t        G      }q|qdk\  rdqdz  dF|qz  dz  |qdDz
  gnt1        t3        q            }rd}sd}t|rD ]  }uN|ut        qdDz
  dD      z  MdF|Nz  z
  z  z   }R|ut        H      k  rHu   nd}bd}c|brJ	 t!        b      }v|vdkD  rvdz  }vddlm}wm}x |wj'                  v|xj(                        j+                  d      }ctdRddN d|Rdd|Nz
   d	z  }tudk(  rdnuqdDz
  k(  rdnd}y|ydk(  rRdFz   nydk(  rRdFz
  nR}zsd|zdddz    dy dc d	z  }s TdOd   j                  t7        d            d    dNz
   d|N d|Nz
   z   }{LdkD  rNz
  dJz
  Lz  dF|Nz  z
  z  z
  nNz
  }|dj                  g dM ddz    ddz    dp t d{ dZ dN d||dd|M|Nz
   d||ddT d|Z d[ dOd   j                  t7        d            d    d|Od   j                  t7        d            dD    d|Z do s dId   dÛdđ|Z dőVdÛdƑYdÛdǑt        |I       dȑ|Z dɑ      }}nGd   }Qd|Qd9d˝}}t9        j:                  |      }~nd}}t9        j:                  g g g d4d4d͜      }~|rg }g }d΄ }|D ]  }|d   dk\  rdnd
}t5        d         }dj                  dЄ |D              }d| }j	                  d| d |       d|d    d|dB    dt        |d/          dt        |d          dt        |d          d| dt        |d          d       g }|j                  |g       D ]  }|d   dk\  rdnd
}j	                  d |d          d ||d          d ||d          d ||d          d|d   dd|d   dd|d   ddt        |d          dt        |d          d| dt        |d          d ||d          d        ddj                        z   d!z   }j	                  d d        dd    d|dB    dR|d   |dB   z
   dt        |d/          dt        |d          dt        |d          d dt        |d          d| d        t=        d |D              }t=        d |D              }|rz  dIz  nd4}t=        d |D              }t=        d |D              }t=        d |D              }|dk\  rdnd
}dk\  rdnd
}j	                  d d dt               d dt               dt               d| dt               d       ddj                  |      z   dz   dj                        z   }nd}|rg }|D ]  }|d   }q|j                  dd4      }|j                  d d4      }|d   }|dk7  r!j/                  dd      j?                         nd}qdFk\  rWd7k\  rdndk  rd
nd}d6k\  rdndk  rd
nd}d}d}d dq ddB    d|q|dB   z
   d|d/   dd	|d   d9d
}ndx}}dx}}d dq d}j	                  d d dq d d d d d        ddj                         d}nd}|r7g }g }d }|D ]  }|d   dk\  rdnd
}t5        d         jA                         }dj                  d |D              }d| }j	                  d| d |       d|d    d|dB    dt        |d/          dt        |d          dt        |d          d| dt        |d          d       g }|j                  |g       D ]  }|d   dk\  rdnd
}j	                  d |d          d ||d          d ||d          d ||d          d|d   dd|d   dd|d   ddt        |d          dt        |d          d| dt        |d          d ||d          d        ddj                        z   d!z   }j	                  d d        dd    d|dB    dR|d   |dB   z
   dt        |d/          dt        |d          dt        |d          d dt        |d          d| d        ddj                        z   dz   dj                        z   }nd}d  } ||d      } ||	d
      }| j                  d!g       }|rg }D ]  }j	                  d|j                  d"d       d|j                  dd       d|j                  d#d       d|j                  dd      d$d|j                  d%d      d&d|j                  d'd      d&d(|j                  dd      d9d)|j                  dd      d9d*        d+dj                        z   dz   }nd,}| j                  d-g       }|rkg }d}D ]2  }|d   z  }j	                  d|d.    d/|d    d0|d1    d       4 j	                  d2 d3       d4dj                  |      z   dz   }nd5}|
j                  d6t3        d7      D cg c]	  }dgd8z   c}      |
j                  d9t3        d7      D cg c]	  }dgd8z   c}      |
j                  d:t3        d7      D cg c]	  }d4gd8z   c}      |
j                  d;t3        d7      D cg c]	  }d4gd8z   c}      |
j                  d<t3        d7      D cg c]	  }d4gd8z   c}      t3        d7      D cg c]-  }t3        d8      D cg c]  }   |   |   |   z    c}/ c}}d=}tC        d> D              rΐrt        d? D              ndD}t        |dD      }g }d@g}|
dA   D ]  j	                  dBdCdD        j	                  dEdj                        z   dFz          t        |
dG         D ]  \  }}dH| dIg}t3        d8      D ]h        }M|      }|Mdk(  rdk(  rj	                  dJ       3dkD  rMz  nd}dkD  rz  nd}tE        dKd0z  z         }tE        dLdM|z  z         }tE        dNdO|z  z         }dP| d| d| d>}tE        dKdQ|z  z         }tE        dLdR|z  z         }tE        dNd0|z  z         }dP| d| d| d>} ddCdSM dT }|dk(  r!j	                  dU dV dWM dX       Mdk(  r!j	                  dU dV dY dX       2dZ d[| d\ d\| d]	}j	                  d^| dV dWM d_ dX	       k j	                  dEdj                        z   dFz           d`}dadj                        z   d!z   |z   }db g }t        |
dG         D ]r  \  }}t=        |         }q|qsj	                  qt=                 t=        |         t=        |         t=        |         t=        |         dc       t g }t3        d8      D ]  t=        fddt3        d7      D              }q|qs'j	                  dCdeqt=        fdft3        d7      D              t=        fdgt3        d7      D              t=        fdht3        d7      D              t=        fdit3        d7      D              t=        fdjt3        d7      D              dc        t        Ðdk l      }t        |Ðdm l      }t        Đdn l      }t        |Đdo l      }Ȑdp|Ődq    drt        |d          ds|Ɛdq    dtt        |d          du|ǐdq    drt        |d          dv|Ȑdq    dtt        |d          dw}ɐdx}dj                  fdy|D              }dj                  fdz|D              }|ɐd{z   |z   |z   d|z   |z   |z   d}z   }nd~}| j                  dg       }|͐rKg }D ]r  }|d   dk\  rdnd
}j	                  dd.    d|d    d|dB    d|d/   ddt        |d          dt        |d          d| dt        |d          d|d1    d       t t=        d D              }t=        d |D              }t=        d |D              }t=        d |D              }t=        d |D              }|rz  dIz  nd}dk\  rdnd
}j	                  dћ dқ dddt        Ϋ       dt        ϫ       d|ԛ dt        Ы       d       ddj                  |      z   dz   }nd}Րd}͐rPt        ͫ      dDk\  rAtG        ͐d l      }t        |׫      }|D cg c]  }|d   	 }}g }d4}|D ]  }Q|Qz  }j	                  |۫        t        t        ٫      d      }t        t        |٫      d      }t        ||z
  d      }||ސdz  z   }||ސdz  z
  }||z
  }t        t        ګ      d      }t        t        |ګ      d      }t        ||z
  d      }||dz  z   }||dz  z
  }||z
  }d\  }Md\  }}}}|M|z
  |z
  }쉭|z
  |z
  }g }dDkD  r.t3        ث      D ]  }Pj	                  |PdDz
  z  z  z          ! nj	                  dFz  z          t        t        dD      z  dz  dF      }d}t        t        ٫            D ]a  \  }P\  }}dDt        |d      z
  z  z
  z  z   }|dDt        |d      |z
  |z  z
  |z  z   }|dDd|z
  |z  z
  |z  z   }|dk\  r}}d}Zn}}d}Zc g }t        t        ګ            D ]1  \  }P\  }}dD|z
  z  z
  z  z   }Sj	                  |dd|Sd       3 dj                        }g }t        t        ٫            D ]1  \  }P\  }}dD|z
  z  z
  z  z   }Sj	                  |dd|Sd       3 dj                        }g }dD ](  }l|lz  z   }mdD|lz
  z  z   }nj	                  |m|nf       * d}d}pD ]5  \  }m}npd d|nddMz
   d|ndd	z  }pd|dz
   d|ndz   dd|mdÛdz  }7 g }dD ](  }l|lz  z   }mdD|lz
  z  z   }nj	                  |m|nf       * d} D ]#  \  }m}n dMz
  dz    d|ndz   dd|mdÛdz  } % d}sdkD  r)t        dDؐdz        }t1        t3        d|ؐ|            }rnt1        t3        ث            }rrD ]0  }u|uk  s	u   }Rsd|Rddz
  dz    d|u   d.   dd   dz  }s2 rd   j                  d      nddg}dM d d dp d d d|d    d|dD    d   s d؛ dd   dÛd}|rg }|D ]  }|d   dk\  rdnd
}j	                  dd    d/|d    d|d#   jI                          d|d#    d|d    d|d    d|d    d|d    d| d|d    d|d    d        ddj                        z   dz   }nd}|r5g }|D ]  }|j                  d      rdnd}j                  dd      }|j                  dd      }|j                  d|j                  dd            }	|	dkD  rdn		dk  rd
nd}
j	                  dd    d|d    d|d#    d|d#    d|d    d|d     d|d    d|d    dt               dt               d|
 dt        	       d*        r(dt               ddj                  |      z   dz   }n	d}nd}dj                  g d| d| d| d| d| dD dF d} d d d d d dÑ dđ՛ dő֛ dƑ dǑ      }|S # t,        $ r brbd d nd]dDz    }cY w xY w# t,        $ r t5        b      d d }cY #w xY wc c}w c c}w c c}w c c}w c c}w c c}w c c}}w c c}w (  Nkpisr  r  r0  r   strategy_trade_detailstrade_duration_statstop_badr  r  heatmapr  recent_ordersgenerated_atr   operational_exclusionsrW  rX  r   goodr/   <tr><td>rV  	</td><td>r   r   rY  z</td><td class='pnl '> USDT</td></tr>zC<div class='classification-alert'><b>CLASSIFICAZIONE BLOCCATA:</b> z trade senza prova univoca. Sono inclusi nel PnL totale, ma esclusi dalle statistiche per strategia.<table><tr><th>Chiusura</th><th>Asset</th><th>Order ID</th><th>Motivo</th><th>Net</th></tr>z</table></div>z{<div class='classification-ok'><b>CLASSIFICAZIONE CERTIFICATA:</b> tutti i trade inclusi hanno una strategia provata.</div>rU  r  rZ  z</td><td class='pnl bad'>zB<div class='classification-alert'><b>TRADE OPERATIVI ESCLUSI:</b> z ingresso successivo al blocco asset. Visibile per audit, escluso da KPI, equity e classifiche.<table><tr><th>Entrata</th><th>Chiusura</th><th>Asset</th><th>Entry order ID</th><th>Close order ID</th><th>Motivo</th><th>Net</th></tr>r  r  r  r  r  r  r  re  r  r  r  r  g       @g      ?rX  c   z.2fu   ∞r  r  zTrading days (dal rn  zTrading daysr  r  r  r  r   r  ru   r  g     @@rm  zO
  <div class="kpi"><div class="kpi-label">Balance</div><div class="kpi-value">r  ze USDT</div></div>
  <div class="kpi"><div class="kpi-label">Trade chiusi</div><div class="kpi-value">z7</div></div>
  <div class="kpi"><div class="kpi-label">z</div><div class="kpi-value">z[</div></div>
  <div class="kpi"><div class="kpi-label">Win rate</div><div class="kpi-value ">zB%<br><small style="color:#8b949e;font-size:11px;font-weight:400;">W / zgL</small></div></div>
  <div class="kpi"><div class="kpi-label">Win to Loss</div><div class="kpi-value z`</div></div>
  <div class="kpi"><div class="kpi-label">Profit Factor</div><div class="kpi-value ze</div></div>
  <div class="kpi"><div class="kpi-label">Gross PnL (chiusi)</div><div class="kpi-value zb USDT</div></div>
  <div class="kpi"><div class="kpi-label">Fee totali</div><div class="kpi-value z">-zh USDT</div></div>
  <div class="kpi"><div class="kpi-label">Loss chiuse</div><div class="kpi-value bad">zu USDT</div></div>
  <div class="kpi"><div class="kpi-label">P&L Realized (Gross-Loss-Fee)</div><div class="kpi-value zf USDT</div></div>
  <div class="kpi"><div class="kpi-label">Unrealized PnL</div><div class="kpi-value zu USDT</div></div>
  <div class="kpi"><div class="kpi-label">Net P&L (Realized-Unrealized)</div><div class="kpi-value za USDT</div></div>
  <div class="kpi"><div class="kpi-label">Avg trade</div><div class="kpi-value zh USDT</div></div>
  <div class="kpi"><div class="kpi-label">Best trade</div><div class="kpi-value good">r  zi USDT</div></div>
  <div class="kpi"><div class="kpi-label">Posizioni aperte</div><div class="kpi-value">r  zc</div></div>
  <div class="kpi"><div class="kpi-label">Trade al giorno</div><div class="kpi-value">zj</div></div>
  <div class="kpi"><div class="kpi-label">Nozionale Bybit/giorno</div><div class="kpi-value">zd USDT</div></div>
  <div class="kpi"><div class="kpi-label">Day Profit %</div><div class="kpi-value za%/gg</div></div>
  <div class="kpi"><div class="kpi-label">Day Profit</div><div class="kpi-value zm USDT/gg</div></div>
  <div class="kpi"><div class="kpi-label">Drawdown real</div><div class="kpi-value bad">r  z	 USDT<br>r  z%</div></div>
c              3      K   | ]?  }d |d   j                          d|d    dt        |d          dt        |d          d	 A yw)	<tr><td><b>r   </b></td><td>r  r  r  r  
</td></tr>N)r  r  r  r   s     r,   r	  z#render_dashboard.<locals>.<genexpr>  sj      %  c*o++-.mCL> JS/01 2S!1234J	@%s   AAzZ
<div class="duration-grid">
  <div class="duration-card"><span>Trade analizzati</span><b>r  z</b><small>Mancanti: r  zH</small></div>
  <div class="duration-card"><span>Durata media</span><b>r  z?</b></div>
  <div class="duration-card"><span>Mediana</span><b>r  zA</b></div>
  <div class="duration-card"><span>Min / Max</span><b>r  z</b><small>r  zE</small></div>
  <div class="duration-card"><span>P25 / P75</span><b>r  r  z?</small></div>
  <div class="duration-card"><span>P90</span><b>r  uU   </b></div>
  <div class="duration-card good-border"><span>Vincenti · media</span><b>r  u^    trade</small></div>
  <div class="duration-card bad-border"><span>Perdenti · media</span><b>r  z trade</small></div>
</div>
<table class="duration-table"><tr><th>Strategia</th><th>Trade</th><th>Media</th><th>Mediana</th></tr>z	</table>
r  r  rY  )i      r5   .1fr    r   z#3fb950z#f85149r   g   mBr6   r   r7   z%d/%m %H:%M   r   \z\\z\'z<circle class="eq-pt" cx="z" cy="z0" r="4" fill="#fff" fill-opacity="0.95" stroke="zJ" stroke-width="1.5" style="cursor:pointer" onmouseover="eqShowTip(event, r  zI)" onmousemove="eqMoveTip(event)" onmouseout="eqHideTip()"><title>Trade #z | z | PnL cum: z USDT</title></circle>
    )r  r  r  r  rX  z
<line x1="z" y1="z" x2="z" y2="z*" stroke="#21262d" stroke-width="1"/>
    z	<text x="z" y="   z\" text-anchor="end" font-size="11" fill="#c9d1d9" font-family="monospace" font-weight="600">z</text>
    r   zA" stroke="#21262d" stroke-width="1" stroke-dasharray="2,3"/>
    rr  endmiddler   z" text-anchor="zJ" font-size="11" fill="#c9d1d9" font-family="monospace" font-weight="600">,   zU<div style="background:#0d1117;padding:10px;border-radius:6px;">
  <svg viewBox="0 0    z>" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:z
px;">
    z<polygon points="z" fill="z&" fill-opacity="0.12"/>
    <line x1="zc" stroke="#8b949e" stroke-width="0.5" stroke-dasharray="2,2" opacity="0.5"/>
    <polyline points="z" fill="none" stroke="z" stroke-width="2"/>
    z
    <circle cx="z" r="4" fill="z"/>
    z
  </svg>
  <div style="display:flex;justify-content:space-between;font-size:11px;color:#8b949e;margin-top:4px;">
    <span>Start: z+.2fz$ USDT</span>
    <span style="color:z;font-weight:600;">End: z USDT (z%)</span>
  </div>
  <div style="display:flex;justify-content:space-between;align-items:center;font-size:11px;color:#8b949e;margin-top:2px;">
    <span>z trade chiusi</span>
    <span style="display:flex;gap:8px;align-items:center;">
      <span style="display:flex;align-items:center;gap:4px;"><span style="display:inline-block;width:16px;height:2px;background:a  ;"></span>Equity</span>
    </span>
  </div>
  <script>
  (function() {
    if (window._eqTipLoaded) return;
    window._eqTipLoaded = true;
    var t = document.createElement('div');
    t.id = 'eq-tooltip';
    t.style.cssText = 'display:none;position:absolute;background:#161b22;border:1px solid #30363d;color:#fff;padding:10px 14px;border-radius:6px;font-size:13px;pointer-events:none;z-index:10000;box-shadow:0 4px 12px rgba(0,0,0,0.5);font-family:monospace;line-height:1.5;';
    document.body.appendChild(t);
  })();
  function eqShowTip(e, n, date, eq, delta, deltaPct) {
    var t = document.getElementById('eq-tooltip');
    if (!t) return;
    var sign = delta >= 0 ? '+' : '';
    var pctSign = deltaPct >= 0 ? '+' : '';
    var color = delta >= 0 ? '#3fb950' : '#f85149';
    t.innerHTML = '<div style="font-weight:700;color:#fff;margin-bottom:4px;">Trade #' + n + '</div>' +
      '<div style="color:#8b949e;">Data: <span style="color:#c9d1d9;">' + date + '</span></div>' +
      '<div style="color:#8b949e;">Equity: <span style="color:#fff;font-weight:600;">' + eq.toFixed(2) + ' USDT</span></div>' +
      '<div style="color:#8b949e;">Delta: <span style="color:' + color + ';font-weight:600;">' + sign + delta.toFixed(2) + ' USDT (' + pctSign + deltaPct.toFixed(2) + '%)</span></div>';
    t.style.display = 'block';
    eqMoveTip(e);
  }
  function eqMoveTip(e) {
    var t = document.getElementById('eq-tooltip');
    if (t && t.style.display === 'block') {
      t.style.left = (e.pageX + 14) + 'px';
      t.style.top = (e.pageY + 14) + 'px';
    }
  }
  function eqHideTip() {
    var t = document.getElementById('eq-tooltip');
    if (t) t.style.display = 'none';
  }
  </script>
</div>zy<div style="background:#0d1117;padding:20px;border-radius:6px;text-align:center;color:#8b949e;">1 trade chiuso: equity = z USDT</div>uc   <div class="empty">Nessun trade chiuso dal 1° agosto. Aspetto chiusure Pine (Max exit bars).</div>)r  r  r  r  r  c                 T    t        d      j                  t        | | nd      d      S Nre  r/   Trc  ru  rf  r;   rg  s    r,   r   z"render_dashboard.<locals>.<lambda>	  s)    Z%7%>%>sEL]5ce?fnr%>%s rL   r   c              3   B   K   | ]  }|j                         s|  y wr  isalnumr  chs     r,   r	  z#render_dashboard.<locals>.<genexpr>	  s     #J2RZZ\B#J   zstrategy-detail-zA<tr><td><button type='button' class='strategy-link' data-dialog='z</button></td><td>r  rj  zW)</td><td>z%</td><td class='pnl good'>ro  z</td><td class='pnl warn'>-r  r:  r  r6  r7  rR  ,.4frz  z,.6fr8  r9  z</td><td class='warn'>-rp  z</td><td><small>z</small></td></tr>z<div class='asset-detail-scroll'><table><tr><th>Apertura</th><th>Chiusura</th><th>Asset</th><th>Direzione</th><th>Qty</th><th>Entry</th><th>Exit</th><th>Gross</th><th>Fee</th><th>Net</th><th>Close Order ID</th></tr>z<dialog id='zq' class='asset-dialog strategy-dialog'><div class='asset-dialog-head'><div><small>DETTAGLIO STRATEGIA</small><h2>z</h2></div><button type='button' class='dialog-close' aria-label='Chiudi' data-close-dialog>x</button></div><div class='asset-dialog-summary'><span>z trade</span><span>zL</span><span>WR z%</span><span>Gross z USDT</span><span>Fee -z USDT</span><strong class='z'>Net z USDT</strong></div>z	</dialog>c              3   &   K   | ]	  }|d      ywr  Nr   r  rD   s     r,   r	  z#render_dashboard.<locals>.<genexpr>	  s     2af2r  c              3   &   K   | ]	  }|d      ywr  Nr   r  s     r,   r	  z#render_dashboard.<locals>.<genexpr>	       8q68r  c              3   &   K   | ]	  }|d      ywro  Nr   r  s     r,   r	  z#render_dashboard.<locals>.<genexpr>	  s     >Q!K.>r  c              3   &   K   | ]	  }|d      ywr  Nr   r  s     r,   r	  z#render_dashboard.<locals>.<genexpr>	  r  r  c              3   &   K   | ]	  }|d      ywr  r   r  s     r,   r	  z#render_dashboard.<locals>.<genexpr>	  s     6Q%6r  zM<tr style='border-top:2px solid #58a6ff;font-weight:700;'><td>TOTALE</td><td>z%</td><td class='pnl zb<table><tr><th>Strategia</th><th>Trades</th><th>WR</th><th>Gross</th><th>Fee</th><th>Net</th></tr></table>z[<div class="empty">Nessun trade chiuso ancora. Aspetto chiusure Pine (Max exit bars).</div>r  r  r  r\  Unknownz.3fzStrategia: z
Trade: zW/zL)
WR: z%
Net: z USDT
Sharpe: mean/std (rf=0) - &gt;=1 buono, &lt;0 in perdita
Sortino: mean/downside_dev (rf=0) - &gt;=1.5 buono, &lt;0 in perditazn/az< trade: servono almeno 2 trade per calcolare Sharpe/Sortino)z<div class="kpi" title="z"><div class="kpi-label">zt)</div><div class="kpi-value z" style="font-size:18px;">Sh: z</div><div class="kpi-value z-" style="font-size:13px;margin-top:2px;">So: z</div></div>z<div class="kpi-grid">r~  zw<div class="empty">Nessun trade chiuso ancora. Servono almeno 2 trade per strategia per calcolare Sharpe/Sortino.</div>c                 T    t        d      j                  t        | | nd      d      S r  r  rg  s    r,   r   z"render_dashboard.<locals>.<lambda> 
  s)    *V"4";";CIZ`b<cko";"p rL   c              3   B   K   | ]  }|j                         s|  y wr  r  r  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     !F"!Fr  zasset-detail-z><tr><td><button type='button' class='asset-link' data-dialog='z<div class='asset-detail-scroll'><table><tr><th>Apertura</th><th>Chiusura</th><th>Strategia</th><th>Direzione</th><th>Qty</th><th>Entry</th><th>Exit</th><th>Gross</th><th>Fee</th><th>Net</th><th>Close Order ID</th></tr>z]' class='asset-dialog'><div class='asset-dialog-head'><div><small>DETTAGLIO ASSET</small><h2>u   </h2></div><button type='button' class='dialog-close' aria-label='Chiudi' data-close-dialog>×</button></div><div class='asset-dialog-summary'><span>z_<table><tr><th>Symbol</th><th>Trades</th><th>WR</th><th>Gross</th><th>Fee</th><th>Net</th></tr>3<div class="empty">Nessun trade chiuso ancora</div>c                    | syg }| D ]  }|j                  dd      }|j                  d      }|dk(  r5|3d}dt        |       dt        |       d}d	| d
| dt        |       d}n"|dkD  rdn|dk  rdnd}	d	|	 dt        |       d}|j                  d|d    d|d    dt        |d          d| d	        ddj	                  |      z   dz   S )a<  FIX 07/08: colore PnL DINAMICO basato sul segno (verde se >0, rosso se <0).
        cls_color indica sezione ('best' o 'worst'). Per Worst, se l'item ha
        'worst_single_loss', mostra quella al posto del pnl aggregato (perche'
        un asset puo' avere pnl aggregato positivo ma loss singola grossa).
        r  rX  r   r  r  ztitle="Worst single: z USDT | PnL aggregato: z USDT"z<td class="pnl z" rk  z
 USDT</td>r  r/   r  r  r   r  r  r  z%</td></tr>zE<table><tr><th>Symbol</th><th>Trades</th><th>WR</th><th>PnL</th></tr>r  )r&   ru  r  r  r  )
r   	cls_colorr6  rW   r  wslwsl_clstitlepnl_cellrow_clss
             r,   
_top_tablez$render_dashboard.<locals>._top_table,
  s!    H 	yAeQA%%+,CE!co030@@WXabcXdWeelm,WIRwa	#?OzZ %&E&QB,WIR	!~ZPKK(1X;-y3	(STU^S_J`Iaaghpgqqvwx	y WY[Y`Y`aeYffisssrL   single_lossesr  rP  ,.2frT  ,.5frn  z</td><td class="pnl bad">z  USDT</td><td class="pnl warn">-r  z|<table><tr><th>Data</th><th>Symbol</th><th>Side</th><th>Qty</th><th>Entry</th><th>Exit</th><th>Net PnL</th><th>Fee</th></tr>z><div class="empty">Nessuna singola loss. Vai tranquillo.</div>open_by_dayrc  z</td><td><b>z</b></td><td><small>r  zM<tr style="border-top:2px solid #58a6ff;font-weight:600;"><td>TOTALE</td><td>uL   </td><td><small>aperture totali (entry Buy) dal 1° agosto</small></td></tr>zS<table><tr><th>Data Entry</th><th>N. Aperture</th><th>Symbols (qty@price)</th></tr>z5<div class="empty">Nessuna apertura registrata.</div>rU  rK  rL  rV  rW  rX  rY  z;<div class="empty">Nessun dato statistico giorno/ora.</div>c              3   8   K   | ]  }t        |      d kD    yw)r   N)r  r  s     r,   r	  z#render_dashboard.<locals>.<genexpr>h
  s     
.C3s8a<
.s   c              3   2   K   | ]  }t        |        y wr  )r  r  s     r,   r	  z#render_dashboard.<locals>.<genexpr>j
  s     7SC7s   z'<th class='hm-corner'>Giorno / Ora</th>rT  z<th class='hm-h'>02dz:00</th>z<tr>r  r  z<th class='hm-d'>z</th>z5<td class="hm-c hm-empty" title="Nessun trade">-</td>            9   zrgb(   @   z
:00 - Win z, Loss z#<td class="hm-c" style="background:z
;" title="z"><span class="hm-win">W z</span></td>z"><span class="hm-loss">L zlinear-gradient(to right, z 0%, z 50%, z 100%)z,<td class="hm-c hm-mixed" style="background:z</span><span class="hm-loss">L z<div class="hm-legend"><span><i class="hm-key hm-key-win"></i>W = trade positivi</span><span><i class="hm-key hm-key-loss"></i>L = trade negativi</span><span>Scorrere orizzontalmente per tutte le 24 ore</span></div>z)<div class='hm-scroll'><table class='hm'>c                     |r||z  dz  nd}|r||z  nd}|dk\  rdnd}	d|  d| d| d	| d
|ddt        |       dt        |       d|	 dt        |       d|	 dt        |       dS )Nrm  r  r   r  r  r  r  r  r  z
L</td><td>r  z
%</td><td>z USDT</td><td class='warn'>-z USDT</td><td class='pnl r  r  )ru  )
labelr  r  r  r9  r  r:  r'  avgclss
             r,   _period_rowz%render_dashboard.<locals>._period_row
  s    %&$(S.CB 37cC1H&%C!%aS	$tF8 Tc(*Yu-=,> ?))24(9 :&&)U"Ys^,< =&&)U"Ys^,<O	M NrL   )r)  r  r  r  r9  r  r:  c              3   .   K   | ]  }|        y wr  r   )r  r&  h
matrix_tots     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     7JqM!$7r  z:00c              3   .   K   | ]  }|        y wr  r   )r  r&  r.  rU  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     A1AAr  c              3   .   K   | ]  }|        y wr  r   )r  r&  r.  rV  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     PrdeQYZ[Q\]^Q_Prr  c              3   .   K   | ]  }|        y wr  r   )r  r&  r.  rW  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s      Fa!3 Fr  c              3   .   K   | ]  }|        y wr  r   )r  r&  r.  rX  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     SxjkT_`aTbcdTeSxr  c              3   .   K   | ]  }|        y wr  r   )r  r&  r.  rY  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     BAz!}Q/Br  c                     | d   S Nr:  r   r  s    r,   r   z"render_dashboard.<locals>.<lambda>
  s
    % rL   r   c                     | d   S r6  r   r  s    r,   r   z"render_dashboard.<locals>.<lambda>
  s
    5 rL   c                     | d   S r6  r   r  s    r,   r   z"render_dashboard.<locals>.<lambda>
  s
    !E( rL   c                     | d   S r6  r   r  s    r,   r   z"render_dashboard.<locals>.<lambda>
  s
    1U8 rL   zE<div class="period-highlights"><div><small>GIORNO MIGLIORE</small><b>r)  z</b><span class="good">z8 USDT</span></div><div><small>GIORNO PEGGIORE</small><b>z</b><span class="bad">z5 USDT</span></div><div><small>ORA MIGLIORE</small><b>z5 USDT</span></div><div><small>ORA PEGGIORE</small><b>z USDT</span></div></div>zx<tr><th>Periodo</th><th>Trade</th><th>W/L</th><th>WR</th><th>Gross</th><th>Fee</th><th>Net</th><th>Media/trade</th></tr>c              3   .   K   | ]  } di |  y wNr   r   r  r   r,  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     C#;--Cr  c              3   .   K   | ]  } di |  y wr;  r   r<  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     E3K.#.Er  zn<div class="period-tables"><div><h3>Risultati per giorno della settimana</h3><div class="table-scroll"><table>z`</table></div></div><div><h3>Risultati per ora di chiusura</h3><div class="table-scroll"><table>z</table></div></div></div>zD<div class="empty">Nessun dato heatmap. Aspetto chiusure Pine.</div>trades_by_dayz USDT</td><td><small>c              3   &   K   | ]	  }|d      ywr  r   r  r&  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     ?1+?r  c              3   &   K   | ]	  }|d      ywr
  r   r@  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
       9Qqy9r  c              3   &   K   | ]	  }|d      yw)rW  Nr   r@  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     ;qa	l;r  c              3   &   K   | ]	  }|d      ywr  r   r@  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  s     3qAcF3r  c              3   &   K   | ]	  }|d      ywr  r   r@  s     r,   r	  z#render_dashboard.<locals>.<genexpr>
  rB  r  zM<tr style='border-top:2px solid #58a6ff;font-weight:600;'><td>TOTALE</td><td>z USDT</td><td></td></tr>zm<table><tr><th>Data</th><th>Trades</th><th>WR</th><th>Gross</th><th>Fee</th><th>Net</th><th>Simboli</th></tr>u<   <div class="empty">Nessun trade chiuso dal 1° agosto.</div>z@<div class="empty">Nessun dato giornaliero per il grafico.</div>c                     | d   S )Nrc  r   )r&  s    r,   r   z"render_dashboard.<locals>.<lambda>
  s
    1V9 rL   g?)i  i  )r  r  r5   #   g333333?   z\" text-anchor="end" font-size="10" fill="#3fb950" font-family="monospace" font-weight="600">z^" text-anchor="start" font-size="10" fill="#58a6ff" font-family="monospace" font-weight="600">r      z_" text-anchor="middle" font-size="10" fill="#8b949e" font-family="monospace" font-weight="600">0z
    <polyline points="zW" fill="none" stroke="#3fb950" stroke-width="2" opacity="0.85"/>
    <polyline points="zD" fill="none" stroke="#58a6ff" stroke-width="2.5"/>
    <circle cx="z" r="4" fill="#58a6ff"/>
    z
  </svg>
  <div style="display:flex;justify-content:space-between;align-items:center;font-size:11px;color:#8b949e;margin-top:4px;">
    <span>a   giorni di trading</span>
    <span style="display:flex;gap:14px;align-items:center;">
      <span style="display:flex;align-items:center;gap:4px;"><span style="display:inline-block;width:14px;height:2px;background:#3fb950;"></span>Daily PnL (asse sx)</span>
      <span style="display:flex;align-items:center;gap:4px;"><span style="display:inline-block;width:14px;height:2px;background:#58a6ff;"></span>Cumulativo (asse dx): <b style="color:#58a6ff;">z, USDT</b></span>
    </span>
  </div>
</div>z </b></td><td><span class='badge z</span></td><td>size_fmt	entry_fmtmark_fmtsl_fmtpnl_fmtz USDT</td><td>levzx</td></tr>z<table><tr><th>Symbol</th><th>Strategia</th><th>Side</th><th>Size</th><th>Entry</th><th>Mark</th><th>SL</th><th>PnL</th><th>Lev</th></tr>z1<div class="empty">Nessuna posizione aperta</div>r  u    ⚠️placeholdercreated_at_fmtz</td><td><span class='badge qty_fmt	price_fmtnotional_fmtz</td><td class='pnl good'>a  <table><tr><th>Quando</th><th>Symbol</th><th>Side</th><th>Qty</th><th>Price</th><th>Notional</th><th>Strategy</th><th>Gross</th><th>Fee</th><th>Net</th></tr><tr><td colspan='10' style='text-align:center;color:#6e7681;font-size:11px;padding:4px;'>Trade chiusi Bybit (no miei test). z trade mostrati.</td></tr>zC<div class="empty">Nessun trade chiuso reale (solo miei test)</div>z,<div class="empty">Nessun trade chiuso</div>u4  <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>v2 Stats Dashboard — 2° Account</title>
<meta http-equiv="refresh" content="30">
<!-- Plotly rimosso: tutto render server-side -->
<style>
* { box-sizing: border-box; }
body { background: #0d1117; color: #c9d1d9; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; margin: 0; padding: 20px; }
h1 { color: #58a6ff; margin: 0 0 8px 0; }
h2 { color: #58a6ff; margin: 20px 0 10px 0; font-size: 16px; }
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; margin-bottom: 20px; }
.kpi { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 12px 14px; }
.kpi-label { color: #8b949e; font-size: 11px; text-transform: uppercase; margin-bottom: 4px; }
.kpi-value { color: #f0f6fc; font-size: 22px; font-weight: 600; }
.kpi-value.good { color: #3fb950; }
.kpi-value.bad { color: #f85149; }
.duration-grid {display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:14px;}
.duration-card {background:#0d1117;border:1px solid #30363d;border-radius:8px;padding:12px 14px;display:flex;flex-direction:column;gap:4px;}
.duration-card span {color:#8b949e;font-size:11px;text-transform:uppercase;}
.duration-card b {color:#f0f6fc;font-size:20px;}
.duration-card small {color:#8b949e;font-size:11px;}
.duration-card.good-border {border-color:#238636;} .duration-card.bad-border {border-color:#da3633;}
.duration-table {margin-top:6px;}
.section { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 20px; margin-bottom: 20px; }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 8px 12px; border-bottom: 1px solid #21262d; }
th { color: #8b949e; font-size: 11px; text-transform: uppercase; font-weight: 600; }
tr.good td.pnl { color: #3fb950; }
tr.bad td.pnl { color: #f85149; }
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.badge.buy { background: rgba(63, 185, 80, 0.2); color: #3fb950; }
.badge.sell { background: rgba(248, 81, 73, 0.2); color: #f85149; }
.classification-alert { background:#2d1717; border:1px solid #f85149; color:#ffb3ad; border-radius:6px; padding:12px; margin:12px 0 20px; }
.classification-ok { background:#13251a; border:1px solid #3fb950; color:#8fe39d; border-radius:6px; padding:12px; margin:12px 0 20px; }
.empty { color: #6e7681; text-align: center; padding: 30px; font-style: italic; }
.footer { text-align: center; color: #6e7681; font-size: 12px; margin-top: 30px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.hm-scroll {overflow-x:auto;border:1px solid #30363d;border-radius:4px;background:#0d1117;}
table.hm {border-collapse:separate;border-spacing:2px;font-size:11px;min-width:1240px;width:100%;padding:4px;}
table.hm th,table.hm td {text-align:center;height:34px;border-radius:3px;white-space:nowrap;}
table.hm th {background:#161b22;color:#c9d1d9;font-weight:700;}
table.hm .hm-corner {position:sticky;left:0;z-index:3;min-width:90px;border-right:1px solid #30363d;}
table.hm .hm-d {position:sticky;left:0;z-index:2;min-width:90px;border-right:1px solid #30363d;color:#f0f6fc;}
table.hm .hm-h {min-width:42px;font-size:10px;color:#8b949e;}
table.hm .hm-c {min-width:42px;color:#fff;font-weight:700;text-shadow:0 1px 2px #000;}
table.hm .hm-empty {background:#11161d;color:#484f58;text-shadow:none;font-weight:400;}
table.hm .hm-mixed {display:table-cell;}
.hm-win,.hm-loss {display:inline-block;padding:2px 3px;}
.hm-mixed .hm-win,.hm-mixed .hm-loss {width:50%;padding:0;}
.hm-legend {display:flex;gap:18px;flex-wrap:wrap;margin-top:10px;font-size:12px;color:#8b949e;align-items:center;}
.hm-legend span {display:inline-flex;align-items:center;gap:5px;}
.hm-key {display:inline-block;width:12px;height:12px;border-radius:2px;}
.hm-key-win {background:#3fb950;} .hm-key-loss {background:#f85149;}
.period-highlights {display:grid;grid-template-columns:repeat(4,minmax(150px,1fr));gap:10px;margin:18px 0 12px;}
.period-highlights div {display:grid;grid-template-columns:1fr auto;gap:4px 10px;background:#161b22;border:1px solid #30363d;border-radius:4px;padding:12px;}
.period-highlights small {grid-column:1/-1;color:#8b949e;font-size:10px;}
.period-highlights b {font-size:16px;color:#f0f6fc;} .period-highlights span {font-weight:700;}
.period-title {margin-top:20px;}
.period-tables {display:grid;grid-template-columns:1fr 1fr;gap:16px;}
.period-tables h3 {font-size:13px;color:#c9d1d9;margin:8px 0;}
.table-scroll {overflow:auto;max-height:430px;border:1px solid #30363d;border-radius:4px;}
.table-scroll table {min-width:720px;margin:0;} .table-scroll th {position:sticky;top:0;z-index:1;background:#161b22;}
@media(max-width:1100px) {.period-highlights {grid-template-columns:1fr 1fr;} .period-tables {grid-template-columns:1fr;}}
.asset-link,.strategy-link {background:none;border:0;color:#58a6ff;font:inherit;font-weight:700;padding:0;cursor:pointer;text-decoration:underline;text-underline-offset:3px;}
.asset-dialog {width:min(1500px,94vw);max-height:88vh;background:#0d1117;color:#c9d1d9;border:1px solid #58a6ff;border-radius:6px;padding:18px;}
.asset-dialog::backdrop {background:rgba(1,4,9,.78);}
.asset-dialog-head {display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #30363d;padding-bottom:10px;}
.asset-dialog-head small {color:#8b949e;font-size:10px;} .asset-dialog-head h2 {margin:2px 0 0;font-size:22px;}
.dialog-close {width:36px;height:36px;padding:0;background:#21262d;border:1px solid #30363d;color:#f0f6fc;border-radius:4px;font-size:24px;line-height:1;cursor:pointer;}
.asset-dialog-summary {display:flex;flex-wrap:wrap;gap:10px;margin:14px 0;}
.asset-dialog-summary span,.asset-dialog-summary strong {background:#161b22;border:1px solid #30363d;border-radius:4px;padding:8px 10px;}
.asset-detail-scroll {overflow:auto;max-height:58vh;border:1px solid #30363d;border-radius:4px;}
.asset-detail-scroll table {min-width:1280px;margin:0;} .asset-detail-scroll th {position:sticky;top:0;z-index:1;background:#161b22;}
</style>
</head>
<body>
<h1>📊 v2 Stats Dashboard — 2° Account <span style="font-size: 14px; color: #6e7681;">(U05gSwYlB5)</span>
<a id="anomalyReviewLink" href="/review" style="float:right;background:#1f6feb;color:#fff;text-decoration:none;font-size:13px;padding:9px 12px;border-radius:4px;">Da certificare z | Anomalie u=   </a></h1>
<div class="footer">Auto-refresh 30s • Generato: uD    • <a href="/json" style="color:#58a6ff;">/json</a> per API</div>
r[   z
<div class="kpi-grid">uQ   </div>
<div class="section">
  <h2>⏱ Durata statistica di tutti i trade</h2>
  u=   
</div>
<div class="section">
  <h2>📈 Equity Curve</h2>
  ua   
</div>
<div class="section">
  <h2>🎯 Sharpe / Sortino per Strategia (per-trade, rf=0)</h2>
  uN   
</div>
<div class="section">
  <h2>📋 Posizioni Aperte (live Bybit)</h2>
  uO   
</div>
<div class="grid-2">
  <div class="section"><h2>📊 Per Strategia</h2>u5   </div>
  <div class="section"><h2>💎 Per Asset</h2>u]   </div>
</div>
<div class="section">
  <h2>🔥 Heatmap Giorno × Ora (chiusure trade)</h2>
  zG
  <h2 class="period-title">Risultati numerici per giorno e ora</h2>
  uB   
</div>

<div class="section">
  <h2>📅 Trade per Giorno</h2>
  uW   
</div>
<div class="section">
  <h2>📊 Daily PnL (barre) + Cumulativo (linea)</h2>
  uK   
</div>
<div class="section">
  <h2>📜 Ordini Recenti (ultimi 20)</h2>
  u  
</div>
<div class="footer">v2_stats_dashboard.py — 2° account Bybit (U05gSwYlB5)</div>
<script>
// Equity: render server-side in HTML (vedi sopra)
// Heatmap e Equity: render server-side in HTML (no Plotly CDN necessario)
const reviewButton=document.getElementById('anomalyReviewLink');
if(reviewButton){reviewButton.href=location.pathname.replace(/\/$/,'')+'/review';}
document.querySelectorAll('.asset-link,.strategy-link').forEach((button)=>{
  button.addEventListener('click',()=>{
    const dialog=document.getElementById(button.dataset.dialog);
    if(dialog) dialog.showModal();
  });
});
document.querySelectorAll('[data-close-dialog]').forEach((button)=>{
  button.addEventListener('click',()=>button.closest('dialog')?.close());
});
document.querySelectorAll('.asset-dialog').forEach((dialog)=>{
  dialog.addEventListener('click',(event)=>{if(event.target===dialog) dialog.close();});
});
</script>
</body>
</html>)%r&   r=   r   r#  r  ru  r  r  r  r  r  rw  	enumerater  zipr#   r  r   r   r?   r@   rH   r'   rB   rm   r  r;   chrrj   r   r  r  r  r]  r>   r   r   (  rn   r  r  r  r0  r   r  duration_statsr  r  r  r  recentr  r  r  certification_countanomaly_countunclassified_rowsr<  rX  	pnl_classclassification_alert_htmlexclusion_rowsoperational_exclusions_htmlpgross_class
fees_class
upnl_class	tot_classwr_class	avg_classpfpf_class
pf_display
first_dater  
days_labelsharpe_v	sortino_vsharpe_classsortino_classsharpe_displaysortino_display
gross_baser  r  losses_classr  pnl_realized_classr9  gross_classn_winsn_losses_countwtlwtl_display	wtl_classr  unrealized_classr  	net_classtdtrades_per_daynotional_per_dayday_profit_absday_profit_classDAY_PROFIT_CAPITALEday_profit_pct_4000day_profit_pct_classkpi_htmlduration_strategy_rowsduration_htmleq_ptseq_datescum_pnl_ptsmin_vmax_vrngwpadpointsir+   r  ysvg_linecum_pnl_svg_linelast_vfirst_vlast_change
change_pctcolorhover_pointsn_eqi_ppt_xyv_pcx_pcy_pdt_rawdt_labelts_valr  r  dt_objdelta_v	delta_pctdt_jsy_labelsfracv_labely_posy_label_svg
grid_h_svgr  x_idxx_label_svg
grid_v_svgidxts_v_dt2_tz2anchortxfill_ptszero_yequity_htmlequity_jsonr6  strategy_dialogsstrategy_escrD   r+  r   strategy_safe	dialog_id
trade_rowsnet_clsdetail_tabletotal_n
total_winstotal_wrtotal_grossr  	total_net	gross_clsstrategy_htmlboxesshsoname_raw	name_dispsh_clsso_clssh_dispso_dispr  strategy_sharpe_htmlasset_dialogs	asset_escrW   r   symbol_safe
asset_htmlr  top_htmlbad_htmlr  r  single_losses_htmlr  r&  open_by_day_htmlr\  r.  heatmap_stats_html	max_countheatmap_rowscellsr^  rq  lintensity_wintensity_lrwgwbwcolor_wrlglblcolor_l
cell_titlebglegendaheatmap_html	day_stats
hour_statsbest_day	worst_day	best_hour
worst_hourr  r   day_rows	hour_rows_trades_by_day	tot_grosstot_feestot_nettot_ntot_winstot_wrtot_clstrades_by_day_htmldaily_chart_htmldays_sortedn_days	daily_pnlr  runningd_maxd_mind_rngd_topd_botd_rng_totalc_maxc_minc_rngc_topc_botc_rng_totalpad_lpad_rpad_tpad_bplot_wplot_hx_positionsbar_wbars_svgxvdvy_topy_boty_zeroy1y2cum_ptscvcum_line	daily_pts
daily_liney_labels_left
y_left_svgy_labels_righty_right_svgsteplast_cum_ptr  positions_htmlr  r  ro  rp  rW  pnl_net_classorders_htmlre  r,  rX  rW  rV  rY  r/  rU  s                                                                                                                                                                               `                                                                                               @@@@@@@r,   render_dashboardr.  6  sy9   <D(^F}%KJH((#8"=!XX&>CXX4b9N
y/%
 C
y/%
 C9oG[!I/"F'L88126L!XX&>C7=>*401M! 		E))Iuyy':;C"%'auRI$$599\267 8yy2./ 0yyR01 2yy!8"=> ?""+By~.>o	O		 R< ! "//
 gg'()  	"G 	"
 + 
	E))Iuyy':;C!!599\267 8yyr23 4yy2./ 0yy!1267 8yyR01 2yy!5r:; <''0~&6oG
	 Q)*+ ,]]
 ggn%&  	$ ')# !#"$ /14%I!"3496uL-1rJ 01Q6EJ:;q@eIiB.vd9oPR>RUXZHy/Q.EI	/3	'B	Sy	s	s "RBs8UJ,b1J88NA.L7A%j\3~J HILMNO
 '(JDJ.!FL'L#/1#4%6!D(E!QJ&EKXXfa FXXh*N~%S	#:ICZII	&'J!+qveZ'G!Q,EI 88NA.3!L	\1	B?Cxx
TU?VU488J2R7;\]Nxx 0!4r9r\N!/1!4v% ),??3F%8A%=65  O OXY]^gYhOiNjkTTXYcTdSef+ ,6, 7T UaSabO PXj	 Y[	 \ddhirds[tZu	 vx	 y}  ~D  yE  xF	 FJ	 KO  PX  KY  JZ	ZR	
 S\Q\
 ]_
 `k^k
lT U]S] ^` ak_klY ZeXe fh irrwhxgyzQ R\P\ ]` ajjn`o_pqW XaagWhVijd ewcw xz {D  EQ  {R  zSSU VfTf gi jss}i~h@d encn oq r{  |C  rD  qEEP QZ{ [] ^ggklugv]w\xyW XaaefrasWtVuvX Y]]mXnWopW  XfVf! g^!" _hhx^y]z#"{S#$ ThRh%$ ik%$ l  @C  kD%$DQ%& RbPb'& ce'& foo}e~d'&@Y'( ZccijwcxYyXz)( {D)( EK  LX  EY  Z]  D^)(^)H.  WW % "%%mR8	% >>L>P>PQXZ[>\=]]r  tB  tF  tF  GP  RS  tT  sU U::GHZHZ[hjkHl:m9n o55B>CUCUVfhiCj5k4l m77D^EWEWXeghEi7j6kkv  xE  FT  FX  FX  Yf  hi  Fj  xk  wl l77D^EWEWXeghEi7j6kkv  xE  FT  FX  FX  Yf  hi  Fj  xk  wl l11>~?Q?QR_ab?c1d0e fKKXYgYkYkluwyYzY~Y~  @M  OP  ZQ  LR  KS  S^  _m  _q  _q  r{  }  _@  _D  _D  EL  NO  _P  ^Q QJJWXfXjXjksuwXxX|X|  ~K  MN  YO  KP  JQ  Q\  ]k  ]o  ]o  px  z|  ]}  ]A  ]A  BI  KL  ]M  \N Nff|e} ~M n!!'?{q {+S-=5EeemT*CDAqCF!+. 211K 01 45!a#g+FFGE	S0QS[AA3q3012 xx'H! _F!!nG 7*K?F!|+G4s:QRJ!,!1IyEL{#D%.s6;/G%H !\eS"[[-
d*-H*=#2s1ug;J!&v!D=%+f_FM!$!2!26cgg!2!F#)??=#A A.EPQR^WXEXWs;q>'::S@^_	h..tV<DDS%PPSVV0fTFBrsxry z558UG2eWBs3irRYZ]Q^^`ajkn`o p% &)UG3xjSI N&'': H3 2$*,C$!a#g+"66% 012 KJ"* {
3%veC[qugVTYZ]S^  _J  K  K
3q5'uQwsm  D`  ah  il  `m  mz   {  {{ FA./1fQ1ac1fac*$uQx.EKJ w3QUA.1q3w;??*-H*=#24$V}$;#'&=DO#'#5#5dtxx#5#H#Q#QR_#` 
1S'uF1S'PQRUPUw  WY  Z  Z
$'1HC1Q3J5H$/QUva!eTU2c(%"v_VH  U_  `h  _i  iv   w  w#w&  AfRj&6&6s2w&?&B%C1QsUG1SEQRSTUXSXRY"ZZHFIAgQWUc 1a!c'kBBSTWZSZF5
 5
  5
C5
5
25
\5
]^_a]a\b5
c5
L5
5
-5
.6Z5
7?5
@Ew5
G5
 e5
 5
 !5
 &,5
 -.cE75
 395
 :@5
E5
  j	5
 !7	5
 8=g	5
>	5

 N5

5
 !!#b'*1-.5
 /55
 6<BZ5E5Ec"g5Nq5Q4R5
 Sa5
 bg`g5
h5
 M5
 5
5
 a.&5
'5
 w5
 75
 8>dm5
 DK5
 LVVZJ[5
\5
 {
5
A5
  BG  AH!5
 %H!5
Kp q	A V  WX  Y\  V]  ]h  iKjj({jj2[^nq!rs s "	AeHM&uC1Z=)HGG#J#JJM*=/:IKKST]S^^`amnvaw`x yvhb6;x)7M6N O((1!K.(A'BB]^ghijphq^r]s t""%b1U8)<(=_N J/33HbA $)%LA$5&5!!|E+,>?@	,W\]hWiJjIk l'h89<PUVaPbCcBd e <-YuW~d6K9UZ[aUbcgTh i$U7^455LYW\]bWcMdLe f&&-Yb5<1H0IIYZfglmwgxZyYz  {M	NN''*%&(89 
 ##yk *>>J8>T=U V;;<S6(BUVWX^V_U``defgjeklmntlueudv w$Qy\233G	RST_R`HaGb c'&	233NseSYZcdefkdlZmYn  oC.	+5"	F 2k228K88
3:J(3.>+>>8K88
6+66	)Q.FE	%N&"")"ZL 9H%& ''[9[+A*B C%%.z%:$; <%Yb9)=(>oO	
 qggdm()+-773C+DE 	
 v  	A#Ax%By#&B}H>F)>S((c288:YbIAv#%9BF5#%9BF5HH&xj	!BqykAPQRXPYM? [  !)S1!E(3 H`a
 #%$$))'%hZr!4pqLL*5' 2**3Bqc :))/0Nwi X))/0]^e]f g)	6 "87GvN  Y p	 "	AeHM&uC8%++-F''!Fv!FFK'}5IKKPQZP[[]^ghn^o]p qvhb6;x)7M6N O((1!K.(A'BB]^ghijphq^r]s t""%b1U8)<(=_N J,00< $)%LA$5&5!!y{);<=YyQVWbQcGdFe f$U:%678	)ER]L^B_A` a <-YuW~d6K9UZ[aUbcgTh i$U7^455LYW\]bWcMdLe f&&-Yb5<1H0IIYZcdijtduZvYw  xJ	KN''*%&(89 
   yk *::CF:K9L M;;<S6(BUVWX^V_U``defgjeklmntlueudv w$Qy\233G	RST_R`HaGb c'&	233NseSYZcdefkdlZmYn  oC.	+5"	H nggdm()+-77=+AB 	
 K
t2 #v&H#u%H HH_b1M 	SAKK(155R#8"9155SUCVBWW`abafafgmoqar`ss|}~  ~C  ~C  DI  KL  ~M  NR  }S  S\  ]^  ]b  ]b  cp  rs  ]t  uy  \z  zC  DE  DI  DI  JV  XY  DZ  [_  C`  `y  z{  z  z  @I  KL  zM  NQ  yR  Rr  st  sx  sx  y~  @A  sB  CF  rG  GQ  R  S	S \  _a  _f  _f  gk  _l  l  oy  y] ((="-K 	xAqvGKK(1V9+\!C&AUVWXaVbUccuvw	x 	cdkcl  my  z  	{psuszsz{  tA  A  DN  NR {{:a'A1B'ABH{{:a'A1B'ABH;;~%(/KQb/KLL++ma-I1seBh-IJK\eAh+GSE"H+GHJPUVWPXY1E"IFq8A;q>HQKN2FYJV

.:
..;EC7J771		1%	:;! 	>ALL,QsG8<=	>FRWWU^3g=>#GFO4 !	CJE3(U34E2Y zUOA&UOA&6a1fLL!XY 4=q=!i-aK3<q=!i-aKR7k"99:BR8{"::;BR7k"99:B $RD"Qrd!4GR8{"::;BR7k"99:BR7k"99:B $RD"Qrd!4G$'5!C
1#WQC!HJAv'J7)S]^h]i  jC  DE  CF  FR  &S  Ta'J7)S]^h]i  jD  EF  DG  GS  &T  U  :'%yPVW^V__efmenntu'STVSWWablam  nG  HI  GJ  Ji  jk  il  lx  &y  z=z>  7' ABC!	CFU CRWW\EZZ]mmpww	N 	#GFO4 	JE3Ju%&A   q#huo2FRUV^_dVeRf e!45s;uCU?V_bcmnsct_u" 	 
r 	A7eAh77A!! !#wc]AaAASPrinopiqPrMr  FU1X FFPSSxotuvowSxPxBqBB	# 	 y&89	'9:	
(:;	);<
55=g5F4GG^_hiqrwix_y^z {55>w5G4HH^_hirsxiy_z^{ |22;G2D1EE\]fgpqvgw]x\y z22<W2E1FF\]fgqrwgx]y\z {	 	 L77CCCGGE*EE	 b bdjkmuvy[[]cdfops 	 ^ XXor2N 	{AiLA-&5CKK(1V9+Yqvhb6;WXYbWcdgVh  iD  EN  OP  Q\  O]  E^  D_  _z  {D  EF  GM  EN  {O  zP  Pd  eh  di  ik  lu  vw  xA  vB  lC  kD  DY  Z[  \e  Zf  Yg  gy  z  {	{ ???	9.99;N;;3N339.99-2(U"S(#qL&ecdicjjlmulv  wB  CI  JM  BN  Ni  js  t}  j~  i  Z  [d  em  [n  Zo  oC  DK  CL  LN  OX  Y`  Oa  Nb  bz  {  	| M  PR  PW  PW  X\  P]  ]  `j  j[ Z#n-2^1DE[!+67aQy\7	7 	$AqLGNN7#	$
 C	NA&C	NA&EEM4(##em CL!$CL!$EEM4(##em1%3"ueUUU"UU"A:6] H""5A!,<+F#FGH uvz12FS^+c115$Si%@A 	KAxBQ#b!*u"4!CCvMMEQ#b!*u"4!CCvMMEa1u9";;vEEFQw!! 	" $Sg%>? 	0KAxBb5jK776AAANNbXQqg./	0 88G$ 	$Si%@A 	2KAxBb5jK776AAA3xq301	2 XXi(
/ 	3Dd[00GQX//E  '5!12	3 

+ 	yNGUJugVE#;fQuWIVTYZ]S^  _J  K  KJIeAgYeE!GC=  A]  ^e  fj  ]k  kx  y  yJ	y / 	4Dd[00GQX//E!!7E"23	4 , 	~NGUYqwqykuQwsm  Db  cj  ko  bp  p}  ~  ~K	~ B;q&A+&Dq&$/0Ev'E 	NCV|$1S'qwrzl  Cb  cn  or  cs  tz  c{  |}  |~  c  b@  @M   N  N	N
 18gbk'',c3Z CqYZ[Y\ ]L !l #j !Q {1~&6 7Lk] + ( B CJ  KM  CN  OS  BT T
$  	AeHM&uCKK(1X;-|AjM?Jjklmsktkzkzk|j}}  AB  CI  AJ  @K  K[  \]  ^h  \i  [j  js  tu  vA  tB  sC  CL  MN  OY  MZ  L[  [d  ef  go  ep  dq  qE  FI  EJ  JL  MN  OX  MY  LZ  Zh  ij  kp  iq  hr  r}  ~  	 e  hj  ho  ho  pt  hu  u  xB  BL  	SA+,55+?'RDk1-I%%q/CeeIquuUA7G&-kF!uQSMKK(1%5#6"7y8Mijklrjsittvwxy  xA  wB  BR  ST  U^  S_  R`  `i  jk  lw  jx  iy  z~  y  H  IJ  KY  IZ  H[  [d  ef  gq  er  ds  sM  NW  Xa  Nb  Mc  c~  H  IL  M  ~N  Nb  cp  bq  qs  t}  ~E  tF  sG  GQ  R  S	S  v  wz  {  w@  vA  A[  \  _a  _f  _f  gk  _l  l  oy  yK_KDO O Os O^ tG  sH_O^ HT_O^ Ub  Tc_O^c4_O` 5A>aO`BaOb  cObcOd  eOdeOf  jgOf!gOl /mOlmOt -uOtuO| }O|}OD EOD3EOJ 4A/KOJB/KOL 0:lMOL;MOT .UOTUOX YOXYOb cObcOj kOjkOr -sOrsOD` KK % J286#2;#a%kJV % 4#&v;s#34^ (B'A/K-I+GFYH 8s   ABJ=
A	BKRBK:
SBK?
S3BL
T$BL	
UBL
U:BLVBLV'BLp2BLJ=BKKBKKBK7K6BK7LBLc                  	   t               } | D cg c]  }|j                  d      r| }}| D cg c]  }|j                  d      s| }}|D cg c]  }|j                  d      t        k(  r| }}|D cg c]  }|j                  d      t        k7  r| }}t               }t	               }t               }t        dd      }	t        |||      }
t        ||      }t        |      }t        |      }t        |      }t        |      }t        |      }t        |      }t        |d      }t!        |      }t#        |      }t%        |d      }t'        |	      }g }|D ]_  }t)        |j                  d            }t)        |j                  d	            }t)        |j                  d
            }t)        |j                  d            }t)        |j                  d            }t)        |j                  d      d      }|j                  dd      }t+               } |j-                         | v r| |j-                            }!nt/        |      }!dddddd}"|"j                  |!|!j-                               }#|j1                  ||#|j                  dd      ||d||d||d||dkD  r|dnd||d|dkD  r|dndd       b g }$t3        |d d !      }%|%d"d# D ]<  }&t5        |&j                  d$      xs |&j                  d%            }'|$j1                  |'r|'j7                  d&      nd|&j                  dd      |&j                  dd      |&j                  d'd      d|&j                  d(d      d|&j                  d'd      |&j                  d(d      z  d|&j                  dd      |&j                  d)d      |&j                  d*d      |&j                  d+|&j                  d,d            |&j                  d+|&j                  d,d            d-d d-d.       ? i d/|
d0|d1|d2|d3|d4|d5|d6|d7|d8|d9|d:|d;|d<|d=|$d>|d?||sd@ndAt9        |      t9        |      t;        dB |D              t9        |      dCdD|t=        j>                  t@        jB                        jE                         j7                  dE      dFS c c}w c c}w c c}w c c}w )Gu   Dati SOLO da Bybit (no webhook DB orders). Trade chiusi + posizioni aperte,
    filtrati dal 1° agosto ed escludendo MIEI test Pine-style.rB  r     
2026-08-01)ri  r  rH  )r  r   ry  	markPricestopLossr  leverager   r   r/   VPTR3
RETTANGOLORETT_SIMPLEMA_TRAILINGSUPERTREND_BOSW)r  r  r  r  r  rP  r   r  r   ro  r  z.0f)r   r   rP  r   rK  rz  rL  markrM  slrN  rX  rO  rP  c                 R    | j                  d      xs | j                  d      xs dS r  r.  r	  s    r,   r   zassemble_data.<locals>.<lambda>b  s"    aeeL)FQUU<-@FB rL   Tr   Nr  rV  rG  r5  rR  rT  ro  rp  rW  rX  F)rQ  r   rP  rR  rS  rT  r   ro  rp  rW  rX  r  is_realis_testr  r  r  r0  r   r  r  by_asset_strategyr  r  r>  r  r  r  r  r   r  OKWARNINGc           
   3   r   K   | ]/  }t        |j                  d |j                  dd                   1 ywr  )r?  r&   )r  r<  s     r,   r	  z assemble_data.<locals>.<genexpr>  s3      ( EIIi5!1DEF(s   57(exact_order_id_or_unique_entry_lifecycle)r   rt  r  pending_net_excludedoperational_excludedr  %Y-%m-%d %H:%M:%S)classification_integrityqueue_statsr  )#r  r&   r
  r  r  r  r  r  r  r+  r1  rA  rD  r  rI  r  r_  rg  r  rv  r?  r  r  r  r  r   rF   rH   r=   r  r   r\   r   r@   rN   )(all_closed_tradesr<  r  performance_candidatesr   r  r  r  rH  r|  r  r  r  r0  r   r  r  r?  r  r  r>  r  r  positions_fmtr  r   rz  r:  r;  rX  rP  r]  pos_overrider  strat_labelsstrat_labelrY  closed_trades_sorted_recentr  _tss(                                           r,   assemble_datarQ    sz    01,99+, 	 
 -yy/0 	 
 299Z $99 	  299Z $99 	M  12I!G!#K,?I"=)WED,]GDF0?K*=9H5mD;MJ7F<]K(a@G(7G)-8M-m1EM(3KM 155=)AEE*-.155-.z*+!%%01!%%
+Q/eeHb! 6799;,& -E+C0EL!.}0

 #&&uekkm<#EE&"%dE$<dQ2d)Ec$Z#&7c#Y

 
	+H F"(F#
 )"- aeeL1HQUU<5HI@Ccll+;<eeHb)EE&"%%%q/$/EE-3D9 uuUA}a1HHNj"-{A.55?uuYeQ855AEE%O4 
 	&& 	{ 	H	
 	2 	!"8 	 4 	. 	7 	7 	 	 	{ 	] 	  	2!" 	!"8#& #6d9m, 34$' (0( % %((>$?>
%
 # X\\2==?HHI\]= Is   SS!S6!Sc                   >    e Zd Zd Zd Zd Zd
dZd Zd Zd Z	d	 Z
y)StatsHandlerc                      y r  r   )selfrI   argss      r,   log_messagezStatsHandler.log_message  s    rL   c                 ~   t         sy| j                  j                  dd      }|j                  d      sy	 dd l}|j                  |dd        j                  dd	
      }d|vry|j                  dd      \  }}t        j                  |t              xr t        j                  |t               S # t        $ r Y yw xY w)NTAuthorizationr/   zBasic Fr   rs   rX   ignorer   r   r   )	AUTH_PASSheadersr&   r"   base64	b64decoder   r#   hmaccompare_digestr;  r'   )rU  authr]  decodedur  s         r,   _check_authzStatsHandler._check_auth  s    ||4x(	&&tABx0777QG'!==a(DAq&&q)4Z9L9LQPY9ZZ 		s   -B0 %A
B0 0	B<;B<c                     | j                  d       | j                  dd       | j                  dd       | j                          | j                  j	                  d       y )Ni  zWWW-AuthenticatezBasic realm="v2-stats"Content-Typez
text/plains   401 Unauthorized)send_responsesend_headerend_headerswfilerc   )rU  s    r,   _send_unauthorizedzStatsHandler._send_unauthorized  sQ    3+-EF6

,-rL   Nc                    t        j                  |t        d      j                  d      }| j	                  |       | j                  dd       | j                  dt        t        |                   | j                  dd       |r(| j                  d	d
| d       | j                  dd       | j                          | j                  j                  |       y )NF)r   rw   rX   rf  zapplication/json; charset=utf-8Content-LengthCache-Controlno-storeContent-Dispositionzattachment; filename="r   X-Content-Type-Optionsnosniff)
rj   r   r;   r   rg  rh  r=   ri  rj  rc   )rU  codern   attachment_namer   s        r,   
_send_jsonzStatsHandler._send_json  s    zz$%@GGP4 )JK)3s4y>:*526L_L]]^4_`5yA

rL   c                 .   |j                  d      }| j                  |       | j                  dd       | j                  dt        t	        |                   | j                  dd       | j                          | j                  j                  |       y )NrX   rf  ztext/html; charset=utf-8rm  rn  ro  )r   rg  rh  r;   r=   ri  rj  rc   )rU  rs  r   
body_bytess       r,   
_send_htmlzStatsHandler._send_html  sw    [[)
4 )CD)3s:+?@*5

$rL   c                    d}||v r|j                  |d      d   nd}|r|t        |      j                  k7  r| j                  dddi      S t        |z  }|j                         s| j                  dddi      S |j                  j                         }ddd	d
j                  |      }|| j                  dddi      S |j                         }| j                  d       | j                  d|       | j                  dt        t        |                   | j                  dd       | j                  dd       | j                  dd       | j                          | j                  j!                  |       y )N/review/evidence/r   r/     r  evidence_not_foundr   r   r   )r   r   r   r  rf  rm  rn  zprivate, no-storerp  inlinerq  rr  )r#   r   r}   ru  r   is_filesuffixr   r&   r   rg  rh  r;   r=   ri  rj  rc   )rU  r  markerr   r   r  r   r   s           r,   _send_evidencezStatsHandler._send_evidence  sX   $28D.djj+A.bkT+->-C-CC??32F(GHH${2~~??32F(GHH$$& +\LY]]^de??32F(GHH  "36)3s4y>:*=>.919=

rL   c                    | j                         s| j                         S t        | j                        j                  j	                  d      }d|v r| j                  |      S |dk(  xs |j                  d      }|dk(  xs |j                  d      }	 t               }|rP| j                  d	t        j                  t        j                         j#                         d
dt%               dd      S |rt'        t        | j                        j(                        }|j+                  d      dgk(  rd}n2|j+                  d      dgk(  rd}n|j+                  d      dgk(  rd}nd}|d t-        d        xs d}	| j                  d	t/        |||	            S |dv s|j                  d      r| j                  d	t1        |            S |dk(  r| j                  d	|      S |dk(  r| j                  d	dd
d      S | j3                  d       | j5                          | j6                  j9                  d       y # t        $ r2}dd l	}| j                  dd|j                          d      cY d }~S d }~ww xY w) Nrh  rz  /reviewz/review/export.jsonr   r  z<h1>500</h1><pre>z</pre>r  zv2-stats-dashboardnone_pending_review)r  servicepolicy_effect	proposalsr   )rt  r5  1z*Trade certificato. Statistiche aggiornate.r  z-Proposta rifiutata e spostata nelle anomalie.r}  z,Proposta registrata nella coda di revisione.r/   )r   r  )r/   rh  z/indexz	/v2-statsz/jsonz/healthzok)r   r  r{  s   404)rd  rk  r   r  rstripr  r  rQ  r'   	tracebackrx  
format_excru  r   r\   r   r@   r]   rp   r   queryr&   r=   r  r.  rg  ri  rj  rc   )
rU  r  	is_reviewis_review_exportrn   r  r  r  r   r  s
             r,   do_GETzStatsHandler.do_GET  sN   !**,,		"''..s3$&&&t,,I%Ay)A	#88`DMMJ_<`	\ ?D ??3 (X\\ : D D F/!6/1	)
  E # F F Xdii0667Eyy%#.F:&3%/I9%#.H,c)n_-4H??3(?g`h(ijj((DMM+,F??3(8(>??W_??3--Z??34DX(YZZs#JJV$?  	\??3*;I<P<P<R;SSY(Z[[	\s   
H4 4	I/='I*$I/*I/c           
         | j                         s| j                         S t        | j                        j                  j	                  d      }d}dD ]  \  }}||k(  s|j                  |      s|} n |s| j                  dddi      S | j                  j                  dd      j                         }| j                  j                  dd      j                         }|r,t        |      j                  |k7  r| j                  d	dd
i      S 	 t        | j                  j                  dd            }|dk  s	|t        kD  r| j                  dddi      S 	 | j                  j                  |      }t!        | j                  j                  dd      |      \  }	}
t#               }|dk(  r|
t        d      t%        |	|       n-|dk(  r|
t        d      t'        |	|       nt)        |	||
       | j9                  d       |dk(  rdn|dk(  rd nd!}| j;                  d"d#|        | j;                  d$d%       | j=                          y # t        $ r | j                  dddi      cY S w xY w# t        $ r}	 t#               }|j+                  dd      d   }|d t-        d        xs d}| j/                  dt1        |t3        |      |            cY d }~S # t4        $ r% | j                  ddt3        |      i      cY cY d }~S w xY wd }~wt4        $ r,}t7        d|        | j                  dddi      cY d }~S d }~ww xY w)&Nrh  r/   ))z/review/proposalsr=  )z/review/certifycertify)z/review/rejectrejecti  r  method_not_allowedOriginHosti  origin_not_allowedrm  rJ  i  invalid_content_lengthr   i  invalid_payload_sizerf  r  z1Allegato non previsto nella certificazione rapidar  z(Allegato non previsto nel rifiuto rapido)r   r   r  )r  r  zreview proposal err: r  review_save_failedi/  zcertified=1z
rejected=1z	created=1Locationz
../review?rn  ro  )rd  rk  r   r  r  r  ru  r\  r&   r!   netlocr>   r   MAX_REVIEW_BODY_BYTESrfilereadr   rQ  rA  rM  r`  rsplitr=   rx  r  r;   r'   rf   rg  rh  ri  )rU  r  r   r  r}   originhostlengthr   r   r   rn   ro   review_pathr  result_flags                   r,   do_POSTzStatsHandler.do_POST  s,   !**,,		"''..s3
 	LFD
 v~v!6	 ??32F(GHH!!(B/557||+113hv&--5??32F(GHH	M))*:C@AF Q;&#88??32H(IJJ	I::??6*D1$,,2B2B>SU2VX\]D* ?D")$%XYYtT*8#)$%OPP%dD1'dzJ 	3'-':mPVZbPbhsz+%?@*5C  	M??32J(KLL	M$  	AA$"kk#q1!4&'7Y8?Cs,CDPSTWPXck,lmm AsWc#h,?@@A 	I'u-.??32F(GHH	Isb   %I	 BI, 	I)(I),	L=6AKL=&L:L;L=LLL=!L82L=8L=r  )__name__
__module____qualname__rW  rd  rk  ru  rx  r  r  r  r   rL   r,   rS  rS    s+     .
%,)%V6rL   rS  c                  D   t        dt         dt                t        dt                t        dt        rdnd        t        t        t        ft              } 	 | j                          | j                          y # t        $ r Y w xY w# | j                          w xY w)Nzv2 stats dashboard avviato su r   zDB: zAuth: 	abilitataz"disabilitata (no password settata))
rf   LISTEN_HOSTPORTr  r[  r
   rS  serve_foreverKeyboardInterruptserver_close)httpds    r,   mainr  E  s    
(Qtf=>$wi&	/STUVT*L9E 	   	s$   A> >	B
B 	B

B B__main__)rF  r  )r/   r/   rh  )r0  r1  )r1  )rH  )ru   )r   )r  )__doc__r$   r  rj   r"  r  r_  r~   stringre  r   email.parserr   email.policyr   r   r   r   pathlibr   http.serverr	   r
   urllib.parser   r   collectionsr   zoneinfor   r   r  r   ri   r   r   r   r  r   r>   r%   r&   r  r  r_   rb   r-   r;  r[  	frozensetr\  rO   rF   rK   rP   rf   rp   r   r   r   r   r   r   r   r   r   r   r#  r%  r)  rA  rM  r`  r  r  r  r\  r   r   r
  r  r  r  r  r  r  r=  rT  ru  r@   r   rv  r_  rb  r  r  r  r  r  r  r  r  r  r+  r1  rA  rD  rI  r_  rg  rv  r  r  r  r  r  ru  r  r?  r  r  r  r.  rQ  rS  r  r  r   rL   r,   <module>r     sU   
 
         $ 0 '  : + #  ./
-,
,77 @@ @@ "OO !:: ' $ 
2::>>/623
---$  JJNN?,=>	JJNN?B/	   =)0E	("$(	Z"J6"N.b
J!AH$7NIX{"~$ "&! 		%* !* 
+ 
!  ' GT/ 8v\(<&~3B\~ Jz*33D!Q1aPZ[ePfPoPoPsPs3t~~  A  DH  H  I" [|;,G$ (.1haHB"J.::6"J F1h0f#$L0,^*_"6tVtGVg) gT
 zF rL   