+
    *Caj-                      a R tg0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt	^ RI
t
^ RIHt ^ RIHt ]! ]4      P                  4       P                   ^,          t]R,          R,          R,          t]R,          tRtR	t ]! ]R
,          R,          4      t]]P0                  9  d   ]P0                  P3                  ^ ]4       ^ RItRtRtRt^<t ^t!]R
,          R,          R,          t"]R
,          R,          R,          t#Rs$] ^ k Rs%] ^k R	s&] ^k ]
PN                  ! 4       t(R t)R t*Rt+R t,Rt-Rt./ R^UbR^UbR^UbR^PbR^UbR^PbR^PbR ^KbR!^KbR"^KbR#^KbR$^7bR%^FbR&^KbR'^KbR(^_bR)^_bR*^AR+^<R,^-R-^-R.^-R/^-R0^#R1^R2^#R3^(R4^(R5^-R6^(R7^/Ct// R8^ZbR9^ZbR:^UbR;^FbR<^FbR=^AbR^AbR^<bR>^AbR?^2bR@^2bRA^<bR+^7bRB^(bRC^(bR%^(bRD^(bRE^(RF^#/Ct0. RGNRHNRINRJNRKNRLNRMNRNNRONRPNRQNRRNRSNRTNRUNRVNRWNRXNRYNRZNR[NR\NR]NR^NR_NR`NRaNRbNRcNRdNReNRfNt1. ROt2. ROt3]3 U u. uFA  p ]Pi                  V Rg4      ]5! Rh4      Pm                  ^Ri7      ,           Po                  Rg4      NKC  	  up t8RRRjR/t9Rk t:Rl t;RRn lt<Ro t=RRRjRRpR/t>RqRRjRRrRRsR/t?Rt t@RRu ltARv tBRw tCRxRRyRRzRR{R	R|R	/tDR} tER~ tFR tG ! R R]	P                  P                  4      tJR tKR tLR tM]R
,          R,          R,          tN]R,          tO]R,          R,          R,          tP]R
,          R,          R,          tQ]
PN                  ! 4       tRRm.tSR tTR tUR tV]R
,          R,          R,          tW]
PN                  ! 4       tXRm.tYR tZ]R
,          R,          R,          t[]R,          t\]R,          t]]R,          t^]R,          R,          R,          t_]
PN                  ! 4       t`Rm.taR tbR tcR tdR te]fR8X  d
   ]e! 4        R# R#   ] d   t]! R] R24        RtAEL,RtAii ; iu up i )ub  
dashboard_server.py
====================
Reads the live_monitor.log file every 30 seconds and writes
dashboard_data.json which the dashboard.html reads automatically.

Run this alongside the live signal monitor:
  python src/execution/dashboard_server.py

Then open dashboard.html in any browser.
No internet required — runs entirely on your machine.
N)Pathdatetimedatalogszlive_monitor_v2.logzdashboard_data.jsoni="  Fsrc	executionTz[regime] module not available: u#    — regime cards will show Unknown  researchextract_live_trades.pybuild_equity_curve.pyc                 B   R^ RRRRR^ R^ RR/p  ^ RI p. pR F  p\        R	,          R
,          V,          pVP                  4       '       g   K6   VP                  ! VP	                  RR7      4      p\        V\        4      '       d   VP                  V4       K  K  	  V'       g   V # V Uu. uF  qfP                  R^ 4      NK  	  pp\        V4      V R&   \        \        V4      ^4      V R&   \        \        ^ \        V4      4      ^4      V R&   \        R V 4       4      V R&   \        R V 4       4      V R&   V'       d+   \        V R,          \        V4      ,          ^d,          ^4      MRV R&   WpR&   V #   \         d     EKn  i ; iu upi   \         d     T # i ; i)z
Read trade history from the pair-specific trade logs written by
live_signal_monitor. Reads BOTH trade_history_eurusd.json and
trade_history_usdjpy.json from data/logs/ and combines them.
trade_count	pnl_total        p1_pnlwinslosseswin_rateNr   r   utf-8encodingnet_pnlc              3   6   "   T F  q^ 8  g   K  ^x  K  	  R# 5i    N .0ns   & SC:\Users\Administrator\OneDrive\fx_macro_intraday\src\execution\dashboard_server.py	<genexpr>(get_mt5_trade_history.<locals>.<genexpr>i   s     %>AAaa   
c              3   6   "   T F  q^ 8:  g   K  ^x  K  	  R# 5ir   r   r   s   & r    r!   r"   j   s     %?AQaar#   trade_resultsztrade_history_eurusd.jsonztrade_history_usdjpy.json)json	BASE_PATHexistsloads	read_text
isinstancelistextend	Exceptiongetlenroundsummax)resultr'   
all_trades	pair_filepathpair_tradestnets           r    get_mt5_trade_historyr<   F   s    	qssqqsF
SIv%.:D;;=="jj)IJk400%%k2 1 T M,67JquuY"J7"%c(}"'C!"4{"'As3x(8!"<x"%%>%>">v"%%?%?"?x36 #(6NSX%+Q#0<? 	z"% M#   8  MsO   >F A	E7F &F (F ,F
B/F 7FF FF FFc                 F   ^ RI p . pR F  p\        R,          R,          V,          pVP                  4       '       g   K6   V P                  ! VP	                  RR7      4      p\        V\        4      '       d   VP                  V4       K  K  	  V#   \         d     K  i ; i)z;Helper: load combined trades from both pair-specific files.Nr   r   r   r   r&   )	r'   r(   r)   r*   r+   r,   r-   r.   r/   )r'   r6   r7   r8   r9   s        r    _load_all_tradesr>   s   s    JO	6!F*Y6{{}}	**T^^W^%EFK+t,,!!+. - P   		s    A	BB B g     j@c                 r    ^ RI p \        R,          R,          R,          pVP                  4       '       g   R# V P                  VP	                  RR7      4      pRV9   d    \
        P                  ! VR,          P                  RR	4      4      p\
        P                  ! VP                  4      V,
          P                  4       R
,          pVR8  d   \        RVR R24       R#  RRRVP                  RR4      RVP                  RR4      RVP                  RR4      RVP                  RR4      RVP                  RR4      RVP                  R^ 4      RVP                  RRRRR/4      RVP                  RR^ R^ /4      /	#   \         d     Li ; i  \         d   p\        RT 24        Rp?R# Rp?ii ; i)a  
Authoritative source of truth for P&L and DD.

Reads the account snapshot file written by live_signal_monitor_v2 every
hour (monitor has MT5 connected; server can't share that connection since
MT5 terminal only allows one). If snapshot exists and is fresh, returns
its contents. If missing or stale, returns None and callers fall back
to JSON trade history.

Snapshot fields: pnl_total, balance, equity, floating_pnl, daily_loss,
                 trade_count, pair_pnl, pair_trades
Nr   r   zaccount_snapshot.jsonr   r   snapshot_atZz+00:00r	          @z[Account snapshot] stale (.1fzh old), falling backsourcemonitor_snapshotr   r   current_balancebalancecurrent_equityequityfloating_pnl
daily_lossr   pair_pnlEURUSDUSDJPYr9   z [Account snapshot] read failed: )r'   r(   r)   r*   r+   r   fromisoformatreplacenowtzinfototal_secondsprintr/   r0   )_json	snap_pathsnap	snap_time	age_hourses         r    get_mt5_account_snapshotr[      s    &/2II	!!{{9...@A D $2243F3N3NsT\3]^	%\\)*:*:;iGVVX[__	s?6yoEYZ[ # 1txxS9txx	37txx#6txx<txxc:txxq9txx
XsHc4RStxx!Xq7QR

 
	
	    045sB   4F (F "B F $BF FF FF F6F11F6@2d9e4c37c81f1b4c970d7b1f8d7d382ff450312cd0adf57117f28d5708e6e38e b4e39ea4507e1ceca1a389cfacee8a00zcore inflation rate monthzcore inflation rate yearzinflation rate monthzinflation rate yearzconsumer price indexzcore pcezpce price indexzpersonal spendingzpersonal incomeznonfarm payrollsznon-farm payrollszadp employment changezunemployment ratezfomc meeting minuteszfed minutesz	fomc ratezfederal funds ratezgdp growth rategdpzretail sales monthzism manufacturing pmizism services pmizism non-manufacturingzdurable goods orderszconsumer confidencezmichigan consumerzjolts job openingszproducer price indexz10-year note auctionz30-year bond auctiontreasuryzecb interest ratezecb rate decisionzecb monetary policyzecb presidentlagardezecb minuteszconsumer pricezzew economiczifo businessz
gdp growthzindustrial productionzfactory orderszmanufacturing pmizservices pmizretail salesmortgageredbookzweekly earningszweekly joblesszadp employment change weeklyz
adp weeklyz3-month treasuryz6-month treasuryz4-weekz8-weekzbill auctionzt-billbubillnon-monetaryspeaksspeech	interview	testimonyzindex of coincidentzindex of leadingzwholesale inventorieszbuilding permitszhousing startszexisting homezpending homezconstruction spendingznatural gasz	crude oileiaz
api weeklymilkgrain%Y-%m-%dr   )weeksfetchedc                 ^  a
 V P                  R R4      P                  4       pV P                  RR4      P                  4       o
\        V P                  R^4      4      pRV9   pRV9   pRV9   pRV9   pV'       g   V'       g   V'       g   V'       g   ^ # \        ;QJ d#    V
3R l\         4       F  '       g   K   R	M	  R
M! V
3R l\         4       4      '       d   ^ # V'       dh   R^ZR^ZR^ZR^UR^KR^KR^FR^AR^<R^<R^2R^-R^FR^-/p\        V
3R lVP                  4        4       ^ R7      pV^ 8X  d   V^8X  d   ^(pV# V^ 8X  d
   V^8X  d   ^pV# V'       d   \        M\        p	\        V
3R lV	P                  4        4       ^ R7      pV^ 8X  d
   V^8X  d   ^#pV'       d   V^ 8  d
   RS
9   d   ^pV# )Country Category
Importanceunited statesgermanyeurojapanc              3   ,   <"   T F	  qS9   x  K  	  R # 5iNr   )r   exclcategorys   & r    r!   "_score_te_event.<locals>.<genexpr>!  s     
68   TFbojzbank of japanzinterest ratezmonetary policy	inflationcpir^   ztrade balancezcurrent account
employment
industrialretailtankanpmic              3   >   <"   T F  w  rVS9   g   K  Vx  K  	  R # 5iry   r   r   kvr{   s   &  r    r!   r|   /  s     D!2#!a8mAA!2   
)defaultc              3   >   <"   T F  w  rVS9   g   K  Vx  K  	  R # 5iry   r   r   s   &  r    r!   r|   7  s     ?~h!!~r   rd   )	r0   lowerintanyTE_EXCLUSIONSr4   itemsTE_US_SCORESTE_DE_EU_SCORES)eventcountry
importanceis_usis_deis_euis_jp	JP_SCORESbasescoresr{   s   &         @r    _score_te_eventr     s   9R(..0G:b)//1HUYY|Q/0Jw&E EgEwEUeu s
6
6sss
6
666 b/Rb"3Rb%Rb/Rb,Rb(Rb%R
	 D!2DaP19qD  QY:?D"\F?v||~?KD qyZ1_n8K    c                    ^ RI p^ RIpVP                  VP                  P                  4       . pR1 EFU  w  rV RpTP                  TR\        RTRT RT/^
RR	7      pTP                  ^8X  Ed   TP                  4       p	T	P                  R
4      '       Ed   \        T	P                  R4      \        4      '       Edy   T	R,          p
\        RT R\        T
4       RT  RT R2	4       T
 EFD  pTP                  RR4      pRp\        T4      ^8  dm    \        P                  ! TR,          R4      p^TP                   u;8  d   ^8  d   M M^M^ pTP"                  T,           ^,          pTR RTP$                  R 2pTP)                  RTP                  RT4      RTP                  RR4      RTP                  RR4      RTR,          RTRR ^R!^R"^/P                  TP                  R#R"4      ^4      R$TP                  R%R4      R&TP                  R'R4      R(TP                  R)R4      /	4       EKG  	  EK  \        R*T R\+        T	4      R+,           24       EK&  \        R*T R,TP                   RTP,                  R-,           24       EKX  	  \        R/\        T4       R024       T#   \
         d    \        R4       . u # i ; i  \&         d    TR,          p EL_i ; i  \&         d   p\        R*T R.T 24        Rp?EK  Rp?ii ; i)2z$Fetch calendar from FinanceFlow API.NuH   [WARNING] requests not installed — run: python -m pip install requestsz4https://financeflowapi.com/api/v1/financial-calendarapi_keyr   	date_fromdate_toF)paramstimeoutverifysuccessr   z[INFO] FinanceFlow : z	 events (    → )r   rq   :N   Nz%Y-%m-%d %H:%M02d::   r   Nrp   Eventreport_namerr   DateN
   NTimers   HighModerateLoweconomicImpactForecast	consensusPreviouspreviousActualactualz[WARNING] FinanceFlow Nd   N HTTP :NP   Nz	 failed: z[INFO] FinanceFlow total: z events fetched))United StatesUS)GermanyDE)	Euro AreaEU)JapanJP)requestsurllib3disable_warnings
exceptionsInsecureRequestWarningImportErrorrT   r0   
TE_API_KEYstatus_coder'   r,   r-   r1   r   strptimemonthhourminuter/   appendstrtext)startend_reqr   eventscountry_namelabelurlrespr   rawrZ   dt_struk_timedt_utcoffsetuk_hs   &&               r    _fetch_te_calendarr   B  s     !3!3!J!JK F  k*	@IC88CZ\US	)
 %  )D 3&yy{88I&&:dhhv6F+M+Mv,C/wbS
)E7RWX[W\\]^_ "#%%
2"6"$v;",8)1):):6#;HX)Y./&,,.C.C*0++*>")D-1#Jac7J*K %!%%	<*H#!%%b*A&!%%b*A"&+"'(6!Jqq*I*M*M !&6u =q+B&!%%B*?&!%%
2*>$!%%*<'  !2 25'CIdO;LMN.ugVD<L<L;MRPTPYPYZ]P^O_`aS  kX 
&s6{m?
CDMi  XY	> $- 8*0-8$  	@*5'1#>??	@sb   -J' AK A:K A+K=B5K 5!K /K 'KKKK KK  L+LLr   c                6   \         P                  ! 4       p\        pVP                  4       pV^8  d+   V\	        R4      P                  ^V,
          R7      ,           pM"V\	        R4      P                  VR7      ,
          pVR,          '       d   WR,          ,
          P                  4       MRpVP                  R4      '       d#   VR,          VP                  R4      8w  d   RVR&   VR,          '       d   VR8  d   \        VR	,          V 4      # VP                  R4      pV\	        R4      P                  ^R7      ,           P                  R4      p\        ^4       Uu/ uF5  pV\	        R4      P                  VR7      ,           P                  R4      . bK7  	  p	p\        Wg4      p
\        V
4      ^ 8  pV
 EF  pVP                  R
R4      R,          pVP                  RR4      P                  4       P                  4       pRV9   d   KT  \        V4      pW9   g   Kg  V^ 8  g   Kp  W,          P!                  RVP                  RVP                  RR4      4      RVP                  RR4      RVRVP                  RR4      RVP                  RR4      RVP                  RR4      RVP                  RR4      RR/4       EK
  	  V	 EFS  pW,           Uu. uF  pVR,          NK  	  ppV\"        9   dZ   \$        ;QJ d    R V 4       F  '       g   K   RM	  R M! R V 4       4      '       g    W,          P!                  RR!RR"R^ZRR#/4       V\&        9   dZ   \$        ;QJ d    R$ V 4       F  '       g   K   RM	  R M! R$ V 4       4      '       g    W,          P!                  RR%RR&R^_RR#/4       V\(        9   g   K  \$        ;QJ d    R' V 4       F  '       g   K   RM	  R M! R' V 4       4      '       d   EK4  W,          P!                  RR(RR&R^KRR#/4       EKV  	  V'       g   \+        R)4        ^ RIHp R*V R+V R,\0         R-2p\2        P4                  ! VP7                  V^R.7      P9                  4       4      p^R;^2R<^3R=^
R>^.R?^R@^eRA^fRB^4RC^7RD/
pVP                  R/. 4       Fi  pVP                  R04      VP                  R1R4      R,          ppW9   g   K5  VV9   g   K>  VV,          w  ppW,          P!                  RVRR&RVRR2/4       Kk  	  . p\        ^4       F  pV\	        R4      P                  VR7      ,           P                  R4      p\=        V	P                  V. 4      R4 RR57      pTP!                  R1TR6. REOV,          R7VR8,          R9V'       d   V^ ,          R,          MR:RV'       d   RMR2/4       K  	  VVR	&   WR&   VP                  R4      VR&   \        VV 4      # u upi u upi   \:         d   p\+        R3T 24        Rp?ELRp?ii ; i)Fz,Build weekly signal outlook. Caches 6 hours.r   daysrn   韆 
week_startrl   Nr	   r   r   rq   r   rp   rw   r   r   rr   r   scoretimer   forecastr   r   r   r   r   rD   FFc              3   F   "   T F  pR V9   ;'       d    RV9   x  K  	  R# 5i)ECBRateNr   r   evs   & r    r!   %get_weekly_outlook.<locals>.<genexpr>  s&     0aX`RT"1M1M21MX`   !!TFzECB Rate Decisionr   	hardcodedc              3   F   "   T F  pR V9   ;'       d    RV9   x  K  	  R# 5iFOMCr   Nr   r   s   & r    r!   r     &     1cZbTV&B,2O2O6R<2OZbr   FOMC Rate Decisionr   c              3   ,   "   T F
  pR V9   x  K  	  R# 5iMinutesNr   r   s   & r    r!   r          0T8Rb8   FOMC Meeting Minutesu'   TE unavailable — falling back to FREDz>https://api.stlouisfed.org/fred/releases/dates?realtime_start=z&realtime_end=z2&include_release_dates_with_no_data=false&api_key=z&file_type=json)r   release_dates
release_iddateFREDz [WARNING] FRED fallback failed: c                     V R ,          # r   r   xs   &r    <lambda>$get_weekly_outlook.<locals>.<lambda>  s    '
r   keyreversedayr   N   N	top_eventNo key events)zConsumer Price Index (CPI)U   )zPersonal Income & PCEr   )zPersonal Income & Outlaysr   )zEmployment Situation (NFP)K   )zGross Domestic Product<   )zRetail Sales-   )zISM Manufacturing PMIr  )zISM Services PMIr  )zDurable Goods Orders#   )PPI(   MonTueWedThuFri)r   rQ   _outlook_cacheweekday
__import__	timedeltarS   r0   strftime_recalc_probsrange_fetch_te_calendar_cachedr1   stripr   r   r   ECB_MEETINGS_2026r   FOMC_MEETINGS_2026FOMC_MINUTES_2026rT   urllib.requestrequestFRED_API_KEYr'   r*   urlopenreadr/   sorted)	current_zrQ   cacher  monday	cache_ager   r   iweek_events	te_eventste_usedrZ   r  r   r   r   existing_ur   r   FRED_IDSrdridr   sfer5   r   s   &                            r    get_weekly_outlookrE    s   LLNCE ++-C
axz*-77a#g7GGz*-77S7AA<A)<L<LY''668RWI yy5#6&//*:U#UiYI,U6]I66__Z(Ez*-77Q7??II*UC qA 
*Z(222:	:DDZPRTT   *%5II"G%%r"3'%%	"%++-335g"519$$AEE'155B+?@AEE)B/EAEE&,AEE*R0AEE(2.AEE*R0D	& 	 ( *5*;<*;BBwKK*;<$$SS0aX`0aSSS0aX`0a-a-a$$g.A)KX_`bcklw%xy%%cc1cZb1cccc1cZb1c.c.c$$g.B9_]deghpq|%}~$$SS0T80TSSS0T80T-T-T$$g.DY_fgijrs~%  A  78	;''',g^C5  ,~_>C ::bjjaj8==?@D4b9U3b9Z0b9L0c:Q.bH hhr2FF<0"&&2CC2HT&3(?#C=DAq%,,ga	/RYZ[\dek-lm	 3 F1X:j1;;;CCMMjYR06JTXY8;v7+?f
 	  E&M) //*5E,++[: =<  	;4RD9::	;s1   ;W*W/0B#W4 W4 !/W4 4X?XXc                :   Rp. pV  EF  pVP                  R. 4      pV'       g   ^pMV^ ,          R,          p\        V4      ^8  d   V^,          R,          R,          M^ p\        Wx,           ^d,          ^2,          ^24      p	V\        V4      ,
          p
V
^ 8:  d   ^M%V
R8  d   ^MV
R8  d   ^MV
R8  d   ^M
V
R8  d   ^M^p\	        R	 VR
,           4       4      p\        \        W,           V,           4      ^U4      pVP                  / VCRVRV/C4       EK  	  V# )z6Recalculate signal probabilities with current z-score.      @r   r   皙?g      ?g      ?g      ?rB   c              3      a"   T FI  o\         ;QJ d    V3R  lR 4       F  '       g   K   RM	  RM! V3R  lR 4       4      '       g   KE  ^x  KK  	  R# 5i)c              3   X   <"   T F  pVSR ,          P                  4       9   x  K!  	  R# 5ir   Nupperr   r   rZ   s   & r    r!   *_recalc_probs.<locals>.<genexpr>.<genexpr>  s/      @)?1  !AgJ$4$4$66)?   '*TFN)CPIPCEr   NFPzECB RATEMINUTESr   r   rZ   s   &@r    r!    _recalc_probs.<locals>.<genexpr>  sL      A:a3 @)?@333 @)?@ @ :   AAA

AN   Nprobsignal_probabilityr0   r1   minabsr3   r   r   	days_datar6  	THRESHOLDoutdr   r[  topsecepdistzpbonuss   &&           r    r)  r)    s   I
Cx$D!9W%C/26{Q6!9W%+AC	S(2-r2Bs9~-D!)Btcz*Bs
"*A!   A6": A AE s27U?+R0D

BaB';TBC# $ Jr   r   r   r   r   c                4   \         P                  ! 4       p\        pVR,          eW   VR,          V 8X  dI   VR,          V8X  d;   VR,          '       d,   W#R,          ,
          P                  4       R8  d
   VR,          # \	        W4      pWCR&   W#R&   WR&   WR&   V# )zKWrapper that caches calendar results for 6 hours to avoid double API calls.r   r   r   rn   r	   )r   rQ   _calendar_cacherS   r   )r   r   rQ   r7  r   s   &&   r    r+  r+    s    
,,.CEh#g%'e#i  Y''6684?X+F(O)'N%LMr   c                	  a ^ RI pVP                   P                  4       p\        pVP                  4       pV^8  d!   W!P	                  ^V,
          R7      ,           pMW!P	                  VR7      ,
          pVR,          '       d   W#R,          ,
          P                  4       MRpVP                  R4      '       d#   VR,          VP                  R4      8w  d   RVR&   VR,          '       d   VR8  d   \        VR,          V 4      # VP                  R4      pWQP	                  ^R7      ,           P                  R4      p\        ^4       U	u/ uF+  p	WQP	                  V	R7      ,           P                  R4      . bK-  	  p
p	\        Wx4      pV EF@  pVP                  R	R
4      R,          pVP                  RR
4      P                  4       P                  4       o\        V4      pW9   g   K^  V^ 8  g   Kg  \        ;QJ d    V3R lR- 4       F  '       g   K   RM	  RM! V3R lR- 4       4      '       g   K  W,          P                  RVP                  RVP                  RR
4      4      RVP                  RR
4      RVRVP                  RR
4      RVP                  RR
4      RVP                  RR
4      RVP                  RR
4      RR/4       EKC  	  V
 F  pW,           Uu. uF  qR,          NK  	  ppV\         9   dZ   \        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       g    W,          P                  RR RR!R^_RR"/4       V\"        9   g   K  \        ;QJ d    R# V 4       F  '       g   K   RM	  RM! R# V 4       4      '       d   K  W,          P                  RR$RR!R^KRR"/4       K  	  . p\        ^4       F  p	WQP	                  V	R7      ,           P                  R4      p\%        V
P                  V. 4      R% RR&7      pTP                  R'TR(. R.OV	,          R)VR*,          R+V'       d   V^ ,          R,          MR,/4       K  	  VVR&   W#R&   VP                  R4      VR&   \        VV 4      # u up	i u upi )/u@   Weekly outlook for USDJPY — US + Japan events. Caches 6 hours.Nr   rn   r   r   rl   r	   r   r   rq   r   rp   c              3   ,   <"   T F	  qS9   x  K  	  R # 5iry   r   )r   cr   s   & r    r!   ,get_usdjpy_weekly_outlook.<locals>.<genexpr>5  s     D)CA<)Cr}   TFr   r   rr   r   r   r   r   r   r   r   r   r   r   rD   r   c              3   F   "   T F  pR V9   ;'       d    RV9   x  K  	  R# 5ir   r   r   s   & r    r!   rp  D  r   r   r   r   r   c              3   ,   "   T F
  pR V9   x  K  	  R# 5ir   r   r   s   & r    r!   rp  G  r  r  r  c                     V R ,          # r
  r   r  s   &r    r  +get_usdjpy_weekly_outlook.<locals>.<lambda>N  s    7r   r  r  r  r   r  r  r  )rt   rw   r  )r   rQ   _uj_outlook_cacher%  r'  rS   r0   r(  _recalc_probs_ujr*  r+  r,  r   r   r   r   r.  r/  r5  )r6  _dtrQ   r7  r  r8  r9  r   r   r:  r;  r<  rZ   r  r   r   r>  r5   r   r   s   &                  @r    get_usdjpy_weekly_outlookrx    s   LLCE
++-C
ax}}1s7}44}}#}..<A)<L<LY''668RWIyy5#6&//*:U#UiYI,fy99OOJ'Emmm++55jAC qA 
--Q-'	'11*=rA   *%5I%%#C(%%	2&,,.446!!$519sD)CDsssD)CDDD!((gquuZ/D Ei 4fb 1j" 5h 3j" 5	* 	 $ *5*;<*;BwKK*;<%%cc1cZb1cccc1cZb1c.c.c$$g/CYP_&-r8[&J K$$SS0T80TSSS0T80T-T-T$$g/EyRa&-r8[&J K  F1X==a=00:::Fb17KUYZ8;v7+?	
 	  !E&M) //*5E,FI..a4 =s   
1RR
c                (   Rp. pV  EF  pVP                  R. 4      pV'       g   ^pMV^ ,          R,          p\        V4      ^8  d   V^,          R,          R,          M^ p\        Wx,           ^d,          ^-,          ^-4      p	V\        V4      ,
          p
V
^ 8:  d   ^MV
R8  d   ^MV
R8  d   ^M
V
R8  d   ^M^p\	        R VR	,           4       4      p\        \        W,           V,           4      ^P4      pVP                  / VCR
VRV/C4       EK	  	  V# )z(Recalculate USDJPY signal probabilities.rB   r   r   rH  g333333?gffffff?g333333?c              3      a"   T FI  o\         ;QJ d    V3R  lR 4       F  '       g   K   RM	  RM! V3R  lR 4       4      '       g   KE  ^x  KK  	  R# 5i)c              3   X   <"   T F  pVSR ,          P                  4       9   x  K!  	  R# 5irK  rL  rN  s   & r    r!   -_recalc_probs_uj.<locals>.<genexpr>.<genexpr>l  s1      F)E1  !AgJ$4$4$66)ErP  TFN)BOJr   rQ  rS  	INFLATIONMONETARYzRATE DECISIONrU  rV  s   &@r    r!   #_recalc_probs_uj.<locals>.<genexpr>k  sN      G:a3 F)EF333 F)EF F :rX  rY  r[  r\  r]  r`  s   &&           r    rv  rv  \  s   I
Cx$D!9W%C/26{Q6!9W%+AC	S(2-r2Bs9~-D!)Btcz*Bs
!  G6": G GE s27U?+R0D

BaB';TBC! " Jr   c                 4  aA \         P                  4       '       g   R#  \         P                  RRR7      P                  4       p R\
        P                  ! 4       P                  4       RRR	R
RRR^ RRRRR^ R^ RR/
p ^ RIp\        R,          R,          R,          pTP                  4       '       dS   TP                  TP                  RR7      4      pTP                  R4      pTe   \        T4      TR&   \        T4      TR&    ^ RIp\        R,          R,          R,          pTP                  4       '       dE   TP                  TP                  RR7      4      pTP                  R4      pTe   \        T4      TR&    . p	. p
\
        P                  ! 4       \        R4      P                  ^<R7      ,
          P                  4       R,          p\        T 4      p\        R,          R,          R,          pTP                  4       '       d*    TP                  RRR7      P                  4       T,           pT EF  pR T9   d   RTR&   M"R!T9   d   TP                  R4      Rv9  d   R"TR&   \         P"                  ! R#T4      pT'       g   KT  TP%                  ^4      pTR,          T8  d   Ku  R$T9   d[   \         P"                  ! R%T4      pT'       d:   T	P'                  R&TR'\)        \        TP%                  ^4      4      ^4      /4       K  K  R(T9   d]   \         P"                  ! R%T4      pT'       d;   T
P'                  R&TR'\)        \        TP%                  ^4      4      ^4      /4       EK6  EK9  R)T9   g   EKC  \         P"                  ! R*T4      pT'       g   EKe  T	P'                  R&TR'\)        \        TP%                  ^4      4      ^4      /4       EK  	  \        T	 Uu/ uF  pTR&,          TbK  	  upP+                  4       4      p	\        T
 Uu/ uF  pTR&,          TbK  	  upP+                  4       4      p
T	P-                  R+ R,7       T
P-                  R- R,7       T	RwR TR.&   T
RwR TR/&    ^ RIp\1        4       pT'       Ed_   ^ .^,          pT F  pTP                  R0R14      R2,          pTP3                  R34      '       g   K5  \5        TR4,          4      ^,
          p^ Tu;8:  d
   ^8  g   K_  M Kc  TT;;,          \)        TP                  R5^ 4      4      ,          uu&   K  	  \
        P                  ! 4       P6                  p\9        T^4       F  pRTT&   K
  	  TTR6&    ^ RIp\        R,          R,          R7,          pTP                  TP                  RR7      4      pTP                  R8/ 4      TR9&   TP                  R:/ 4      TR;&   TP                  R<R=4      TR>&   M  ^ RIp\        R,          R,          R,          p T P                  4       '       d   TP                  ! T P                  RR7      4      p!T!P                  R?4      '       d8   T!P                  R@R14      p"T!P                  RA4      ^8X  d   RBMRCp#T# RDT" 2TR	&   MrT!P                  RE/ 4      p$T$P                  RFRG4      '       dD   T$P                  RHR14      p%T$P                  RI4      ^8X  d   RBMRCp#T%'       d
   RJT# RKT%RL 2MRMTR	&   MR
TR	&    ^ RIp&\        R,          R,          R,          pTP                  4       '       d   T&P                  TP                  RR7      4      pTP                  R?4      '       d8   TP                  R@R14      p'TP                  RA4      ^8X  d   RBMRCp(T( RDT' 2TRN&   MrTP                  RE/ 4      p)T)P                  RFRG4      '       dD   T)P                  RHR14      p*T)P                  RI4      ^8X  d   RBMRCp(T*'       d
   RJT( RKT*RO 2MRMTRN&   MR
TRN&   \;        4       p+TP=                  T+4       \?        4       p,T,e   T,R,          TR&   T,RP,          TRP&   \A        T,R,          T+P                  R^ 4      4      TR&   T,RQ,          TRQ&   T,RR,          TRR&   T,RS,          TRS&   \A        RT,R,          4      TR&   RTTRU&   MRVTRU&    \1        4       p-T- Uu. uF,  pTP                  RWR14      PC                  4       RX8X  g   K*  TNK.  	  p.pT- Uu. uF,  pTP                  RWR14      PC                  4       RY8X  g   K*  TNK.  	  p/pRZ p0T0! T/4      p1T0! T.4      p2T,eo   T,R[,          RX,          T2R&   T,R[,          RY,          T1R&   \A        T2R,          T,R\,          RX,          4      T2R&   \A        T1R,          T,R\,          RY,          4      T1R&   T1TR]&   T2TR^&   R_T2R,          R`T1R,          Ra\)        T2R,          T1R,          ,           ^4      RbT2R,          T1R,          ,           /TRc&    \        TP                  R4      ;'       g    TP                  R4      ;'       g    R4      p\        TP                  R4      ;'       g    R4      p\E        T4      TRd&   \G        T4      TRe&    ^ RI%oA\        R,          Rh,          Ri,          p4Rp5. p6Rp7. p8T4Rj,          p9T4Rk,          p:TA3Rl lp;T9P                  4       '       dm   T;! T94      p<T<'       d]   \)        \        T<Rx,          ^,          4      ^4      p5T<RyR  U=u. uF*  p=RmT=^ ,          Rn\)        \        T=^,          4      ^4      /NK,  	  p6p=T:P                  4       '       d   T5e   T;! T:4      p>T>'       d   \)        \        T>Rx,          ^,          4      ^4      p?\)        T?T5,
          ^4      p7T> U=u/ uF  p=T=^ ,          \        T=^,          4      bK  	  p@p=T6 Uu. uFF  pTRm,          X@9   g   K  RmTRm,          Ro\)        X@TRm,          ,          TRn,          ,
          ^4      /NKH  	  p8pRpTP                  R4      RqTP                  R/. 4      RnT5RrT6RsT7RtT8/TR:&   T#   \         d>     \         P                  RRR7      P                  4       p  ELT  \         d      R# i ; ii ; i  \         d     ELi ; i  \         d     ELRi ; i  \         d     E
Li ; iu upi u upi   \         d    . TR.&   . TR/&    ELi ; i  \         d   pRTR9&   RTR;&    Rp?ELCRp?ii ; i  \         d
    RTR6&    EL^i ; i  \         d     ELXi ; i  \         d     ELSi ; iu upi u upi   \         d   p3 Rp3?3ELmRp3?3ii ; i  \         d%   p3\I        RfRgT3 24       . TRd&   . TRe&    Rp3?3EL!Rp3?3ii ; iu up=i u up=i u upi   \         d@   p3\I        RuT34       RpTP                  R4      RqTP                  R/. 4      /TR:&    Rp3?3T# Rp3?3ii ; i)zz1Parse live_monitor.log and extract current state.Nr   ignore)r   errorscp1252	timestampzscorer   positionNonerate_statusUpdatedr   r   r   r   r   r   r   r   state_eurusd.jsonz	utf-8-sigr   last_zscore	eu_zscorestate_usdjpy.json	uj_zscorer   r   r   zlive_monitor.logzRate data updated successfullyzRate update failedFailedz(\d{4}-\d{2}-\d{2} \d{2}:\d{2})z] [EURUSD] Z-score:zZ-score:\s*([-\d.]+)r:   zz] [USDJPY] Z-score:zCurrent z-score:zCurrent z-score:\s*([-\d.]+)c                     V R ,          # r:   r   r  s   &r    r  parse_log.<locals>.<lambda>      afr   )r  c                     V R ,          # r  r   r  s   &r    r  r    r  r   zscore_historyuj_zscore_history	closed_atrq   :N   Nz2026-:   r  Nr   heatmap_2026zheatmap_data.jsoneurusdheatmap_eu_allusdjpyheatmap_uj_allcutover_monthz2026-04heatmap_cutoverposition_openentry_priceposition_signalLONGSHORTz @ _armedactiveFtarget_price	directionzArmed r   z.5fArmeduj_position.3frK   rF   rH   rJ   mt5_live
pnl_sourcejson_fallbackpairrM   rN   c                 `   V '       g   R ^ RRR^ R^ RR/# V  Uu. uF  qP                  R^ 4      NK  	  pp\        R V 4       4      pR \        V4      R\        \        V4      ^4      RTR\        V4      V,
          RV'       d%   \        V\        V4      ,          ^d,          ^4      /# R/# u upi )r   r   r   r   r   r   r   c              3   6   "   T F  q^ 8  g   K  ^x  K  	  R# 5ir   r   r   s   & r    r!   2parse_log.<locals>._trade_stats.<locals>.<genexpr>I  s     /#QQqq#r#   )r0   r3   r1   r2   )tradesr:   r;   r   s   &   r    _trade_statsparse_log.<locals>._trade_statsF  s    =;s6!HUVWabe"ff/56v!551%vC6/#//D!3s8[%C:KD(CHTMcd3s8mC&7 :L LGJL L 7s   B+rL   r9   usdjpy_tradeseurusd_tradeseu_pnluj_pnlcombined_pnltotal_trades	portfoliosignal_outlookusdjpy_outlookz	[WARNING]zSignal outlook failed: r   ratesjp2y.csvus2y.csvc                   < . pSP                  \        V 4      4       F9  p\        V4      ^8  d   K   \        V^,          4       VP	                  V4       K;  	  V#   \
        \        3 d     KS  i ; i)z>Read CSV rows, skipping header and any non-numeric value rows.)readeropenr1   floatr   
ValueError	TypeError)r8   r5   r_csvs   &  r    
_safe_rowsparse_log.<locals>._safe_rows  sh    F[[d,q6A:x!A$KMM!$	 - M #I. s   #AA21A2r  jp2yspreadr6  	z_historyjp2y_seriescurrent_spreadspread_historyz[WARNING] uj block:)r  i)&LOG_FILEr)   r+   
splitlinesr/   r   rQ   	isoformatr'   r(   r*   r0   r  r&  r'  r-   researchgroupr   r2   valuessortcalendarr>   
startswithr   r   r*  r<   updater[   r4   rM  rE  rx  rT   csv)Blinesr   rU   eu_state_patheu_stateeu_zuj_state_pathuj_stateuj_z
eu_history
uj_historycutoff	all_linesold_loglinem_ttsm_zrZ   r  r  monthly_2026r:   closed	month_idx	now_monthr:  _json_hm_hm_path_hm_hm_er'   
state_pathstateentryr  armedtarget_json_ujuj_entryuj_directionuj_armed	uj_target	mt5_statsrW   r6   eu_trades_rawuj_trades_rawr  uj_statseu_stats_e	rates_diruj_jp2yuj_jp2y_ser	uj_spreaduj_spr_hist	jp2y_path	us2y_pathr  rowsr  us_rowsus_lastus_dictr  sB                                                                    @r    	parse_logr  t  sn   ??	 ""GH"EPPR 	002	D
!F*V36II!!{{=#:#:K#:#PQH<<.D$)$KX$)$K[!	!F*V36II!!{{=#:#:K#:#PQH<<.D$)$K[!
.'

,,.:j#9#C#C#C#LLWWYZ]^ K	f$v-0BB>>#--wx-P[[]`ii	 D/47&/]#%-88M*,>*2D'))>EC1B#w$,ii 7>
))3CuSYYq\?RTU9V*WX3&$.ii 7>
))3CuSYYq\?RTU9V*WX3#t+ii ?F3
))3CuSYYq\?RTU9V*WX+ 0 j9j1S619j9@@BC
j9j1S619j9@@BC
,-,-$.tu$5$.tu$5 !$!#638L{B/3$$W-- #F3K 01 4II***$Y/5y!9L3MM/  !,,I9b)"&Q *#/D 	/'$v-69LLnnX%7%7%7%IJ*-''(B*?%&*-''(B*?%&*-''/9*M&'- <'&03FF
JJz33[3IJEyy))		-4&+ii0A&Ba&GFW	&/[E7#;Z  		(B/99Xu--"YY~r:F*/))K*@A*E7IPV	{%s|'L\cD$'-D$!F*V36II!!~~m&=&={&=&STH||O,,#<<r:)16G)HA)MvSZ)5c(&D]##<<"5<<%00 (^R @I-5\\+-F!-K6QXL.7 .4L>yQTo+V=D ' +1D'
 &'IKK	 $%D $[ 1[ $\ 2\ #D$7}VW9X Y]"&'8"9"&'7"8"&~"6^ #Ck): ;X'\,\(%'
$.WJq!%%r2B2H2H2Jh2VJW$.WJq!%%r2B2H2H2Jh2VJW	L  .. &*:&6x&@H[!&*:&6x&@H[!&)(=*A4CVW_C`&aH]#&)(=*A4CVW_C`&aH]# (_ (_ H[1H[1E(;"7(;:O"OQRSH]3h}6MM	
[%TXXk*GGdhhx.@GGCHTXXk*11c2"4T":";D"A7
&(507:		
*	
*	
	 i(D#E$r(1+$6:(,ST
4(21 !'!feE!A$K6JK(2  4 '"5 +G!%A"7;!'G"3Q7	8?@1QqT51;.@ ) )AfI,@IVQvYuWQvY%7!F)%CQGI(   dhh{3dhh':B?gkik
X Ke	  	&&&JUUWE 		:      6 :9
  '$&$& !'>  /*.%&*.%&/  $#^$,  2  : XWH    %k4RD9:"$"$%B4 A  
#R(+."5r:
X
 K
sG  %q$ <4r/ 1Ar/ 4s 9As >B
s/ 	(s 1As/ As/ A s/ /As/ 6s/ As/ s%0s/ s*!As/ -At. %t. /A2t. "A?t $4u 8u 6u 	)u 33u 'u 6u <4u 17u )6u  )u 
3u >u u ?u3 'u)9u)?u3 'u.1u.7C u3 v 5v #v 2#v Aw +w ;*w %0v>w -w :w ;#ww $w97w02w $r,0%rr(#r,'r((r,/r>=r>sss"s/ !s""s/ /ttt+
t& t. &t++t. .uuuuu&%u&)
u3 3v	v	v;v66v;>w x4xxr  SOFREFFR
SOFR_tried
EFFR_triedc                   ^ RI pVP                   P                  4       P                  4       p\        R,          V8w  d.   V\        R&   R
\        R&   R
\        R&   R\        R&   R\        R&   V R,           p\        P	                  V4      '       d   \        P	                  V R
4      # R	\        V&   V! W4      w  rgWg3\        V &   Wg3# )zFetch a FRED series at most ONCE per calendar day, success or fail.
Returns (value, date) - may be (None, None) if today's single attempt
failed, in which case the caller falls back to the cached CSV.Nr  r  r  Fr  r  _triedTNN)r   rQ   r  _fred_daily_cacher0   )	series_idcsv_pathfetch_fnrw  today	tried_keyvalvdates   &&&     r    _fred_cachedr&    s     LL##%E E)$)&!$0&!$0&!*/,'*/,'H$I Y'' $$Y==#'i ).JC$'<i <r   c                    / p \         R,          R,          R,          pVR,          pVR,          p ^ RIp^<pVR,          pVP                  4       '       d   VP                  \	        V4      4       Uu. uF'  p\        V4      ^8X  g   K  V^,          R,9  g   K%  VNK)  	  ppV'       d   \        VR-,          ^,          4      V R&   VR-,          ^ ,          V R	&   W) R p	V	 Uu. uF  p\        \        V^,          4      ^4      NK!  	  upV R
&   V	 Uu. uF  qw^ ,          NK  	  upV R&   VR,          p
V
P                  4       '       d   VP                  \	        V
4      4       Uu. uF'  p\        V4      ^8X  g   K  V^,          R,9  g   K%  VNK)  	  ppV'       d   \        VR-,          ^,          4      V R&   VR-,          ^ ,          V R&   W) R p	V	 Uu. uF  p\        \        V^,          4      ^4      NK!  	  upV R&   V	 Uu. uF  qw^ ,          NK  	  upV R&   VR,          pVP                  4       '       d   VP                  \	        V4      4       Uu. uF'  p\        V4      ^8X  g   K  V^,          R,9  g   K%  VNK)  	  ppV'       do   \        VR-,          ^,          4      V R&   VR-,          ^ ,          V R&   W) R p	V	 Uu. uF*  pRV^ ,          R\        \        V^,          4      ^4      /NK,  	  upV R&   R R lp\        RY-4      w  rTe
   YR&   YR&   M ^ RIpTP                  4       '       d   TP                  \	        T4      4       Uu. uF'  p\        T4      ^8X  g   K  T^,          R,9  g   K%  TNK)  	  ppT'       d0   \        TR-,          ^,          4      T R&   TR-,          ^ ,          T R&   \        RY=4      w  ppTe   TT R&   M ^ RIpTP                  4       '       dp   TP                  \	        T4      4       Uu. uF'  p\        T4      ^8X  g   K  T^,          R,9  g   K%  TNK)  	  ppT'       d   \        TR-,          ^,          4      T R&   RT 9   d,   RT 9   d%   \        T R,          T R,          ,
          ^4      T R &   RT 9   d3   RT 9   d,   \        T R,          T R,          ,
          ^d,          ^4      T R!&   RT 9   d,   RT 9   d%   \        T R,          T R,          ,
          ^4      T R"&    ^ RIp^ R#IHp \         R,          R,          R,          R,          pTP                  4       '       d   . pTP                  \	        T4      4       F8  p\        T4      ^8  d   K  \        T^,          4       TP                  T4       K:  	  \        T4      ^8  dP   TR.R p	T	 Uu. uF  p\        \        T^,          4      ^4      NK!  	  upT R$&   T	 Uu. uF  qw^ ,          NK  	  upT R%&   R$T 9  dy   RT 9   dr   T R,          p^ R&IHp \!        ^R-R-4       Uu. uF0  pTP#                  4       T! TR'7      ,
          P%                  R(4      NK2  	  ppT.\        T4      ,          T R$&   TT R%&   RT 9   d,   RT 9   d%   \        T R,          T R,          ,
          ^4      T R)&   R
T 9   d   RT 9   d~   T R,           Uu/ uF  qwR,          TR,          bK  	  pp\'        T R,          T R
,          4       UUu. uF-  w  ppTT9   g   K  RTR*\        TTT,          ,
          ^4      /NK/  	  uppT R+&   T # u upi u upi u upi u upi u upi u upi u upi u upi   \         d!   p\        T4      R,          T R&    Rp?ELRp?ii ; iu upi   \         d     ELi ; iu upi   \         d     ELUi ; i  \        \        3 d     EKr  i ; iu upi u upi u upi   \         d     ELyi ; iu upi u uppi )/u  
Fetches yield data for dashboard display.

US 2Y and DE 2Y: read from local CSV files maintained by live_signal_monitor.
SOFR and FFR: fetched from FRED API and cached locally.
No yfinance proxies — those return wrong rates (^IRX is 13-week T-bill, not 2Y).
r   r   r  zsofr.csvzffr.csvNr  
us2y_daily	us2y_dateus2y_series
us2y_timeszde2y.csv
de2y_daily	de2y_datede2y_series
de2y_timesr  
jp2y_daily	jp2y_dater  r  r  r   	csv_errorc                $    V ^8  d   QhR\         /# )rZ  r  )r   )formats   "r    __annotate__&fetch_yield_data.<locals>.__annotate__  s     ,  , 3 , r   c           
     4    ^ RI pRpRV R\        RRR^RR	/pVP                  W4^R
7      pVP                  ^8w  d2   \	        RV  RVP                   RVP
                  R,           24       R# VP                  4       P                  R. 4      pV'       g   \	        RV  R24       R# V Uu. uF,  qwP                  R4      R9  g   K  VR,          VR,          3NK.  	  ppVP                  4        V'       g   R# VP                  RRRR7      ;_uu_ 4       p	V F  w  rV	P                  V
 RV R24       K  	  RRR4       VR,          w  r\        V4      V3# u upi   + '       g   i     L-; i  \         d   p\	        RT  RT 24       Ru Rp?# Rp?ii ; i)u   
Fetch a FRED series via the official API and persist as 2-column CSV
(date, value) in chronological order. Returns (latest_value, latest_date)
or (None, None) on failure (no logging spam — caller decides how loud).
Nz3https://api.stlouisfed.org/fred/series/observationsr  r   	file_typer'   limit
sort_orderdesc)r   r   z	  [fred] r   r   Nx   Nobservationsz returned no observationsvaluerq   r  wr   )r   newline,
z fetch failed: r  ).rq   Nr  )r   r2  r0   r   rT   r   r'   r  r  writer  r/   )r  r   _rqr   r   r  obsocleanfrd  r   latest_date
latest_valr
  s   &&             r    _fred_api_fetch)fetch_yield_data.<locals>._fred_api_fetch  s   &	 "GCilf cfF B7A}}#	)F1==/AFF4L>RS##&&(,,~r2C	),EFG## 7:ccUU7^Sb=b,ai7,cEcMMO## sWbAAQ!DAGGqc1#RL) " B ',Bi#K*%{33 d BA  	  Ii[t<=		 sf   A*E/ -'E/ E/ &E/ *EEE/ 8E/ #E7E/ E/ E,	'E/ /F:FFFr  
sofr_daily	sofr_dater  	ffr_dailyspread_dailysofr_ffr_spread_bp
sofr_vs_2y)r'  sofr_series
sofr_timesr   r   rl   usjp_spread_dailyr  usjp_spread_series)rD  rq   VALUEr  r  )r(   r  r)   r  r  r1   r  r2   r/   r   r&  r   r'  r   r  r  r*  rQ   r(  zip)yieldsr  	sofr_pathffr_pathr  HISTORY_DAYSr  r  r  hist	de2y_pathr  rZ   rM  sofr_valrP  ffr_valffr_date_sc_td
sofr_path2	sofr_rowsr$  _dt2r:  datesjp_dictrd  r   s                                r    fetch_yield_datark    s    FF"U*W4IJ&II%H)+ 
*	"zz$y/: G:!1v{ '(t3E'E A:D G(-d2hqk(:|$(,R{#MN+HL(M1uQqT{A)>(M}%7;(<t!1t(<|$ 
*	"zz$y/: G:!1v{ '(t3E'E A:D G(-d2hqk(:|$(,R{#MN+HL(M1uQqT{A)>(M}%7;(<t!1t(<|$ 
*	"zz$y/: G:!1v{ '(t3E'E A:D G(-d2hqk(:|$(,R{#MN+26)826Q +1!A$eAaDkST@U)V26)8}%, ^ 'vyJH'|({		!!#&::d9o#> K#>aq6Q; +,Q47I+I #> K+0b!+=F<(+/8A;F;'
 &fhHGX%{	  #&::d8n#= K#=aq6Q; +,Q47I+I #= K*/R*<F;'
 v,&"8!&< 6,#77"<~ v+"7',L!F;$773>(C#$ v,&"8$< 6,#77 <|-'%/'9JF
IZZZ 01q6A:x1Q4[)"2"21"5 2 9~! GK(Lt!uQqT{1)=t(L}%7;(<t!1t(<|$&<6+A&C1#BB/1/ hhj3A;.88D/  1%(ECJ$6F=!$)F< 
 v,&"8&+< 6,#77'<"#=F#:171FG1FAV9ai'1FG F<0&2GH(
H1G| <VQ%GAJ":;H(
#$ MYG )N(<
G )N(<
G)8  +!!fTl{+BK
  		K  		4 #I.88 )M(<
1   H(
s  $] ] 2\-	\-\-A] !%\2
] \7!$] ] "\<9\<	\<A] %]6
]  ]$] 6] ])]9]?A] 0]1] ^ 3^ ^&^6^<9^ ^ )^ ^^,^2&^ 6A_ 81_ )#^1_ )%_

_ _)2_ 6__ 9_+1_0"_0-(] ^  ];;^ ^ ^^^ ^.-^.1__ __ _('_(c                 X   \         R,          R,          R,          p \         R,          R,          R,          pV P                  4       ;'       g-    VP                  4       ;'       g    \        P                  4       pV'       g   R# \        P                  4       '       d   \        4       M/ pVf   / p ^ RIpV P                  4       '       d_   VP                  V P                  RR7      4      pVP                  R4      f+   VP                  R	R
4      VR&   VP                  R	R
4      VR&   VP                  4       '       dJ   VP                  VP                  RR7      4      pVP                  R4      f   VP                  R	R
4      VR&   \        4       TR&   TP                  R\        P                  ! 4       P                  4       4      TR&    \         R,          R,          R,          pTP                  4       '       Ed   TP                  RR7      ;_uu_ 4       p\        P                  ! T4      pRRR4       / RXP                  R/ 4      bRTP                  R4      bRTP                  R/ 4      bRTP                  R/ 4      bRTP                  R/ 4      bRTP                  R/ 4      bRTP                  R/ 4      bRTP                  R/ 4      bRTP                  R/ 4      bR TP                  R / 4      bR!TP                  R!/ 4      bR"TP                  R"/ 4      bR#TP                  R#/ 4      bR$TP                  R$/ 4      bR%TP                  R%/ 4      bR&TP                  R&/ 4      bR'TP                  R'/ 4      bR(TP                  R(/ 4      /CTR)&   \!        TP                  R4      ;'       g    TP                  R4      ;'       g    R
4      p
\!        TP                  R4      ;'       g    R
4      pTP                  R+4      '       g   \#        T
4      TR+&   TP                  R,4      '       g   \%        T4      TR,&   \&        '       d    \(        P*                  ! \         4      TR-&   \.        P1                  \        P2                  ! T^R07      RR7       \5        T
4      R18  d   R2MR3p\5        T4      R48  d   R2MR3pTP                  R5^ 4      pTP                  R6R74      p\        R8\        P                  ! 4       P7                  R94       R:T
R; R<T R=TR; R<T R>T R?T 24       R#   \         d     ELi ; i  + '       g   i     EL; i  \         d   p	\        R*T	 24        Rp	?	ELRp	?	ii ; i  \         d+   p\        R.T 24       R/\-        T4      ./TR-&    Rp?EL<Rp?ii ; i)@zParse log and write JSON file for dashboard.
VPS detection: state files exist on VPS. Home machine just serves existing JSON.
Yield/outlook fetches run regardless of whether log file exists.
r   r   r  r  Nr   r   r  r  r   r  r  r[  r  outputzdashboard_equity.jsonmetricsgenerated_atequity_fixedequity_curve_fixedequity_compoundedequity_curve_compoundedequity_eurusd_fixedequity_curve_eurusd_fixedequity_eurusd_compoundedequity_curve_eurusd_compoundedequity_usdjpy_fixedequity_curve_usdjpy_fixedequity_usdjpy_compoundedequity_curve_usdjpy_compoundedequity_curve_dynamic_fixedequity_curve_dynamic_compounded!equity_curve_eurusd_dynamic_fixed&equity_curve_eurusd_dynamic_compounded!equity_curve_usdjpy_dynamic_fixed&equity_curve_usdjpy_dynamic_compoundedyearly_dd_fixedyearly_dd_dynamicdaily_pnl_fixeddaily_pnl_dynamicbacktestz/[WARNING] Could not load backtest equity JSON: r  r  regimez[regime] compute failed: r  )indentrG  SIGNALz	no signalrB   r   r  r  z  [%H:%M:%Sz] EU z=r   z | UJ z=z
 | trades=z | pos=)r(   r)   r  r  r'   r*   r+   r0   r/   rk  r   rQ   r  r  loadrT   r  rE  rx  _REGIME_AVAILABLEregime_livecompute_regimesr   	DATA_FILE
write_textdumpsr_  r(  )r  r  is_vpsr   _j2steq_pathrJ  eq_datar
  r  r  _reeu_siguj_sigtcposs                    r    
write_datar    sT   
 6!F*-@@H6!F*-@@H JJHOO$5JJ9JF"//++9;D|??8--w-?@Bxx$,$&FF=#$>[!$&FF=#$>X??8--w-?@Bxx$,$&FF=#$>[! )*DNhlln.F.F.HID$Ff$x/2II>>w//1))A, 0 gkk)R&@ gkk.&A  gkk2F&K	 
 $gkk2KR&P  &GKK8SUW,X  +GKK8XZ\,]  &GKK8SUW,X  +GKK8XZ\,]  -7;;?[]_3`  27;;?`bd3e  4'++Fikm:n   9'++Fnpr:s! " 4'++Fikm:n# $ 9'++Fnpr:s% ( "W[[1BB%G) * $W[[1Db%I+ . "W[[1BB%G/ 0 $W[[1Db%I1 D: +&CC$((8*<CCDD+&--#.D88$%%"4T":88$%%";D"A 	4(88CDN
 D3gFTd*XFTd*XF	-	#B
((:v
&C	C''
34 5s1VH %s1VH %4wse% &O   0//@  F?tDEEF$  	4-cU34&S
3DN	4sj   2T' A3T'  A	T' AU T90E#U U4 'T65T69U
		U U1U,,U14V)?V$$V)c                   d   a a ] tR tRt oRtRtV 3R ltR tR tR t	R t
R tV 3R	 ltR
tVtV ;t# )DashboardHandleri  aG  Serves dashboard.html and dashboard_data.json from BASE_PATH.

Protected resources (the dashboard HTML and its data JSON) require a
valid ?key=<token> query parameter. Tokens are managed by the live
signal monitor via Telegram (/grantdashboard, /revokedashboard).
Static assets (favicon etc.) are served without a token check.
c                F   < \         SV `  ! VR \        \        4      /VB  R# )	directoryN)super__init__r   r(   )selfargskwargs	__class__s   &*,r    r  DashboardHandler.__init__  s    $C#i.CFCr   c                    R # ry   r   )r  r4  r  s   &&*r    log_messageDashboardHandler.log_message  s    r   c           	         \         R,          R,          R,          pVP                  4       '       g   \        4       # \        P                  ! VP                  RR7      4      pVP                  R. 4       Uu0 uF7  pVP                  R4      '       g   K  \        VP                  RR4      4      kK9  	  up# u upi   \         d    \        4       u # i ; i)	u   Read dashboard_tokens.json and return set of valid token strings.

File is read fresh on each request — overhead is minimal (file is
small) and means token grants/revokes take effect immediately
without restarting the server.
r   r   zdashboard_tokens.jsonr   r   tokenstokenrq   )	r(   r)   setr'   r*   r+   r0   r   r/   )r  pr   r:   s   &   r    _load_valid_tokens#DashboardHandler._load_valid_tokens  s    	F"V+.EEA88::u::akk7k;<D59XXh5K '5KuuW~ ,Cgr*+5K ' ' ' 	5L	s3   0B< 	B< :B< 7B7B74B< 7B< <CCc                   a VP                  4       P                  R^4      ^ ,          o\        ;QJ d)    V3R lV P                   4       F  '       g   K   R# 	  R# ! V3R lV P                   4       4      # )z,Return True if path is a protected resource.?c              3   F   <"   T F  pSP                  V4      x  K  	  R # 5iry   )r  )r   r  
path_lowers   & r    r!   8DashboardHandler._path_requires_token.<locals>.<genexpr>'  s!     N5M:((++5Ms   !TF)r   splitr   _PROTECTED_PREFIXES)r  r8   r  s   &&@r    _path_requires_token%DashboardHandler._path_requires_token$  sU    ZZ\''Q/2
sNT5M5MNssNsNsNT5M5MNNNr   c                    RV9  d   R# ^ RI Hp VP                  R^4      ^,          pV! V4      pVP                  RR.4      ^ ,          P	                  4       # )z9Pull ?key=X from the URL. Returns empty string if absent.r  rq   )parse_qsr  )urllib.parser  r  r0   r,  )r  r8   r  qsr   s   &&   r    _extract_tokenDashboardHandler._extract_token)  sN    d?)ZZQ""zz%"&q)//11r   c                2   RP                  R4      pV P                  R4       V P                  RR4       V P                  R\        \	        V4      4      4       V P                  4         V P                  P                  V4       R#   \         d     R# i ; i)z3Send a friendly access-denied HTML page (HTTP 403).u0  <!doctype html><html><head><meta charset='utf-8'><title>Access required</title><style>body{font-family:system-ui,-apple-system,sans-serif;background:#f5f5f7;color:#1d1d1f;padding:60px 24px;text-align:center}h1{font-size:24px;margin-bottom:8px}p{color:#6e6e73;line-height:1.6}code{background:#e8e8ed;padding:2px 6px;border-radius:4px;font-size:13px}</style></head><body><h1>🔒 Private dashboard</h1><p>This dashboard requires a personal access link.</p><p>Message the bot on Telegram and use <code>/requestdashboard</code> to request access.</p></body></html>r   i  zContent-Typeztext/html; charset=utf-8zContent-LengthN)	encodesend_responsesend_headerr   r1   end_headerswfilerE  r/   )r  bodys   & r    _serve_access_denied%DashboardHandler._serve_access_denied2  s     &/ 	 	3)CD)3s4y>:	JJT" 		s   *B BBc                \  < V P                  V P                  4      '       g   \        SV `  4       # V P	                  V P                  4      pV'       dK   WP                  4       9   d7   V P                  P                  R ^4      ^ ,          V n        \        SV `  4       # V P                  4       # )r  )r  r8   r  do_GETr  r  r  r  )r  r  r  s   & r    r  DashboardHandler.do_GETK  s    ((337>####DII.U5577 		Q/2DI7>##((**r   )r8   )/dashboard.htmlz/dashboard_data.jsonz/dashboard_equity.jsonz/forecast.htmlz/forecast_data.jsonz/forecast_live.jsonz/walls.htmlz/walls_data.json)__name__
__module____qualname____firstlineno____doc__r  r  r  r  r  r  r  r  __static_attributes____classdictcell____classcell__)r  __classdict__s   @@r    r  r    s<     >D"O
22+ +r   r  c                      ^K\         n        \        P                  P	                  R\
        3\         4      ;_uu_ 4       p \        R\
         R24       V P                  4        RRR4       R#   + '       g   i     R# ; i)r  z	127.0.0.1z/  Dashboard server running at http://localhost:r  N)r  r   httpserverThreadingHTTPServerPORTrT   serve_forever)httpds    r    
run_serverr  Z  sY    !		(	(+t)<>N	O	OSX?v_UV 
P	O	O	Os   $A,,A=	c            	     ^	   \         P                  ! 4       p \        '       d   \        P                  R4      MRp\	        RV R24       \
        P                  P                  4       pRVR&   \        RRRR\        \        4      VR	7      p\         P                  ! 4       s \        P                  4       '       g/   \	        R
\         24        \        ;_uu_ 4        RsRRR4       R#  \         P"                  ! \$        P&                  \        \        4      .3R\(        /VB pVP*                  ^ 8w  dW   VP,                  ;'       g    VP.                  ;'       g    RRR P1                  4       p\	        RVP*                   RV 24       \4        P                  4       '       g/   \	        R\4         24        \        ;_uu_ 4        RsRRR4       R#  \         P"                  ! \$        P&                  \        \4        4      .3R\6        /TB pTP*                  ^ 8w  ds   TP,                  ;'       g    TP.                  ;'       g    RRR P1                  4       p\	        RTP*                   RT 24        \        ;_uu_ 4        RsRRR4       R#  \         P                  ! 4       s\        T ,
          P9                  4       pRpTP.                  ;'       g    RP;                  4        F.  p	T	P1                  4       p	RT	9   g   K  RT	9   g   K%  T	R,          p M	  T'       g   Rp\	        RTR RT 24       \        ;_uu_ 4        RsRRR4       R#   + '       g   i     R# ; i  \         P2                   dE    \	        R\(         R24        \        ;_uu_ 4        RsRRR4       R#   + '       g   i     R# ; ii ; i  + '       g   i     R# ; i  + '       g   i     R# ; i  \         P2                   dE    \	        R\6         R24        \        ;_uu_ 4        RsRRR4       R#   + '       g   i     R# ; ii ; i  \<         d   p
\	        RT
 24        Rp
?
EL.Rp
?
ii ; i  + '       g   i     R# ; i  \        ;_uu_ 4        RsRRR4       i   + '       g   i     i ; i; i) a  Background worker: runs extract + build subprocesses sequentially.

Runs in a daemon thread, never raises (failures are logged + swallowed).
On success, the build script overwrites dashboard_equity.json and the
HTTP handler picks it up on the next browser request automatically.
r  neverz)  [live-refresh] Starting (last success: r   r   PYTHONIOENCODINGTrP   )capture_outputr   r   r  cwdenvz1  [live-refresh] WARN: extract script missing at FNr   rq   z"  [live-refresh] extract returned r   z"  [live-refresh] extract timeout (u   s) — skipping rebuildz/  [live-refresh] WARN: build script missing at z   [live-refresh] build returned z   [live-refresh] build timeout (u   s) — abortedzlive trades:rM   r<  OKz  [live-refresh] Complete in rC   u   s — z%  [live-refresh] Failed (non-fatal): i8)r   rQ   _last_live_refreshr(  rT   osenvironcopydictr   r(   _last_live_refresh_attemptEXTRACT_SCRIPTr)   _live_refresh_lock_live_refresh_running
subprocessrunsys
executableLIVE_REFRESH_EXTRACT_TIMEOUT
returncodestderrstdoutr,  TimeoutExpiredBUILD_SCRIPTLIVE_REFRESH_BUILD_TIMEOUTrS   r  r/   )startedlast_str	child_env
run_kwargsr1tailr2elapsedsummaryr  rZ   s              r    _do_refresh_live_tradesr  a  s    llnG:L:L!**:6RYH	5hZq
AB 

!I$+I !	NJ "*9*$$&&EnEUVWh  $)!  g	^!454 B
 }}! 		44RYY44"de<BBD:2==/D6RS ""$$CL>RSB  $)!  A	\!232 B
 }}!		44RYY44"de<BBD8r$PQ.  $)!  5 " &\\^%/>>@ YY__"002D::<D%(d*:t*	 3
 G-gc]&	JK
  $)!  Q (( 	67S6TTklmL  $)!  Q	P  - (( 	45O4PP^_`(  $)!  -	&  ;5aS9::;  $)!  s  ,Q M(AM# M# /M# 	Q #Q N?AO' 0O' /O' OAQ (Q Q Q  Q Q*M 	#(N<Q N''N8	;N<<Q ?O	O$	'(Q Q P++P<	?Q  Q Q'Q"Q> "Q''Q> *Q;	>R,R		R,R)$R,c                    \         '       g   R# \        ;_uu_ 4        \        '       d    RRR4       R# \        ;'       g    \        p V eA   \
        P                  ! 4       V ,
          P                  4       pV\        8  d    RRR4       R# RsRRR4       \        P                  ! \        RR7      P                  4        R#   + '       g   i     L<; i)a  Decide whether a live-data refresh is due. Non-blocking.

Called from the main update loop. Spawns a daemon thread to run the
actual extract + build if (a) feature is enabled, (b) no refresh is
already running, and (c) enough time has elapsed since last refresh
ATTEMPT (success or failure). Throttling on failure prevents log spam
when MT5 is momentarily disconnected or scripts have issues.
NTr  daemon)LIVE_REFRESH_ENABLEDr  r  r  r  r   rQ   rS   LIVE_REFRESH_INTERVAL_SEC	threadingThreadr  r   )lastr  s     r    maybe_refresh_live_tradesr    s      		   
	
 *??-?||~,;;=G22 
	 !% 
 3DAGGI 
	s   CCACCC	zbuild_forecast.pyzforecast_data.jsonzforecast_build.logznotify_forecast.pyc                     ^ RI Hp Hp  ^ RIHp \         P
                  ! V! R4      4      pW1! ^R7      ,           #   \         d2    \         P
                  ! T P                  4      T! ^R7      ,
          p LJi ; i)u   FX session clock. Sessions roll at 17:00 New York (= broker
midnight): the returned datetime's .date() is the session date —
after Tue 5pm NY it reads Wednesday, and Sunday's rollover opens
Monday's session. UTC-4 fallback if tzdata isn't installed.)timezoner'  )ZoneInfozAmerica/New_York)hours)r   r  r'  zoneinfor  rQ   r/   utc)r  r'  r  nys       r    _session_nowr    sb    
 -=%\\(#567 	"""  =\\(,,')!*<<=s   "; 9A76A7c                 `   \         P                  4       '       g   R# \        4       p V P                  4       ^8  d   R# V P                  ^ 8X  d   V P
                  ^
8  d   R# \        P                  4       '       g   R#  \        \        RR7      ;_uu_ 4       p\        P                  ! V4      pRRR4       XP                  RR4      T P                  R4      8w  d   R# TP                  R	4      '       d   T P                  ^8  d   R# R#   + '       g   i     Ld; i  \         d     R# i ; i)
z3True when a new session's forecast should be built.FTr   r   Nsession_daterq   rl   anchor_pending)FORECAST_SCRIPTr)   r  r%  r   r   FORECAST_JSONr  r'   r  r/   r0   r(  )rC  rJ  r   s      r    _forecast_staler    s    !!##Ayy{avv{qxx"}!!-'22a99Q<D 3 xx#qzz*'== xx !!affqj 32 s0   ?D D/D D	D D D-,D-c                 L   \         P                   ! 4       \        ^ ,          ,
          R8  d   R# \        4       '       g   R# \        P	                  RR7      '       g   R# \         P                   ! 4       \        ^ &   R p \
        P                  ! V RR7      P                  4        R# )zNon-blocking: spawns build_forecast.py when a new session starts.
At most one attempt per 15 min (covers failures and pending anchors).i  NFblockingc            
          \        R \        4       R R24       \        \        RRR7      ;_uu_ 4       p V P	                  R\
        P                  ! 4        R24       V P                  4        \        P                  ! \        P                  \        \        4      .\        \        4      V \        P                  RR	7      pVP                   ^ 8X  dn   \"        P%                  4       '       dT   \        P                  ! \        P                  \        \"        4      .\        \        4      V \        P                  ^ZR	7       R
R
R
4       \        RXP                    R24       \(        P+                  4        R
#   + '       g   i     L?; i  \&         d   p\        RT 24        R
p?LGR
p?ii ; i  \(        P+                  4        i ; i)z"  [forecast] building for session rl   z ...ar   r   
=== build  ===
i,  r  r  r  r   Nz"  [forecast] build finished (exit r   z  [forecast] build failed: )rT   r  r  FORECAST_LOGrE  r   rQ   flushr  r  r  r  r   r  r(   STDOUTr  FORECAST_NOTIFY_SCRIPTr)   r/   _forecast_lockreleaselfr  rZ   s      r    _run$maybe_refresh_forecast.<locals>._run  s=   	%6|~h6OtTUlC'::b<'7v>?
NN^^S%9:Ir%,,c
 <<1$)?)F)F)H)HNN-C)DE	N2)00" ; 6q||nAFG ""$% ;:  	5/s344	5 ""$sH   2F B6E5+AE5>!F 5F	 F F+F&!F. &F++F. .GTr  )r   _forecast_last_attemptr  r(  acquirer
  r  r   r,  s    r    maybe_refresh_forecastr1    st     yy{+A..4!!5!11 $		1%. D.446r   zupdate_live_quotes.pyc                    \         P                  4       '       g   R# \        P                  ! 4       \        ^ ,          ,
          ^<8  d   R# \	        4       P                  4       ^8  d   R# \        P                  RR7      '       g   R# \        P                  ! 4       \        ^ &   R p \        P                  ! V RR7      P                  4        R# )zARuns update_live_quotes.py roughly once a minute during sessions.NFr  c                      \         P                  ! \        P                  \	        \
        4      .\	        \        4      \         P                  \         P                  ^7R7      p V P                  ^ 8w  d   \        RV P                   R24       \        P                  4        R#   \         d   p\        RT 24        Rp?L4Rp?ii ; i  \        P                  4        i ; i)7   r#  z  [quotes] update failed (exit r   z  [quotes] update failed: N)r  r  r  r  r   LIVE_QUOTES_SCRIPTr(   DEVNULLr  rT   r/   _live_quotes_lockr)  )r  rZ   s     r    r,  'maybe_refresh_live_quotes.<locals>._run;  s    	(%7!89	N:+=+=!))2A
 ||q 7~QGH %%'  	4.qc233	4 %%'s*   BB# #C.C<C	 CC	 	CTr  )r5  r)   r   _live_quotes_lastr  r%  r7  r/  r
  r  r   r0  s    r    maybe_refresh_live_quotesr:  /  s    $$&&yy{&q))B.~1$$$e$4499;a( D.446r   zbuild_walls.pyzoi_data.xlsxoi_pdfszwalls_data.jsonzwalls_build.logc            	     <   . p  \         P                  4       '       dh   \        \         P                  R4      4       FE  p V P	                  VP
                   R\        VP                  4       P                  4       24       KG  	  \        P                  4       '       d;    T P	                  R\        \        P                  4       P                  4       24       RP                  T 4      #   \         d     K  i ; i  \         d     Li ; i  \         d     LAi ; i)zFingerprint of the OI sources: top-level PDFs in oi_pdfs
(history\ ignored) plus oi_data.xlsx if present. Must match
what build_walls.py writes as source_sig.z*.pdfr   zxlsx:|)WALLS_PDF_DIRis_dirr5  globr   namer   statst_mtimeOSErrorr/   
WALLS_XLSXr)   join)partsr  s     r    _walls_signaturerH  V  s     E!!M..w78LLAFF81S1B1B-C,D!EF 9 	LL5Z__%6%?%?!@ ABC 88E?   
  		sM   C< !C<  AC*C<  9D *C95C< 8C99C< <D
	D
DDc                    \         P                  4       '       g   R# \        4       p V '       g   R# \        P                  4       '       g   R#  \	        \        RR7      ;_uu_ 4       p\
        P                  ! V4      P                  RR4      pRRR4       W8g  #   + '       g   i     T X8g  # ; i  \         d     R# i ; i)z6True when the OI sources changed since the last build.FTr   r   
source_sigrq   N)	WALLS_SCRIPTr)   rH  
WALLS_JSONr  r'   r  r0   r/   )sigrJ  dones      r    _walls_stalerO  l  s      

C*w//199Q<##L"5D 0 ;	 0/ $;  s0   B1 ''BB1 B.	%B1 .B1 1C ?C c                 L   \         P                   ! 4       \        ^ ,          ,
          R8  d   R# \        4       '       g   R# \        P	                  RR7      '       g   R# \         P                   ! 4       \        ^ &   R p \
        P                  ! V RR7      P                  4        R# )zARebuilds walls whenever a new oi_data.xlsx lands (OneDrive sync).iX  NFr  c            
      x    \        R 4       \        \        RRR7      ;_uu_ 4       p V P                  R\        P
                  ! 4        R24       V P                  4        \        P                  ! \        P                  \        \        4      .\        \        4      V \        P                  ^R7      pRRR4       \        RXP                   R	24       \"        P%                  4        R#   + '       g   i     L?; i  \          d   p\        R
T 24        Rp?LGRp?ii ; i  \"        P%                  4        i ; i)u6     [walls] new oi_data.xlsx detected — rebuilding ...r   r   r   r!  r"  r#  Nz  [walls] build finished (exit r   z  [walls] build failed: )rT   r  	WALLS_LOGrE  r   rQ   r%  r  r  r  r  r   rK  r(   r&  r  r/   _walls_lockr)  r*  s      r    r,  !maybe_refresh_walls.<locals>._run  s    	"JKiw772<'7v>?
NN^^S%67Ir%,,c 8 3ALL>CD ! 87  	2,QC011	2 !sA   %C= BC*3!C= *C:	5C= =D DD# D  D# #D9Tr  )r   _walls_last_attemptrO  rS  r/  r
  r  r   r0  s    r    maybe_refresh_wallsrV  }  sp    yy{(++c1>>..!YY["" D.446r   c                  b   \        R4       \        R4       \        R\         24       \        R\         24       \        R\         24       \        R,          R,          R,          p \        P                  4       '       g   V P                  4       '       d   \        R4       M\        R	4        \        '       d,   \        \        4      ^8  d   \        R
\        RR  R24       M\        R4        \        '       d   \        ^<,          p\        P                  4       ;'       d    \        P                  4       pV'       d   \        RV R24       M. p\        P                  4       '       g   VP                  R4       \        P                  4       '       g   VP                  R4       \        RRP                  V4       R24       M\        R4       \        R4       \        P                   ! \"        RR7      pVP%                  4        \        R\         R24       \        R4         \'        4        \)        4        \+        4        \-        4        \/        4        \0        P2                  ! ^4       KL    \         d    \        R4        ELi ; i  \4         d    \        R4        R# i ; i)=zDASHBOARD SERVERz  Log file : z  Data file: z  Port     : r   r   r  z$  Mode     : VPS (writing live data)uG     Mode     : Home machine (read-only — serving VPS data via OneDrive)z-  Calendar : FinanceFlow API enabled (key ...Nr   z.  Calendar : FinanceFlow DISABLED (no API key)z2  Calendar : FinanceFlow DISABLED (no API key set)z  Live-refresh: ENABLED (every u/    min) → fires on first request after intervalr   r   z#  Live-refresh: DISABLED (missing: z, zQ  Live-refresh: DISABLED (set LIVE_REFRESH_ENABLED=True in server file to enable)Tr  z%
  Open in browser: http://localhost:z/dashboard.html
z.  Updating every 30 seconds (Ctrl+C to stop):
z
  Dashboard server stopped.z<============================================================i)rT   r  r  r  r(   r)   r   r1   	NameErrorr  r	  r  r  r   rF  r
  r  r  r   r  r  r1  r:  rV  r   sleepKeyboardInterrupt)eu_stminsokmissingserver_threads        r    mainra    s   	(O	
	M(
$%	M)
%&	M$
 !'*==EELLNN46WYE:#j/A-A*RS/ARRSTUBD (B.""$>>)<)<)>3D69hijG!((**GNN;S,T&&((GNN;R,S7		'8J7K1MNac	(O $$JtDM	24&8I
JK 

;<

	L%'"$%'!JJrNA  EBDEB ! 	12	s1   0I7 <*I7 'I7 -AJ 7JJJ.-J.__main__c                    V ^8  d   Qh/ ^ \         9   d   \        R,          ;R&   ^\         9   d   \        R,          ;R&   ^\         9   d
   \        ;R&   # )rZ  Nr  r  r  )__conditional_annotations__r   bool)r4  s   "r    r5  r5     sP      ~ + *HtO *@ 3 2HtO 2AB $ #t #Cr   )z
2026-03-19z
2026-04-30z
2026-06-11z
2026-07-23z
2026-09-10z
2026-10-29z
2026-12-17)z
2026-01-28z
2026-03-18z
2026-04-29z
2026-06-17z
2026-07-29z
2026-09-16z
2026-10-28z
2026-12-09)r   r  )hrd  r  r'   r  r  r  r   r  http.serverr  r
  pathlibr   r   __file__resolveparentsr(   r  r  r  r  r   	_src_pathr8   insertr  r/   r
  rT   r  r	  r  r  r  r  r  r  r  Lockr  r<   r>   STARTING_BALANCEr[   r   r2  r   r   r   r-  r.  r   r&  r'  r(  r/  r$  r   r   rE  r)  ru  rl  r+  rx  rv  r  r  r&  rk  r  r  SimpleHTTPRequestHandlerr  r  r  r  r  r  r$  r'  r(  r.  r  r  r1  r5  r7  r9  r:  rK  rE  r>  rL  rR  rS  rU  rH  rO  rV  ra  r  r5  )rd  rd  s   0@r    <module>rp     s    	 	 
      (^##%--a0	&(+@@..	  UI%34I 9% !%  $  "  # U"Z/2JJU"Z/2II&*  *.2  2#  #^^% *Z$  -d R
1 " "  "  "	 
 "  "  "  "  "  "  "  "  "  "  "   "! " "# $ "	"""""""""""""? B"" " "	
 " " " " " " " " 
" " "  "!" "#$ ""'.


,
.>
"
$0
 
 +
 -5
 7?
 	
 	
 '	

 

 

 '

 )4

 6A
 
 .
 0G
 
 )
 +:
 
 ,
 .;
 
 
 %
 '-
 /6
     q$Z
%;%E%EA%E%NNXXYcd 
 $	40+\:zd,N4 i|TJ tYgtUDQ"E/P0|D
 T\6<!5,? .BJe&PZ+t{{;; Z+zV*rJ6 e#k14GG22f$v-0DD"U*[8;OO ! #2"7L &47NN NN$ E 7< 5 ;.1AA>)
I%,,
6!F*->>	nne ,"7<4n zF O5  U	+B4/R
STTUBs%   &O ("O AO>O;$O66O;