
    j֏                      U d Z ddlmZ ddlZddlZddlZddlmZmZmZ ddl	m
Z
 ddlmZmZmZ ddlmZ ddl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mZ ddl 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+ ddl,m-Z- ddl.m/Z/m0Z0 ddl1m2Z2m3Z3 ddl4m5Z5m6Z6 ddl7m8Z8m9Z9 dZ:de;d<   dZ<de;d<   dZ=de;d<   dZ>de;d<   d#d Z? G d! d"      Z@y)$uI  
APEX V16 — Orchestrator (Phase B: full trade lifecycle).

Top-level async loop replacing the V15 monolith's main while loop
(APEX_PREDATOR_V15.py:2660-2712).

Phase B scope:
  - Entry path: brain.evaluate_entry -> sizing.size_for_entry ->
    risk_manager.check_entry -> opener.open_trade -> state mutation
    (active_trades, daily counters) -> save.
  - Exit path: brain.manage_exit -> dispatch on action:
        HOLD       -> persist runtime.last_exit_eval_time, save
        EXIT       -> closer.close_trade -> risk hooks -> state cleanup -> save
        PARTIAL_50 -> closer.partial_close -> risk hooks -> runtime updates
                      -> optional broker.modify_stop for set_be_after_partial
                      -> save
        MOVE_SL    -> broker.modify_stop -> runtime.current_sl_price -> save
  - PAPER and DRY collapse here: opener/closer constructed with is_paper=True.
    LIVE is_paper=False (production wireup of broker.connect() lives in main.py;
    Phase C does the full LIVE provider/broker integration for real Topstep).

Phase C (out of scope here):
  - SIGTERM signal handler + asyncio.Event wired in main.py
  - Broker.connect() + BrokerMarketDataProvider for production
  - DRY mode that connects broker but suppresses orders
  - Orphan recovery, FORCE_FLAT close-all, watchdog

Public API unchanged from Phase A:
  Orchestrator(*, config, ai_client, market_data_provider, state, store,
               logger, brain_dispatch, bias_resolver=None,
               opener=None, closer=None, risk_manager=None,
               max_iterations=None)
    .run() -> int
    .stop()
    )annotationsN)datetime	timedeltatimezone)Path)AnyCallableOptional)BiasResolver)StaleDataErrorTechSnapshotbuild_tech_snapshotinvalidate_tech_cachetech_log_fields)choose_brain)config_futures)
ASSETS_MAPENABLE_TRADING_HOURS_FILTERTRADING_HOURS)BrainContextBrainDecisionEntryDecisionTradeActionTradeRuntime)
NewsFilter)DashboardWriter)ActiveTrade)RiskManager)SizingDecisionsize_for_entry)TPResolutionresolve_tp_price)TradeCloseResultTradeCloser)TradeOpenerTradeOpenResult   intEXIT_BROKER_UNRECOVERABLE)g      ?g      @      @ztuple[float, ...]OPEN_TRADE_RETRY_DELAYS_SEC)
connectionconnect	websockettimeoutz	timed outresetzbroken pipeunreachablessl	transportnetworkztuple[str, ...]_TRANSIENT_ERROR_TOKENS)401403unauthorized	forbiddenexpiredzinvalid token_AUTH_ERROR_TOKENSc                    t        |       j                         t        fdt        D              ryt        fdt        D              ryt        | t        t        j                  t        f      ryy)z
    Returns "transient" | "auth" | "fatal".
      transient -> connection/timeout, retry via reconnect
      auth      -> token issue, retry via reconnect (loginKey refresh)
      fatal     -> unknown error class, treat as transient (safer default)
    c              3  &   K   | ]  }|v  
 y wN .0tokmsgs     #/home/work/apex_v16/orchestrator.py	<genexpr>z(classify_broker_error.<locals>.<genexpr>v   s     
4#3#:
4   authc              3  &   K   | ]  }|v  
 y wr>   r?   r@   s     rD   rE   z(classify_broker_error.<locals>.<genexpr>x   s     
9#3#:
9rF   	transientfatal)	strloweranyr;   r5   
isinstanceConnectionErrorasyncioTimeoutError)excrC   s    @rD   classify_broker_errorrS   n   sV     c(..
C

4!3
44

9!8
99#)=)=|LM    c                  "   e Zd ZdZddddddddddd
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d8dZd9dZd:dZd:dZd:dZd:d	Z	d;d
Z
d:dZd<d=dZd:dZd>dZd?dZd@dZ	 	 	 	 	 	 	 	 	 	 dAdZdBdZd:dZdCdZd:dZdCdZ	 	 	 	 	 	 dDdZdd	 	 	 	 	 	 	 	 	 dEdZ	 	 	 	 	 	 dFdZ	 	 	 	 	 	 	 	 	 	 dGdZ	 	 	 	 	 	 	 	 	 	 dGdZ	 	 	 	 	 	 	 	 dHdZd;dZdId Zd:d!Zd:d"Z dJd#Z!dKd$Z"d%d&	 	 	 	 	 dLd'Z#dMd(Z$dd)	 	 	 	 	 	 	 	 	 dNd*Z%	 	 	 	 	 	 	 	 	 	 dOd+Z&	 	 	 	 	 	 	 	 dPd,Z'	 d<	 	 	 	 	 	 	 	 	 dQd-Z(dd.d/	 	 	 	 	 	 	 	 	 	 	 	 	 dRd0Z)dd1	 	 	 	 	 	 	 	 	 dSd2Z*	 	 	 	 	 	 	 	 	 	 	 	 dTd3Z+	 	 	 	 	 	 	 	 dUd4Z,ddddd5	 	 	 	 	 	 	 	 	 	 	 dVd6Z-	 	 	 	 	 	 	 	 	 	 dWd7Z.y)XOrchestratorzKPhase B: full lifecycle loop with brain -> sizing -> risk -> opener/closer.N)
brain_dispatchbias_resolveropenercloserrisk_managerbroker
reconcilernews_filternow_utc_providermax_iterationsc               `   || _         || _        || _        || _        || _        || _        t        |xs i       | _        |xs t        |||      | _	        |	| _
        |
| _        || _        || _        || _        |xso t        t         j"                  t         j$                  t         j&                  t         j(                  t         j*                  |t-        d      j/                               | _        dd}||n|| _        || _        t7        j8                         | _        d| _        ||j>                  ntA        jB                  d      | _"        d| _#        d | _$        d | _%        t7        jL                         | _'        d| _(        d | _)        d | _*        d| _+        d| _,        t[               | _.        y )	N)	ai_clientstateloggerz~/apex_v16/cache)enabled
before_min	after_min
source_urlhttp_timeoutrd   	cache_dirc                 H    t        j                  t        j                        S r>   )r   nowr   utcr?   rT   rD   _real_utc_nowz,Orchestrator.__init__.<locals>._real_utc_now   s    <<--rT   r   orchestratorFreturnr   )/configrb   providerrc   storerd   dictrW   r   rX   rY   rZ   r[   r\   r]   r   cfg_futENABLE_NEWS_FILTERNEWS_BLOCK_BEFORE_MINNEWS_BLOCK_AFTER_MINNEWS_SOURCE_URLNEWS_HTTP_TIMEOUT_SECr   
expanduserr^   _now_utcr`   rP   Event_stop_event
_iterationsystemlogging	getLogger_sys_log_broker_degraded_degraded_since_reconnect_fnLock_state_lock_maintenance_iter_cached_daily_rpnl_cached_daily_rpnl_at_last_scanned_m5_close_stale_data_in_scanr   dashboard_writer)selfrr   rb   market_data_providerrc   rt   rd   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r`   rn   s                     rD   __init__zOrchestrator.__init__   s   ( ",

.2>3GR.H* 
luV/
 ($ (3 (
j..4422.. 66-.99;7
	. !1 < 	 -"==?#/FMMW5F5F~5V 	 ',37! #<<> '( 489="
 ,-# */  2A1BrT   c                   	K    j                   j                  d j                  j                  j                  t         j                               t        t         j                  dd            t        t         j                  dd            t        t         j                  dd                    G d d	t              	 G d
 dt              	 fd}	 t        j                   | j                               d      t        j                   | j                               d      t        j                   | j                               d      g}t        j                   |ddi d {   }|D ]  }t#        |	      rC j                   j%                  d        	  j&                  j)                   j*                         yt#        |t        j,                        r|t#        |      s| j                   j/                  d|j0                          j2                  1	  j2                  j5                  dt7        |j0                                	  j&                  j)                   j*                         y  j8                  r j:                  t        t         j                  dd      xs d      } j=                          j:                  z
  j?                         dz  }||kD  r,t@        	  j&                  j)                   j*                         S 	 	  j&                  j)                   j*                         y7 # t        $ r&} j                   j%                  d|       Y d }~yd }~ww xY w# t        $ r Y -w xY w# t        $ r&} j                   j%                  d|       Y d }~yd }~ww xY w# t        $ r&} j                   j%                  d|       Y d }~S d }~ww xY w# t        $ r&} j                   j%                  d|       Y d }~yd }~ww xY w# 	  j&                  j)                   j*                         w # t        $ r&} j                   j%                  d|       Y d }~w d }~ww xY wxY ww)Nu   Orchestrator starting in %s mode, %d assets — 3-loop architecture: scan=M5 boundary +%.0fs, manage=%ds (skip if flat), maintenance=%dsscan_loop_phase_offset_seconds      @manage_loop_interval_seconds   !maintenance_loop_interval_seconds<   c                      e Zd Zy)0Orchestrator.run.<locals>._LoopKeyboardInterruptN)__name__
__module____qualname__r?   rT   rD   _LoopKeyboardInterruptr      s    rT   r   c                        e Zd Zd fdZ xZS )&Orchestrator.run.<locals>._LoopCrashedc                D    || _         t        | 	  t        |             y r>   )originalsuperr   rK   )r   r   	__class__s     rD   r   z/Orchestrator.run.<locals>._LoopCrashed.__init__   s     ( X/rT   )r   BaseExceptionrq   None)r   r   r   r   __classcell__)r   s   @rD   _LoopCrashedr      s    0 0rT   r   c                >  K   	 |  d {    y 7 # t         $ r# j                  j                                  d t        j                  $ r j                  j                           t
        $ r(}j                  j                           |      |d }~ww xY wwr>   )KeyboardInterruptr   setrP   CancelledErrorr   )coroer   r   r   s     rD   _wrapzOrchestrator.run.<locals>._wrap  s     
-

$ 9  $$&,.D8))   $$&  -  $$&"1o1,-s2   B  B A B2#BBB	scan_loop)namemanage_loopmaintenance_loopreturn_exceptionsTzInterrupted by user (Ctrl+C)zfinal save failed: %s   zUnhandled exception in loop: %szorchestrator.run)whereerror   broker_degraded_max_minutes         N@r   )!r   inforr   modevaluelen_asset_listfloatgetattrr(   	ExceptionrP   create_task
_scan_loop_manage_loop_maintenance_loopgatherrN   warningrt   saverc   r   	exceptionr   rd   	log_errorrK   r   r   r}   total_secondsr)   )
r   r   tasksresultsrr   max_minelapsed_minr   r   s
   `       @@rD   runzOrchestrator.run   s    RKK""  "#'$++'GMN%CRHI%H"MN	
	Y 		09 	0
	-'	B##E$//*;$<;O##E$*;*;*=$>]S##E$*@*@*B$CJ\]E
 $NNEJTJJG a!78MM))*HI4B



+5 a!7!78Ga.MM++91:: {{.! KK11&8AJJ 2 
 B



+=( $$)=)=)I5RTV W ][]^MMOd&:&::-/D) (4B



+ B



+? K@  B%%&=qAAB!  ) ! !   B%%&=qAAB9 B%%&=qAAB9 B%%&=qAABB



+ B%%&=qAABs4  CQ=BP  3M42P  '%M Q=(P  62P  )0M:P  %N
  Q=A5P  7%N<Q=%O. Q=P  	M7M2-Q=2M77Q=:	NP  NP  
	N9N4/Q=4N99Q=<	O+O&!Q=&O++Q=.	P7PQ=PQ= Q:"%QQ:	Q7Q2-Q:2Q77Q::Q=c                8    | j                   j                          y r>   )r   r   )r   s    rD   stopzOrchestrator.stop7  s    rT   c                  K   | j                   j                         s| j                         }|dkD  r9	 t        j                  | j                   j                         |       d{    y| xj                  dz  c_        ddl}| j                  }d| _
        t        |j                         dz  dz        | _	        	 | j                  s=| j                  4 d{    | j                          d{    ddd      d{    | j                  r.| j                  j!                  d| j                  |       || _	        | j(                  @| j                  | j(                  k\  r'| j                  j!                  d	| j(                         yt        j*                  d       d{    | j                   j                         syy7 a# t        j                  $ r Y tw xY w7 7 7 # 1 d{  7  sw Y   xY w# t"        $ r  t$        $ r1}| j                  j'                  d| j                  |       Y d}~d}~ww xY w7 w)
a  Scan entries on every M5 boundary + phase_offset.

        Stateful: `self._last_scanned_m5_close` tracks which M5 close we
        already scanned, so we never rescan the same candle twice within
        its 5-minute window. Cold start: if we boot inside the valid
        post-close window for an M5 we haven't yet scanned, run
        immediately; otherwise wait until next close + offset.
        r   r/   Nr   F,  zR[scan_loop] stale broker data detected; rollback _last_scanned_m5_close (%d -> %d)z[scan_loop] iter %d failed: %sz,scan_loop max_iterations=%d reached, exiting)r   is_set_scan_decision_secondsrP   wait_forwaitrQ   r   timer   r   r(   r   r   _scan_entriesr   r   r   r   r   r`   sleep)r   	sleep_for_timeprev_scanned_m5_closer   s        rD   r   zOrchestrator._scan_loop>  s     ""))+335I1}!**((--/    OOq O !$($?$?!',D$*-uzz|s/Bc.I*JD'\,,#// 3 3"002223 3++ MM&&E335J
 3HD/
 "".4??dFYFY3Y""BDDWDW  --"""U ""))++ ++ 323 3 3 3 %  \%%&FYZ[[\ #s   1I2G
 &G'G
 +AI=H  G$H  G+1G'2G+6H  G)>H   A$I$I%IIG
 
G!I G!!I$H  'G+)H  +G=1G42G=9H   I'H>9I>IIc                B  K   t        t        | j                  dd            }d}| j                  j	                         s	 | j
                  j                  r=| j                  4 d{    | j                          d{    ddd      d{    |dz  }| j                  || j                  k\  ry|dkD  r9	 t        j                  | j                  j!                         |       d{    yt        j$                  d       d{    | j                  j	                         syy7 7 7 # 1 d{  7  sw Y   xY w# t        $ r  t        $ r&}| j                  j                  d|       Y d}~d}~ww xY w7 # t        j"                  $ r Y w xY w7 w)z8Manage open trades. Skip tick if active_trades is empty.r   r   r   Nz[manage_loop] failed: %sr   r   )r(   r   rr   r   r   rc   active_tradesr   _manage_open_tradesr   r   r   r   r`   rP   r   r   rQ   r   )r   intervalmanage_iterr   s       rD   r   zOrchestrator._manage_loops  sr    wt{{,JBOP""))+E::++#// 9 9"668889 9 1K"".;$BUBU3U!|!**4+;+;+@+@+BHUUU mmA&&&' ""))+989 9 9 9$  E%%&@!DDE V++  's   =F &E &D,'E *D2>D.?D2E D0E &F:2F ,F-F 1F
FF*F,E .D20E 2E8D;9E E E?E:5F:E??FF FFFFc                  K   t        t        | j                  dd            }| j                  j	                         s#| xj
                  dz  c_        t        | j                  dd      r}| j                  j                  d| j
                  t        | j                  j                        | j                  j                  | j                  t        t        | dd      xs d             	 t        j                  t         j"                        j%                         j'                         }| j                  j(                  j$                  |k7  r}d	d
lm} | j                  j(                  j$                  } ||      | j                  _        d| j                  _        d| j                  _        | j                  j                  d||       | j                  r8| j1                          d{   }|dk(  r| j                  j3                          y| j5                          d{    | j7                          d{    | j9                          d{    | j                  s#| j;                  | j
                         d{    	 | j<                  j?                  | j                         | jD                  jG                  |        | jJ                  | j
                  | jJ                  k\  ry|d	kD  r9	 tM        jN                  | j                  jQ                         |       d{    ytM        jT                  d	       d{    | j                  j	                         s"yy7 |7 G7 27 7 # t@        $ r&}| j                  jC                  d|       Y d}~d}~ww xY w# tH        $ r  t@        $ r'}| j                  jC                  d|       Y d}~d}~ww xY w7 # tL        jR                  $ r Y w xY w7 w)z=Reconnect + balance refresh + news sync + watchdog + persist.r   r   r   maintenance_heartbeat_enabledTzM[maintenance] heartbeat iter=%d active=%d halted=%s degraded=%s balance=$%.2f_cached_account_balance        r   )DailyCounters)dateF z=[maintenance] daily reset %s -> %s (counters + halts cleared)Nexitz[maintenance] save failed: %sz[maintenance_loop] failed: %sr   )+r(   r   rr   r   r   r   r   r   r   rc   r   haltedr   r   r   rl   r   rm   r   	isoformatdailypersistence.state_storer   halt_reason_maybe_reconnectr   _refresh_account_balance_refresh_daily_rpnl_maybe_sync_news_maybe_run_watchdogrt   r   r   r   r   writer   r`   rP   r   r   rQ   r   )r   r   	today_utcr   	prev_dateoutcomer   s          rD   r   zOrchestrator._maintenance_loop  s7    wt{{,OQSTU""))+""a'" t{{$CTJ""$**

001JJ%%))'$(A3GN3O%J %LL6;;=GGI	::##((I5E $

 0 0 5 5I'4)'DDJJ$(-DJJ%-/DJJ*MM&&W!9 (($($9$9$;;G&(((,,.33555..000++---,,2243I3IJJJNJJOODJJ/
 %%++D1 ##/**d.A.AA!|!**4+;+;+@+@+BHUUU mmA&&&G ""))++F < 60-J ! NMM))*I1MMN
 %  J%%&EqIIJ V++  's	  C%O;(C>N" &M"'#N" 
O;N" M%N" 6M(7N" M+.N" =M.>N" %M0 (N" +O;/2O  !O"O  &O;?O9 O; O;"N" %N" (N" +N" .N" 0	N9NN" NN" "O4OO;OO;O   O63O;5O66O;c                N   ddl }d}t        t        | j                  dd            }|dk  ryt        t        | j                  dd            }|j                         }t	        ||z  |z        }||z
  }t        | d	d      }||cxk  xr |k  nc }	||k  }
|	r|
sy||z   }||z
  |z   S )
u$  
        Returns seconds to sleep before the next scan, or 0.0 if scan
        should execute immediately.

        Logic:
          - The M5 candle that just closed has identifier `current_close`
            (unix sec, multiple of 300).
          - The "valid scan window" for that candle is post-close in
            [offset, candle_max_age_seconds] — the same range the brain
            accepts (CANDLE_STABILIZING / CANDLE_TOO_OLD gates).
          - We scan AT MOST ONCE per current_close (tracked via
            self._last_scanned_m5_close), so the loop runs the entry
            evaluation exactly once per candle.

        Returns 0.0 only when:
          (a) we're inside the valid window for current_close, AND
          (b) current_close has not yet been scanned.
        Otherwise returns the seconds until the NEXT M5 close + offset.

        Test escape hatch: when offset==0 we bypass the boundary logic
        entirely (always 0.0). Tests use offset=0 + max_iterations to
        drive N consecutive scan iters deterministically.
        r   Nr   r   r   r   candle_max_age_secondsr   r   )r   r   r   rr   r(   )r   r   M5offsetmax_agerl   current_closesecs_since_closelast_scannedin_valid_windowalready_scanned_this_candle
next_closes               rD   r   z#Orchestrator._scan_decision_seconds  s    0 	wt{{,LcRSS=-EtLMjjlSBY",-.t%=qA!%5@@'4'D##> #R'
S F**rT   c                H  K   | j                   j                  sy| j                   j                  }| j                         }t	        t
        j                        }|	||z
  |k  ryt        t        | j                  dd            }	 t        j                  | j                   j                         |       d{    y7 # t        j                  $ r | j                  j                  d|       Y yt         $ r&}| j                  j                  d|       Y d}~yd}~ww xY ww)u   
        Top-of-iteration check; sync if stale > NEWS_SYNC_INTERVAL_MIN
        (or never synced). Async, non-blocking — NewsFilter.sync wraps
        urllib in asyncio.to_thread. Fail-open on any exception.
        Nminutesnews_sync_timeout_seconds      >@r   z![news] sync timed out after %.0fsz[news] sync raised: %s)r^   re   last_sync_atr}   r   rv   NEWS_SYNC_INTERVAL_MINr   r   rr   rP   r   syncrQ   r   r   r   )r   lastrl   r   r/   r   s         rD   r   zOrchestrator._maybe_sync_news  s      '',,mmoW%C%CDtx 7-H$OP	?""4#3#3#8#8#:GLLL## 	PMM!!"EwO 	?MM!!":A>>	?sN   BD"2C  8B>9C  =D">C   /D/D"1D9DD"DD"c                ,   | j                   ryd| _         | j                         | _        | j                  j	                  d||       | j
                  3	 | j
                  j                  j                  d|t        |             yy# t        $ r Y yw xY w)zGIdempotent: first call records timestamp + logs; subsequent are no-ops.NTz3[broker] entering DEGRADED mode (reason=%s, exc=%s)broker_degraded_entered)reasonr   )
r   r}   r   r   r   rd   	brain_logr   rK   r   )r   r  rR   s      rD   _mark_degradedzOrchestrator._mark_degraded  s       $#}}AC	
 ;;"%%++-fCH ,  #
  s   1B 	BBc                t   | j                   sy d }| j                  +| j                         | j                  z
  j                         }d| _         d | _        | j                  j                  d|xs d       | j                  )	 | j                  j                  j                  d|       y y # t        $ r Y y w xY w)NFz'[broker] RECOVERED after %.1fs degradedr   broker_degraded_exited)elapsed_seconds)
r   r   r}   r   r   r   rd   r  r   r   )r   elapseds     rD   _mark_recoveredzOrchestrator._mark_recovered,  s    $$+}})=)==LLNG %#DgnQTU;;"%%++,g ,  #
  s   'B+ +	B76B7c                n    | j                   yt        |      }|dv r| j                  | d| |       yy)zIRoute a broker-call exception: classify and (if connection-like) degrade.N)rI   rG   rJ   :)r  rR   )r\   rS   r  )r   r   rR   kinds       rD   _maybe_handle_broker_exceptionz+Orchestrator._maybe_handle_broker_exception=  sG    ;;$S)11 %$'8cB 2rT   c                  K   | j                   yt        t        | j                  dd      xs d      }| j                  | j                         | j                  z
  j                         dz  }||kD  rY| j                  j                  d||t               | j                  *	 | j                  j                  j                  d||       y	y	| j                          d{   }|sy| j                          t!                | j"                  &	 | j"                  j%                  d
       d{    yy# t        $ r Y y	w xY w7 c7 # t&        $ rZ 	 | j"                  j%                          d{  7   Y y# t        $ r'}| j                  j)                  d|       Y d}~Y yd}~ww xY wt        $ r&}| j                  j)                  d|       Y d}~yd}~ww xY ww)a  
        Attempt mid-loop reconnect. Returns:
          "recovered" -> reconnect succeeded, post-reconnect reconcile run
          "still_degraded" -> reconnect failed but timeout not exceeded
          "exit" -> hard timeout exceeded, orchestrator must exit
        Nstill_degradedr   r   r   uB   [broker] degraded for %.1fmin (> %.1fmin) — exiting with code %dbroker_unrecoverable)elapsed_minutesmax_minutesr   T)post_reconnectz#post-reconnect reconcile failed: %s	recovered)r\   r   r   rr   r   r}   r   r   r   r)   rd   r  r   r   _do_reconnectr  r   r]   reconcile_startup	TypeErrorr   )r   r   r   okr   s        rD   r   zOrchestrator._maybe_reconnectG  s     ;;# -JBOUSUV+$"6"66mo%K W$##X*C ;;*--332,7W 4  %%''# 	 	??&	Poo77t7LLL 3 %  ( M TT//;;===
 	 ! TMM))*OQRSS 	T P%%&KQOOPs   BG"(D4 
GE -GE -E.E 2G4	E =G?E  GE 	GE6.E1/E64G6	F&?F!GG!F&&G1GGGGc                  K   | j                   -	 t        | j                  | j                         d{         S 	 	 | j                  j                          d{    t        | j                  j                          d{         S 7 W# t        $ r&}| j                  j                  d|       Y d}~yd}~ww xY w7 c# t        $ r Y lw xY w7 M# t        $ r&}| j                  j                  d|       Y d}~yd}~ww xY ww)an  
        Issue a single broker.disconnect()+connect() cycle. Falls back
        to broker.connect() alone if disconnect raises. Returns True on
        success, False on failure (caller decides what to do next).

        For multi-attempt mid-loop retries, main.py composes this with
        _connect_with_retry by passing a callable via self._reconnect_fn.
        Nzreconnect_fn raised: %sFzbroker reconnect failed: %s)r   boolr\   r   r   r   
disconnectr-   )r   r   s     rD   r(  zOrchestrator._do_reconnect~  s      )$"4"4T[["AABB	kk,,... dkk113344 B %%&?C
 / 3 	MM!!"?C	s   D#B BB DC B?C  "C CC 
DB 	B<B72D7B<<D?C 	C
C CC 	DC<7D<DDc                 K   | j                   t        | j                   dd      ry| j                  yt        | j                   dd      }|y	  ||||||j                         |       d{   }|j                  r|j                  r|j                  r|S y7 +# t        $ r'}	| j
                  j                  d||	       Y d}	~	yd}	~	ww xY ww)a&  
        After an opener failure, ask the opener to verify whether a position
        actually opened broker-side and (if so) re-attach SL/TP. Returns
        the recovered TradeOpenResult on success, None if no recovery
        possible. PAPER skips (no broker side state to inspect).
        Nis_paperFpost_order_safety_check)symbol
brain_namedecision	contractstech_nowerror_contextz![scan] %s safety_check raised: %s)
rY   r   r\   to_dictr   r   r   successentryruntime)
r   r2  brainr4  r5  techr7  checkr'  r   s
             rD   _maybe_run_safety_checkz$Orchestrator._maybe_run_safety_check  s      ;;'$++z5"I;;%>E=	/4%(#dlln+0 *I Y5F5F*
  	MM!!"EvqQ	sB   ACB .B/B 3'CB 	C%CCCCc                  K   | j                   yt        t        | j                  dd      xs d      }|dk  s||z  dk7  ryt	        t        | j                  dd            }	 t        j                  | j                   j                         |       d{    y7 # t
        j                  $ r | j                  j                  d|       Y yt        $ r&}| j                  j                  d	|       Y d}~yd}~ww xY ww)
un  
        Periodically run reconciler.watchdog_naked_positions() to catch
        broker-side position closures that race the bot's main loop.

        Cadence (V16 3-loop): every N maintenance_loop iterations, where
        N = config.reconcile_interval_iterations (default 1 → 60s).
        Failures are warning-only; watchdog never raises into the loop.
        Nreconcile_interval_iterations   r   watchdog_timeout_secondsr  r   z [watchdog] timed out after %.0fsz[watchdog] failed: %s)r]   r(   r   rr   r   rP   r   watchdog_naked_positionsrQ   r   r   r   )r   	iterationeveryr/   r   s        rD   r   z Orchestrator._maybe_run_watchdog  s      ??"GDKK)H!LQPQRA:U*a/-GNO	>""88:G   ## 	OMM!!"DgN 	>MM!!"91==	>sN   A C?#2B BB C?B /C<C?C<C72C?7C<<C?c                  K   | j                         D ]C  }|| j                  j                  v r	 | j                  |       d {    | j                  sC y  y 7 # t        $ r}}| j
                  j                  d||       | j                  d|       | j                  8	 | j                  j                  dt        |      |       n# t        $ r Y nw xY wY d }~d }~ww xY ww)Nz[scan] %s failed: %sscanzorchestrator.scanr   r   r2  )r   rc   r   	_scan_oner   r   r   r   rd   r   rK   r   r   r2  r   s      rD   r   zOrchestrator._scan_entries  s     &&( 	F111nnV,,, $$ %	 - 	%%&<faH33FA>;;*--"5SVF .  % 	sj   -C%AAA	C%C%A	C"%;C!'C	C		CCCCC%C""C%c                l  K   t         rMt        j                  |      }|6| j                         j                  }||vr| j                  |d||d       y | j                  j                  || j                               }|| j                  |d|j                  j                  |j                  j                  |j                  j                  |j                  j                  j                         t        |j                  d      |j                   d       y | j"                  j%                  |      rd }n| j'                  |       d {   }| j"                  j)                  ||       d {   }dd l}t-        |j+                         dz        dz
  dz  }	 | j/                  ||	       d {   }	|	y t9        ||	|| j                               }|j:                  }|/| j                  ||j<                  xs d|	||j>                         y | j@                  j                  |      }|| j                  |d| |	|       y tC        | jD                  jF                  jH                  j                  |d            }	 |jK                  ||	||       d {   }|jX                  r| j                  |d|	||       y |j<                  !| j                  ||j<                  |	||       y |jZ                  6tC        |jZ                        | jD                  jF                  jH                  |<   |j\                  }|| j                  |d|	||       y | j_                  ||||	       	 ta        ||| jc                         | jd                  jf                  | jD                  jh                  jj                  | jd                  jl                  | jd                  jn                        }| jr                  | j                  |d|	||       y | jr                  ju                  |||| jD                  jv                        }|jx                  s?| j{                  |||||       | jD                  jh                  xj|                  dz  c_>        y tC        |j~                  j                  d d      xs d      }	 t        ||j                  |j                  |j                  |j                  |j                  |!      }t        j                  ||j                  $      }| j                  ||||       | j                  | j                  |d%|	||       y d }d }dt        t              z   }t        d|dz         D ]j  }d }	 | j                  j                  ||||j                  |	j                         &       d {   }|dk(  rW|j                  sK| jR                  ?	 | jR                  j                  j                  d-|||j                  |j                  .       |j                  s|j                  d)k7  r n||k\  r nt        |dz
     }| jN                  jQ                  d/|||||j                         | jR                  E	 | jR                  j                  j                  d0||||dz   ||j                  |j                  1       t        j                  |       d {    m |j                  r|j                  |j                  | j                  ||||j                  |	|j                  xs |rtW        |      nd23       d {   }||}n| jN                  jQ                  d4|||j                  |j                         | jR                  A	 | jR                  j                  j                  d5|||j                  |j                  |6       y y |j                  j                  |j                  _]        	 tC        |j~                  j                  d7d      xs d      |j                  _^        t        |j                  |j                  8      | jD                  jv                  |<   | jD                  jh                  xj                  dz  c_a        | jD                  jh                  xj                  dz  c_b        | j                  |||j                  ||       y 7 7 k7 ,# t0        $ r<}
d
| _        | j                  |d|
j4                  |
j6                  d       Y d }
~
y d }
~
ww xY w7 # tL        $ rl}
| jN                  jQ                  d||
       | jR                  9	 | jR                  jU                  dtW        |
      ||       n# tL        $ r Y nw xY wY d }
~
y d }
~
ww xY w# tp        $ r@}
| jN                  jQ                  d||
       | j                  |d|
 |	||       Y d }
~
y d }
~
ww xY w# t        tp        f$ r@}
| jN                  jQ                  d"||
       | j                  |d#|
 |	||       Y d }
~
y d }
~
ww xY w7 # tL        $ r}
| jN                  jQ                  d'||||
       |
}t        d(tW        |
      d)*      }| jR                  8	 | jR                  jU                  d+tW        |
      |,       n# tL        $ r Y nw xY wY d }
~
d }
~
ww xY w# tL        $ r Y w xY w# tL        $ r Y 2w xY w7 7 # tL        $ r Y y w xY w# t        tp        f$ r d|j                  _^        Y w xY ww)9NOUTSIDE_TRADING_HOURS)now_hour_utcallowed_hours)details
NEWS_BLOCKr   )titlecountryimpactevent_dt_utcminutes_to_eventwindow_reasonr   r   min_candle_timeTDATA_STALE_BROKER_LAG)candle_time_seencandle_time_expected)r2  r=  biasnow_utcbrain_selector_none)r=  r]  rP  brain_dispatch_missing:r=  r]  r   )	bias_datalast_entry_eval_timez)[scan] %s brain.evaluate_entry raised: %szorchestrator.evaluate_entry)r   r   r2  r<  SAME_CANDLE_DEDUP)r=  r]  r<  brain_no_setupr=  )r:  r2  account_balancerisk_per_trade	daily_pnldaily_loss_hard_stopmax_risk_vs_daily_budgetz$[scan] %s sizing rejected inputs: %szsizing_invalid:risk_manager_missing)r:  sizingr2  r   tp_price_suggested_ai)r2  	directionentry_pricerr_multiplierr5  sl_tickstp_price_suggestedz[scan] %s tp_resolve failed: %sztp_resolve_invalid:)tp_priceopener_missing)r2  r3  r4  r5  r6  z+[scan] %s opener raised (attempt=%d/%d): %sFbroker_failure)r9  r   
error_kindzorchestrator.openerrI  open_failed)r2  r<  r   rw  zE[scan] %s open_trade broker_failure attempt=%d/%d, retry in %.1fs: %s
open_retry)r2  r<  attemptnext_attemptdelay_secondsr   rw  r   )r2  r<  r4  r5  r=  r7  z>[scan] %s opener failed permanently after %d attempts: %s (%s)open_failed_permanent)r2  r<  r   rw  total_attemptssl_price_ai_raw)r:  r;  )dr   r   getr}   hour	_log_skipr^   
is_blockedeventrR  rS  rT  dtr   roundrV  r  rX   has_fresh_cache	_fetch_h4resolver   r(   _build_techr   r   r[  r\  r   chosenreject_reasonrP  rW   r   rc   entry_eval_cache	last_evalevaluate_entryr   r   r   rd   r   rK   dedup_skippedevaluated_candle_timer4  _log_entry_approvedr    _resolve_account_balancerr   rh  r   ri  rj  rk  
ValueErrorr[   check_entryr   approved_log_risk_skiprejected_countmetadatar"   ro  rp  rq  r5  rr  KeyErrordataclassesreplacert  _log_tp_resolvedrY   r   r+   range
open_trader8  r&   r9  r  r   r   rw  rP   r   r:  r;  r?  sl_pricecurrent_sl_pricer  r*  r   approved_countexecuted_count_log_trade_opened)r   r2  rO  now_hourblockingdf4r]  r   expected_openr=  r   selr  r<  r  eval_resultr4  rm  riskrn  tp_res
opener_excresultmax_attemptsrz  delayr'  s                              rD   rJ  zOrchestrator._scan_one  s
     ')--f5M(==?//=0NN 7,4-:! #   ##..vt}}GNN%^^11'~~55&nn33$,NN$5$5$?$?$A(-h.G.G(K%-__  
 
 --f5Cv..C''//<< 	UZZ\S01A5<	))&-)PPD <&t$X>NN))B-Bckk   ##''/=NN6%<VH#EDW[N\ JJ''1155fcB
		 % 4 49 !5 ! K $$NN+F   
 $$0NN11F    ,,8<A11=DJJ''11&9 ''NN6#3$TQWNX 	   E	# $ = = ?#{{99****44%)[[%E%E)-)M)MF $NN6#94W]N^  ,,**22	 - 
 }}&$GJJ++q0+ !&!!"93?F3!
	%",,$00&44 **#8F  &&x&//Jffh? ;;NN6#3$TQWNX +/
,03:;;Qq 01 D	'GJ#{{55!%%$..!\\^  6   4 !|FNN;;*	--33)#)"("(,,'-'8'8 4  ~~!2!26F!F,&/!<EMM!!Wufll {{&KK))//$%$ '%,q[&+$ll#)#4#4 0 	 --&&&ID	'L ~~!59O
 #::Vh **$llU*s:RT ;  I
 $"%%TL&,,8I8I ;;*
--333#)"("(,,'-'8'8+7 4   +1,,*?*?'	1-2!!%%&7=D.FNN*
 ,7,,,


  ( 	

''1,'

''1,'vvv||VTJA	 /< Q 		'+D$NN/()(:(:,-,B,B   		@  
	MM!!"MvWXY{{&KK));!!fV6 *  ! 
	t  	MM!!"H&RSTNN6_QC#8t$V\N]	P *% 	MM!!"CVQONN-aS1F   	:  %%AG\1 
(!Q<L ;;*--"7s1vf .  % : % 6 ! &, %  :& 	1-0FNN*	1s.  E
l4c#l40c1*l4c! 2c3c! 7Cl4d, d)d, !Cl4.A:f$ (C
l43Ag0 7Bl4;;i6i7i;l4>kA&l4>Ak(l4k8A*l4k;Al4?k> 'l468l .B+l4l4c! !	d&*2d!l4!d&&l4)d, ,	f!5)f(ff	ffffl4f!!l4$	g--6g(#l4(g--l40h??6h:5l4:h??l4i	kAk'j;:k;	kkkk
l4kl4	k%!l4$k%%l4(	k51l44k55l4;l4>	l
l4	l

l4 l1-l40l11l4c                  K   t        | j                  j                  j                               D ]  }	 | j	                  |       d {     y 7 # t
        $ r}}| j                  j                  d||       | j                  d|       | j                  8	 | j                  j                  dt        |      |       n# t
        $ r Y nw xY wY d }~d }~ww xY ww)Nz[manage] %s failed: %smanagezorchestrator.managerI  )listrc   r   keys_manage_oner   r   r   r   rd   r   rK   rK  s      rD   r   z Orchestrator._manage_open_trades9  s     4::3388:; 	F&&v...	. 	%%&>J33Ha@;;*--"7s1vf .  % 	sd   1CAA	ACA	C;C'B?>C?	CC
CCCCCc                  K   | j                   j                  j                  |      }|y | j                  ||       d {   ry | j	                  |       d {   }|y | j                  ||       d {    |j                  j                  }| j                  j                  |      }|| j                  |d| |d        y t        |j                  |j                  |      }	 |j                  |       d {   }|j                   }	|	t"        j$                  j&                  k(  r| j)                  ||j                         y |	t"        j*                  j&                  k(  r=| j,                  r| j/                  |d|       y | j1                  ||||       d {    y |	t"        j2                  j&                  k(  r=| j,                  r| j/                  |d|       y | j5                  ||||       d {    y |	t"        j6                  j&                  k(  r<| j,                  r| j/                  |d|       y | j9                  |||       d {    y | j                  j                  d||	       | j)                  ||j                         y 7 Q7 :7  7 # t        $ r'}| j                  j                  d||       Y d }~y d }~ww xY w7 27 7 w)	Nr`  ra  )r:  r;  r6  z([manage] %s brain.manage_exit raised: %sEXIT
PARTIAL_50MOVE_SLz&[manage] %s unknown action %s, holding)rc   r   r  _check_external_closer  _refresh_runtimer:  r3  rW   r  r   r;  manage_exitr   r   r   actionr   HOLDr   _apply_candle_dedupr  r   _log_action_deferred_handle_exitr  _handle_partialr  _handle_move_sl)
r   r2  activer6  r  r<  ctxr4  r   r  s
             rD   r  zOrchestrator._manage_oneH  s    ))--f5> ++FF;;;))&11 ##FH555((##''/=NN6%<VH#EH[_N`v~~PXY	,1,=,=c,B&BH
 [%%+++$$Xv~~>[%%+++$$))&&(C##FFHhGGG[++111$$))&,I&&vvxJJJ[((...$$))&)XF&&vvx@@@ 	FPVW  6>>:o < 2 	6 'C 	MM!!"LfVWX	 H K As   >K JKJK7J8A2K+J ?J J BKKAK8K9AKKA KKKJ 	K&KKKKKKc           
       K   ddl m} |j                  j                  }t	        j
                  t        j                        }|j                   |j                  t        j                        }t        d||z
  j                         dz        |j                  _        t        j                  |j                  j                   i       }t#        |j                  dd            }t#        |j                  dd            }|dk  s|dk  ry|j$                  }	| j&                  `|j                  j(                  sJ	 | j&                  j+                  |j                  j                          d{   }
|
|
dkD  rt#        |
      }		  ||j                  j.                  |j                  j0                  |j                  j2                  |	|j                  j4                  |j                  j6                  ||	      }|j>                  |j                  _        |j@                  |j                  _         | j:                  jC                  d|j                  j                   |j                  j                  |j>                         |j                  jD                  dkD  r|j                  jF                  s|j                  j4                  dk(  }|j                  jD                  }|xr |	|k  xs
 | xr |	|k\  }|rd|j                  _#        | j:                  jC                  d|j                  j                   ||j                  j0                  |j                  j                  |j                  j>                         yyyy7 # t,        $ r Y w xY w# t8        $ r;}| j:                  j=                  d
|j                  j                   |       Y d}~yd}~ww xY ww)zBUpdate minutes_open / net_profit_usd / progress_pct from tech_now.r   )compute_pnlN)tzinfor   r   	tick_size
tick_value)rp  r  rt  current_pricero  r5  r  r  z#[manage] %s compute_pnl skipped: %sz:[refresh_runtime] %s minutes_open=%.1f net_profit_usd=%.2fBUYTzO[ab_test] %s sl_ai_raw HIT @ %.5f (real SL @ %.5f, minutes_open=%.1f, pnl=%.2f))$trading.pnl_calculatorr  r:  	opened_atr   rl   r   rm   r  r  maxr   r;  minutes_openr   r  r2  r   pricer\   r0  get_last_pricer   rp  r  rt  ro  r5  r  r   debugnet_profit_usdprogress_pctr   r  sl_ai_raw_hit)r   r  r6  r  r  r^  specr  r  r  broker_pricepnlr   is_longsl_rawhits                   rD   r  zOrchestrator._refresh_runtime  s     	7LL**	,,x||,#!)))>I&)'I%446='
# ~~fll1126$((;45	488L#67
>Z1_ !;;"6<<+@+@%)[[%?%?LL''&    +q0@$),$7M	"LL44....+ ,,00 ,,00#%	C ),(:(:%&)&6&6#HLLNN''		
 NN**S0NN00ll,,5G^^33F4]f4 =K;MV$;  /3,""3LL''LL))NN//NN11  1 1O 
    	MM5v||7J7JA 		sb   D4O72M8 )M5*M8 A4N 5F O5M8 8	NONO	O1OOOOrB  )max_age_minc                 K   | j                   y	 |t        |      z
  }| j                   j                  ||d       d{   }|dk(  rdnd}t        |d	 d
      D ]>  }	|	j                  |k(  st        |	j                        t        |	j                        dfc S  y7 ^# t        $ r'}| j                  j                  d||       Y d}~yd}~ww xY ww)ud  
        Recover (exit_price, pnl_usd, pnl_source) for the most-recent
        broker-side closing leg of an active trade. The closing leg is
        the `ClosedTrade` with `side` opposite to the position's
        direction; we sort by `closed_at` descending and pick the
        first match within the window.

        Used by all three close paths so the broker-authoritative pnl
        is logged uniformly (`balance_confirmed` for full closes,
        `partial_close` for partials). Without this the dashboard has
        to guess from balance deltas (often stale post-fill) or from
        tick math (uses tech_now.price, not the real broker fill).

        Returns (None, None, "unknown") on broker absence, broker error,
        or no matching closing leg. Failures are debug-logged only —
        the caller's primary log line continues regardless.
        N)NNunknownr  
   )r2  sincelimitz([broker_pnl] %s recent_trades failed: %sr  SELLc                    | j                   S r>   )	closed_at)xs    rD   <lambda>z0Orchestrator._fetch_broker_pnl.<locals>.<lambda>  s
    akk rT   T)keyreverser\   )r\   r   recent_tradesr   r   r  sortedsider   
exit_pricepnl_usd)
r   r2  ro  r  r  r  recentr   opp_sidets
             rD   _fetch_broker_pnlzOrchestrator._fetch_broker_pnl  s     2 ;;(		)	+ >>E;;44U" 5  F '%/6U$94H 	GAvv!Q\\*E!)),<hFF	G %  	)MM:FA )		)sF   C0B" B B" *C1/C B" "	C+CCCCc                d  K   |j                   j                  ry| j                  y| j                  ryt	        t        | j                  dd            }	 t        j                  | j                  j                  |      |       d{   }|ry| j                  ||j                   j                  |j                   j                          d{   \  }}}d	}	d
}
d	}d|j                   j"                  fd|j                   j$                  ffD ]@  \  }}|s		 | j                  j'                  ||       d{   }t        |dd      s<|dz  }B |	|z  }	|d	kD  rd}
d	}	 | j                  j)                  |       d{   }|	|z  }	|d	kD  r|
d
k(  rd}
|	d	k(  rOt        j*                  d       d{    d	}	 | j                  j)                  |       d{   }|	|z  }	|d	kD  rd}
| j,                  	 | j,                  j.                  j1                  d||j                   j2                  |j                   j                  |j                   j4                  |j                   j6                  |j                   j8                  |j                   j:                  |j                   j"                  |j                   j$                  |	|
|||       | j                  j=                  d||	|
       ||| j>                  p|d	kD  }| j>                  jA                  |||j                   j2                         |r| j>                  jC                  |       n| j>                  jE                  |       | jF                  jH                  |= tK        |       | j                  t        | dd      }d}t        j*                  d       d{    	 t	        | j                  jM                          d{         }|C|| _'        |
|d	kD  r||z
  nd}| j,                  q	 | j,                  j.                  j1                  d|tQ        |j                   j4                        tS        |d      |tS        |d      nd|tS        |d      nd|d        ||t	        |      nd!}||z
  }tU        |      d"kD  r| j                  j                  d#||||       | j,                  b	 | j,                  j.                  j1                  d$|tS        |d      tS        |d      tS        |d      tS        |d      tS        |d      d|%	       y&y&7 # t        j                  $ r  | j                  j                  d||       Y yt        $ r'}| j                  j                  d||       Y d}~yd}~ww xY w7 7 f# t        $ r*}| j                  j                  d||||       Y d}~d}~ww xY w7 X# t        $ r(}| j                  j                  d||       Y d}~d}~ww xY w7 \7 9# t        $ r(}| j                  j                  d||       Y d}~cd}~ww xY w# t        $ r Y w xY w7 7 w# t        $ r(}| j                  j                  d||       Y d}~d}~ww xY w# t        $ r Y w xY w# t        $ r Y y&w xY ww)'us  
        Detect broker-side position close (TP or SL filled standalone).

        ProjectX SL/TP orders placed by place_market_bracket are NOT
        server-side OCO — they live independently. When one fills, the
        other stays open and can fill later, causing an involuntary
        opposite position. This polling check, run before each manage
        tick, reads the broker's position snapshot. If the position is
        gone we know one of the two filled, so we cancel the surviving
        orphan and drop the active_trade.

        Returns True if cleanup performed (caller must skip rest of tick).
        Returns False if the check is skipped (paper / no broker /
        degraded) or the position is still open.

        V18 fix: when recent_trades returns a matching closing leg, this
        path now updates risk_manager (update_daily_pnl + register_sl_hit/
        register_tp_hit) so daily counters and consecutive_sl_count stay
        in sync with broker reality. If pnl_usd cannot be recovered (no
        match / API failure), counters stay un-touched and the gap is
        logged for manual reconcile.
        FNbroker_call_timeout_seconds      $@r   z/[manage] %s positions_get timed out after %.0fsz$[manage] %s positions_get failed: %sr2  ro  r  r   noner   targetz*[manage] %s cancel_order(%s=%s) raised: %sr9  r   id_firstzA[manage] %s cancel_all_for_symbol after external close failed: %s
searchopeng       @zG[manage] %s cancel_all_for_symbol retry after external close failed: %sretryposition_closed_externally)r2  r<  ro  r5  rp  r  rt  stop_id	target_idcancelled_orphansorphan_cancel_methodr  r  
pnl_sourcezb[manage] %s position closed broker-side (TP/SL fill); cancelled %d orphan(s) via %s; state cleanedis_winr<  r         ?z8[manage] %s post-external-close balance fetch failed: %sbalance_confirmedrB  EXTERNAL_CLOSEr2  r5  balance_postpnl_realbroker_pnl_usdr  exit_reasonr   r*   zS[manage] %s PnL discrepancy (external close): estimated=%.2f, real=%.2f, delta=%.2fpnl_discrepancy)r2  estimated_pnlreal_pnldeltabalance_prer  r  r  T)+r:  r0  r\   r   r   r   rr   rP   r   positions_getrQ   r   r   r   r  ro  r  stop_order_idtarget_order_idcancel_ordercancel_all_for_symbolr   rd   r  r   r3  r5  rp  r  rt  r   r[   update_daily_pnlregister_tp_hitregister_sl_hitrc   r   r   get_account_balancer   r(   r  abs)r   r2  r  r/   	positionsr   r  r  r  	cancelledr   cancelled_id_firsttagoidrescancelled_searchopencancelled_retryr  r  r  r	  r  r  s                          rD   r  z"Orchestrator._check_external_close  s    2 <<  ;;  -JDQR	%..))&17 I   150F0Fll,,ll,, 1G 1
 +
'
GZ* 	% V\\//0v||334
 	(HC  KK44VSAA sIu-"a'"	(  	''	!#-   !	)-)J)J6)R#R  	))	!#(<(F#/  >--$$$O(,(I(I&(Q"Q (I"'.$;;"%%++0! ,,11$ll44$ll44 & 8 8#\\22#\\22"LL66$ll::&/)=)#) , ( 	;I3	
 !!-q[F..fll.E.E /  !!11&9!!11&9JJ$$V,f% ;;"!$(A4HK,0L
 --$$$$4;;+J+J+L%LM '/;, #.;? !;.  ;;*--33/#)&)&,,*@*@&A).|Q)? $,#7 !&h 2=A $+#6 !&gq 1<@'1(8 4 * '6=6IE'NsM$}4E5zC'--D"M8U
  ;;2% $ 5 5 ; ;$5+127q2I-28Q-?*/q/05k10E16|Q1G0@/9 !< 
!" S ## 	MM!!A67  	 MM!!6 	 +
B B %%@Ca  $S 	MM!!$a 	 % #R %%017 8  Z %%L %%NA J % 6 $- % $%s  AZ03T6 T3	T6 AZ0VAZ0V 7V8V <Z0
Z0 W >W?W .Z01X2Z09X XX Z05CY 	C2Z0;Y<Z0"Y #Y$Y ,$Z0A0Z AZ0A Z! 1Z03T6 60V&Z0(V0VZ0VZ0V  	W)WZ0WZ0W 	X
"X?Z0X

Z0X 	YX?9Z0?YZ0	YZ0YZ0Y 	Z&Z	Z0	ZZ0	ZZ0ZZ0!	Z-*Z0,Z--Z0c                4
  K   | j                   | j                  | j                  j                  d|       y t	        j
                  |i       }t        |j                  dd            }t        |j                  dd            }|j                  }	 | j                   j                  |j                  ||j                  ||       d {   }	|	j                  s| j                  j                  d||	j                  |	j                         | j                   x	 |	j                  dk(  rd	nd
}| j                   j"                  j%                  ||t'        |	j                  xs d      d d |j                  xs dd d |	j                  xs d       y y | j                  j)                  |	j*                  |	j,                  |j                  j.                         |	j,                  r| j                  j1                  |       n| j                  j3                  |       | j4                  j6                  |= | j9                  ||	||       | j;                  ||j<                         t?        |       | j@                  tC        | dd       }d }tE        jF                  d       d {    	 t        | j@                  jI                          d {         }d\  }}| jK                  ||j                  jL                  |j                  jN                         d {   \  }}}|U|| _(        |
|dkD  r||z
  nd }| j                   q	 | j                   j"                  j%                  d|tS        |	jT                        tW        |d      |tW        |d      nd |tW        |d      nd ||j                         |t        |	j*                        }||z
  }tY        |      dkD  r| j                  j                  d||||       | j                   k	 | j                   j"                  j%                  d|tW        |d      tW        |d      tW        |d      tW        |d      tW        |d      |j                         y y y y y y 7 # t        $ r'}
| j                  j                  d||
       Y d }
~
y d }
~
ww xY w# t        $ r Y y w xY w7 7 # t        $ r(}
| j                  j                  d||
       Y d }
~
d }
~
ww xY w7 # t        $ r Y Sw xY w# t        $ r Y y w xY ww)Nz3[manage] %s EXIT: closer/risk_manager missing, skipr  r   r  )r:  r  r  r  r  z[manage] %s closer raised: %szA[manage] %s closer failed: %s (%s); leaving active_trade in placeclose_success_but_position_openclose_unconfirmedclose_failedr      )r2  r  r  rw  r  r   r  z/[manage] %s post-close balance fetch failed: %sNr  r  r   r  rB  r  r*   zB[manage] %s PnL discrepancy: estimated=%.2f, real=%.2f, delta=%.2fr  )r2  r  r  r  r  r  r  )-rZ   r[   r   r   r   r  r   r  close_trader:  r  r   r9  r   r   rw  rd   r  r   rK   r  r  r  r3  r  r  rc   r   _log_trade_closedr  r;  r   r\   r   rP   r   r  r  ro  r  r   r(   r5  r  r  )r   r2  r  r4  r6  r  r  r  r  r  r   
event_namer  r  r
  broker_pnl_sourcebroker_exit_pricer	  r  r  s                       rD   r  zOrchestrator._handle_exit  s     ;;$"3"3";MM!!"WY_`~~fb)$((;45	488L#67
^^
	-1[[-D-Dllz)
 .E . (F ~~MMSf&7&7 {{& ",,0QQ ,+ 
 KK))//"%"6<<#526t<%-__%:DS$A#)#4#4#: 0   	**!!&--v||?V?V 	+ 	
 ==--f5--f5 JJ$$V,vvx@  6>>: 	f% ;;"!$(A4HK,0L --$$$$4;;+J+J+L%LM 1@-N-,,!$ll44$ll44 -   A~/@ '/;, #.;? !;.  ;;*--33/#)&)&*:*:&;).|Q)? $,#7 !&h 2=A $2#= !&na 8CG'8(0 4 ( '$)&*?*?$@M$}4E5zC'--4"M8U
  ;;2% $ 5 5 ; ;$5+127q2I-28Q-?*/q/05k10E16|Q1G08 !< 	!" 3 ( (G (9 #o(  	MM!!"A61M	. ! D %%L %%EA L % 2 $- % $%s	  BT7Q: Q7	Q: A
TA6R- DTR< T%"S R?S ATS6,TA0S9 2ATA)T	 1T7Q: :	R*R% T%R**T-	R96T8R99T?S 	S3S.(T.S33T9	TTTT		TTTTc           
     ~	  K   | j                   | j                  y t        j                  |i       }t	        |j                  dd            }t	        |j                  dd            }|j
                  }t        d|j                  j                  dz        }	|	|j                  j                  k\  r| j                  ||||       d {    y t        |j                  j                  d            }
|j                  j                  d|j                  j                        }|j                  j                  xs |j                  j                  }|
rt	        |      n
t	        |      }t	        |j                  j                         }	 | j                   j#                  |j                  ||	|j$                  ||||       d {   }|j0                  s`| j(                  j3                  d||j4                  |j6                         d
|j                  _        | j/                  ||j                         y | j                  j9                  |j:                  |j<                  |j                  j>                         d
|j                  _        |j:                  |j                  _         ||j                  _        |j                  j                  |	z
  }tC        jD                  |j                  ||jF                  xs |j                  jH                  |jJ                  xs |j                  jL                        |_        d\  }}| jN                  tQ        jR                  d       d {    	 t	        | jN                  jU                          d {         }|dkD  r|| _+        | jY                  ||j                  jZ                  |j                  j\                         d {   \  }}}| j_                  ||||||       | j/                  ||j                         y 7 U7 ^# t&        $ rT}| j(                  j+                  d	||       d
|j                  _        | j/                  ||j                         Y d }~y d }~ww xY w7 7 # t&        $ r(}| j(                  j+                  d||       Y d }~d }~ww xY w7 ۭw)Nr  r   r  r   rB  set_be_after_partialbe_price)r:  r  contracts_to_closer  r  r  new_sl_pricenew_tp_pricez[manage] %s partial raised: %sTz#[manage] %s partial failed: %s (%s)r  )r5  r  r  r(  r  r   z1[manage] %s post-partial balance fetch failed: %sr  r
  r,  )0rZ   r[   r   r  r   r  r  r:  r5  r  r-  r  rp  r;  r  r  rt  partial_closer  r   r   r   partial_doner  r9  r   r   rw  r  r  r  r3  partial_pnl_usdr  r  new_stop_order_idr  new_target_order_idr  r\   rP   r   r  r   r  ro  r  _log_partial_close)r   r2  r  r4  r6  r  r  r  r  r1  set_ber0  
current_slr2  r3  r  r   residual_contractsr
  r,  r  _s                         rD   r  zOrchestrator._handle_partial  s     ;;$"3"3";~~fb)$((;45	488L#67
^^
 FLL$:$:a$?@!7!77##FFHhGGG h''++,BCD$$((V\\5M5MN^^44M8M8M
*0uXeJ6GV\\223	-1[[-F-Fllz#5)
)	 .G . (F ~~MM5vv||VM^M^ +/FNN'$$Xv~~> 	**!!&--v||?V?V 	+ 	
 '+#)/)>)>& +7' $\\336HH"**LL( 22Pfll6P6P"66V&,,:V:V	
 -<));;"
 --$$$$4;;+J+J+L%LM!#3?D0 :>9O9O ,,00 ,,00 :P : 40A~0 	FFH)/ 	  	
 	  6>>:W H(  	MM!!"BFAN +/FNN'$$Xv~~>	x %%L  %%GA 4s   CR=PB>R=:P" PP" FR=#R$R=)"R RR  ?R=R; =R=P" "	Q?+A
Q:5R=:Q??R=R 	R8R3-R=3R88R=c           	       K   |j                   | j                  j                  d|       y t        |j                  j
                  xs |j                  j                        }| j                  |j                  j                  r	 | j                  j                  ||j                  j                  |j                          d {   }|nt        |dd      sat        |dd      xs d	}| j                  j                  d
||       | j                  |||||       | j                  ||j                         y |j                   |j                  _        | j                  ||||       | j                  ||j                         y 7 # t        $ r\}| j                  j                  d||       | j                  ||||d|        | j                  ||j                         Y d }~y d }~ww xY ww)Nz0[manage] %s MOVE_SL with no move_sl_to, ignoringz"[manage] %s modify_stop raised: %szraised: )prev_slr   r9  Tr   r   zbroker rejected modify_stopz$[manage] %s modify_stop rejected: %sr@  )
move_sl_tor   r   r   r;  r  r:  r  r\   r  modify_stopr   _log_move_sl_failedr  r   _log_move_sl)r   r2  r  r4  r@  r  r   errs           rD   r  zOrchestrator._handle_move_sl5  s     &MM!!"TV\]77P6<<;P;PQ;;"v||'A'A#{{66FLL668K8K   !'&)T*J fgr2S6S%%&LfVYZ((FH#3 )  ((6>>B*2*=*='&&(GD  6>>:3  %%&JFTUV((FH#XaS> )  ((6>>BsD   BG0>F FF 	B=G0F 	G-AG(#G0(G--G0c                    t        | j                  j                        }| j                  |S 	 d}t        | dd      }|r|dkD  rt        |      S |S # t        $ r d}Y .w xY w)au  
        Account balance for sizing.
          - PAPER (no broker)     -> config.dry_run_balance
          - LIVE / DRY (broker present) -> await broker.get_account_balance()
            with fallback to config.dry_run_balance on exception or zero.
        DRY mode reads through DryRunBroker which delegates to the real
        broker (real balance, fake writes).
        Nr   r   )r   rr   dry_run_balancer\   rP   run_coroutine_threadsafer  get_event_loopr  r   r   )r   balancerealcacheds       rD   r  z%Orchestrator._resolve_account_balance^  su     334;;N	 15  8$?fqj=   	D	s   A A A c                F   	 ddl m}  |d      }| j                         j                  |      }|j                  dddd      }||k  r|t	        d	      z
  }|j                  t        j                        S # t        $ r  | j                         t	        d      z
  cY S w xY w)
u  
        UTC instant of the most recent 17:00 America/Chicago — the CME
        futures session-day anchor. TopstepX's "RP&L" in the UI is the
        sum of realized P&L since this moment, so we use it as the
        `since` argument when fetching broker trades for the dashboard.

        DST-aware via zoneinfo. If we're before 17:00 CT today, the
        session began at 17:00 CT *yesterday*; otherwise it's today.
        r   )ZoneInfo   )hourszAmerica/Chicago   )r  minutesecondmicrosecondr   )days)	zoneinforO  ImportErrorr}   r   
astimezoner  r   rm   )r   rO  ctnow_ctanchor_todays        rD   _cme_session_day_start_utcz'Orchestrator._cme_session_day_start_utcy  s    	9) '(++B/~~2aq~QL ')*;;L&&x||44  	9==?YR%888	9s   A7 7&B B c                J  K   | j                   y	 | j                         }| j                   j                  |d       d{   }|yt        |      | _        | j                         | _	        y7 -# t        $ r&}| j                  j                  d|       Y d}~yd}~ww xY ww)a  
        Pull broker-side realized P&L for the current CME session day
        and cache it on `self._cached_daily_rpnl`. Fail-open: on any
        error keep the previous cached value (or None) so the writer
        falls back to the in-memory daily_pnl counter.
        Ni  )r  r  z+[maintenance] daily_rpnl refresh failed: %s)
r\   r]  get_daily_rpnlr   r   r   r   r   r}   r   )r   r  r   r   s       rD   r   z Orchestrator._refresh_daily_rpnl  s      ;;	335E++4454LLE ="',%)]]_" M 	MM!!"OQRS	s@   B#0A1 A/A1 )B#/A1 1	B :BB#B  B#c                  K   | j                   %t        | j                  j                        | _        yt        t        | j                  dd            }	 t        j                  | j                   j                         |       d{   }||dk  rt        d|       t        |      | _        y7 *# t        j                  $ rR | j                  j                  d|       t        | dd      s&t        | j                  j                        | _        Y yY yt        $ r\}| j                  j                  d	|       t        | dd      s)t        | j                  j                        | _        Y d}~yY d}~yd}~ww xY ww)
z
        Refresh self._cached_account_balance from the broker. Called once
        per tick (via _run_iteration). On exception -> keep last value (or
        config.dry_run_balance on first failure). LIVE / DRY only.
        Nr  r  r   r   z&broker returned non-positive balance: zFbroker.get_account_balance timed out after %.0fs; keeping last/dry_runr   z;broker.get_account_balance failed: %s; keeping last/dry_run)r\   r   rr   rH  r   r   rP   r   r  r  rQ   r   r   r   )r   r/   vr   s       rD   r   z%Orchestrator._refresh_account_balance  sN     ;;+01L1L+MD(-JDQR	R&&//17 A yAF #I!!MNN+08D( ## 	RMM!!X 4!:DA/4T[[5P5P/Q, B 	RMM!!Mq 4!:DA/4T[[5P5P/Q,, B		RsP   AE?2B4 B2)B4 1E?2B4 4A E<E?E< AE7-
E?7E<<E?c                    |j                   r|j                   j                  d      nd }|r	 t        |      |_        y y # t        t
        f$ r Y y w xY w)Nr  )r  r  r   last_exit_eval_timer*  r  )r   r4  r;  cds       rD   r  z Orchestrator._apply_candle_dedup  sV    ?G?P?PX""#:;VZ.3Bi+  z* s   ? AAc                    | j                   j                  r-| j                   j                  D cg c]  }|t        v s| c}S t        t        j                               S c c}w r>   )rr   asset_filterr   r  r  )r   as     rD   r   zOrchestrator._asset_list  sH    ;;###{{77K!1
?AKKJOO%&& Ls
   A!A!r   rX  c          	       K   t        j                  |      }|y t        t        | j                  dd            }	 t        j                  t        || j                  |d   |d   |      |       d {   S 7 # t        $ r  t
        j                  $ r  | j                  j                  d||       Y y t        $ r'}| j                  j                  d||       Y d }~y d }~ww xY ww)	Nmarket_data_timeout_secondsr  r  r  )r2  rs   r  r  rY  r   z3[tech] %s build_tech_snapshot timed out after %.0fsz[tech] %s build failed: %s)r   r  r   r   rr   rP   r   r   rs   r   rQ   r   r   r   r  )r   r2  rY  metar/   r   s         rD   r  zOrchestrator._build_tech  s      ~~f%<-JDQR	 ))#!!]]";/#L1$3  	 	 	 	  	## 	
 MM!!Evw  	MM <faH	sL   9C(8A; 4A95A; 8C(9A; ;9C%4C(6C%>C C( C%%C(c                D  K   t        t        | j                  dd            }	 t        j                  | j
                  j                  |dd      |       d {   S 7 # t        j                  $ r  | j                  j                  d||       Y y t        $ r Y y w xY ww)Nh4_fetch_timeout_secondsg      .@4hour2   r   z([tech] %s H4 fetch timed out after %.0fs)r   r   rr   rP   r   rs   get_barsrQ   r   r   r   )r   r2  r/   s      rD   r  zOrchestrator._fetch_h4  s     -GNO		 ))&&vw;    ## 	MM!!"LfV]^ 		sF   !B 5A  AA  B A   0BB BB BB rf  c               v   | j                   y|j                  xs i }	  | j                   j                  j                  	 di d|d|d|j                  d|j
                  d|j                  d|j                  d|j                  d	t        |j                        d
|j                  rt        |j                        dd ndd|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      d|j                  d      t        |       y# t        $ r Y yw xY w)u  
        Symmetric to brain_tf/brain_mr._reject's "entry_rejected" event.
        NOTE: tp_price is the sentinel 0.0 here (Brain didn't finalize TP);
        the resolved tp_price is logged separately via _log_tp_resolved.

        V18 12-mag — quando `tech` è disponibile, i campi RADAR
        (rsi_m5/rsi_h4/h1_compat/macd_*/pattern/atr_ratio/bias/...)
        vengono inclusi così la dashboard web mostra il contesto tecnico
        del trade approvato senza secondary lookup.
        Nr2  r<  ro  rp  r  tp_price_pre_resolverr_multiplier_ai
confidencer  r'  r   sl_atr_multipliertp_rationale_aiclamp_activesl_ticks_used
sl_flooredsl_min_ticksprofile_originrisk_multiplierstep_1step_2step_3key_risk)entry_approved)rd   r  r  r   ro  rp  r  rt  rq  r(   rs  	rationalerK   r  r   r   )r   r2  r<  r4  r=  rj  s         rD   r  z Orchestrator._log_entry_approved  s    ;;  &B	'DKK!!''   #,,	
 %00 "** &.%6%6 "*!7!7 x223 9A8J8Js8--.t4PR #'((+>"? !%): ; "XXn5 #hh7  88L1  "XXn5!"  $xx(89#$ !%): ;%& xx)'( xx))* xx)+, *-!$'/2  		s   FF, ,	F87F8c                   | j                   y	 | j                   j                  j                  d|||j                  |j                  |j
                  |j                  |j                  t        |j                  j                  dd      xs d      |j                  |j                  |j                  |j                  |j                  |j                   |j"                  |j$                         y# t&        $ r Y yw xY w)a,  
        Emit tp_resolved event on brain_log so calibration can correlate
        rr_multiplier (AI input) with tp_ticks_final / rr_effective (post
        MIN_TP_TICKS clamp) and the dollar-domain values (sl_usd_actual,
        tp_usd_target). Lifecycle event, separate from entry_approved.
        Ntp_resolvedrn  r   )r2  r<  ro  rp  r  rt  	tp_sourcern  rr  rr_multiplier_usedrr_effectivetp_ticks_finaltp_distancesl_usd_actualtp_usd_targetmin_tp_ticks_applied)rd   r  r   ro  rp  r  rt  r  r   r  r  rq  r  r  r  r  r  r  r  r   )r   r2  r<  r4  r  s        rD   r  zOrchestrator._log_tp_resolved/  s     ;;	KK!!''",,$00!** **&+%%))*A3GN3' "*!7!7#)#<#<#00%44"..$22$22%+%@%@' ( *  		s   CC/ /	C;:C;c                   | j                   y 	 | j                   j                  |||j                  |j                  |j                  |j
                  |j                  |j                  |j                  	       y # t        $ r Y y w xY w)N)	r2  r<  ro  r5  rp  r  rt  rulereal_risk_usd)
rd   log_trade_openedro  r5  rp  r  rt  r  r  r   )r   r2  r<  r:  rm  r  s         rD   r  zOrchestrator._log_trade_openedW  sx     ;;		KK((U//U__!--YYf.B.B )   		s   A*A: :	BBc                D   | j                   y i }|]t        |j                  j                        t	        |j                  j
                        t	        |j                  j                        d}	  | j                   j                  d||j                  |j                  |j                  |j                  |j                  |j                  |j                  |j                   |j"                  |j$                  |j&                  |j(                  d| y # t*        $ r Y y w xY w)N)r  r  sl_price_real)r2  r<  ro  r5  r  rp  r  profit_ticksr  r  duration_minutesbroker_orders_cancelledr   r?   )rd   r-  r;  r  r   r  r:  r  log_trade_closedr3  ro  r5  r  rp  r  r  r  r  r  r  r   r   )r   r2  r  r4  r  ab_extras         rD   r*  zOrchestrator._log_trade_closedg  s     ;; #'(D(D#E#()G)G#H#()>)>#?H
	(DKK(( V%6%6 **f6F6F"..6;L;L#00%44}}!'!8!8(.(F(F%+%@%@   		s   0B"D 	DDr  r4  c                  | j                   y 	 | j                   j                  j                  d||j                  j                  |j
                  |j                  j
                  |j
                  z
  |j                  |t        |d      nd |t        |j                  j                  d            |j                  d d 
       y # t        $ r Y y w xY w)Nr5  rB  r/  r'  )	r2  r<  contracts_closedcontracts_remainingr7  r
  r  r/  r  )rd   r  r   r:  r3  r5  r  r  r-  r  r  r  r   )r   r2  r  r  r4  r
  r,  s          rD   r:  zOrchestrator._log_partial_close  s     ;;	KK!!''V\\%<%<!'!1!1$*LL$:$:V=M=M$M & 5 5 &1 .!,7;,%)(*;*;*?*?@V*W%Xt, (   		s   B5C 	CCrA  c                  | j                   y |j                  xs i }	 ddlm} t	        |j                  |i       j                  dd      xs d      }	 | j                   j                  j                  d||j                  j                  ||j                  |j                  |j                  d      ||j                  d      |j                  d d 	
       y # t        $ r d}Y w xY w# t        $ r Y y w xY w)
Nr   )r   r  r   move_slraw_sl_price	sl_targetr'  )	r2  r<  r  r2  aligned_sl_pricer  r  r  r  )rd   r  core.config_futuresr   r   r  r   r  r   r:  r3  rB  r  )r   r2  r  r4  r@  rj  _AMr  s           rD   rE  zOrchestrator._log_move_sl  s     ;;  &B	=cggfb155k3GN3OI	KK!!''V\\%<%<!(%00!)!4!4!XXn5#xx,t, ( 
  	I	  		s$   5C BC) C&%C&)	C54C5c               \   | j                   y	 | j                   j                  j                  d||j                  j                  ||j
                  |j                  xs i j                  d      t        |      dd |j                  r|j                  dd nd       y# t        $ r Y yw xY w)z
        Emitted when broker.modify_stop returns success=False or raises.
        Distinct from move_sl (which is success-only) so jq queries on
        brain_log.jsonl can isolate failed attempts.
        Nmove_sl_failedr  r'  r   )r2  r<  r  attempted_sl_pricer  r   r  )rd   r  r   r:  r3  rB  r  r  rK   r  r   )r   r2  r  r4  r@  r   s         rD   rD  z Orchestrator._log_move_sl_failed  s     ;;	KK!!'' V\\%<%<!(#+#6#6 ))/R44[A%j#&08xt,R (   		s   BB 	B+*B+c                    | j                   y 	 | j                   j                  j                  d|||r|j                  r|j                  d d nd       y # t        $ r Y y w xY w)Nexit_deferred_disconnectedr'  r   )r2  r  r  )rd   r  r   r  r   )r   r2  r  r4  s       rD   r  z!Orchestrator._log_action_deferred  sh     ;;	KK!!'',f08X__xt,RT ( 
  		s   AA 	A"!A")r=  r]  r<  rP  c          	     <   | j                   y i }|r,h d}|j                         D 	
ci c]  \  }	}
|	|vs|	|
 }}	}
	  | j                   j                  j                  	 d|||||j                  nd |r|j
                  nd d| y c c}
}	w # t        $ r Y y w xY w)N>   r<  r  r  regimer2  allowed_direction)r2  r  r<  r  r  )	scan_skip)rd   itemsr  r   r  r  r   )r   r2  r  r=  r]  r<  rP  extrareservedkra  s              rD   r  zOrchestrator._log_skip  s    
 ;;
 H '.mmoKda(9JQTKEK		'DKK!!''fE&*&6t{{D<@$"8"8d	
  L  		s   B	B	A	B 	BBc                   | j                   y 	  | j                   j                  j                  	 d|||j                  |j                  |j
                  |j                  |j                  d|j                          y # t        $ r Y y w xY w)N)r2  r<  r  r  ro  r5  r  )scan_skip_risk)
rd   r  r   r  r  ro  r5  r  
audit_dictr   )r   r2  r<  r4  rm  r  s         rD   r  zOrchestrator._log_risk_skip	  s     ;;	'DKK!!'' UYYt{{",, **$22 //#  		s   A/A? ?	B
B)rW   zOptional[dict[str, Any]]rX   zOptional[BiasResolver]rY   zOptional[TradeOpener]rZ   zOptional[TradeCloser]r[   zOptional[RiskManager]r\   Optional[Any]r]   r  r^   zOptional[NewsFilter]r_   z Optional[Callable[[], datetime]]r`   zOptional[int]rq   r   )rq   r(   )rq   r   )rq   r   r>   )r  rK   rR   zOptional[BaseException]rq   r   )r   rK   rR   r   rq   r   )rq   rK   )rq   r-  )
r2  rK   r<  rK   r5  r(   r7  rK   rq   zOptional[TradeOpenResult])rE  r(   rq   r   )r2  rK   rq   r   )r  r   r6  r   rq   r   )
r2  rK   ro  rK   r  r   r  r(   rq   z,tuple[Optional[float], Optional[float], str])r2  rK   r  r   rq   r-  )
r2  rK   r  r   r4  r   r6  r   rq   r   )r2  rK   r  r   r4  r   rq   r   rp   )r4  r   r;  r   rq   r   )rq   z	list[str])r2  rK   rY  r(   rq   Optional[TechSnapshot])r2  rK   )
r2  rK   r<  rK   r4  r   r=  r  rq   r   )
r2  rK   r<  rK   r4  r   r  r!   rq   r   )r2  rK   r<  rK   rm  r   rq   r   )
r2  rK   r  r#   r4  r   r  zOptional[ActiveTrade]rq   r   )r2  rK   r  r   r  r#   r4  r   r
  Optional[float]r,  rK   rq   r   )
r2  rK   r  r   r4  r   r@  r  rq   r   )r2  rK   r  r   r4  r   r@  r   r   rK   rq   r   )r2  rK   r  rK   r4  r   rq   r   )r2  rK   r  rK   r=  r  r<  zOptional[str]rP  zOptional[dict]rq   r   )
r2  rK   r<  rK   r4  r   rm  r   rq   r   )/r   r   r   __doc__r   r   r   r   r   r   r   r   r  r  r   r   r(  r?  r   r   rJ  r   r  r  r  r  r  r  r  r  r]  r   r   r  r   r  r  r  r  r  r*  r:  rE  rD  r  r  r  r?   rT   rD   rV   rV      s   U 4804(,(,.2 $$(,0=A(,%^C 1^C .^C &^C &^C ,^C ^C "^C  *!^C" ;#^C$ &%^C& 
'^CHKBZ3#j'2F'P++Z?2$"C5n2%(?B 
#<>8*MKf
A;NW!W-9W	W~ )% )% 	)%
 )% )% 
6)%VJJ#.J	JXY%Y%#.Y%:GY%Y% 
Y%vy;y;#.y;:Gy;y; 
y;v#;#;#.#;:G#;	#;R65*5(R>' 67  /2 	 D& +/,,"%,1>,', 
,\&& &  	&
 & 
&P"%6D	$ )-!!#3!?L!%! 
!N +/!*#.8H (	
  
: '+#.:G# 
6#.:G"% 
0#&2?	  (,$t"&#&$?L   
	8"%1> 
rT   rV   )rR   r   rq   rK   )Ar  
__future__r   rP   r  r   r   r   r   pathlibr   typingr   r	   r
   analysis.biasr   analysis.tech_snapshotr   r   r   r   r   brain.brain_selectorr   corer   rv   r  r   r   r   core.contractsr   r   r   r   r   core.news_filterr   r   r   r   r   trading.risk_managerr   trading.sizingr   r    trading.tp_resolverr!   r"   trading.trade_closerr#   r$   trading.trade_openerr%   r&   r)   __annotations__r+   r5   r;   rS   rV   r?   rT   rD   <module>r     s   "H #    2 2  * * &  . * 
  ( , / , 9 > > = "# 3 " 2A . @
,   ' O 
*P" P"rT   