
    pjTK                    2   d Z ddlmZ ddlZddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlZddlmZ dd	lmZmZmZ dd
lmZmZ ddlmZ ddlmZ ddlmZmZmZmZmZm Z  ddl!m"Z" ddl#m$Z$ ddl%m&Z&m'Z' ddl(m)Z)m*Z*m+Z+m,Z,m-Z-  e
d      Z. ee/      ja                         jb                  d   Z2e2dz  dz  dz  Z3e3dz  Z4e3dz  Z5d(dZ6dd	 	 	 	 	 	 	 d)dZ7	 	 	 	 	 	 	 	 d*dZ8ddd+dZ9d,dZ:d-d Z;d.d!Z<dd"ddd#	 	 	 	 	 	 	 	 	 	 	 	 	 d/d$Z=dd"d%	 	 	 	 	 d0d&Z>d1d'Z?y)2z
Live Best Ideas fund signals sourced from IBKR (bars + portfolio + VRP cycle).

Writes ``RenTech/data/logs/live_fund_signals.json`` for the command center UI.
    )annotationsN)datetime)Path)Any)ZoneInfo)fetch_daily_panel)
connect_ibdisconnect_ibensure_positions_loaded)BrokerConfigload_platform_config)fetch_portfolio_snapshot)VrpIbkrStrategy)MACRO_TICKERSSLEEVE_LABELS_actions_from_recommendations_compare_etf_book_ib_stock_mv
_read_json)STRATEGY_DEFINITIONS) FUND_WEIGHT_TABLE_TACTICAL_TSMOM)SPDR_SECTOR_TICKERSSectorETFRotation)BASE_WEIGHTSBOND_TICKERSTacticalAWConfigTacticalAllWeatherManager_momentum_from_closezAmerica/New_York   RenTechdatalogszlive_fund_signals.jsonz#tactical_aw_variant_sweep_best.jsonc                    t        t              } t        | t              rt        | j	                  d      t              r| d   }t        t        |j	                  dd            t        |j	                  dd            t        |j	                  dd            t        |j	                  dd	            t        |j	                  d
d            t        |j	                  dd            t        |j	                  dd	            t        |j	                  dd            t        |j	                  dd            	      S t        d      S )Nconfig
sma_window   mom_skip_days   mom_lookback_days   mom_thresholdg        weight_modebinarypartial_fracg      ?risk_on_min_investedbond_baseline_mult      ?cash_annual_yieldg{Gz?)	r%   r'   r)   r+   r,   r.   r/   r0   r2   gffffff?)r0   )	r   TACTICAL_CONFIG_PATH
isinstancedictgetr   intfloatstr)rawcfgs     5/opt/rentech/trading_bot/RenTech/live/fund_signals.py_load_tactical_configr=   0   s    
)
*C#tCGGH,=t!D(m377<56cggor:;!#''*=s"CD =>CGGM8<=sww~s;<!&sww/Es'K!L$SWW-A3%GH#CGG,?$FG

 
	
 s33       top_kc          	        g }| j                         D ]  \  }}|j                  sd|j                  vr!|j                         }t	        j
                  |j                        j                  d       |_        t        |d   j                  d         }||k(  s|j                  ||f        |j                  d        g }t        |d      D ].  \  }	\  }}|j                  ||	t        |d      ||v |	|k  d       0 |S )	Naqr_momc                    | d    S )N    )xs    r<   <lambda>z-_sector_rankings_from_panel.<locals>.<lambda>Q   s    QqTE r>   keyrF   )start   )tickerrankrC   heldin_top_k)itemsemptycolumnscopypdto_datetimeindextz_localizer8   ilocappendsort	enumerateround)
etf_dicttargetsrA   rowstkrdfdfxmomoutis
             r<   _sector_rankings_from_panelrh   B   s     %'D>># $R88y

2ggiNN399-99$?	C	N''+,#:KKc
#$ 	II/I" "C"4q1 	
:C

 a=wJ	
	
 Jr>   c                t   |j                   rg S |j                         }t        j                  |j                        j                  d       |_        t        j                  j                  t              j                         j                  d       }||j                  |k     j                  j                         }|j                  |   }t        dt        |j                              }g }t        j                         D ]  \  }	}
|	| vr| |	   j                         }t        j                  |j                        j                  d       |_        t!        |d   j"                  d         }t!        |d   j%                  ||      j'                         j"                  d         }t!        t)        |d   t        |j*                        t        |j,                              j"                  d         }t!        |
      |	t.        v rt!        |j0                        ndz  }t!        |j3                  d|	 d	            }|j5                  |	t7        |d
      t7        |d
      t7        |d      t9        ||kD        t9        |t!        |j:                        kD        t7        |d      t7        |d      d        |S )Ntz   closerD   )min_periods)skiplookbackr1   weight_r   r   rM   )rN   rm   smamomentumtrend_okmom_okbaseline_weighttarget_weight)rS   rU   rV   rW   rX   rY   	TimestampnowNY	normalizemaxlocr7   r%   r   rR   r8   rZ   rollingmeanr   r'   r)   r   r0   r6   r[   r^   boolr+   )
macro_dicttac_portr$   porttodaydrowsma_wchecksrb   base_wrc   rm   rr   re   bwtws                    r<   _tactical_gate_checksr   `   sB   
 ~~	==?D

+77=DJLL#--/;;DAETZZ5 !''++-A
((1+CC))*+E#%F#))+ 
Vj _!!#>>"((+77=bk&&r*+BwK''5'AFFHMMbQR 7--.V556 d2	
 6]#BUeF$=$=>[^_377WSE?A./uaS!}!#qM -sU6+?+?%@@A#(Q<!&r1		
!
8 Mr>   c                  t               }|j                  | |      }dd|dd}|j                  r
d|d<   i ||fS t        j                  |d         j
                  j                         |d<   t        j                  j                  t        	      j                         j                  d       }||d   |kD     }t        |      r|d   j                         }d
}n||d   |k     d   j                         }d}||d   |k(  |d   j                  t              dkD  z     }	|	j!                         D 
ci c]   \  }
}t#        |d         t        |d         " }}
}t        ||d   |k(           r||d   |k(     j$                  d   nd }|j'                  ||t#        |d         nd t#        t        j                  |      j)                               |	j*                  |	d   dk(  df   j                  t"              j-                         |j*                  |d   |k(  |d   dk(  z  df   j                  t"              j-                         t/        |j1                               d       |||fS c c}}
w )Nr@   okibkr_historical_barslive_sector_rebalance)statussourcerA   pathrS   r   effective_daterj   upcomingcurrentweightr   rN   signal_dateis_new_entryTis_exit_from_prior)moder   r   new_entriesexits_from_priortickers)r   generate_rebalance_logrS   rV   rW   dtr{   rx   ry   rz   rY   lenminr|   astyper8   iterrowsr9   rZ   updatedater}   tolistlistkeys)r_   rA   rotlog_dfmetar   futureeffr   grp_rr`   sig_rows                 r<   _sector_targets_from_panelr      s}   

C'''>F('	D || X4!~~f5E.FGJJTTVFLL#--/;;DAEF+,u45F
6{%&**,V,-678HIMMO
&)*c1fX6F6M6Me6TWX6XY
ZC@CO1s1X;q{!33OGOADVFScLdhkLkElAmfV,-45::1=swGKK:A:M3w}56SW!",,s"3"8"8":;773~#6$#>#HIPPQTU\\^ &

()S0V<P5QUY5YZ! VC[VXGLLN+	
 D&  # Ps   3%I,c                   | j                   ri dddfS | j                         } t        j                  | j                        j                  d       | _        t        j                  j                  t              j                         j                  d       }d| j                  v r#| | j                  |k     d   j                         n| j                  j                         }| j                  |   }i }t        D ]%  }d| }||v st        ||         }|dkD  s!|||<   ' t        |j                  dd	t!        |j#                               z
              }d
dt%        t        j                  |      j'                               |t)        |j+                               t        |j                  dt!        |j#                                           d}	||	fS )NrS   r   )r   r   rj   r   rq   g&.>cash_weightr1   r   total_invested_weight)r   r   as_ofr   r   r   )rS   rU   rV   rW   rX   rY   rx   ry   rz   r{   rT   r|   r}   r   r8   r6   sumvaluesr9   r   r   r   )
r   r   r   r   r`   tcolwcash_wr   s
             r<    _tactical_targets_from_portfolior      s   zzg1GHHH99;D

+77=DJLL#--/;;DAE39T\\3ITZZ5 !&)--/tzz~~O_A
((1+C "G sm#:c#hA4x
 377=#GNN4D0E*EFGF(R\\!_))+,'!&sww/FGNNL\H]'^!_D D=r>   c                   | j                   D cg c]s  }|j                  |j                  |j                  |j                  |j
                  |j                  |j                  |j                  |j                  |j                  d
u }}| j                  j                         | j                  | j                  | j                  | j                   | j"                  | j$                  | j&                  |t)        |D ch c]  }|d   	 c}      D ci c]  }||D cg c]  }|d   |k(  s| c} c}}d
S c c}w c c}w c c}w c c}}w )N)
symbolsec_typeexpirystrikerightpositionavg_costmarket_valueunrealized_pnlcon_idr   )
r   net_liquidation_usdavailable_funds_usdexcess_liquidity_usdmaintenance_margin_usdunrealized_pnl_usdrealized_pnl_today_usdmargin_utilization	positionspositions_by_symbol)r   r   r   r   r   r   r   r   r   r   r   r   	isoformatr   r   r   r   r   r   r   sorted)	portfoliopr   symrH   s        r<   _portfolio_payloadr      s,    $$  hh

hhhhWW



NN..hh	
I   **,(<<(<< ) > >"+"B"B'::"+"B"B'::IOfoPpabQRS[Q\PpIq 
BECY=!H+*<!== 
 4 Qq= 
s*   A8D69D;
EE  'E  +E Ec                   K   ddl m} ddlm}  |ddd      }| j	                  |       d {     || |       d {   \  }}||t        ||kD        ddS 7 +7 w)	Nr   )get_spy_sma200)StockSPYSMARTUSDibkr)spy_last
spy_sma200spy_gt_sma200r   )'RenTech.strategy_stack.live_ibkr_traderr   	ib_insyncr   qualifyContractsAsyncr   )ibr   r   spyrr   lasts         r<   _spy_regime_gatesr      si     F
w
&C

"
"3
'''$R--ICdSj)	  (-s   +AAAAAAT)fund_weightsrun_vrpwrite_sector_csvwrite_tactical_csvc                 K   t        |xs t              }t        |j                               }|dkD  r&|j	                         D 	ci c]  \  }}	||	|z   }}}	t        |        d{    t        |        d{   }
t        |
j                        }t        |
      }t        |      }t        t        t              t        t              z  dhz        }t        dt!        |       dd       t#        | |d	       d{   }t        D ci c]  }||v s|||    }}t%        |d
      \  }}}t'        ||d
      |d<   |r<|j(                  s0|j*                  j-                  dd       |j/                  |d       t        D ci c]  }||v s|||    }}t1               }t3        |      }|j5                  |      }t7        |      \  }}|j8                  |d<   t;        |||      |d<   |r
|j*                  j-                  dd       g }|j<                  D cg c]  }|j?                  d      s| }}|j@                  D ]  }|s nt        |jB                  |df         }|D ]d  } | jE                  dd      }!|jG                  tI        jJ                  |      jM                  d      |!t        |jB                  || f         |d       f  |r&tI        jN                  |      j/                  |d       tQ        |        d{   }"g }#d}$|r|jS                  dd      dkD  rt        dd       ddl*m+}%m,}&m-}'  |'dddddt        |jS                  dd            d d!dd"d#d$d%&
      }( |%t\        d'z  d(t^        d)z  t\        d*z  t\        d+z  | |&dd,      |(f-      })dd.l0m1}* dd/l2m3}+m4},m5}- tm        jn                  tp              js                         }.tm        jn                  tp              }/ |+|)|
|.d| 0      }0|(}1 |-|1|
      }2 |,|1|
|0|2|)jt                  |.|/d1d2	      }3 |*d^i d3d4d5|.d6|/d7| d8|
d9|0d:|3d;dd<dd=d1d>|1jv                  d?|1jx                  d@t        |1jz                        dA|2dBt\        dC|)j|                  dD|)jt                  dE|1j~                  dF|1j                  dG|1j                  }4t               }5|5j                  |4       d{   }6|6j                  |6j                  |6j                  |6j                  xs i j	                         D 	ci c]  \  }}	|t        |	       c}	}dH}$t        d$      t        dI      t        dJ      fD ]?  }7t        |7      }8t        |8t               s|#jG                  i |8dK|7j                  i       A g }9|9j                  t        |#             |jS                  dLd      dkD  r#|9j                  t        dL||||dL   |M             |jS                  dNd      dkD  r#|9j                  t        dN||||dN   |M             dOD ]v  }:|jS                  |:d      dk  rt        jR                  |:|:      };t        jR                  |:i       }<|9jG                  dPdQ|:d|; dR||:   |<jS                  dSd      dTdUdV       x |9j                  dW X       tm        jn                  tp              j                         dY||d|dZ|"d[|i|d[|i|d|j8                  i|$|#d\|9t        |j                               t        t        |      t        |j                               z
        d]	S c c}	}w 7 7 7 gc c}w c c}w c c}w 7 m7 c c}	}w w)_zc
    Connect must already be established. Fetches IB history and optional VRP recommend cycle.
    r   Nr   z'[live_fund] Fetching IB daily bars for u    symbols …T)flushz2 Y)duration_strr?   r@   rankingsparentsexist_okF)rX   )r$   r$   gate_checksrq   r    z%Y-%m-%d)r   rN   r   r   	spy_thetau#   [live_fund] VRP recommend cycle …)PlatformConfig
RiskConfigStrategySlotvrp_corez0RenTech.live.strategies.vrp_ibkr:VrpIbkrStrategy
   nav_pctg)\(?r   rF   z1RenTech/strategy_stack/sleeve_risk_fractions.jsonz%RenTech/data/live_state/vrp_core.jsonz0RenTech/data/logs/ibkr_trade_recommendation.json)strategy_config_path
state_pathrecommend_out)
idenabledmoduleprioritycapital_budget_modecapital_budget_nav_pctmax_new_entries_per_daymax_open_positionsenabled_for_entriesr$   z&RenTech/live/config/live_fund_vrp.jsonlive_fund_vrplive_platformzRenTech/data/live_statezRenTech/live/config/KILL_SWITCH)recommend_onlyhalt_on_kill_switch)r   namelog_dir	state_dirkill_switch_pathbrokerrisk
strategies)StrategyContext)evaluate_platform_riskevaluate_strategy_riskstrategy_capital_budget)r  r   z15:40)capital_budget_usdr  r   now_etentry_after_etforce_entry_nowrun_idfund_signalsr   r  r   r   platform_riskstrategy_riskr  r  r  entry_before_etstrategy_idstrategy_configr  	repo_rootr  r  r  r  r	  )r   actionmessages	artifactsz=RenTech/data/logs/ibkr_trade_recommendation_r2a_diagonal.jsonz;RenTech/data/logs/ibkr_trade_recommendation_r2b_spread.json_sourcesector_momentum)bookr`   ib_mvfund_navfund_weightr   tactical_aw)
vxx_regimemacro_awvxx_long_calltsmom-   WATCHz/: use backtest model until IB live plugin addedrunnerzBTheta/VXX stack sleeves not yet driven from IB bars in this runner)r-  r5  note)r  r%  r*  r   summarydetailc                8    | d   | d   | j                  dd      fS )Nr  r%  r*  r   )r6   )as    r<   rI   z)build_live_fund_signals.<locals>.<lambda>  s     *q{AEE&"<MN r>   rJ   	ibkr_live)	connectedr   r`   )	spy_gatesr)  r.  	vrp_cyclerecommendations)	generated_atdata_sourcefund_nav_usdr   r   signalsactionsbars_fetchedbars_missingrG   )Ur5   r   r   r   rR   r   r   r8   r   r   r   r   setr   r   printr   r   r   rh   rS   parentmkdirto_csvr=   r   build_portfolior   __dict__r   rT   
startswithrX   r}   replacer[   rV   rx   strftime	DataFramer   r6   RenTech.live.platform_configr   r   r   _REPOLOGSRenTech.live.protocolsr  RenTech.live.risk_gater  r  r  r   ry   rz   r   r  r!  r  r$   r  r  r  r	  r   	run_cycler   r%  r&  r'  r9   r   r   r4   r  extendr   r   r   r   r\   r   r   )=r   r  r   r   r   r   weightswsumkvr   r,  
ib_payloadr+  symbolspanelsr   sector_dictsector_targetssector_meta
sector_logr   tac_cfgpmr   tactical_targetstactical_meta
alloc_rowscwcolsr   r   r   rb   r=  recs
vrp_reportr   r   r   vrp_slotmini_cfgr  r  r  r  r   r  r  slotbudget
strat_riskctxstratreportr   r!   rD  rK   labeldefns=                                                                r<   build_live_fund_signalsrw    s     <C#CDGw~~ Dax+2==?;41a1a$h;;;
!"
%%%.r22IY223H#I.J$ES,-M0BBeWLMG	3CL>
NVZ[$RuEEF)<LAV1fQi<LKL.H\].^+NK9+~]^_K

 0 0%%dT%B*%8(5E1f!VAY,EJE#%G	"'	2B!!*-H&Fx&P#m%..M(#8Xw#WM- !!''t'D
$,,HqY0GHH.. 	B8<<M(9:;F 	kk)R0!! "R 0 9 9* E"%"'RW(=">'-				 LL$++,>e+L'++I!#D(,J7;;{A.234@YYE )#([$)G#H$%  $([E!S
  "AA ?*77"%FF4TJ {	
 	;rrR %%'b!.xEZ^cef(y9+%(("!


  
!

 
 	

  
 (
 %
  
 "
 #
 !00
 
 !-
  &
 
  $$!
" ((#
$ %)$@$@%
&  $66'
( !% 8 8)
,  !s++))mm171A1A1GR0N0N0PQ1!SV)Q	

 CDPQNO
 	9A
 a=D$%7t7Y78	9 %'GNN067{{$a(1,&&!#$56 		
 {{=!$q("(!#M2"		
 D 
;;sA!#!!#s+#''R0!#W$ST#*3<"hhx4`	

( LLNLO !R(224" "<" )>I[I%'7e=e(T[TdTde##
 v{{}-s7|c&++-.@@A w <%2 FL F I$ ,Z ,
 Rs   A^]^(]#)^;]&<B^])^	],],!A*^	]1]1B^#]6:]6>C^];G^+]>,A^2^A^G^&^)^,^>^^)config_pathr   c                :  K   t        | xs	 t        dz        }t        |j                         d {   }	 t	        ||j                  |t
        dz  t
        dz         d {   }|t        |       d {    S 7 J7 7 	# t        |       d {  7   w xY ww)Nz.RenTech/live/config/live_platform_default.jsonz#sector_momentum_live_rebalances.csvz tactical_aw_live_allocations.csv)r  r   r   r   )r   rS  r	   r  rw  rT  r
   )rx  r   r;   r   payloads        r<   run_live_fund_signals_asyncr{    s     
 {hu7g/g
iC#**%	%B
 /::!$II#&HH
 
 B 
&
 	 mBsV   /BA<B+B "A>#B (B6B 7B>B  BBBBBc                    | j                         j                         } | j                  j                  dd       | j	                  t        j                  |dt              dz   d       | S )NTr   r   )indentdefault
zutf-8)encoding)
expanduserresolverI  rJ  
write_textjsondumpsr9   )r   rz  s     r<   write_live_fund_signalsr    sV    ??$$&DKKdT2OODJJwq#>EPWOXKr>   )returnr   )r_   dict[str, pd.DataFrame]r`   zdict[str, float]rA   r7   r  list[dict[str, Any]])r   r  r   pd.DataFramer$   r   r  r  )r_   r  rA   r7   r  z5tuple[dict[str, float], dict[str, Any], pd.DataFrame])r   r  r  z'tuple[dict[str, float], dict[str, Any]])r   r   r  dict[str, Any])r   r   r  r  )r   r   r  r   r   zdict[str, float] | Noner   r   r   Path | Noner   r  r  r  )rx  r  r   r   r  r  )r   r   rz  r  r  r   )@__doc__
__future__r   r  r   pathlibr   typingr   zoneinfor   pandasrV   RenTech.live.ibkr_market_datar   RenTech.live.ibkr_sessionr	   r
   r   rR  r   r   RenTech.live.portfolior    RenTech.live.strategies.vrp_ibkrr   -RenTech.monitor.build_command_center_snapshotr   r   r   r   r   r    RenTech.monitor.strategy_catalogr   /RenTech.strategy_stack.combine_best_ideas_stackr   -RenTech.strategy_stack.multi_strategy_managerr   r   -RenTech.strategy_stack.portfolio_risk_managerr   r   r   r   r   rz   __file__r  r   rS  rT  DEFAULT_OUTr3   r=   rh   r   r   r   r   r   rw  r{  r  rG   r>   r<   <module>r     s   #       ; X X K ; <  B \ `   !X ((+y6!F*--CC 4, 	% 	
 <*'** * 	*Z ST (!V6@& -1$(&*ZZ Z *	Z
 Z "Z $Z Z~  $     	 (r>   