
    ]j7                        U d Z ddlmZ ddlmZ ddlmZ dZde	d<   dZ
de	d	<   d
Zde	d<   dZde	d<    ed       G d d             Zdd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZy)u	  
APEX V16/V17 — TP price resolver.

Two resolution paths (V17):

  1. AI-suggested (preferred when valid, V17 narrative prompt):
     Brain forwards `tp_price_suggested` (assoluto, basato su VWAP / EMA50 /
     swing). Resolver applica un margine conservativo del 15% verso l'entry
     prima di snappare al tick e applicare MIN_TP_TICKS floor. Selezionato
     quando tp_price_suggested > 0 ed è coerente con la direzione
     (BUY: > entry; SELL: < entry).

  2. rr-fallback (V16 originale, variante γ):
     Brain emette `rr_multiplier` ∈ [0.17, 0.67] (advisory, post_val).
     Resolver calcola tp_ticks = round(rr × sl_ticks), poi floor MIN_TP_TICKS.
     Selezionato quando AI path non è disponibile o non è coerente.

In entrambi i path Brain lascia `EntryDecision.tp_price = 0.0` come sentinel
e l'orchestrator chiama `resolve_tp_price(...)` post-sizing per finalizzare
il prezzo TP assoluto.

Math (rr-fallback):
    sl_usd_actual = contracts × sl_ticks × tick_value
    tp_usd_target = rr_multiplier × sl_usd_actual
    tp_distance   = tp_usd_target / (contracts × tick_value)
                  = rr_multiplier × sl_ticks × tick_size      [contracts cancels]
    tp_ticks_raw  = round(rr_multiplier × sl_ticks)
    tp_ticks_final = max(MIN_TP_TICKS[symbol], tp_ticks_raw)
    tp_price       = entry ± tp_ticks_final × tick_size  (BUY: +, SELL: -)

Math (ai_suggested, conservative margin 15% toward entry):
    distance_raw  = |tp_price_suggested − entry|
    distance_cons = (1 − TP_SUGGESTED_CONSERVATIVE_MARGIN) × distance_raw
    tp_ticks_raw  = round(distance_cons / tick_size)
    tp_ticks_final = max(MIN_TP_TICKS[symbol], tp_ticks_raw)
    tp_price       = entry ± tp_ticks_final × tick_size  (BUY: +, SELL: -)

Note: `contracts` algebraically cancels out of the points-distance formula
in the rr-fallback path. We keep it in the signature for narrative coherence
with the AI prompt ("rr × $rischio reale"), and so `sl_usd_actual` /
`tp_usd_target` can be logged for calibration forensics.

Hard clamp on `rr_multiplier` is applied here (RR_MULT_MIN/MAX) on the
rr-fallback path only. The Brain post_validate enforces a *narrower*
prompt-range [0.17, 0.67] as advisory rejection. Hard clamp is
defense-in-depth for marginal AI drift.

Pure function — no broker, no AI, no I/O.
    )annotations)	dataclass)config_futuresg?floatRR_MULT_MINg?RR_MULT_MAXg333333? TP_SUGGESTED_CONSERVATIVE_MARGINg       @MAX_RR_EFFECTIVET)frozenc                  ~    e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded	<   ded
<   ded<   dZded<   dZded<   y)TPResolutionu  
    Output of resolve_tp_price.

    tp_price            : finalized absolute price (rounded to asset digits).
    tp_ticks_final      : post-floor TP distance in ticks.
    tp_distance         : tp_ticks_final × tick_size (price points).
    sl_usd_actual       : contracts × sl_ticks × tick_value (real $ at risk).
    tp_usd_target       : target $ on TP hit. rr_fallback: rr_multiplier ×
                          sl_usd_actual; ai_suggested: rr_effective ×
                          sl_usd_actual (de-facto rr derived from the
                          AI-suggested distance after conservative margin
                          and tick snap).
    rr_effective        : tp_ticks_final / sl_ticks. rr-fallback: equals
                          rr_multiplier unless MIN_TP_TICKS floor lifted
                          tp_ticks above the raw round. ai_suggested:
                          de-facto rr produced by the AI suggestion path.
    rr_multiplier_used  : rr-fallback: rr_multiplier post hard-clamp (the
                          value math used). ai_suggested: equals
                          rr_effective (no rr_multiplier consumed).
    min_tp_ticks_applied: True iff MIN_TP_TICKS[symbol] raised tp_ticks above
                          the raw round (in either path).
    tp_source           : "ai_suggested" when AI's tp_price_suggested was
                          used (post 15% conservative margin); "rr_fallback"
                          when the legacy rr_multiplier path was taken.
    r   tp_priceinttp_ticks_finaltp_distancesl_usd_actualtp_usd_targetrr_effectiverr_multiplier_usedboolmin_tp_ticks_appliedrr_fallbackstr	tp_sourceF	rr_cappedN)__name__
__module____qualname____doc____annotations__r   r        */home/work/apex_v16/trading/tp_resolver.pyr   r   d   sN    2 O"Is"
 Itr"   r           )tp_price_suggestedc                   |dk  rt        |  d|       |dk  rt        |  d|       |dk  rt        |  d|       |dvrt        |  d|      t        j                  |    }t        |d         }t        |d         }	t	        |d	         }
t	        t        j
                  j                  | d
            }||z  |	z  }|dkD  xr |dk(  xr ||kD  xs |dk(  xr ||k  }|rdt        z
  }|dk(  r	||z
  |z  }n||z
  |z  }t	        t        ||z              }||k  r|}d}n|}d}t	        t        |z        }||kD  rt        ||      }d}n|}d}||z  }|dk(  r||z   }n||z
  }|dkD  r||z  nd}||z  }t        t        ||
      |t        ||
dz         t        |d      t        |d      t        |d      t        |d      |d|
      S |dk  rt        |  d|       t        t        t        |t                    }||z  }t	        t        ||z              }||k  r|}d}n|}d}t	        t        |z        }||kD  rt        ||      }d}n|}d}||z  }|dk(  r||z   }n||z
  }|dkD  r||z  nd}t        t        ||
      |t        ||
dz         t        |d      t        |d      t        |d      t        |d      |d|
      S )uX  
    Compute the absolute TP price for an approved entry, post-sizing.

    V17 dual-path:
      - When `tp_price_suggested > 0` AND coherent with `direction`
        (BUY: > entry, SELL: < entry), use the AI-suggested path with
        conservative margin TP_SUGGESTED_CONSERVATIVE_MARGIN (default 15%
        toward entry). Returns TPResolution.tp_source = "ai_suggested".
      - Otherwise fall back to the legacy V16 rr_multiplier math
        (variante γ). Returns TPResolution.tp_source = "rr_fallback".

    Backward compatible: callers that don't pass `tp_price_suggested` get
    the V16 rr-fallback behavior unchanged.

    Args:
        symbol: e.g. "MES", "6B" (must be in ASSETS_MAP).
        direction: "BUY" or "SELL".
        entry_price: float > 0.
        rr_multiplier: AI-chosen multiplier; hard-clamped to
                       [RR_MULT_MIN, RR_MULT_MAX] when used (rr-fallback).
                       Required (>0) only on rr-fallback path; the
                       AI-suggested path ignores it.
        contracts: post-sizing contract count (> 0).
        sl_ticks: post-clamp SL distance in ticks (> 0; from sizing).
        tp_price_suggested: V17 AI-emitted absolute TP price. Default 0.0
                            (= AI suggestion absent, use rr-fallback). When
                            > 0 but NOT direction-coherent, also falls back
                            to rr-multiplier (silent — incoherence is just
                            "no usable suggestion").

    Returns:
        TPResolution with finalized tp_price, tp_source, full diagnostics.

    Raises:
        ValueError on entry_price<=0, sl_ticks<=0, contracts<=0,
                   unknown direction, OR rr_multiplier<=0 when the
                   AI-suggested path is not selected (rr-fallback then
                   has no usable input). KeyError on unknown symbol.
    r   z: entry_price must be > 0, got z: sl_ticks must be > 0, got z: contracts must be > 0, got )BUYSELLz": direction must be BUY|SELL, got 	tick_size
tick_valuedigits   r'   r(   g      ?TFr$         ai_suggested)
r   r   r   r   r   r   r   r   r   r   z!: rr_multiplier must be > 0, got r   )
ValueErrorcfg_fut
ASSETS_MAPr   r   MIN_TP_TICKSgetr	   roundr
   maxr   r   minr   )symbol	directionentry_pricerr_multiplier	contractssl_ticksr%   specr)   r*   r+   min_tp_ticksr   use_ai_pathscaletp_raw_distancetp_ticks_rawtp_ticks_after_floorr   tp_ticks_capr   r   r   r   r   r   rr_useds                              r#   resolve_tp_pricerG      s   b aF8#B;-PQQ1}F8#?zJKKA~F8#@LMM'F8#Ei]STTf%Dd;'(ItL)*Jh Fw++//:;L(:5M %q( 	e		A!3k!A 	C	f		A!3k!A 
 
 661K?5HO*-??5HO59!<=>,&#/ #' #/ #(  +h67,. |<NI1NI$y0"[0H"[0H4<qL~0c %}48V,)k6A:6q1q1|Q/$\15!5$
 	
 F8#D]OTUU +s=+>?Gm+MuWx/01Ll"+#+$ '(23Ll*\<8	-	 9,KE,,081>H,#Lx(%+vz2M1-M1-<+ !,1 r"   N)r8   r   r9   r   r:   r   r;   r   r<   r   r=   r   r%   r   returnr   )r   
__future__r   dataclassesr   corer   r1   r   r    r   r	   r
   r   rG   r!   r"   r#   <module>rL      s   0d # ! * U U  +/  % .*  %  $' ' 'l !$rr r 	r
 r r r r rr"   