Indicator · Pine Script v6 · On the chart

UT Bot v6

by Stolzel

This indicator calculates and plots trend-following signals based on an adaptive UT Bot trailing stop mechanism on the price chart.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code1,768
Settings40inputs
LicenceMIT
Last update4 months ago9 Jun 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

1,768 lines of Pine Script v6 from UT_Bot_v6_github.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

UT_Bot_v6_github.pine
//@version=6
indicator(title="UT Bot v6", overlay=true, max_boxes_count=500, max_labels_count=500)

// 
// INPUTS
// 
buy_key        = input.int(2,  "Key [BUY] tendencia",  minval=1)
buy_key_range  = input.int(3,  "Key [BUY] lateral",    minval=1)
buy_atr        = input.int(10, "ATR Period [BUY]",     minval=1)
sell_key       = input.int(2,  "Key [SELL] tendencia", minval=1)
sell_key_range = input.int(3,  "Key [SELL] lateral",   minval=1)
use_dynamic_key = input.bool(true, "Key dinamico segun regimen")
sell_atr       = input.int(10, "ATR Period [SELL]",    minval=1)

use_candles    = input.bool(true,  "Filtro consistencia de velas")
use_vwap       = input.bool(true,  "Filtro VWAP")
use_session    = input.bool(true,  "Filtro horario")
session_open   = input.session("1330-1530", "Sesion 1 UTC NY Open")
session_pm     = input.session("1800-2000", "Sesion 2 UTC NY Tarde")

use_early      = input.bool(true, "Filtro Early Zone (apertura NY)")
i_body_pct     = input.float(40.0, "Early: cuerpo minimo % rango", minval=10.0, maxval=90.0, step=5.0)
i_trail_dist   = input.float(8.0, "Early: distancia minima trail (pts)", minval=2.0, maxval=30.0, step=1.0)

use_bias        = input.bool(true, "Filtro sesgo D/W")
i_bias_strength = input.int(2, "Umbral sesgo (1-3)", minval=1, maxval=3)
use_regime      = input.bool(true, "Filtro regimen")

// PMT — configuracion de conexion
grp_pmt       = "PMT Automatizacion"
i_pmt_symbol  = input.string("MNQ1!",       "Simbolo PMT",   group=grp_pmt)
i_pmt_token   = input.string("TU-TOKEN-AQUI",  "Token PMT",     group=grp_pmt)
i_pmt_account = input.string("TU-ACCOUNT-ID",  "Account ID PMT",group=grp_pmt)

i_sl_min       = input.float(35.0, "SL minimo (pts)", minval=5.0,  step=5.0)
i_sl_max       = input.float(50.0, "SL maximo (pts)", minval=10.0, step=5.0)
i_tp1_r        = input.float(1.0, "TP1 (R)", minval=0.5, step=0.5)
i_tp2_r        = input.float(2.0, "TP2 (R)", minval=1.0, step=0.5)
i_tp3_r        = input.float(3.0, "TP3 (R)", minval=1.5, step=0.5)
i_show_boxes   = input.bool(true, "Mostrar boxes TP/SL")
i_box_width    = input.int(20, "Ancho boxes (barras)", minval=5, step=5)

use_trade_rule = input.bool(true, "Regla: max losses por sesion")
i_max_losses   = input.int(2, "Max losses por sesion", minval=1, maxval=5)
i_tp1_r_gate   = input.float(1.0, "TP1 gate T1 ganador (R)", minval=0.5, step=0.5)

i_show_exhaust  = input.bool(true,  "Mostrar agotamiento")
i_show_presignal= input.bool(true,  "Mostrar pre-senal intrabar")
i_exhaust_be    = input.int(2, "Score BE (1-3)",  minval=1, maxval=3)
i_exhaust_exit  = input.int(3, "Score 1R (1-3)",  minval=1, maxval=3)
i_use_f1        = input.bool(true,  "F1: CVD divergencia")
i_use_f2        = input.bool(false, "F2: Delta decreciente")
i_use_f3        = input.bool(false, "F3: Vela de rechazo")
i_mecha_pct     = input.float(60.0, "F3: mecha minima %", minval=30.0, maxval=90.0, step=5.0)

i_use_atr_filter = input.bool(true,  "Filtro ATR: bloquear volatilidad anormal")
i_atr_lookback   = input.int(20, "Filtro ATR: periodo promedio barras", minval=5, maxval=100)
i_atr_mult_max   = input.float(1.5, "Filtro ATR: max vs promedio", minval=1.0, maxval=3.0, step=0.1)

i_show_bt      = input.bool(true, "Mostrar tabla BT")
i_show_live    = input.bool(true,  "Mostrar dashboard LIVE")
i_risk_usd     = input.float(300.0, "Riesgo base por trade USD",    minval=50.0, step=50.0)
i_risk_scaled  = input.float(600.0, "Riesgo escalado tras win USD",  minval=50.0, step=50.0)
i_use_scaling  = input.bool(true, "Activar riesgo dinamico win->up loss->down")
i_cooldown     = input.int(3, "Cooldown: velas minimas entre seales", minval=0, maxval=20)
i_bt_tp        = input.float(2.0, "BT: cerrar en TP (R)", minval=1.0,  step=0.5)

i_show_prop    = input.bool(true, "Mostrar simulador fondeo")
i_prop_cost    = input.float(45.0, "Costo cuenta ($)",      minval=10.0,  step=5.0)
i_prop_goal    = input.float(3000.0, "Objetivo profit ($)",   minval=500.0, step=500.0)
i_prop_maxdd   = input.float(2000.0, "Max DD total ($)",      minval=500.0, step=500.0)
i_prop_daily   = input.float(1000.0, "Max loss diario ($)",   minval=100.0, step=100.0)
i_prop_payout  = input.float(3000.0, "Payout por pasada ($)", minval=500.0, step=500.0)
i_prop_trigger = input.float(50.0, "Pipeline trigger %",    minval=10.0,  maxval=100.0, step=10.0)
i_prop_maxaccs = input.int(3, "Pipeline max cuentas",  minval=1,     maxval=5)

// 
// SESION
// 
is_regular     = not na(time(timeframe.period, "0930-1600", "America/New_York"))
is_new_session = is_regular and not is_regular[1]

_h_et            = hour(time, "America/New_York")
_m_et            = minute(time, "America/New_York")
is_session_start = _h_et == 18 and _m_et == 0

var int bars_since_open = 0
if is_new_session
    bars_since_open := 0
if is_regular and barstate.isconfirmed
    bars_since_open += 1

past_blackout = bars_since_open >= 3
in_early_zone = bars_since_open >= 3 and bars_since_open <= 5

in_session1 = not na(time(timeframe.period, session_open))
in_session2 = not na(time(timeframe.period, session_pm))
in_session  = in_session1 or in_session2
in_blackout = use_session and in_session1 and not past_blackout
f_time      = use_session ? (in_session2 or (in_session1 and past_blackout)) : true

// 
// VWAP
// 
var float vwap_pv = 0.0
var float vwap_v = 0.0
if is_new_session
    vwap_pv := 0.0
    vwap_v  := 0.0
if is_regular
    vwap_pv += (high + low + close) / 3.0 * volume
    vwap_v  += volume
vwap_val   = vwap_v > 0 ? vwap_pv / vwap_v : na
above_vwap = not na(vwap_val) and close > vwap_val
below_vwap = not na(vwap_val) and close < vwap_val
f_vwap_long  = use_vwap ? above_vwap : true
f_vwap_short = use_vwap ? below_vwap : true

// 
// SESGO D/W
// 
float d_close = request.security(syminfo.tickerid, "D", close[1],           lookahead=barmerge.lookahead_on)
float d_sma20 = request.security(syminfo.tickerid, "D", ta.sma(close, 20)[1], lookahead=barmerge.lookahead_on)
float d_sma5  = request.security(syminfo.tickerid, "D", ta.sma(close, 5)[1], lookahead=barmerge.lookahead_on)
float w_close = request.security(syminfo.tickerid, "W", close[1],           lookahead=barmerge.lookahead_on)
float w_open  = request.security(syminfo.tickerid, "W", open[1],            lookahead=barmerge.lookahead_on)

int bias_bull  = ((not na(d_close) and not na(d_sma20) and d_close > d_sma20) ? 1 : 0) + ((not na(d_sma5) and not na(d_sma20) and d_sma5 > d_sma20) ? 1 : 0) + ((not na(w_close) and not na(w_open) and w_close > w_open) ? 1 : 0)
int bias_bear  = ((not na(d_close) and not na(d_sma20) and d_close < d_sma20) ? 1 : 0) + ((not na(d_sma5) and not na(d_sma20) and d_sma5 < d_sma20) ? 1 : 0) + ((not na(w_close) and not na(w_open) and w_close < w_open) ? 1 : 0)
int bias_score = bias_bull - bias_bear
bool period_bull    = bias_score >=  i_bias_strength
bool period_bear    = bias_score <= -i_bias_strength
bool period_neutral = not period_bull and not period_bear
f_bias_long  = use_bias ? (period_bull  or period_neutral) : true
f_bias_short = use_bias ? (period_bear  or period_neutral) : true

// 
// REGIMEN
// 
var float vwap_5bars_ago = na
if is_new_session
    vwap_5bars_ago := na
if is_regular and bars_since_open == 5
    vwap_5bars_ago := vwap_val

float vwap_slope       = not na(vwap_5bars_ago) ? vwap_val - vwap_5bars_ago : na
bool  vwap_trending_up = not na(vwap_slope) and vwap_slope >  5.0
bool  vwap_trending_dn = not na(vwap_slope) and vwap_slope < -5.0
bool  vwap_flat        = not na(vwap_slope) and math.abs(vwap_slope) <= 5.0
float dist_vwap        = not na(vwap_val) ? math.abs(close - vwap_val) : na
bool  price_far_vwap   = not na(dist_vwap) and dist_vwap >  30.0
bool  price_near_vwap  = not na(dist_vwap) and dist_vwap <= 15.0

var int vwap_crosses = 0
var bool prev_above_vwap = false
if is_new_session
    vwap_crosses    := 0
    prev_above_vwap := false
if is_regular and barstate.isconfirmed and not na(vwap_val)
    bool cur_above = close > vwap_val
    if prev_above_vwap != cur_above and bars_since_open > 1
        vwap_crosses += 1
    prev_above_vwap := cur_above

bool regime_ready      = bars_since_open >= 6
int  regime_trend_score= regime_ready ? ((vwap_trending_up or vwap_trending_dn ? 1 : 0) + (price_far_vwap ? 1 : 0) + (vwap_crosses <= 1 ? 1 : 0)) : 0
int  regime_range_score= regime_ready ? ((vwap_flat ? 1 : 0) + (price_near_vwap ? 1 : 0) + (vwap_crosses >= 3 ? 1 : 0)) : 0
bool regime_trend      = regime_ready and regime_trend_score >= 2
bool regime_range      = regime_ready and regime_range_score >= 2
f_regime = use_regime ? (not regime_ready or regime_trend or not regime_range) : true

// 
// CVD
// 
bar_delta = high != low ? volume * (2.0 * (close - low) / (high - low) - 1.0) : 0.0
var float cvd = 0.0
cvd := is_new_session ? bar_delta : cvd[1] + bar_delta
cvd_rising  = cvd > cvd[1] and cvd[1] > cvd[3]
cvd_falling = cvd < cvd[1] and cvd[1] < cvd[3]

// 
// TRAILING STOP  solo close[1], estable entre ticks
// 
// nLoss congelado al cierre  elimina seales fantasma en v6
// Key dinamico segun regimen:
// TREND  → key normal (2): trail ajustado, captura tendencia rapidamente
// LATERAL → key amplio (3): trail amplio, filtra ruido en mercado sin direccion
// MIXTO/SIN DATO → key normal por defecto
int eff_buy_key  = use_dynamic_key ? (regime_range ? buy_key_range  : buy_key)  : buy_key
int eff_sell_key = use_dynamic_key ? (regime_range ? sell_key_range : sell_key) : sell_key

float nLoss_buy_rt  = eff_buy_key  * ta.atr(buy_atr)
float nLoss_sell_rt = eff_sell_key * ta.atr(sell_atr)

var float nLoss_buy = 0.0
var float nLoss_sell = 0.0
if barstate.isconfirmed
    nLoss_buy  := nLoss_buy_rt
    nLoss_sell := nLoss_sell_rt

var float trailStop = 0.0
var float trailStop_c = 0.0
var float trailStop_p = 0.0
var int pos = 0

float prevStop = nz(trailStop[1], 0.0)
trailStop := close[1] > prevStop ? math.max(prevStop, close[1] - nLoss_buy) : math.min(prevStop, close[1] + nLoss_sell)

if barstate.isconfirmed
    trailStop_p := trailStop_c
    trailStop_c := trailStop

// Cruces con valores congelados  estables en live
crossUp   = close[2] < trailStop_p and close[1] > trailStop_c
crossDown = close[2] > trailStop_p and close[1] < trailStop_c

// 
// EARLY ZONE FILTER
// 
candle_range = high[1] - low[1]
candle_body  = math.abs(close[1] - open[1])
body_pct     = candle_range > 0 ? (candle_body / candle_range) * 100.0 : 0.0
trail_dist   = math.abs(close[1] - trailStop_c)
f_body_ok    = not use_early or not in_early_zone or body_pct   >= i_body_pct
f_dist_ok    = not use_early or not in_early_zone or trail_dist >= i_trail_dist
f_early      = f_body_ok and f_dist_ok

// 
// FILTRO CONSISTENCIA DE VELAS
// 
candle_bull    = close[1] > open[1] and close[2] > open[2]
candle_bear    = close[1] < open[1] and close[2] < open[2]
f_candle_long  = use_candles ? candle_bull : true
f_candle_short = use_candles ? candle_bear : true

// Delta early zone
i_delta_thresh  = 30.0
f_bull_bar(o) =>
    float d   = high[o] != low[o] ? volume[o] * (2.0 * (close[o] - low[o]) / (high[o] - low[o]) - 1.0) : 0.0
    float pct = volume[o] > 0 ? math.abs(d) / volume[o] * 100.0 : 0.0
    d > 0 and pct >= i_delta_thresh
f_bear_bar(o) =>
    float d   = high[o] != low[o] ? volume[o] * (2.0 * (close[o] - low[o]) / (high[o] - low[o]) - 1.0) : 0.0
    float pct = volume[o] > 0 ? math.abs(d) / volume[o] * 100.0 : 0.0
    d < 0 and pct >= i_delta_thresh

bull_prev_count = (f_bull_bar(1) ? 1 : 0) + (f_bull_bar(2) ? 1 : 0) + (f_bull_bar(3) ? 1 : 0)
bear_prev_count = (f_bear_bar(1) ? 1 : 0) + (f_bear_bar(2) ? 1 : 0) + (f_bear_bar(3) ? 1 : 0)
bar_delta_cur   = high != low ? volume * (2.0 * (close - low) / (high - low) - 1.0) : 0.0
delta_pct_cur   = volume > 0 ? math.abs(bar_delta_cur) / volume * 100.0 : 0.0
bull_delta_cur  = bar_delta_cur > 0 and delta_pct_cur >= i_delta_thresh
bear_delta_cur  = bar_delta_cur < 0 and delta_pct_cur >= i_delta_thresh
delta_ok_long   = in_early_zone ? bull_prev_count >= 2 : bull_delta_cur
delta_ok_short  = in_early_zone ? bear_prev_count >= 2 : bear_delta_cur

// 
// SL ESTRUCTURAL
// 
f_calc_sl(is_long) =>
    float extremo = is_long ? low[1] : high[1]
    float dist    = is_long ? (close[1] - extremo) : (extremo - close[1])
    float safe    = na(dist) or dist <= 0 ? i_sl_min : dist
    float clamped = math.max(i_sl_min, math.min(i_sl_max, safe))
    math.round(clamped / 0.25) * 0.25

// 
// SEALES BASE
// 
// Filtro ATR relativo  detecta volatilidad anormal
// Compara el ATR actual con su promedio de las ultimas N barras
// Si ATR actual > N x promedio  mercado en regimen de alta volatilidad
// Ejemplos de cuando se activa: spikes de noticias, liquidaciones, gaps
atr_current = ta.atr(buy_atr)
atr_avg     = ta.sma(atr_current, i_atr_lookback)
atr_ratio   = atr_avg > 0 ? atr_current / atr_avg : 1.0
f_atr_ok    = not i_use_atr_filter or atr_ratio <= i_atr_mult_max

// Cooldown  evita seales dentro de N velas de la ultima seal
// Bloquea tanto seales en la misma direccion como whipsaws opuestos
// last_signal_bar se actualiza DESPUES de calcular buy/sell
// usando crossUp/crossDown raw (sin cooldown) para detectar el cruce
var int last_signal_bar = -999
bars_since_signal = bar_index - last_signal_bar
f_cooldown = i_cooldown == 0 or bars_since_signal >= i_cooldown

buy_raw  = crossUp   and pos[1] != 1  and f_cooldown
sell_raw = crossDown and pos[1] != -1 and f_cooldown

// Actualizar last_signal_bar cuando hay seal confirmada
if buy_raw or sell_raw
    last_signal_bar := bar_index

buy_filtered  = buy_raw  and f_candle_long  and f_vwap_long  and f_time and f_bias_long  and f_regime and f_early and f_atr_ok
sell_filtered = sell_raw and f_candle_short and f_vwap_short and f_time and f_bias_short and f_regime and f_early and f_atr_ok

// 
// EXHAUST SCORE PREV  para regla T2 (antes de buy/sell)
// 
bool _ep_f1 = (pos[1] == 1 and close[1] > close[4] and cvd[1] < cvd[4]) or (pos[1] == -1 and close[1] < close[4] and cvd[1] > cvd[4])
float _d0   = high[1] != low[1] ? math.abs(volume[1]*(2.0*(close[1]-low[1])/(high[1]-low[1])-1.0)) : 0.0
float _d1   = high[2] != low[2] ? math.abs(volume[2]*(2.0*(close[2]-low[2])/(high[2]-low[2])-1.0)) : 0.0
float _d2   = high[3] != low[3] ? math.abs(volume[3]*(2.0*(close[3]-low[3])/(high[3]-low[3])-1.0)) : 0.0
bool _ep_f2 = (pos[1] == 1 or pos[1] == -1) and (_d0 < _d1 and _d1 < _d2)
float _vr   = high[1] - low[1]
float _mb   = _vr > 0 ? (pos[1] == 1 ? (high[1]-close[1])/_vr : (close[1]-low[1])/_vr) : 0.0
bool _ep_f3 = (pos[1] == 1 or pos[1] == -1) and _mb >= 0.6
int exhaust_score_prev = (_ep_f1 ? 1 : 0) + (_ep_f2 ? 1 : 0) + (_ep_f3 ? 1 : 0)

// 
// REGLA 2 TRADES POR SESION
// 
var int trade_count = 0
var int loss_count       = 0  // losses desde 9:30 ET (logica)
var int loss_count_apex  = 0  // losses desde 18:00 ET (display Apex)
var bool first_win = false
var bool sess_locked = false
var bool t1_exhausted = false
var float t1_sl = na
var float t1_tp1 = na
var bool t1_is_long = false

if is_new_session  // reset sesion NY: 9:30 ET
    trade_count  := 0
    loss_count   := 0
    first_win    := false
    sess_locked  := false
    t1_exhausted := false
    t1_sl        := na
    t1_tp1       := na

if trade_count == 1 and not na(t1_sl) and not na(t1_tp1)
    if t1_is_long
        if high >= t1_tp1
            first_win := true
        if low <= t1_sl and not first_win
            sess_locked := true
    else
        if low  <= t1_tp1
            first_win := true
        if high >= t1_sl and not first_win
            sess_locked := true

if trade_count == 1 and first_win and not t1_exhausted
    if exhaust_score_prev >= 2
        t1_exhausted := true

t2_bias_changed = t1_is_long ? period_bear : period_bull
t2_allow_long   = first_win and t1_exhausted and (t1_is_long ? not t2_bias_changed : t2_bias_changed)
t2_allow_short  = first_win and t1_exhausted and (t1_is_long ? t2_bias_changed : not t2_bias_changed)

// Sesion bloqueada cuando se alcanzan max losses configurados
// Wins no cuentan — solo losses bloquean
session_gate_t1 = not use_trade_rule or (not sess_locked and loss_count < i_max_losses)
session_closed  = use_trade_rule and loss_count >= i_max_losses

buy  = buy_filtered  and not session_closed and (session_gate_t1 or (trade_count == 1 and t2_allow_long))
sell = sell_filtered and not session_closed and (session_gate_t1 or (trade_count == 1 and t2_allow_short))

pos := buy ? 1 : sell ? -1 : crossUp ? 1 : crossDown ? -1 : pos

// 
// NIVELES DE ENTRADA
// 
var float sig_entry = na
var float sig_sl = na
var float sig_tp1 = na
var float sig_tp2 = na
var float sig_tp3 = na

if buy or sell
    trade_count += 1
    bool  _long   = buy
    float _sl_pts = f_calc_sl(_long)
    sig_entry := close  // close de vela B = precio de entrada en vela C
    sig_sl    := _long ? close - _sl_pts             : close + _sl_pts
    sig_tp1   := _long ? close + _sl_pts * i_tp1_r   : close - _sl_pts * i_tp1_r
    sig_tp2   := _long ? close + _sl_pts * i_tp2_r   : close - _sl_pts * i_tp2_r
    sig_tp3   := _long ? close + _sl_pts * i_tp3_r   : close - _sl_pts * i_tp3_r
    if trade_count == 1
        float _gp  = f_calc_sl(_long)
        t1_sl      := _long ? close - _gp                : close + _gp
        t1_tp1     := _long ? close + _gp * i_tp1_r_gate : close - _gp * i_tp1_r_gate
        t1_is_long := _long

// 
// DETECTOR DE AGOTAMIENTO  dentro del trade activo
// 
var float entry_price_ref = na
var float entry_cvd_ref = na
var bool in_trade = false
var int trade_dir = 0

if is_new_session
    in_trade        := false
    entry_price_ref := na
    entry_cvd_ref   := na
    trade_dir       := 0

if buy or sell
    entry_price_ref := close[1]
    entry_cvd_ref   := cvd
    in_trade        := true
    trade_dir       := buy ? 1 : -1

bool trade_active = in_trade

// F1 CVD divergencia
bool f1_exhaust = false
if trade_active and not na(entry_cvd_ref)
    bool _p_adv = trade_dir == 1 ? close > entry_price_ref : close < entry_price_ref
    bool _c_ret = trade_dir == 1 ? cvd < entry_cvd_ref     : cvd > entry_cvd_ref
    f1_exhaust := _p_adv and _c_ret

// F2 Delta decreciente
float d_cur = high   != low   ? math.abs(volume  *(2.0*(close  -low  )/(high  -low  )-1.0)) : 0.0
float d_1   = high[1] != low[1] ? math.abs(volume[1]*(2.0*(close[1]-low[1])/(high[1]-low[1])-1.0)) : 0.0
float d_2   = high[2] != low[2] ? math.abs(volume[2]*(2.0*(close[2]-low[2])/(high[2]-low[2])-1.0)) : 0.0
bool f2_exhaust = trade_active and (d_cur < d_1 and d_1 < d_2)

// F3 Vela de rechazo
float vr       = high - low
float mb_long  = vr > 0 ? (high - close) / vr : 0.0
float mb_short = vr > 0 ? (close - low)  / vr : 0.0
float mecha_r  = trade_dir == 1 ? mb_long : mb_short
bool f3_exhaust = trade_active and mecha_r >= (i_mecha_pct / 100.0)

int exhaust_score = trade_active ? ((i_use_f1 and f1_exhaust ? 1 : 0) + (i_use_f2 and f2_exhaust ? 1 : 0) + (i_use_f3 and f3_exhaust ? 1 : 0)) : 0

bool exhaust_be   = i_show_exhaust and trade_active and exhaust_score >= i_exhaust_be  and exhaust_score < i_exhaust_exit
bool exhaust_exit = i_show_exhaust and trade_active and exhaust_score >= i_exhaust_exit
bool exh_be_long  = exhaust_be   and trade_dir == 1
bool exh_be_short = exhaust_be   and trade_dir == -1
bool exh_1r_long  = exhaust_exit and trade_dir == 1
bool exh_1r_short = exhaust_exit and trade_dir == -1

// 
// RIESGO DINAMICO  sube tras win, baja tras loss
// Sesion 18:00 ET a 17:00 ET del dia siguiente
// 
// Detectar inicio de sesion 18:00 ET

var float risk_current = i_risk_usd   // riesgo actual del proximo trade
var bool last_was_win = false
var bool risk_updated = false

// Reset al inicio de cada sesion (18:00 ET)
if is_session_start
    risk_current     := i_risk_usd
    last_was_win     := false
    loss_count_apex  := 0

// 
// BACKTEST  2 slots independientes
// 
var int bt_total = 0
var int bt_wins = 0
var int bt_losses = 0
var float bt_pnl_usd = 0.0
var float bt_pnl_pts = 0.0
var float bt_peak = 0.0
var float bt_max_dd = 0.0
var int   bt_max_dd_time = 0
var int   bt_first_trade_time = 0  // timestamp del primer trade
var int   bt_last_trade_time  = 0  // timestamp del ultimo trade       // timestamp del valle (DD maximo)
var int   bt_max_dd_peak_time = 0   // timestamp del pico que causo el max DD
var int   bt_cur_peak_time = 0      // timestamp del pico actual (se actualiza con cada nuevo peak)
var int bt_t1_total = 0
var int bt_t1_wins = 0
var int bt_t2_total = 0
var int bt_t2_wins = 0

var bool bt_a_active = false
var bool bt_a_long = false
var float bt_a_entry = na, var float bt_a_sl = na
var float bt_a_tp = na, var int bt_a_num = 0
var float bt_a_risk = 0.0
var bool bt_a_new = false

var bool bt_b_active = false
var bool bt_b_long = false
var float bt_b_entry = na, var float bt_b_sl = na
var float bt_b_tp = na, var int bt_b_num = 0
var float bt_b_risk = 0.0
var bool bt_b_new = false

var bool bt_c_active = false
var bool bt_c_long = false
var float bt_c_entry = na, var float bt_c_sl = na
var float bt_c_tp = na, var int bt_c_num = 0
var float bt_c_risk = 0.0
var bool bt_c_new = false

var bool bt_d_active = false
var bool bt_d_long = false
var float bt_d_entry = na, var float bt_d_sl = na
var float bt_d_tp = na, var int bt_d_num = 0
var float bt_d_risk = 0.0
var bool bt_d_new = false

// Reset flags new al inicio de cada barra
bt_a_new := false
bt_b_new := false
bt_c_new := false
bt_d_new := false

var float prop_a_usd = 0.0
var float prop_b_usd = 0.0
var bool prop_a_fired = false
var bool prop_b_fired = false
var float prop_c_usd = 0.0
var bool prop_c_fired = false
var float prop_d_usd = 0.0
var bool prop_d_fired = false

prop_a_fired := false
prop_b_fired := false
prop_a_usd   := 0.0
prop_b_usd   := 0.0
prop_c_fired := false
prop_c_usd   := 0.0
prop_d_fired := false
prop_d_usd   := 0.0

// Riesgo del proximo trade segun historial de la sesion
float risk_this_trade = i_use_scaling ? risk_current : i_risk_usd

if buy or sell
    float _sl_pts = buy ? sig_entry - sig_sl : sig_sl - sig_entry
    if bt_first_trade_time == 0
        bt_first_trade_time := time
    bt_last_trade_time  := time
    float _tp_val = buy ? sig_entry + _sl_pts * i_bt_tp : sig_entry - _sl_pts * i_bt_tp
    if not bt_a_active
        bt_a_active := true
        bt_a_long   := buy
        bt_a_entry  := sig_entry
        bt_a_sl     := sig_sl
        bt_a_tp     := _tp_val
        bt_a_num    := trade_count
        bt_a_risk   := risk_this_trade
        bt_a_new    := true  // saltar verificacion en vela de apertura (vela B)
    else if not bt_b_active
        bt_b_active := true
        bt_b_long   := buy
        bt_b_entry  := sig_entry
        bt_b_sl     := sig_sl
        bt_b_tp     := _tp_val
        bt_b_num    := trade_count
        bt_b_risk   := risk_this_trade
        bt_b_new    := true
    else if not bt_c_active
        bt_c_active := true
        bt_c_long   := buy
        bt_c_entry  := sig_entry
        bt_c_sl     := sig_sl
        bt_c_tp     := _tp_val
        bt_c_num    := trade_count
        bt_c_risk   := risk_this_trade
        bt_c_new    := true
    else if not bt_d_active
        bt_d_active := true
        bt_d_long   := buy
        bt_d_entry  := sig_entry
        bt_d_sl     := sig_sl
        bt_d_tp     := _tp_val
        bt_d_num    := trade_count
        bt_d_risk   := risk_this_trade
        bt_d_new    := true

// Slot A  bt_a_new=true significa que se abrio en esta vela (vela B)
// Saltar verificacion hasta vela C (siguiente barra)
if bt_a_active and not na(bt_a_entry) and not bt_a_new
    bool _a_tp = bt_a_long ? high >= bt_a_tp : low  <= bt_a_tp
    bool _a_sl = bt_a_long ? low  <= bt_a_sl : high >= bt_a_sl
    bool _a_fc = is_new_session
    // Ambos SL y TP en misma vela: usar open para determinar orden
    // Long: open cerca del TP -> TP fue primero -> WIN
    // Long: open cerca del SL -> SL fue primero -> LOSS
    bool _a_both = _a_tp and _a_sl and not _a_fc
    bool _a_tp_first = bt_a_long ? (_a_both ? (open - bt_a_sl) > (bt_a_tp - open) : _a_tp) : (_a_both ? (bt_a_sl - open) > (open - bt_a_tp) : _a_tp)
    if _a_tp or _a_sl or _a_fc
        bool  _a_win  = _a_tp_first and not _a_fc
        float _a_slr  = bt_a_long ? bt_a_entry - bt_a_sl : bt_a_sl - bt_a_entry
        float _a_exit = _a_fc ? close[1] : _a_win ? bt_a_tp : bt_a_sl
        float _a_pts  = bt_a_long ? _a_exit - bt_a_entry : bt_a_entry - _a_exit
        float _a_r    = _a_slr > 0 ? _a_pts / _a_slr : 0.0
        float _a_usd  = _a_win ? bt_a_risk * i_bt_tp : not _a_fc ? -bt_a_risk : bt_a_risk * _a_r
        bool  _a_fwin = _a_win or (_a_fc and _a_usd > 0)
        bt_total   += 1
        bt_pnl_usd += _a_usd
        bt_pnl_pts += _a_pts
        if _a_fwin
            bt_wins += 1
        else
            bt_losses += 1
            if not _a_fc and use_trade_rule
                loss_count      += 1
                loss_count_apex += 1
        if bt_a_num == 1
            bt_t1_total += 1
            if _a_fwin
                bt_t1_wins += 1
        else
            bt_t2_total += 1
            if _a_fwin
                bt_t2_wins += 1
        if bt_pnl_usd > bt_peak
            bt_peak          := bt_pnl_usd
            bt_cur_peak_time := time
        float _a_dd = bt_peak - bt_pnl_usd
        if _a_dd > bt_max_dd
            bt_max_dd           := _a_dd
            bt_max_dd_time      := time
            bt_max_dd_peak_time := bt_cur_peak_time
        if i_use_scaling and not _a_fc
            risk_current := _a_fwin ? i_risk_scaled : i_risk_usd
        prop_a_usd   := _a_usd
        prop_a_fired := true
        bt_a_active  := false
        bt_a_entry   := na
        bt_a_sl      := na
        bt_a_tp      := na
        bt_a_num     := 0
        bt_a_risk    := 0.0

// Slot B
if bt_b_active and not na(bt_b_entry) and not bt_b_new
    bool _b_tp = bt_b_long ? high >= bt_b_tp : low  <= bt_b_tp
    bool _b_sl = bt_b_long ? low  <= bt_b_sl : high >= bt_b_sl
    bool _b_fc = is_new_session
    // Ambos SL y TP en misma vela: usar open para determinar orden
    // Long: open cerca del TP -> TP fue primero -> WIN
    // Long: open cerca del SL -> SL fue primero -> LOSS
    bool _b_both = _b_tp and _b_sl and not _b_fc
    bool _b_tp_first = bt_b_long ? (_b_both ? (open - bt_b_sl) > (bt_b_tp - open) : _b_tp) : (_b_both ? (bt_b_sl - open) > (open - bt_b_tp) : _b_tp)
    if _b_tp or _b_sl or _b_fc
        bool  _b_win  = _b_tp_first and not _b_fc
        float _b_slr  = bt_b_long ? bt_b_entry - bt_b_sl : bt_b_sl - bt_b_entry
        float _b_exit = _b_fc ? close[1] : _b_win ? bt_b_tp : bt_b_sl
        float _b_pts  = bt_b_long ? _b_exit - bt_b_entry : bt_b_entry - _b_exit
        float _b_r    = _b_slr > 0 ? _b_pts / _b_slr : 0.0
        float _b_usd  = _b_win ? bt_b_risk * i_bt_tp : not _b_fc ? -bt_b_risk : bt_b_risk * _b_r
        bool  _b_fwin = _b_win or (_b_fc and _b_usd > 0)
        bt_total   += 1
        bt_pnl_usd += _b_usd
        bt_pnl_pts += _b_pts
        if _b_fwin
            bt_wins += 1
        else
            bt_losses += 1
            if not _b_fc and use_trade_rule
                loss_count      += 1
                loss_count_apex += 1
        if bt_b_num == 1
            bt_t1_total += 1
            if _b_fwin
                bt_t1_wins += 1
        else
            bt_t2_total += 1
            if _b_fwin
                bt_t2_wins += 1
        if bt_pnl_usd > bt_peak
            bt_peak          := bt_pnl_usd
            bt_cur_peak_time := time
        float _b_dd = bt_peak - bt_pnl_usd
        if _b_dd > bt_max_dd
            bt_max_dd           := _b_dd
            bt_max_dd_time      := time
            bt_max_dd_peak_time := bt_cur_peak_time
        if i_use_scaling and not _b_fc
            risk_current := _b_fwin ? i_risk_scaled : i_risk_usd
        prop_b_usd   := _b_usd
        prop_b_fired := true
        bt_b_active  := false
        bt_b_entry   := na
        bt_b_sl      := na
        bt_b_tp      := na
        bt_b_num     := 0
        bt_b_risk    := 0.0

// Slot C
if bt_c_active and not na(bt_c_entry) and not bt_c_new
    bool _c_tp = bt_c_long ? high >= bt_c_tp : low  <= bt_c_tp
    bool _c_sl = bt_c_long ? low  <= bt_c_sl : high >= bt_c_sl
    bool _c_fc = is_new_session
    // Ambos SL y TP en misma vela: usar open para determinar orden
    // Long: open cerca del TP -> TP fue primero -> WIN
    // Long: open cerca del SL -> SL fue primero -> LOSS
    bool _c_both = _c_tp and _c_sl and not _c_fc
    bool _c_tp_first = bt_c_long ? (_c_both ? (open - bt_c_sl) > (bt_c_tp - open) : _c_tp) : (_c_both ? (bt_c_sl - open) > (open - bt_c_tp) : _c_tp)
    if _c_tp or _c_sl or _c_fc
        bool  _c_win  = _c_tp_first and not _c_fc
        float _c_slr  = bt_c_long ? bt_c_entry - bt_c_sl : bt_c_sl - bt_c_entry
        float _c_exit = _c_fc ? close[1] : _c_win ? bt_c_tp : bt_c_sl
        float _c_pts  = bt_c_long ? _c_exit - bt_c_entry : bt_c_entry - _c_exit
        float _c_r    = _c_slr > 0 ? _c_pts / _c_slr : 0.0
        float _c_usd  = _c_win ? bt_c_risk * i_bt_tp : not _c_fc ? -bt_c_risk : bt_c_risk * _c_r
        bool  _c_fwin = _c_win or (_c_fc and _c_usd > 0)
        bt_total   += 1
        bt_pnl_usd += _c_usd
        bt_pnl_pts += _c_pts
        if _c_fwin
            bt_wins += 1
        else
            bt_losses += 1
            if not _c_fc and use_trade_rule
                loss_count      += 1
                loss_count_apex += 1
        if bt_c_num == 1
            bt_t1_total += 1
            if _c_fwin
                bt_t1_wins += 1
        else
            bt_t2_total += 1
            if _c_fwin
                bt_t2_wins += 1
        if bt_pnl_usd > bt_peak
            bt_peak          := bt_pnl_usd
            bt_cur_peak_time := time
        float _c_dd = bt_peak - bt_pnl_usd
        if _c_dd > bt_max_dd
            bt_max_dd           := _c_dd
            bt_max_dd_time      := time
            bt_max_dd_peak_time := bt_cur_peak_time
        if i_use_scaling and not _c_fc
            risk_current := _c_fwin ? i_risk_scaled : i_risk_usd
        prop_c_usd   := _c_usd
        prop_c_fired := true
        bt_c_active := false
        bt_c_entry  := na
        bt_c_sl     := na
        bt_c_tp     := na
        bt_c_num    := 0
        bt_c_risk   := 0.0

// Slot D
if bt_d_active and not na(bt_d_entry) and not bt_d_new
    bool _d_tp = bt_d_long ? high >= bt_d_tp : low  <= bt_d_tp
    bool _d_sl = bt_d_long ? low  <= bt_d_sl : high >= bt_d_sl
    bool _d_fc = is_new_session
    // Ambos SL y TP en misma vela: usar open para determinar orden
    // Long: open cerca del TP -> TP fue primero -> WIN
    // Long: open cerca del SL -> SL fue primero -> LOSS
    bool _d_both = _d_tp and _d_sl and not _d_fc
    bool _d_tp_first = bt_d_long ? (_d_both ? (open - bt_d_sl) > (bt_d_tp - open) : _d_tp) : (_d_both ? (bt_d_sl - open) > (open - bt_d_tp) : _d_tp)
    if _d_tp or _d_sl or _d_fc
        bool  _d_win  = _d_tp_first and not _d_fc
        float _d_slr  = bt_d_long ? bt_d_entry - bt_d_sl : bt_d_sl - bt_d_entry
        float _d_exit = _d_fc ? close[1] : _d_win ? bt_d_tp : bt_d_sl
        float _d_pts  = bt_d_long ? _d_exit - bt_d_entry : bt_d_entry - _d_exit
        float _d_r    = _d_slr > 0 ? _d_pts / _d_slr : 0.0
        float _d_usd  = _d_win ? bt_d_risk * i_bt_tp : not _d_fc ? -bt_d_risk : bt_d_risk * _d_r
        bool  _d_fwin = _d_win or (_d_fc and _d_usd > 0)
        bt_total   += 1
        bt_pnl_usd += _d_usd
        bt_pnl_pts += _d_pts
        if _d_fwin
            bt_wins += 1
        else
            bt_losses += 1
            if not _d_fc and use_trade_rule
                loss_count      += 1
                loss_count_apex += 1
        if bt_d_num == 1
            bt_t1_total += 1
            if _d_fwin
                bt_t1_wins += 1
        else
            bt_t2_total += 1
            if _d_fwin
                bt_t2_wins += 1
        if bt_pnl_usd > bt_peak
            bt_peak          := bt_pnl_usd
            bt_cur_peak_time := time
        float _d_dd = bt_peak - bt_pnl_usd
        if _d_dd > bt_max_dd
            bt_max_dd           := _d_dd
            bt_max_dd_time      := time
            bt_max_dd_peak_time := bt_cur_peak_time
        if i_use_scaling and not _d_fc
            risk_current := _d_fwin ? i_risk_scaled : i_risk_usd
        prop_d_usd   := _d_usd
        prop_d_fired := true
        bt_d_active := false
        bt_d_entry  := na
        bt_d_sl     := na
        bt_d_tp     := na
        bt_d_num    := 0
        bt_d_risk   := 0.0

float bt_wr    = bt_total > 0 ? (bt_wins / bt_total) * 100.0 : 0.0
float bt_avg   = bt_total > 0 ? bt_pnl_usd / bt_total : 0.0
float bt_pf    = bt_losses > 0 ? (bt_wins * i_bt_tp) / bt_losses : 999.0
float bt_t1_wr = bt_t1_total > 0 ? (bt_t1_wins / bt_t1_total) * 100.0 : 0.0
float bt_t2_wr = bt_t2_total > 0 ? (bt_t2_wins / bt_t2_total) * 100.0 : 0.0

// 
// SIMULADOR FONDEO  pipeline escalonado
// 
// Simulador Apex simplificado
// Cuenta pasadas y quemadas basado en PnL acumulado
var float apex_bal      = 0.0   // balance actual de la cuenta

// Tracker PAs — hasta 5 PAs independientes
// Cada evaluacion pasada genera una PA nueva
// EOD trailing: sube con balance, se congela cuando balance baja
// Max DD desde EOD: $2,000
var int   pa_count    = 0     // total PAs activas/historicas

// PA 1
var bool  pa1_active  = false
var float pa1_bal     = 0.0   // PnL acumulado (sobre los $50K iniciales)
var float pa1_eod     = -2000.0  // floor inicial = $48K   // EOD trailing (maximo alcanzado, tope en 2K sobre inicio)
var float pa1_day     = 0.0   // PnL del dia
var int   pa1_trades  = 0
var int   pa1_wins    = 0
var bool  pa1_dd_hit  = false
var float pa1_frozen  = 0.0
var bool  pa1_day_lock  = false  // bloqueo diario temporal
var float pa1_day_start = 0.0    // balance al inicio de la sesion   // balance congelado al momento del hit // si alcanzo el DD de $2000

// PA 2
var bool  pa2_active  = false
var float pa2_bal     = 0.0
var float pa2_eod     = -2000.0  // floor inicial = $48K
var float pa2_day     = 0.0
var int   pa2_trades  = 0
var int   pa2_wins    = 0
var bool  pa2_dd_hit  = false
var float pa2_frozen  = 0.0
var bool  pa2_day_lock  = false  // bloqueo diario temporal
var float pa2_day_start = 0.0    // balance al inicio de la sesion   // balance congelado al momento del hit

// PA 3
var bool  pa3_active  = false
var float pa3_bal     = 0.0
var float pa3_eod     = -2000.0  // floor inicial = $48K
var float pa3_day     = 0.0
var int   pa3_trades  = 0
var int   pa3_wins    = 0
var bool  pa3_dd_hit  = false
var float pa3_frozen  = 0.0
var bool  pa3_day_lock  = false  // bloqueo diario temporal
var float pa3_day_start = 0.0    // balance al inicio de la sesion   // balance congelado al momento del hit

// PA 4
var bool  pa4_active  = false
var float pa4_bal     = 0.0
var float pa4_eod     = -2000.0  // floor inicial = $48K
var float pa4_day     = 0.0
var int   pa4_trades  = 0
var int   pa4_wins    = 0
var bool  pa4_dd_hit  = false
var float pa4_frozen  = 0.0
var bool  pa4_day_lock  = false  // bloqueo diario temporal
var float pa4_day_start = 0.0    // balance al inicio de la sesion   // balance congelado al momento del hit

// PA 5
var bool  pa5_active  = false
var float pa5_bal     = 0.0
var float pa5_eod     = -2000.0  // floor inicial = $48K
var float pa5_day     = 0.0
var int   pa5_trades  = 0
var int   pa5_wins    = 0
var bool  pa5_dd_hit  = false
var float pa5_frozen  = 0.0
var bool  pa5_day_lock  = false  // bloqueo diario temporal
var float pa5_day_start = 0.0    // balance al inicio de la sesion   // balance congelado al momento del hit

// PA 6
var bool  pa6_active  = false
var float pa6_bal     = 0.0
var float pa6_eod     = -2000.0  // floor inicial = $48K
var float pa6_day     = 0.0
var int   pa6_trades  = 0
var int   pa6_wins    = 0
var bool  pa6_dd_hit  = false
var float pa6_frozen  = 0.0
var bool  pa6_day_lock  = false  // bloqueo diario temporal
var float pa6_day_start = 0.0    // balance al inicio de la sesion   // balance congelado al momento del hit

// PA 7
var bool  pa7_active  = false
var float pa7_bal     = 0.0
var float pa7_eod     = -2000.0  // floor inicial = $48K
var float pa7_day     = 0.0
var int   pa7_trades  = 0
var int   pa7_wins    = 0
var bool  pa7_dd_hit  = false
var float pa7_frozen  = 0.0
var bool  pa7_day_lock  = false  // bloqueo diario temporal
var float pa7_day_start = 0.0    // balance al inicio de la sesion   // balance congelado al momento del hit

// PA 8
var bool  pa8_active  = false
var float pa8_bal     = 0.0
var float pa8_eod     = -2000.0  // floor inicial = $48K
var float pa8_day     = 0.0
var int   pa8_trades  = 0
var int   pa8_wins    = 0
var bool  pa8_dd_hit  = false
var float pa8_frozen  = 0.0
var bool  pa8_day_lock  = false  // bloqueo diario temporal
var float pa8_day_start = 0.0    // balance al inicio de la sesion   // balance congelado al momento del hit

// PA 9
var bool  pa9_active  = false
var float pa9_bal     = 0.0
var float pa9_eod     = -2000.0  // floor inicial = $48K
var float pa9_day     = 0.0
var int   pa9_trades  = 0
var int   pa9_wins    = 0
var bool  pa9_dd_hit  = false
var float pa9_frozen  = 0.0
var bool  pa9_day_lock  = false  // bloqueo diario temporal
var float pa9_day_start = 0.0    // balance al inicio de la sesion   // balance congelado al momento del hit

// PA 10
var bool  pa10_active = false
var float pa10_bal    = 0.0
var float pa10_eod    = -2000.0   // floor inicial = $48K
var float pa10_day    = 0.0
var int   pa10_trades = 0
var int   pa10_wins   = 0
var bool  pa10_dd_hit = false
var float pa10_frozen = 0.0
var bool  pa10_day_lock  = false  // bloqueo diario temporal
var float pa10_day_start = 0.0    // balance al inicio de la sesion    // balance congelado al momento del hit
var float apex_day_pnl  = 0.0   // PnL del dia actual
var float apex_peak     = 0.0   // maximo balance alcanzado
var int   prop_passed   = 0     // cuentas pasadas
var int   prop_blown    = 0     // cuentas quemadas
var float prop_total_cost = i_prop_cost
var int   prop_days     = 0


// Reset diario Apex — sesion 18:00 ET a 17:00 ET
if is_session_start
    apex_day_pnl := 0.0
    pa1_day      := 0.0
    pa1_day_start := pa1_bal   // floor = este balance - $1000
    pa1_day_lock  := false
    pa2_day      := 0.0
    pa2_day_start := pa2_bal   // floor = este balance - $1000
    pa2_day_lock  := false
    pa3_day      := 0.0
    pa3_day_start := pa3_bal   // floor = este balance - $1000
    pa3_day_lock  := false
    pa4_day      := 0.0
    pa4_day_start := pa4_bal   // floor = este balance - $1000
    pa4_day_lock  := false
    pa5_day      := 0.0
    pa5_day_start := pa5_bal   // floor = este balance - $1000
    pa5_day_lock  := false
    pa6_day      := 0.0
    pa6_day_start := pa6_bal   // floor = este balance - $1000
    pa6_day_lock  := false
    pa7_day      := 0.0
    pa7_day_start := pa7_bal   // floor = este balance - $1000
    pa7_day_lock  := false
    pa8_day      := 0.0
    pa8_day_start := pa8_bal   // floor = este balance - $1000
    pa8_day_lock  := false
    pa9_day      := 0.0
    pa9_day_start := pa9_bal   // floor = este balance - $1000
    pa9_day_lock  := false
    pa10_day     := 0.0
    pa10_day_start := pa10_bal   // floor = este balance - $1000
    pa10_day_lock  := false
    prop_days    += 1
// Aplicar PnL de cada slot al balance
// Aplicar PnL de cada slot — inline porque Pine v6 no permite
// modificar variables globales desde funciones
if prop_a_fired
    apex_bal     += prop_a_usd
    apex_day_pnl += prop_a_usd
    if apex_bal > apex_peak
        apex_peak := apex_bal

if prop_b_fired
    apex_bal     += prop_b_usd
    apex_day_pnl += prop_b_usd
    if apex_bal > apex_peak
        apex_peak := apex_bal

if prop_c_fired
    apex_bal     += prop_c_usd
    apex_day_pnl += prop_c_usd
    if apex_bal > apex_peak
        apex_peak := apex_bal

if prop_d_fired
    apex_bal     += prop_d_usd
    apex_day_pnl += prop_d_usd
    if apex_bal > apex_peak
        apex_peak := apex_bal

// Aplicar PnL a todas las PAs activas
// EOD trailing: max EOD = min(bal, 2000) — congela en $2K sobre inicio
float _pa_total = 0.0
if prop_a_fired
    _pa_total += prop_a_usd
if prop_b_fired
    _pa_total += prop_b_usd
if prop_c_fired
    _pa_total += prop_c_usd
if prop_d_fired
    _pa_total += prop_d_usd

// logica PA inline por slot

if _pa_total != 0.0
    if pa1_active and not pa1_dd_hit and not pa1_day_lock
        pa1_bal    += _pa_total
        pa1_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa1_trades += 1
            if _pa_total > 0
                pa1_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa1_eod := math.min(math.max(pa1_eod, pa1_bal - 2000.0), 0.0)
        if not pa1_dd_hit
            // EOD DD — congela PA permanentemente
            if pa1_bal < pa1_eod
                pa1_dd_hit  := true
                pa1_frozen  := pa1_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa1_bal < pa1_day_start - i_prop_daily
                pa1_day_lock := true  // congelar balance en el momento del hit
    if pa2_active and not pa2_dd_hit and not pa2_day_lock
        pa2_bal    += _pa_total
        pa2_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa2_trades += 1
            if _pa_total > 0
                pa2_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa2_eod := math.min(math.max(pa2_eod, pa2_bal - 2000.0), 0.0)
        if not pa2_dd_hit
            // EOD DD — congela PA permanentemente
            if pa2_bal < pa2_eod
                pa2_dd_hit  := true
                pa2_frozen  := pa2_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa2_bal < pa2_day_start - i_prop_daily
                pa2_day_lock := true  // congelar balance en el momento del hit
    if pa3_active and not pa3_dd_hit and not pa3_day_lock
        pa3_bal    += _pa_total
        pa3_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa3_trades += 1
            if _pa_total > 0
                pa3_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa3_eod := math.min(math.max(pa3_eod, pa3_bal - 2000.0), 0.0)
        if not pa3_dd_hit
            // EOD DD — congela PA permanentemente
            if pa3_bal < pa3_eod
                pa3_dd_hit  := true
                pa3_frozen  := pa3_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa3_bal < pa3_day_start - i_prop_daily
                pa3_day_lock := true  // congelar balance en el momento del hit
    if pa4_active and not pa4_dd_hit and not pa4_day_lock
        pa4_bal    += _pa_total
        pa4_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa4_trades += 1
            if _pa_total > 0
                pa4_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa4_eod := math.min(math.max(pa4_eod, pa4_bal - 2000.0), 0.0)
        if not pa4_dd_hit
            // EOD DD — congela PA permanentemente
            if pa4_bal < pa4_eod
                pa4_dd_hit  := true
                pa4_frozen  := pa4_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa4_bal < pa4_day_start - i_prop_daily
                pa4_day_lock := true  // congelar balance en el momento del hit
    if pa5_active and not pa5_dd_hit and not pa5_day_lock
        pa5_bal    += _pa_total
        pa5_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa5_trades += 1
            if _pa_total > 0
                pa5_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa5_eod := math.min(math.max(pa5_eod, pa5_bal - 2000.0), 0.0)
        if not pa5_dd_hit
            // EOD DD — congela PA permanentemente
            if pa5_bal < pa5_eod
                pa5_dd_hit  := true
                pa5_frozen  := pa5_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa5_bal < pa5_day_start - i_prop_daily
                pa5_day_lock := true  // congelar balance en el momento del hit
    if pa6_active and not pa6_dd_hit and not pa6_day_lock
        pa6_bal    += _pa_total
        pa6_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa6_trades += 1
            if _pa_total > 0
                pa6_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa6_eod := math.min(math.max(pa6_eod, pa6_bal - 2000.0), 0.0)
        if not pa6_dd_hit
            // EOD DD — congela PA permanentemente
            if pa6_bal < pa6_eod
                pa6_dd_hit  := true
                pa6_frozen  := pa6_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa6_bal < pa6_day_start - i_prop_daily
                pa6_day_lock := true  // congelar balance en el momento del hit
    if pa7_active and not pa7_dd_hit and not pa7_day_lock
        pa7_bal    += _pa_total
        pa7_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa7_trades += 1
            if _pa_total > 0
                pa7_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa7_eod := math.min(math.max(pa7_eod, pa7_bal - 2000.0), 0.0)
        if not pa7_dd_hit
            // EOD DD — congela PA permanentemente
            if pa7_bal < pa7_eod
                pa7_dd_hit  := true
                pa7_frozen  := pa7_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa7_bal < pa7_day_start - i_prop_daily
                pa7_day_lock := true  // congelar balance en el momento del hit
    if pa8_active and not pa8_dd_hit and not pa8_day_lock
        pa8_bal    += _pa_total
        pa8_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa8_trades += 1
            if _pa_total > 0
                pa8_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa8_eod := math.min(math.max(pa8_eod, pa8_bal - 2000.0), 0.0)
        if not pa8_dd_hit
            // EOD DD — congela PA permanentemente
            if pa8_bal < pa8_eod
                pa8_dd_hit  := true
                pa8_frozen  := pa8_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa8_bal < pa8_day_start - i_prop_daily
                pa8_day_lock := true  // congelar balance en el momento del hit
    if pa9_active and not pa9_dd_hit and not pa9_day_lock
        pa9_bal    += _pa_total
        pa9_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa9_trades += 1
            if _pa_total > 0
                pa9_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa9_eod := math.min(math.max(pa9_eod, pa9_bal - 2000.0), 0.0)
        if not pa9_dd_hit
            // EOD DD — congela PA permanentemente
            if pa9_bal < pa9_eod
                pa9_dd_hit  := true
                pa9_frozen  := pa9_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa9_bal < pa9_day_start - i_prop_daily
                pa9_day_lock := true  // congelar balance en el momento del hit
    if pa10_active and not pa10_dd_hit and not pa10_day_lock
        pa10_bal    += _pa_total
        pa10_day    += _pa_total
        if math.abs(_pa_total) > 0
            pa10_trades += 1
            if _pa_total > 0
                pa10_wins += 1
        // EOD: sube trailing hasta techo de 0 (= $50K en terminos reales)
        // Cuando bal > 2000 el EOD ya llego a 0 y se congela
        pa10_eod := math.min(math.max(pa10_eod, pa10_bal - 2000.0), 0.0)
        if not pa10_dd_hit
            // EOD DD — congela PA permanentemente
            if pa10_bal < pa10_eod
                pa10_dd_hit  := true
                pa10_frozen  := pa10_bal
            // Daily floor fijo = balance inicio sesion - $1,000
            // No cambia aunque ganes durante el dia
            // Ventaja: si ganas $500 tienes $1,500 de margen ese dia
            if pa10_bal < pa10_day_start - i_prop_daily
                pa10_day_lock := true  // congelar balance en el momento del hit


// Verificar objetivo y drawdown
if apex_bal >= i_prop_goal
    prop_passed      += 1
    prop_total_cost  += i_prop_cost
    apex_bal         := 0.0
    apex_peak        := 0.0
    apex_day_pnl     := 0.0
    // Activar siguiente PA disponible
    pa_count += 1
    if pa_count == 1
        pa1_active := true
    else if pa_count == 2
        pa2_active := true
    else if pa_count == 3
        pa3_active := true
    else if pa_count == 4
        pa4_active := true
    else if pa_count == 5
        pa5_active := true
    else if pa_count == 6
        pa6_active := true
    else if pa_count == 7
        pa7_active := true
    else if pa_count == 8
        pa8_active := true
    else if pa_count == 9
        pa9_active := true
    else if pa_count == 10
        pa10_active := true

if apex_bal <= -i_prop_maxdd or apex_day_pnl <= -i_prop_daily
    prop_blown       += 1
    prop_total_cost  += i_prop_cost
    apex_bal         := 0.0
    apex_peak        := 0.0
    apex_day_pnl     := 0.0

float apex_progress  = i_prop_goal > 0 ? apex_bal / i_prop_goal * 100.0 : 0.0
float apex_dd_used   = apex_peak > 0 ? (apex_peak - apex_bal) / i_prop_maxdd * 100.0 : 0.0
float apex_daily_pct = i_prop_daily > 0 ? math.max(-apex_day_pnl, 0.0) / i_prop_daily * 100.0 : 0.0
float prop_net_pnl   = prop_passed * i_prop_payout - prop_total_cost

// PRE-SEAL INTRABAR
// Condicion 1: vela[1] cerro del lado contrario al trail (fija)
// Condicion 2: precio actual cruzo el trail (intrabar, cambia)
// 
bool pre_c1_buy  = close[1] < trailStop_c
bool pre_c1_sell = close[1] > trailStop_c
bool pre_c2_buy  = close > trailStop
bool pre_c2_sell = close < trailStop
// Filtros verificables en vela A — mismos que buy_filtered excepto el cruce
// El cruce se confirma en vela B, pero todo lo demas se puede verificar ya
bool f_pre_filters = f_time          // filtro horario
                 and f_atr_ok        // volatilidad normal
                 and f_regime        // regimen de mercado
                 and f_early         // early zone
                 and (loss_count < i_max_losses)  // max losses sesion
                 and not session_closed            // sesion no cerrada
                 and (bar_index - last_signal_bar) >= i_cooldown  // cooldown

bool pre_buy  = i_show_presignal and pre_c1_buy  and pre_c2_buy  and f_pre_filters and f_bias_long  and f_vwap_long  and f_candle_long  and not buy
bool pre_sell = i_show_presignal and pre_c1_sell and pre_c2_sell and f_pre_filters and f_bias_short and f_vwap_short and f_candle_short and not sell

// 
// PLOTS
// 
stopColor = pos == 1 ? color.green : pos == -1 ? color.red : color.blue
plot(trailStop, title="Trailing Stop", color=stopColor, linewidth=2)
plot(vwap_val,  title="VWAP", color=color.new(color.orange, 20), linewidth=1)

barcolor(in_blackout ? color.new(color.gray,   60) : buy  ? color.new(color.green, 40) : sell ? color.new(color.red, 40) : close > trailStop ? color.new(color.green, 70) : color.new(color.red, 70))

bgcolor(in_blackout ? color.new(color.red, 92) : use_session and in_session ? color.new(color.blue, 92) : na)

// Boxes
// buy[1]/sell[1]  valor de la vela anterior ya cerrada
// El label aparece al ABRIR la vela siguiente al cruce
// Flujo: Vela A cierra con cruce -> buy=true
//        Vela B abre -> buy[1]=true -> label BUY aparece aqui
//        Entry = close[A] = sig_entry (correcto)
// buy[1] nunca cambia porque A ya cerro  label permanente
buy_confirmed  = buy[1]
sell_confirmed = sell[1]
// Boxes usan sig_entry[1] etc porque buy_confirmed = buy[1]
// La seal fue en la vela anterior, los niveles vienen de ahi
if i_show_boxes and (buy_confirmed or sell_confirmed)
    int _r = bar_index + i_box_width
    box.new(bar_index, sig_entry[1], _r, sig_sl[1],  border_color=color.new(color.red,   0), bgcolor=color.new(color.red,   80), border_width=1)
    box.new(bar_index, sig_entry[1], _r, sig_tp1[1], border_color=color.new(color.green,  0), bgcolor=color.new(color.green, 82), border_width=1)
    box.new(bar_index, sig_tp1[1],   _r, sig_tp2[1], border_color=color.new(color.green, 20), bgcolor=color.new(color.green, 87), border_width=1)
    box.new(bar_index, sig_tp2[1],   _r, sig_tp3[1], border_color=color.new(color.green, 40), bgcolor=color.new(color.green, 92), border_width=1)
    label.new(x=_r, y=sig_sl[1],  text="SL " + str.tostring(math.round(sig_sl[1])),  style=label.style_label_left, color=color.new(color.red,   0), textcolor=color.white, size=size.tiny)
    label.new(x=_r, y=sig_tp1[1], text="1R " + str.tostring(math.round(sig_tp1[1])), style=label.style_label_left, color=color.new(color.green, 0), textcolor=color.white, size=size.tiny)
    label.new(x=_r, y=sig_tp2[1], text="2R " + str.tostring(math.round(sig_tp2[1])), style=label.style_label_left, color=color.new(color.green, 0), textcolor=color.white, size=size.tiny)
    label.new(x=_r, y=sig_tp3[1], text="3R " + str.tostring(math.round(sig_tp3[1])), style=label.style_label_left, color=color.new(color.green, 0), textcolor=color.white, size=size.tiny)

// Pre-seal  azul=buy, morado=sell
barcolor(pre_buy  and not buy  ? color.new(color.blue,   30) : na)
barcolor(pre_sell and not sell ? color.new(color.purple,  30) : na)
plotshape(pre_buy,  title="Pre-BUY",  text="?", style=shape.labelup,   location=location.belowbar, color=color.new(color.yellow, 0), textcolor=color.black, size=size.small)
plotshape(pre_sell, title="Pre-SELL", text="?", style=shape.labeldown, location=location.abovebar, color=color.new(color.yellow, 0), textcolor=color.black, size=size.small)

// Seales confirmadas
// buy_confirmed y sell_confirmed solo se muestran al cierre de vela
// En live intrabar: barstate.isconfirmed = false -> label no aparece
// Al cierre: barstate.isconfirmed = true -> label aparece y es permanente
// Esto elimina los labels que aparecen y desaparecen sin tocar el BT
plotshape(buy_confirmed,  title="BUY",  text="BUY",  style=shape.labelup,   location=location.belowbar, color=color.new(color.green, 0), textcolor=color.white, size=size.normal)
plotshape(sell_confirmed, title="SELL", text="SELL", style=shape.labeldown, location=location.abovebar, color=color.new(color.red,   0), textcolor=color.white, size=size.normal)

// Agotamiento
plotshape(exh_be_long,  title="BE Long",  text="BE", style=shape.diamond, location=location.abovebar, color=color.new(color.orange, 0), textcolor=color.white, size=size.small)
plotshape(exh_be_short, title="BE Short", text="BE", style=shape.diamond, location=location.belowbar, color=color.new(color.orange, 0), textcolor=color.white, size=size.small)
plotshape(exh_1r_long,  title="1R Long",  text="1R", style=shape.xcross,  location=location.abovebar, color=color.new(color.red,    0), textcolor=color.white, size=size.small)
plotshape(exh_1r_short, title="1R Short", text="1R", style=shape.xcross,  location=location.belowbar, color=color.new(color.red,    0), textcolor=color.white, size=size.small)

plot(trade_active and exhaust_score == 1 ? trailStop : na, title="Exh 1/3", color=color.new(color.yellow, 0), linewidth=3, style=plot.style_circles)
plot(trade_active and exhaust_score == 2 ? trailStop : na, title="Exh 2/3", color=color.new(color.orange, 0), linewidth=3, style=plot.style_circles)
plot(trade_active and exhaust_score >= 3 ? trailStop : na, title="Exh 3/3", color=color.new(color.red,    0), linewidth=3, style=plot.style_circles)

// 
// DASHBOARD
// 
var label dash = na
label.delete(dash)

pos_txt    = pos == 1 ? "LONG" : pos == -1 ? "SHORT" : "FLAT"
cvd_txt    = cvd_rising ? "CVD+" : cvd_falling ? "CVD-" : "CVD~"
vwp_txt    = above_vwap ? "V+" : "V-"
cnl_txt    = candle_bull ? "C+" : candle_bear ? "C-" : "C~"
bias_txt   = period_bull ? "BIAS+" : period_bear ? "BIAS-" : "BIAS~"
regime_txt = not regime_ready ? "REG?" : regime_trend ? "TREND" : regime_range ? "RANGO" : "MIXTO"
key_txt    = use_dynamic_key ? " K:" + str.tostring(eff_buy_key) : ""
exh_txt    = not trade_active ? "-" : exhaust_score == 0 ? "OK" : exhaust_score == 1 ? "1/3" : exhaust_score == 2 ? "BE" : "1R"
tc_txt     = "L:" + str.tostring(loss_count_apex) + "/" + str.tostring(i_max_losses) + (session_closed ? " CERRADO" : sess_locked ? " BLOQ" : "")
ses_txt    = not in_session ? "OFF" : in_blackout ? "BLK" : in_early_zone ? "EARLY" : "ON"
ez_txt     = not in_early_zone ? "" : (f_body_ok and f_dist_ok) ? " EZ:OK" : not f_body_ok ? " EZ:B?" : " EZ:D?"
atr_txt    = not i_use_atr_filter ? "" : atr_ratio > i_atr_mult_max ? " ATR:ALTO" : atr_ratio > i_atr_mult_max * 0.85 ? " ATR:WARN" : ""
pre_txt    = pre_buy ? " PRE:BUY" : pre_sell ? " PRE:SELL" : ""

dash_txt = "UT v5 | " + pos_txt + " | " + bias_txt + " | " + regime_txt + " | " + vwp_txt + " | " + cnl_txt + " | " + cvd_txt + " | Exh:" + exh_txt + " | T:" + tc_txt + " | " + ses_txt + ez_txt + pre_txt + atr_txt
dash := label.new(x=bar_index, y=trailStop, text=dash_txt, style=label.style_label_left, color=color.new(color.gray, 80), textcolor=color.white, size=size.small)

// 
// TABLA BT
// 
var table bt_table = table.new(position.top_right, 2, 15, bgcolor=color.new(#0d1f2d, 10), border_width=1, border_color=color.new(#3a5060, 60))

if i_show_bt and barstate.islast
    C_HDR = color.new(#1b3a4d, 0)
    C_KEY = color.new(#0d1f2d, 20)
    C_POS = color.new(#00e5a0, 0)
    C_NEG = color.new(#ff3d5a, 0)
    C_WRN = color.new(#ff9d00, 0)
    C_TXT = color.new(#cce8f0, 0)
    C_DIM = color.new(#5a8090, 0)
    string _risk_hdr = i_use_scaling ? "R=$" + str.tostring(math.round(i_risk_usd)) + "/" + str.tostring(math.round(i_risk_scaled)) + " TP:" + str.tostring(i_bt_tp) + "R" : "R=$" + str.tostring(math.round(i_risk_usd)) + " TP:" + str.tostring(i_bt_tp) + "R"
    string _ft   = bt_first_trade_time > 0 ? str.format("{0,date,dd/MM/yy}", bt_first_trade_time) : "N/A"
    string _lt   = bt_last_trade_time  > 0 ? str.format("{0,date,dd/MM/yy}", bt_last_trade_time)  : "N/A"
    string pf_txt   = bt_pf >= 999 ? "inf" : str.tostring(math.round(bt_pf * 100) / 100)
    string pnl_txt  = (bt_pnl_usd >= 0 ? "+" : "") + str.tostring(math.round(bt_pnl_usd))
    string pts_txt  = (bt_pnl_pts >= 0 ? "+" : "") + str.tostring(math.round(bt_pnl_pts))
    string avg_txt  = (bt_avg >= 0 ? "+" : "") + str.tostring(math.round(bt_avg))
    string _dd_valle = bt_max_dd_time      > 0 ? str.format("{0,date,dd/MM/yy}", bt_max_dd_time)      : "N/A"
    string _dd_pico  = bt_max_dd_peak_time > 0 ? str.format("{0,date,dd/MM/yy}", bt_max_dd_peak_time) : "N/A"
    string t1_txt   = str.tostring(bt_t1_wins) + "/" + str.tostring(bt_t1_total) + " (" + str.tostring(math.round(bt_t1_wr)) + "%)"
    string t2_txt   = bt_t2_total > 0 ? str.tostring(bt_t2_wins) + "/" + str.tostring(bt_t2_total) + " (" + str.tostring(math.round(bt_t2_wr)) + "%)" : "N/A"
    float  t1v2     = bt_t1_wr - bt_t2_wr
    string diff_txt = bt_t2_total > 0 ? (t1v2 > 0 ? "T1+" : "T2+") + str.tostring(math.round(math.abs(t1v2))) + "%" : "N/A"
    table.cell(bt_table, 0, 0,  "BACKTEST MNQ",  text_color=C_TXT, bgcolor=C_HDR, text_size=size.small)
    table.cell(bt_table, 1, 0,  _risk_hdr,       text_color=C_DIM, bgcolor=C_HDR, text_size=size.small)
    table.cell(bt_table, 0, 1,  "Periodo",       text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 1,  _ft + " a " + _lt, text_color=C_TXT, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 2,  "Trades",        text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 2,  str.tostring(bt_total), text_color=C_TXT, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 3,  "W / L",         text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 3,  str.tostring(bt_wins) + " / " + str.tostring(bt_losses), text_color=bt_wins >= bt_losses ? C_POS : C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 4,  "Win Rate",      text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 4,  str.tostring(math.round(bt_wr)) + "%", text_color=bt_wr >= 50.0 ? C_POS : C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 5,  "Prof Factor",   text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 5,  pf_txt,          text_color=bt_pf >= 1.5 ? C_POS : bt_pf >= 1.0 ? C_WRN : C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 6,  "PnL USD",       text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 6,  pnl_txt,         text_color=bt_pnl_usd >= 0 ? C_POS : C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 7,  "PnL pts",       text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 7,  pts_txt,         text_color=bt_pnl_pts >= 0 ? C_POS : C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 8,  "Avg/trade",     text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 8,  avg_txt,         text_color=bt_avg >= 0 ? C_POS : C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 9,  "Max DD",        text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 9,  "-$" + str.tostring(math.round(bt_max_dd)), text_color=C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 10, "DD inicio",     text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 10, _dd_pico,        text_color=C_WRN, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 11, "DD fin",        text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 11, _dd_valle,       text_color=C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 12, "T1 W/N",        text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 12, t1_txt,          text_color=bt_t1_wr >= 50.0 ? C_POS : C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 13, "T2 W/N",        text_color=C_DIM, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 1, 13, t2_txt,          text_color=bt_t2_wr >= 50.0 ? C_POS : bt_t2_total == 0 ? C_DIM : C_NEG, bgcolor=C_KEY, text_size=size.tiny)
    table.cell(bt_table, 0, 14, "Diferencia",    text_color=C_DIM, bgcolor=C_HDR, text_size=size.tiny)
    table.cell(bt_table, 1, 14, diff_txt,        text_color=C_WRN, bgcolor=C_HDR, text_size=size.tiny)

var table prop_table = table.new(position.bottom_left, 2, 10, bgcolor=color.new(#0d1f2d, 10), border_width=1, border_color=color.new(#3a5060, 60))
if i_show_prop and barstate.islast
    C_H = color.new(#1b3a4d, 0)
    C_K = color.new(#0d1f2d, 20)
    C_P = color.new(#00e5a0, 0)
    C_N = color.new(#ff3d5a, 0)
    C_W = color.new(#ff9d00, 0)
    C_T = color.new(#cce8f0, 0)
    C_D = color.new(#5a8090, 0)
    string _pft  = bt_first_trade_time > 0 ? str.format("{0,date,dd/MM/yy}", bt_first_trade_time) : "N/A"
    string _plt  = bt_last_trade_time  > 0 ? str.format("{0,date,dd/MM/yy}", bt_last_trade_time)  : "N/A"
    string net_s = (prop_net_pnl >= 0 ? "+" : "") + "$" + str.tostring(math.round(prop_net_pnl))
    string daily_s = (apex_day_pnl >= 0 ? "+" : "") + "$" + str.tostring(math.round(apex_day_pnl)) + " (" + str.tostring(math.round(apex_daily_pct)) + "%)"
    table.cell(prop_table, 0, 0,  "FONDEO APEX",    text_color=C_T, bgcolor=C_H, text_size=size.small)
    table.cell(prop_table, 1, 0,  "Obj:$" + str.tostring(math.round(i_prop_goal)) + " DD:$" + str.tostring(math.round(i_prop_maxdd)), text_color=C_D, bgcolor=C_H, text_size=size.small)
    table.cell(prop_table, 0, 1,  "Periodo",        text_color=C_D, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 1, 1,  _pft + " a " + _plt, text_color=C_T, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 0, 2,  "Balance",        text_color=C_D, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 1, 2,  "$" + str.tostring(math.round(apex_bal)) + " (" + str.tostring(math.round(apex_progress)) + "%)", text_color=apex_bal >= 0 ? C_P : C_N, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 0, 3,  "DD usado",       text_color=C_D, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 1, 3,  str.tostring(math.round(apex_dd_used)) + "%", text_color=apex_dd_used >= 70 ? C_N : apex_dd_used >= 50 ? C_W : C_P, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 0, 4,  "Daily P&L",      text_color=C_D, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 1, 4,  daily_s,          text_color=apex_day_pnl >= 0 ? C_P : apex_daily_pct >= 70 ? C_N : C_W, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 0, 5,  "Dias",           text_color=C_D, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 1, 5,  str.tostring(prop_days), text_color=C_T, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 0, 6,  "Pasadas",        text_color=C_D, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 1, 6,  str.tostring(prop_passed), text_color=prop_passed > 0 ? C_P : C_T, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 0, 7,  "Quemadas",       text_color=C_D, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 1, 7,  str.tostring(prop_blown), text_color=prop_blown > 0 ? C_N : C_T, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 0, 8,  "Costo total",    text_color=C_D, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 1, 8,  "$" + str.tostring(math.round(prop_total_cost)), text_color=C_N, bgcolor=C_K, text_size=size.tiny)
    table.cell(prop_table, 0, 9,  "PnL neto",       text_color=C_D, bgcolor=C_H, text_size=size.tiny)
    table.cell(prop_table, 1, 9,  net_s,            text_color=prop_net_pnl >= 0 ? C_P : C_N, bgcolor=C_H, text_size=size.tiny)

// TABLA PA
var table pa_table = table.new(position.bottom_right, 8, 12, bgcolor=color.new(#0d1f2d, 10), border_width=1, border_color=color.new(#3a5060, 60))
if i_show_prop and barstate.islast and pa_count > 0
    C_H = color.new(#1b3a4d, 0)
    C_K = color.new(#0d1f2d, 20)
    C_P = color.new(#00e5a0, 0)
    C_N = color.new(#ff3d5a, 0)
    C_W = color.new(#ff9d00, 0)
    C_T = color.new(#cce8f0, 0)
    C_D = color.new(#5a8090, 0)
    // Header
    table.cell(pa_table, 0, 0,  "PA",      text_color=C_T, bgcolor=C_H, text_size=size.tiny)
    table.cell(pa_table, 1, 0,  "PnL",     text_color=C_T, bgcolor=C_H, text_size=size.tiny)
    table.cell(pa_table, 2, 0,  "DD%",     text_color=C_T, bgcolor=C_H, text_size=size.tiny)
    table.cell(pa_table, 3, 0,  "Daily",   text_color=C_T, bgcolor=C_H, text_size=size.tiny)
    table.cell(pa_table, 4, 0,  "Trades",  text_color=C_T, bgcolor=C_H, text_size=size.tiny)
    table.cell(pa_table, 5, 0,  "Wins",    text_color=C_T, bgcolor=C_H, text_size=size.tiny)
    table.cell(pa_table, 6, 0,  "DD hit?", text_color=C_T, bgcolor=C_H, text_size=size.tiny)
    table.cell(pa_table, 7, 0,  "Balance", text_color=C_T, bgcolor=C_H, text_size=size.tiny)
    if pa1_active
        float _wr1   = pa1_trades > 0 ? pa1_wins / pa1_trades * 100.0 : 0.0
        float _ddu1  = math.max(0.0, (pa1_eod - pa1_bal) / 2000.0 * 100.0)
        color _cbg1  = pa1_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 1,  "PA1",  text_color=pa1_dd_hit ? C_N : C_P, bgcolor=_cbg1, text_size=size.tiny)
        float _disp_bal1 = pa1_dd_hit ? pa1_frozen : pa1_bal
        table.cell(pa_table, 1, 1,  (_disp_bal1 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal1)),  text_color=_disp_bal1 >= 0 ? C_P : C_N, bgcolor=_cbg1, text_size=size.tiny)
        table.cell(pa_table, 2, 1,  str.tostring(math.round(_ddu1)) + "%", text_color=_ddu1 >= 80 ? C_N : _ddu1 >= 50 ? C_W : C_P, bgcolor=_cbg1, text_size=size.tiny)
        float _margin1  = pa1_bal - (pa1_day_start - i_prop_daily)  // margen restante hoy
        string _day_s1  = pa1_day_lock ? "BLOQ" : (pa1_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa1_day)) + " [" + str.tostring(math.round(_margin1)) + "]"
        table.cell(pa_table, 3, 1,  _day_s1, text_color=pa1_day_lock ? C_W : _margin1 < 300 ? C_N : _margin1 < 600 ? C_W : C_P, bgcolor=_cbg1, text_size=size.tiny)
        table.cell(pa_table, 4, 1,  str.tostring(pa1_trades), text_color=C_T, bgcolor=_cbg1, text_size=size.tiny)
        table.cell(pa_table, 5, 1,  str.tostring(pa1_wins) + "(" + str.tostring(math.round(_wr1)) + "%)", text_color=_wr1 >= 50 ? C_P : C_N, bgcolor=_cbg1, text_size=size.tiny)
        table.cell(pa_table, 6, 1,  pa1_dd_hit ? "SI" : "NO", text_color=pa1_dd_hit ? C_N : C_P, bgcolor=_cbg1, text_size=size.tiny)
        table.cell(pa_table, 7, 1,  "$" + str.tostring(math.round(50000.0 + _disp_bal1)), text_color=_disp_bal1 >= 0 ? C_P : C_N, bgcolor=_cbg1, text_size=size.tiny)
    if pa2_active
        float _wr2   = pa2_trades > 0 ? pa2_wins / pa2_trades * 100.0 : 0.0
        float _ddu2  = math.max(0.0, (pa2_eod - pa2_bal) / 2000.0 * 100.0)
        color _cbg2  = pa2_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 2,  "PA2",  text_color=pa2_dd_hit ? C_N : C_P, bgcolor=_cbg2, text_size=size.tiny)
        float _disp_bal2 = pa2_dd_hit ? pa2_frozen : pa2_bal
        table.cell(pa_table, 1, 2,  (_disp_bal2 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal2)),  text_color=_disp_bal2 >= 0 ? C_P : C_N, bgcolor=_cbg2, text_size=size.tiny)
        table.cell(pa_table, 2, 2,  str.tostring(math.round(_ddu2)) + "%", text_color=_ddu2 >= 80 ? C_N : _ddu2 >= 50 ? C_W : C_P, bgcolor=_cbg2, text_size=size.tiny)
        float _margin2  = pa2_bal - (pa2_day_start - i_prop_daily)  // margen restante hoy
        string _day_s2  = pa2_day_lock ? "BLOQ" : (pa2_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa2_day)) + " [" + str.tostring(math.round(_margin2)) + "]"
        table.cell(pa_table, 3, 2,  _day_s2, text_color=pa2_day_lock ? C_W : _margin2 < 300 ? C_N : _margin2 < 600 ? C_W : C_P, bgcolor=_cbg2, text_size=size.tiny)
        table.cell(pa_table, 4, 2,  str.tostring(pa2_trades), text_color=C_T, bgcolor=_cbg2, text_size=size.tiny)
        table.cell(pa_table, 5, 2,  str.tostring(pa2_wins) + "(" + str.tostring(math.round(_wr2)) + "%)", text_color=_wr2 >= 50 ? C_P : C_N, bgcolor=_cbg2, text_size=size.tiny)
        table.cell(pa_table, 6, 2,  pa2_dd_hit ? "SI" : "NO", text_color=pa2_dd_hit ? C_N : C_P, bgcolor=_cbg2, text_size=size.tiny)
        table.cell(pa_table, 7, 2,  "$" + str.tostring(math.round(50000.0 + _disp_bal2)), text_color=_disp_bal2 >= 0 ? C_P : C_N, bgcolor=_cbg2, text_size=size.tiny)
    if pa3_active
        float _wr3   = pa3_trades > 0 ? pa3_wins / pa3_trades * 100.0 : 0.0
        float _ddu3  = math.max(0.0, (pa3_eod - pa3_bal) / 2000.0 * 100.0)
        color _cbg3  = pa3_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 3,  "PA3",  text_color=pa3_dd_hit ? C_N : C_P, bgcolor=_cbg3, text_size=size.tiny)
        float _disp_bal3 = pa3_dd_hit ? pa3_frozen : pa3_bal
        table.cell(pa_table, 1, 3,  (_disp_bal3 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal3)),  text_color=_disp_bal3 >= 0 ? C_P : C_N, bgcolor=_cbg3, text_size=size.tiny)
        table.cell(pa_table, 2, 3,  str.tostring(math.round(_ddu3)) + "%", text_color=_ddu3 >= 80 ? C_N : _ddu3 >= 50 ? C_W : C_P, bgcolor=_cbg3, text_size=size.tiny)
        float _margin3  = pa3_bal - (pa3_day_start - i_prop_daily)  // margen restante hoy
        string _day_s3  = pa3_day_lock ? "BLOQ" : (pa3_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa3_day)) + " [" + str.tostring(math.round(_margin3)) + "]"
        table.cell(pa_table, 3, 3,  _day_s3, text_color=pa3_day_lock ? C_W : _margin3 < 300 ? C_N : _margin3 < 600 ? C_W : C_P, bgcolor=_cbg3, text_size=size.tiny)
        table.cell(pa_table, 4, 3,  str.tostring(pa3_trades), text_color=C_T, bgcolor=_cbg3, text_size=size.tiny)
        table.cell(pa_table, 5, 3,  str.tostring(pa3_wins) + "(" + str.tostring(math.round(_wr3)) + "%)", text_color=_wr3 >= 50 ? C_P : C_N, bgcolor=_cbg3, text_size=size.tiny)
        table.cell(pa_table, 6, 3,  pa3_dd_hit ? "SI" : "NO", text_color=pa3_dd_hit ? C_N : C_P, bgcolor=_cbg3, text_size=size.tiny)
        table.cell(pa_table, 7, 3,  "$" + str.tostring(math.round(50000.0 + _disp_bal3)), text_color=_disp_bal3 >= 0 ? C_P : C_N, bgcolor=_cbg3, text_size=size.tiny)
    if pa4_active
        float _wr4   = pa4_trades > 0 ? pa4_wins / pa4_trades * 100.0 : 0.0
        float _ddu4  = math.max(0.0, (pa4_eod - pa4_bal) / 2000.0 * 100.0)
        color _cbg4  = pa4_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 4,  "PA4",  text_color=pa4_dd_hit ? C_N : C_P, bgcolor=_cbg4, text_size=size.tiny)
        float _disp_bal4 = pa4_dd_hit ? pa4_frozen : pa4_bal
        table.cell(pa_table, 1, 4,  (_disp_bal4 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal4)),  text_color=_disp_bal4 >= 0 ? C_P : C_N, bgcolor=_cbg4, text_size=size.tiny)
        table.cell(pa_table, 2, 4,  str.tostring(math.round(_ddu4)) + "%", text_color=_ddu4 >= 80 ? C_N : _ddu4 >= 50 ? C_W : C_P, bgcolor=_cbg4, text_size=size.tiny)
        float _margin4  = pa4_bal - (pa4_day_start - i_prop_daily)  // margen restante hoy
        string _day_s4  = pa4_day_lock ? "BLOQ" : (pa4_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa4_day)) + " [" + str.tostring(math.round(_margin4)) + "]"
        table.cell(pa_table, 3, 4,  _day_s4, text_color=pa4_day_lock ? C_W : _margin4 < 300 ? C_N : _margin4 < 600 ? C_W : C_P, bgcolor=_cbg4, text_size=size.tiny)
        table.cell(pa_table, 4, 4,  str.tostring(pa4_trades), text_color=C_T, bgcolor=_cbg4, text_size=size.tiny)
        table.cell(pa_table, 5, 4,  str.tostring(pa4_wins) + "(" + str.tostring(math.round(_wr4)) + "%)", text_color=_wr4 >= 50 ? C_P : C_N, bgcolor=_cbg4, text_size=size.tiny)
        table.cell(pa_table, 6, 4,  pa4_dd_hit ? "SI" : "NO", text_color=pa4_dd_hit ? C_N : C_P, bgcolor=_cbg4, text_size=size.tiny)
        table.cell(pa_table, 7, 4,  "$" + str.tostring(math.round(50000.0 + _disp_bal4)), text_color=_disp_bal4 >= 0 ? C_P : C_N, bgcolor=_cbg4, text_size=size.tiny)
    if pa5_active
        float _wr5   = pa5_trades > 0 ? pa5_wins / pa5_trades * 100.0 : 0.0
        float _ddu5  = math.max(0.0, (pa5_eod - pa5_bal) / 2000.0 * 100.0)
        color _cbg5  = pa5_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 5,  "PA5",  text_color=pa5_dd_hit ? C_N : C_P, bgcolor=_cbg5, text_size=size.tiny)
        float _disp_bal5 = pa5_dd_hit ? pa5_frozen : pa5_bal
        table.cell(pa_table, 1, 5,  (_disp_bal5 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal5)),  text_color=_disp_bal5 >= 0 ? C_P : C_N, bgcolor=_cbg5, text_size=size.tiny)
        table.cell(pa_table, 2, 5,  str.tostring(math.round(_ddu5)) + "%", text_color=_ddu5 >= 80 ? C_N : _ddu5 >= 50 ? C_W : C_P, bgcolor=_cbg5, text_size=size.tiny)
        float _margin5  = pa5_bal - (pa5_day_start - i_prop_daily)  // margen restante hoy
        string _day_s5  = pa5_day_lock ? "BLOQ" : (pa5_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa5_day)) + " [" + str.tostring(math.round(_margin5)) + "]"
        table.cell(pa_table, 3, 5,  _day_s5, text_color=pa5_day_lock ? C_W : _margin5 < 300 ? C_N : _margin5 < 600 ? C_W : C_P, bgcolor=_cbg5, text_size=size.tiny)
        table.cell(pa_table, 4, 5,  str.tostring(pa5_trades), text_color=C_T, bgcolor=_cbg5, text_size=size.tiny)
        table.cell(pa_table, 5, 5,  str.tostring(pa5_wins) + "(" + str.tostring(math.round(_wr5)) + "%)", text_color=_wr5 >= 50 ? C_P : C_N, bgcolor=_cbg5, text_size=size.tiny)
        table.cell(pa_table, 6, 5,  pa5_dd_hit ? "SI" : "NO", text_color=pa5_dd_hit ? C_N : C_P, bgcolor=_cbg5, text_size=size.tiny)
        table.cell(pa_table, 7, 5,  "$" + str.tostring(math.round(50000.0 + _disp_bal5)), text_color=_disp_bal5 >= 0 ? C_P : C_N, bgcolor=_cbg5, text_size=size.tiny)
    if pa6_active
        float _wr6   = pa6_trades > 0 ? pa6_wins / pa6_trades * 100.0 : 0.0
        float _ddu6  = math.max(0.0, (pa6_eod - pa6_bal) / 2000.0 * 100.0)
        color _cbg6  = pa6_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 6,  "PA6",  text_color=pa6_dd_hit ? C_N : C_P, bgcolor=_cbg6, text_size=size.tiny)
        float _disp_bal6 = pa6_dd_hit ? pa6_frozen : pa6_bal
        table.cell(pa_table, 1, 6,  (_disp_bal6 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal6)),  text_color=_disp_bal6 >= 0 ? C_P : C_N, bgcolor=_cbg6, text_size=size.tiny)
        table.cell(pa_table, 2, 6,  str.tostring(math.round(_ddu6)) + "%", text_color=_ddu6 >= 80 ? C_N : _ddu6 >= 50 ? C_W : C_P, bgcolor=_cbg6, text_size=size.tiny)
        float _margin6  = pa6_bal - (pa6_day_start - i_prop_daily)  // margen restante hoy
        string _day_s6  = pa6_day_lock ? "BLOQ" : (pa6_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa6_day)) + " [" + str.tostring(math.round(_margin6)) + "]"
        table.cell(pa_table, 3, 6,  _day_s6, text_color=pa6_day_lock ? C_W : _margin6 < 300 ? C_N : _margin6 < 600 ? C_W : C_P, bgcolor=_cbg6, text_size=size.tiny)
        table.cell(pa_table, 4, 6,  str.tostring(pa6_trades), text_color=C_T, bgcolor=_cbg6, text_size=size.tiny)
        table.cell(pa_table, 5, 6,  str.tostring(pa6_wins) + "(" + str.tostring(math.round(_wr6)) + "%)", text_color=_wr6 >= 50 ? C_P : C_N, bgcolor=_cbg6, text_size=size.tiny)
        table.cell(pa_table, 6, 6,  pa6_dd_hit ? "SI" : "NO", text_color=pa6_dd_hit ? C_N : C_P, bgcolor=_cbg6, text_size=size.tiny)
        table.cell(pa_table, 7, 6,  "$" + str.tostring(math.round(50000.0 + _disp_bal6)), text_color=_disp_bal6 >= 0 ? C_P : C_N, bgcolor=_cbg6, text_size=size.tiny)
    if pa7_active
        float _wr7   = pa7_trades > 0 ? pa7_wins / pa7_trades * 100.0 : 0.0
        float _ddu7  = math.max(0.0, (pa7_eod - pa7_bal) / 2000.0 * 100.0)
        color _cbg7  = pa7_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 7,  "PA7",  text_color=pa7_dd_hit ? C_N : C_P, bgcolor=_cbg7, text_size=size.tiny)
        float _disp_bal7 = pa7_dd_hit ? pa7_frozen : pa7_bal
        table.cell(pa_table, 1, 7,  (_disp_bal7 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal7)),  text_color=_disp_bal7 >= 0 ? C_P : C_N, bgcolor=_cbg7, text_size=size.tiny)
        table.cell(pa_table, 2, 7,  str.tostring(math.round(_ddu7)) + "%", text_color=_ddu7 >= 80 ? C_N : _ddu7 >= 50 ? C_W : C_P, bgcolor=_cbg7, text_size=size.tiny)
        float _margin7  = pa7_bal - (pa7_day_start - i_prop_daily)  // margen restante hoy
        string _day_s7  = pa7_day_lock ? "BLOQ" : (pa7_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa7_day)) + " [" + str.tostring(math.round(_margin7)) + "]"
        table.cell(pa_table, 3, 7,  _day_s7, text_color=pa7_day_lock ? C_W : _margin7 < 300 ? C_N : _margin7 < 600 ? C_W : C_P, bgcolor=_cbg7, text_size=size.tiny)
        table.cell(pa_table, 4, 7,  str.tostring(pa7_trades), text_color=C_T, bgcolor=_cbg7, text_size=size.tiny)
        table.cell(pa_table, 5, 7,  str.tostring(pa7_wins) + "(" + str.tostring(math.round(_wr7)) + "%)", text_color=_wr7 >= 50 ? C_P : C_N, bgcolor=_cbg7, text_size=size.tiny)
        table.cell(pa_table, 6, 7,  pa7_dd_hit ? "SI" : "NO", text_color=pa7_dd_hit ? C_N : C_P, bgcolor=_cbg7, text_size=size.tiny)
        table.cell(pa_table, 7, 7,  "$" + str.tostring(math.round(50000.0 + _disp_bal7)), text_color=_disp_bal7 >= 0 ? C_P : C_N, bgcolor=_cbg7, text_size=size.tiny)
    if pa8_active
        float _wr8   = pa8_trades > 0 ? pa8_wins / pa8_trades * 100.0 : 0.0
        float _ddu8  = math.max(0.0, (pa8_eod - pa8_bal) / 2000.0 * 100.0)
        color _cbg8  = pa8_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 8,  "PA8",  text_color=pa8_dd_hit ? C_N : C_P, bgcolor=_cbg8, text_size=size.tiny)
        float _disp_bal8 = pa8_dd_hit ? pa8_frozen : pa8_bal
        table.cell(pa_table, 1, 8,  (_disp_bal8 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal8)),  text_color=_disp_bal8 >= 0 ? C_P : C_N, bgcolor=_cbg8, text_size=size.tiny)
        table.cell(pa_table, 2, 8,  str.tostring(math.round(_ddu8)) + "%", text_color=_ddu8 >= 80 ? C_N : _ddu8 >= 50 ? C_W : C_P, bgcolor=_cbg8, text_size=size.tiny)
        float _margin8  = pa8_bal - (pa8_day_start - i_prop_daily)  // margen restante hoy
        string _day_s8  = pa8_day_lock ? "BLOQ" : (pa8_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa8_day)) + " [" + str.tostring(math.round(_margin8)) + "]"
        table.cell(pa_table, 3, 8,  _day_s8, text_color=pa8_day_lock ? C_W : _margin8 < 300 ? C_N : _margin8 < 600 ? C_W : C_P, bgcolor=_cbg8, text_size=size.tiny)
        table.cell(pa_table, 4, 8,  str.tostring(pa8_trades), text_color=C_T, bgcolor=_cbg8, text_size=size.tiny)
        table.cell(pa_table, 5, 8,  str.tostring(pa8_wins) + "(" + str.tostring(math.round(_wr8)) + "%)", text_color=_wr8 >= 50 ? C_P : C_N, bgcolor=_cbg8, text_size=size.tiny)
        table.cell(pa_table, 6, 8,  pa8_dd_hit ? "SI" : "NO", text_color=pa8_dd_hit ? C_N : C_P, bgcolor=_cbg8, text_size=size.tiny)
        table.cell(pa_table, 7, 8,  "$" + str.tostring(math.round(50000.0 + _disp_bal8)), text_color=_disp_bal8 >= 0 ? C_P : C_N, bgcolor=_cbg8, text_size=size.tiny)
    if pa9_active
        float _wr9   = pa9_trades > 0 ? pa9_wins / pa9_trades * 100.0 : 0.0
        float _ddu9  = math.max(0.0, (pa9_eod - pa9_bal) / 2000.0 * 100.0)
        color _cbg9  = pa9_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 9,  "PA9",  text_color=pa9_dd_hit ? C_N : C_P, bgcolor=_cbg9, text_size=size.tiny)
        float _disp_bal9 = pa9_dd_hit ? pa9_frozen : pa9_bal
        table.cell(pa_table, 1, 9,  (_disp_bal9 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal9)),  text_color=_disp_bal9 >= 0 ? C_P : C_N, bgcolor=_cbg9, text_size=size.tiny)
        table.cell(pa_table, 2, 9,  str.tostring(math.round(_ddu9)) + "%", text_color=_ddu9 >= 80 ? C_N : _ddu9 >= 50 ? C_W : C_P, bgcolor=_cbg9, text_size=size.tiny)
        float _margin9  = pa9_bal - (pa9_day_start - i_prop_daily)  // margen restante hoy
        string _day_s9  = pa9_day_lock ? "BLOQ" : (pa9_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa9_day)) + " [" + str.tostring(math.round(_margin9)) + "]"
        table.cell(pa_table, 3, 9,  _day_s9, text_color=pa9_day_lock ? C_W : _margin9 < 300 ? C_N : _margin9 < 600 ? C_W : C_P, bgcolor=_cbg9, text_size=size.tiny)
        table.cell(pa_table, 4, 9,  str.tostring(pa9_trades), text_color=C_T, bgcolor=_cbg9, text_size=size.tiny)
        table.cell(pa_table, 5, 9,  str.tostring(pa9_wins) + "(" + str.tostring(math.round(_wr9)) + "%)", text_color=_wr9 >= 50 ? C_P : C_N, bgcolor=_cbg9, text_size=size.tiny)
        table.cell(pa_table, 6, 9,  pa9_dd_hit ? "SI" : "NO", text_color=pa9_dd_hit ? C_N : C_P, bgcolor=_cbg9, text_size=size.tiny)
        table.cell(pa_table, 7, 9,  "$" + str.tostring(math.round(50000.0 + _disp_bal9)), text_color=_disp_bal9 >= 0 ? C_P : C_N, bgcolor=_cbg9, text_size=size.tiny)
    if pa10_active
        float _wr10   = pa10_trades > 0 ? pa10_wins / pa10_trades * 100.0 : 0.0
        float _ddu10  = math.max(0.0, (pa10_eod - pa10_bal) / 2000.0 * 100.0)
        color _cbg10  = pa10_dd_hit ? color.new(#3a1a1a, 20) : C_K
        table.cell(pa_table, 0, 10,  "PA10",  text_color=pa10_dd_hit ? C_N : C_P, bgcolor=_cbg10, text_size=size.tiny)
        float _disp_bal10 = pa10_dd_hit ? pa10_frozen : pa10_bal
        table.cell(pa_table, 1, 10,  (_disp_bal10 >= 0 ? "+" : "") + "$" + str.tostring(math.round(_disp_bal10)),  text_color=_disp_bal10 >= 0 ? C_P : C_N, bgcolor=_cbg10, text_size=size.tiny)
        table.cell(pa_table, 2, 10,  str.tostring(math.round(_ddu10)) + "%", text_color=_ddu10 >= 80 ? C_N : _ddu10 >= 50 ? C_W : C_P, bgcolor=_cbg10, text_size=size.tiny)
        float _margin10  = pa10_bal - (pa10_day_start - i_prop_daily)  // margen restante hoy
        string _day_s10  = pa10_day_lock ? "BLOQ" : (pa10_day >= 0 ? "+" : "") + "$" + str.tostring(math.round(pa10_day)) + " [" + str.tostring(math.round(_margin10)) + "]"
        table.cell(pa_table, 3, 10,  _day_s10, text_color=pa10_day_lock ? C_W : _margin10 < 300 ? C_N : _margin10 < 600 ? C_W : C_P, bgcolor=_cbg10, text_size=size.tiny)
        table.cell(pa_table, 4, 10,  str.tostring(pa10_trades), text_color=C_T, bgcolor=_cbg10, text_size=size.tiny)
        table.cell(pa_table, 5, 10,  str.tostring(pa10_wins) + "(" + str.tostring(math.round(_wr10)) + "%)", text_color=_wr10 >= 50 ? C_P : C_N, bgcolor=_cbg10, text_size=size.tiny)
        table.cell(pa_table, 6, 10,  pa10_dd_hit ? "SI" : "NO", text_color=pa10_dd_hit ? C_N : C_P, bgcolor=_cbg10, text_size=size.tiny)
        table.cell(pa_table, 7, 10,  "$" + str.tostring(math.round(50000.0 + _disp_bal10)), text_color=_disp_bal10 >= 0 ? C_P : C_N, bgcolor=_cbg10, text_size=size.tiny)
    // Fila total
    float _d1  = pa1_dd_hit  ? pa1_frozen  : pa1_bal
    float _d2  = pa2_dd_hit  ? pa2_frozen  : pa2_bal
    float _d3  = pa3_dd_hit  ? pa3_frozen  : pa3_bal
    float _d4  = pa4_dd_hit  ? pa4_frozen  : pa4_bal
    float _d5  = pa5_dd_hit  ? pa5_frozen  : pa5_bal
    float _d6  = pa6_dd_hit  ? pa6_frozen  : pa6_bal
    float _d7  = pa7_dd_hit  ? pa7_frozen  : pa7_bal
    float _d8  = pa8_dd_hit  ? pa8_frozen  : pa8_bal
    float _d9  = pa9_dd_hit  ? pa9_frozen  : pa9_bal
    float _d10 = pa10_dd_hit ? pa10_frozen : pa10_bal
    float _total_pa_pnl = _d1 + _d2 + _d3 + _d4 + _d5 + _d6 + _d7 + _d8 + _d9 + _d10
    float _total_bal    = 50000.0 * pa_count + _total_pa_pnl
    table.cell(pa_table, 0, 11, "TOTAL",   text_color=C_T, bgcolor=C_H, text_size=size.tiny)
    table.cell(pa_table, 1, 11, (_total_pa_pnl >= 0 ? "+" : "") + "$" + str.tostring(math.round(_total_pa_pnl)), text_color=_total_pa_pnl >= 0 ? C_P : C_N, bgcolor=C_H, text_size=size.tiny)
    table.cell(pa_table, 7, 11, "$" + str.tostring(math.round(_total_bal)), text_color=_total_pa_pnl >= 0 ? C_P : C_N, bgcolor=C_H, text_size=size.tiny)

// DASHBOARD LIVE
var table live_table = table.new(position.top_left, 2, 12, bgcolor=color.new(#0d1117, 15), border_width=1, border_color=color.new(#3a5060, 50))

if i_show_live and barstate.islast
    C_H  = color.new(#1b3a4d, 0)
    C_K  = color.new(#0d1f2d, 20)
    C_P  = color.new(#00e5a0, 0)
    C_N  = color.new(#ff3d5a, 0)
    C_W  = color.new(#ff9d00, 0)
    C_T  = color.new(#cce8f0, 0)
    C_D  = color.new(#5a8090, 0)

    // Sesion
    string _ses_col  = not in_session ? "OFF" : in_blackout ? "BLK" : in_early_zone ? "EARLY" : "ABIERTA"
    color  _ses_c    = not in_session ? C_D : in_blackout ? C_N : in_early_zone ? C_W : C_P

    // Regimen
    string _reg_s    = not regime_ready ? "REG?" : regime_trend ? "TENDENCIA" : regime_range ? "LATERAL" : "MIXTO"
    color  _reg_c    = not regime_ready ? C_D : regime_trend ? C_P : regime_range ? C_N : C_W
    string _key_s    = "K:" + str.tostring(eff_buy_key)

    // Sesgo
    string _bias_s   = period_bull ? "ALCISTA" : period_bear ? "BAJISTA" : "NEUTRO"
    color  _bias_c   = period_bull ? C_P : period_bear ? C_N : C_W

    // VWAP
    string _vwap_s   = above_vwap ? "Precio > VWAP" : "Precio < VWAP"
    color  _vwap_c   = above_vwap ? C_P : C_N

    // Velas
    string _cnl_s    = candle_bull ? "BULL (2 alzas)" : candle_bear ? "BEAR (1 baja)" : "NEUTRO"
    color  _cnl_c    = candle_bull ? C_P : candle_bear ? C_N : C_W

    // CVD
    string _cvd_s    = cvd_rising ? "SUBIENDO" : cvd_falling ? "BAJANDO" : "NEUTRO"
    color  _cvd_c    = cvd_rising ? C_P : cvd_falling ? C_N : C_W

    // ATR
    string _atr_s    = not i_use_atr_filter ? "OFF" : atr_ratio > i_atr_mult_max ? "ALTO (" + str.tostring(math.round(atr_ratio * 100) / 100) + "x)" : "OK (" + str.tostring(math.round(atr_ratio * 100) / 100) + "x)"
    color  _atr_c    = not i_use_atr_filter ? C_D : atr_ratio > i_atr_mult_max ? C_N : atr_ratio > i_atr_mult_max * 0.85 ? C_W : C_P

    // Losses sesion
    string _loss_s   = session_closed ? "CERRADO" : str.tostring(loss_count_apex) + "/" + str.tostring(i_max_losses) + " (hoy)"
    color  _loss_c   = session_closed ? C_N : loss_count >= i_max_losses - 1 ? C_W : C_P

    // Riesgo actual
    string _risk_s   = "$" + str.tostring(math.round(i_use_scaling ? risk_current : i_risk_usd))
    color  _risk_c   = risk_current >= i_risk_scaled ? C_W : C_P

    // Pre-señal
    string _pre_s    = pre_buy ? "BUY LISTO" : pre_sell ? "SELL LISTO" : "Esperando..."
    color  _pre_c    = pre_buy ? C_P : pre_sell ? C_N : C_D

    // Header
    table.cell(live_table, 0, 0,  "LIVE",      text_color=C_T, bgcolor=C_H, text_size=size.normal)
    table.cell(live_table, 1, 0,  "UT Bot v6", text_color=C_D, bgcolor=C_H, text_size=size.normal)
    // Filas
    table.cell(live_table, 0, 1,  "Sesion",    text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 1,  _ses_col,    text_color=_ses_c,  bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 0, 2,  "Regimen",   text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 2,  _reg_s + " " + _key_s, text_color=_reg_c, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 0, 3,  "Sesgo",     text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 3,  _bias_s,     text_color=_bias_c, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 0, 4,  "VWAP",      text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 4,  _vwap_s,     text_color=_vwap_c, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 0, 5,  "Velas",     text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 5,  _cnl_s,      text_color=_cnl_c,  bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 0, 6,  "CVD",       text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 6,  _cvd_s,      text_color=_cvd_c,  bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 0, 7,  "ATR",       text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 7,  _atr_s,      text_color=_atr_c,  bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 0, 8,  "Losses",    text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 8,  _loss_s,     text_color=_loss_c, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 0, 9,  "Riesgo",    text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 9,  _risk_s,     text_color=_risk_c, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 0, 10, "Pre-senal", text_color=C_D, bgcolor=C_K, text_size=size.small)
    table.cell(live_table, 1, 10, _pre_s,      text_color=_pre_c,  bgcolor=C_K, text_size=size.small)
    // Trail actual
    string _trail_s = str.tostring(math.round(trailStop_c * 4) / 4)
    color  _trail_c = close > trailStop_c ? C_P : C_N
    table.cell(live_table, 0, 11, "Trail",     text_color=C_D, bgcolor=C_H, text_size=size.small)
    table.cell(live_table, 1, 11, _trail_s,    text_color=_trail_c, bgcolor=C_H, text_size=size.small)

// ALERTAS
// 
// Calcular cantidad de contratos dinamicamente
// MNQ = $2 por punto
// contratos = riesgo_usd / (sl_pts * $2)
float _sl_pts_live  = math.abs(sig_entry - sig_sl)
float _risk_live    = i_use_scaling ? risk_current : i_risk_usd
float _risk_per_ctr = _sl_pts_live * 2.0
int   _qty          = _sl_pts_live > 0 and _risk_per_ctr > 0 ? math.max(1, math.round(_risk_live / _risk_per_ctr)) : 1

// alert() envia valores DINAMICOS en cada barra — cantidad y precios cambian cada trade
// alertcondition() es para alertas manuales con mensaje fijo
// TP y SL ya calculados correctamente en sig_tp1 y sig_sl:
//   sig_sl   → respeta SL min/max (35-50pts)
//   sig_tp1  → respeta TP1 gate R (i_tp1_r_gate)
// Redondear al tick mas cercano (0.25pts) para MNQ
float _sl_rounded  = math.round(sig_sl  * 4.0) / 4.0
float _tp_rounded  = math.round(sig_tp1 * 4.0) / 4.0

// JSON formato PMT completo — igual que OF_MNQ_5M_v3
pmt_json(_action) =>
    '{"symbol":"'           + i_pmt_symbol  + '",'
     + '"date":"'           + str.tostring(timenow) + '",'
     + '"data":"'           + _action       + '",'
     + '"quantity":"'       + str.tostring(_qty) + '",'
     + '"risk_percentage":0,'
     + '"price":"'          + str.tostring(sig_entry, "#.##") + '",'
     + '"tp":'               + str.tostring(_tp_rounded, "#.##") + ','
     + '"percentage_tp":0,"dollar_tp":0,'
     + '"sl":'               + str.tostring(_sl_rounded, "#.##") + ','
     + '"dollar_sl":0,"percentage_sl":0,'
     + '"trail":0,"trail_stop":0,"trail_trigger":0,"trail_freq":0,'
     + '"update_tp":false,"update_sl":false,'
     + '"breakeven":0,"breakeven_offset":0,'
     + '"token":"'          + i_pmt_token   + '",'
     + '"pyramid":true,"same_direction_ignore":false,"reverse_order_close":false,'
     + '"multiple_accounts":[{"token":"' + i_pmt_token + '","account_id":"' + i_pmt_account + '","risk_percentage":0,"quantity_multiplier":1}]}'

if buy
    alert(pmt_json("buy"),  alert.freq_once_per_bar_close)
if sell
    alert(pmt_json("sell"), alert.freq_once_per_bar_close)
// close automatico desactivado — dejar que SL/TP manejen la salida

// alertcondition para activar las alertas en TradingView (necesario para el menu de alertas)
alertcondition(buy,          title="UT BUY",        message="UT v6 BUY — usar alert() para PMT")
alertcondition(sell,         title="UT SELL",       message="UT v6 SELL — usar alert() para PMT")
alertcondition(pre_buy,      title="Pre-BUY",       message="UT v6 - PRE BUY | Intrabar")
alertcondition(pre_sell,     title="Pre-SELL",      message="UT v6 - PRE SELL | Intrabar")
// alertcondition(exhaust_be,   title="Agotamiento BE",message="UT v6 - AGOTAMIENTO BE")
// alertcondition(exhaust_exit, title="Agotamiento 1R",message="UT v6 - AGOTAMIENTO 1R")

Overview

Entry signals trigger on trailing stop crossovers, with sensitivity keys adjusting dynamically between trending and ranging market regimes. Trade setups are filtered using ATR volatility limits, VWAP positioning, session trading windows, multi-timeframe directional bias, and candle structure. The script plots visual stop loss and multi-target take profit boxes, while providing webhook-ready trade variables and internal session loss monitoring.

Details

Published by

Stolzel on GitHub

Draws

On the price chart

Markets

Indices

Timeframes

M1-M5, M15-H1

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Key [BUY] tendenciaint2buy_key
Key [BUY] lateralint3buy_key_range
ATR Period [BUY]int10buy_atr
Key [SELL] tendenciaint2sell_key
Key [SELL] lateralint3sell_key_range
Key dinamico segun regimenbooltrueuse_dynamic_key
ATR Period [SELL]int10sell_atr
Filtro consistencia de velasbooltrueuse_candles
Filtro VWAPbooltrueuse_vwap
Filtro horariobooltrueuse_session
Sesion 1 UTC NY Opensession1330-1530session_open
Sesion 2 UTC NY Tardesession1800-2000session_pm
Show all 40 settings
SettingTypeDefaultVariable
Filtro Early Zone (apertura NY)booltrueuse_early
Early: cuerpo minimo % rangofloat40.0i_body_pct
Early: distancia minima trail (pts)float8.0i_trail_dist
Filtro sesgo D/Wbooltrueuse_bias
Umbral sesgo (1-3)int2i_bias_strength
Filtro regimenbooltrueuse_regime
Simbolo PMTstringMNQ1!i_pmt_symbol
Token PMTstringTU-TOKEN-AQUIi_pmt_token
Account ID PMTstringTU-ACCOUNT-IDi_pmt_account
SL minimo (pts)float35.0i_sl_min
SL maximo (pts)float50.0i_sl_max
TP1 (R)float1.0i_tp1_r
TP2 (R)float2.0i_tp2_r
TP3 (R)float3.0i_tp3_r
Mostrar boxes TP/SLbooltruei_show_boxes
Ancho boxes (barras)int20i_box_width
Regla: max losses por sesionbooltrueuse_trade_rule
Max losses por sesionint2i_max_losses
TP1 gate T1 ganador (R)float1.0i_tp1_r_gate
Mostrar agotamientobooltruei_show_exhaust
Mostrar pre-senal intrabarbooltruei_show_presignal
Score BE (1-3)int2i_exhaust_be
Score 1R (1-3)int3i_exhaust_exit
F1: CVD divergenciabooltruei_use_f1
F2: Delta decrecienteboolfalsei_use_f2
F3: Vela de rechazoboolfalsei_use_f3
F3: mecha minima %float60.0i_mecha_pct
Filtro ATR: bloquear volatilidad anormalbooltruei_use_atr_filter
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

92 stars

This indicator classifies the market into gamma regime types (negative gamma trend, positive gamma mean-reversion, or transition) by calculating a composite score based on daily ATR ratios, session VWAP crossover frequencies, and opening range displacement. It

Indicator v5 Volatility & bandsTrend
Updated 2 months ago · Custom licence GitHub repository of Moon Dev GEX Regime & Trap

42H Map

by aurorascarlet1102
4 stars

42H Map calculates custom time cycle structures and session ranges directly on the price chart. It partitions market action into forty-two-hour cycles, ten-and-a-half-hour micro-sessions, half-week periods, and quarter-month segments to track highs, lows, and

Indicator v5 Sessions & timeSupport & resistance
Updated 3 months ago · None stated GitHub repository of 42H Map

Inverse Choppiness Index

by ryangaraygay
2 stars

This indicator calculates the Choppiness Index to gauge market consolidation versus trending conditions. When the Choppiness Index indicates high choppiness above a threshold of 50 during a defined trading session, the script plots a transparent rectangle over

Indicator v5 TrendVolatility & bands
Updated 1 year ago · MIT GitHub repository of Inverse Choppiness Index

This indicator plots several linear regression channels on the price chart. Each channel can be hidden or drawn as a channel, bands, or both, and its lookback is anchored to price, volume, oscillator extremes, calendar periods, sessions, or corporate events. P

Indicator v6 TrendVolatility & bands
Updated 8 months ago · None stated GitHub repository of Multi-Anchored Linear Regression Channels [TANHEF]

4x4 Futures Ghost Matrix

by knectardev
1 stars

This indicator generates intraday trading signals by combining dual-sigma standard deviation bands, Heikin Ashi candle vectors, and a four-bar confluence score. It triggers long and short signals during defined trading sessions using either mean-reversion boun

Indicator v5 Volatility & bandsMean reversion
Updated 9 months ago · None stated GitHub repository of 4x4 Futures Ghost Matrix

More Trend scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers