Self-Aware Trend System [WillyAlgoTrader]

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #260317 quote
    ahenryahenry
    Participant
    Average

    Hi Gurus,

    Need professional help to convert this indicator please.


    Self-Aware Trend System [WillyAlgoTrader] — Indicator by WillyAlgoTrader — TradingView


    Thanks in advance.


    Cheers!

    #260401 quote
    Iván GonzálezIván González
    Moderator
    Legend

    Hi, here you have the translation:

    //---------------------------------------------------------
    //PRC_Self-Aware Trend System [WillyAlgoTrader]
    //version = 0
    //21.04.2026
    //Iván González @ www.prorealcode.com
    //Sharing ProRealTime knowledge
    //---------------------------------------------------------
    //==========================================================
    // 1. INPUTS
    //==========================================================
    // --- Main ---
    atrLen          = 14        // ATR length
    baseMult        = 2.0       // base band width (xATR)
    // --- Adaptive Engine (legacy ER) ---
    useAdaptive     = 1         // 1=on
    erLen           = 20        // efficiency window
    adaptStrength   = 0.5
    atrBaselineLen  = 100
    // --- Trend Quality Engine ---
    useTqi          = 1
    qualityStrength = 0.4
    qualityCurve    = 1.5
    multSmooth      = 1         // EMA-smooth multipliers
    useAsymBands    = 1
    asymStrength    = 0.5
    useEffAtr       = 1         // efficiency-weighted ATR
    useCharFlip     = 1
    charFlipMinAge  = 5
    charFlipHighTqi = 0.55
    charFlipLowTqi  = 0.25
    wEr             = 0.35
    wVol            = 0.20
    wStruct         = 0.25
    wMom            = 0.20
    structLen       = 20
    momLen          = 10
    // --- Risk ---
    slAtrMult       = 1.5
    useDynTp        = 0         // 0=Fixed, 1=Dynamic
    tp1R            = 1.0
    tp2R            = 2.0
    tp3R            = 3.0
    // --- Dynamic TP ---
    dynTpTqiW       = 0.6
    dynTpVolW       = 0.4
    dynTpMinScale   = 0.5
    dynTpMaxScale   = 2.0
    dynTpFloorR1    = 0.5
    dynTpCeilR3     = 8.0
    labelOffsetBars = 10
    tradeMaxAge     = 100
    // --- Self-learning ---
    useAutoCalib    = 0
    calibWindow     = 20
    calibBadR       = 0.0
    calibGoodR      = 0.7
    calibStepQ      = 0.05
    calibCooldown   = 5
    calibMinQ       = 0.1
    calibMaxQ       = 0.9
    // --- Score (display) ---
    rsiLen          = 14
    rsiOB           = 70
    rsiOS           = 30
    rsiLookback     = 20
    pivotLen        = 3
    volLen          = 20
    useVolScore     = 1
    useRsiScore     = 1
    useStructScore  = 1
    showDash        = 1
    showBands       = 1
    showSignals     = 1
    
    //==========================================================
    // 2. CONSTANTS
    //==========================================================
    maxHistory     = 50        // rolling signal buffer size (reduced from 100 for PRT cost)
    erLow          = 0.25
    erHigh         = 0.50
    volLow         = 0.7
    volHigh        = 1.3
    ewmaAlpha      = 0.2
    multSmoothAlpha = 0.15
    
    //==========================================================
    // 3. WARMUP
    //==========================================================
    warmup = max(50, max(atrLen, max(erLen, max(rsiLen, max(volLen, max(structLen, momLen))))) + 10)
    isWarm = barindex >= warmup
    
    //==========================================================
    // 4. BASE CALCULATIONS: ATR, ER, efficiency-weighted ATR
    //==========================================================
    rawAtr      = averagetruerange[atrLen](close)
    atrBase     = average[atrBaselineLen](rawAtr)
    if atrBase <= 0 then
       volRatio = 1.0
    else
       volRatio = rawAtr / atrBase
    endif
    
    // Efficiency Ratio manual (Kaufman)
    erChange    = abs(close - close[erLen])
    erVolSum    = summation[erLen](abs(close - close[1]))
    if erVolSum > 0 then
       erValue = erChange / erVolSum
    else
       erValue = 0
    endif
    
    if useEffAtr = 1 then
       atrValue = rawAtr * (0.5 + 0.5 * erValue)
    else
       atrValue = rawAtr
    endif
    
    //==========================================================
    // 5. TREND QUALITY INDEX (TQI, 4 factors)
    //==========================================================
    // Factor 1: ER clamped
    tqiEr = min(1.0, max(0.0, erValue))
    
    // Factor 2: Volatility regime
    // Z-score del volumen si hay; si no, mapeo sobre volRatio
    hasVol = volume > 0
    if hasVol then
       vMean = average[volLen](volume)
       vStd  = std[volLen](volume)
       if vStd > 0 then
          volZ = (volume - vMean) / vStd
       else
          volZ = 0
       endif
       // map [-1..2] to [0..1]
       tqiVolRaw = (volZ - (-1.0)) / 3.0
    else
       volZ = 0
       // map volRatio [0.6..1.8] to [0..1]
       tqiVolRaw = (volRatio - 0.6) / 1.2
    endif
    tqiVol = min(1.0, max(0.0, tqiVolRaw))
    
    // Factor 3: Structure (precio en el rango N-barras, desviación de 0.5)
    sHi = highest[structLen](high)
    sLo = lowest[structLen](low)
    sRange = sHi - sLo
    if sRange > 0 then
       pricePos = (close - sLo) / sRange
    else
       pricePos = 0.5
    endif
    tqiStruct = min(1.0, max(0.0, abs(pricePos - 0.5) * 2.0))
    
    // Factor 4: Momentum persistence — fracción de barras alineadas con el cambio N
    aligned = 0
    if barindex > momLen then
       winChg = close - close[momLen]
       for k = 0 to momLen - 1 do
          barChg = close[k] - close[k+1]
          if winChg > 0 and barChg > 0 then
             aligned = aligned + 1
          endif
          if winChg < 0 and barChg < 0 then
             aligned = aligned + 1
          endif
       next
    endif
    tqiMom = aligned / momLen
    
    // Suma ponderada
    wSum = wEr + wVol + wStruct + wMom
    if wSum <= 0 then
       wSum = 1.0
    endif
    if useTqi = 1 then
       tqi = (tqiEr*wEr + tqiVol*wVol + tqiStruct*wStruct + tqiMom*wMom) / wSum
    else
       tqi = 0.5
    endif
    tqi = min(1.0, max(0.0, tqi))
    
    //==========================================================
    // 6. ADAPTIVE MULTIPLIERS (active / passive)
    //==========================================================
    if useAdaptive = 1 then
       legacyAdapt = 1.0 + adaptStrength * (0.5 - erValue)
    else
       legacyAdapt = 1.0
    endif
    
    // qualityStrength puede ser modificado por auto-calibración
    once effQStrength = qualityStrength
    
    if useTqi = 1 then
       qDev = 1.0 - tqi
       if qDev > 0 then
          qDevP = pow(qDev, qualityCurve)
       else
          qDevP = 0
       endif
    else
       qDevP = 0.5
    endif
    tqiMult = 1.0 - effQStrength + effQStrength * (0.6 + 0.8 * qDevP)
    
    symMult = baseMult * legacyAdapt * tqiMult
    
    if useTqi = 1 and useAsymBands = 1 then
       asymTighten = 1.0 - asymStrength * tqi * 0.3
       asymWiden   = 1.0 + asymStrength * tqi * 0.4
       activeMultRaw  = symMult * asymTighten
       passiveMultRaw = symMult * asymWiden
    else
       activeMultRaw  = symMult
       passiveMultRaw = symMult
    endif
    
    // EMA-smoothing de los multiplicadores
    once activeMultSm  = activeMultRaw
    once passiveMultSm = passiveMultRaw
    if multSmooth = 1 then
       activeMultSm  = activeMultSm  * (1.0 - multSmoothAlpha) + activeMultRaw  * multSmoothAlpha
       passiveMultSm = passiveMultSm * (1.0 - multSmoothAlpha) + passiveMultRaw * multSmoothAlpha
    else
       activeMultSm  = activeMultRaw
       passiveMultSm = passiveMultRaw
    endif
    
    //==========================================================
    // 7. ADAPTIVE SUPERTREND (máquina de estado canónica PRT)
    //==========================================================
    // Patrón canónico (learning 003): una sola stLine que hace trailing + flip atómico.
    // Se preserva el carácter asimétrico: lado activo (tighter) para el trail, lado pasivo (wider) al flipear.
    once trendDir      = 1
    once stLine        = close
    once trendStartBar = 0
    
    // prevTrend robusto en primeras barras
    if barindex < 2 then
       prevTrend = 1
    else
       prevTrend = trendDir[1]
    endif
    
    // Warmup guard: no operar máquina de estado hasta tener ATR válido.
    // Durante el warmup stLine queda en su semilla (close de barindex=0) y trendDir = 1.
    if barindex >= atrLen then
       // Bandas raw según la dirección previa
       if prevTrend = 1 then
          activeBandRaw = close - activeMultSm * atrValue   // lowerBand "tight"
          flipBandRaw   = close + passiveMultSm * atrValue  // upperBand "wide" tras flip
       else
          activeBandRaw = close + activeMultSm * atrValue   // upperBand "tight"
          flipBandRaw   = close - passiveMultSm * atrValue  // lowerBand "wide" tras flip
       endif
       
       // Primera barra post-warmup: re-inicializar stLine según dirección
       if barindex = atrLen then
          stLine   = activeBandRaw
          trendDir = 1
       else
          // Máquina de estado: trail + flip
          if prevTrend = 1 then
             // Alcista: stLine = lowerBand, sube (nunca baja)
             if activeBandRaw > stLine then
                stLine = activeBandRaw
             endif
             if close < stLine then
                trendDir = -1
                stLine   = flipBandRaw
             else
                trendDir = 1
             endif
          else
             // Bajista: stLine = upperBand, baja (nunca sube)
             if activeBandRaw < stLine then
                stLine = activeBandRaw
             endif
             if close > stLine then
                trendDir = 1
                stLine   = flipBandRaw
             else
                trendDir = -1
             endif
          endif
       endif
    endif
    
    // Character-flip (colapso de TQI fuerza inversión sobre la dirección PREVIA)
    // Solo aplica si no hubo ya un price-flip en esta barra.
    if barindex < 2 then
       prevTqi = 0.5
    else
       prevTqi = tqi[1]
    endif
    trendAge = barindex - trendStartBar
    priceFlipped = trendDir <> prevTrend
    
    charBase = (useCharFlip = 1) and (useTqi = 1) and (prevTqi > charFlipHighTqi) and (tqi < charFlipLowTqi) and (trendAge >= charFlipMinAge)
    if charBase and not priceFlipped then
       if prevTrend = 1 then
          trendDir = -1
          stLine   = close + passiveMultSm * atrValue
       else
          trendDir = 1
          stLine   = close - passiveMultSm * atrValue
       endif
    endif
    
    // Trend-start tracking
    if trendDir <> prevTrend then
       trendStartBar = barindex
    endif
    
    flipUp = (trendDir =  1) and (prevTrend = -1)
    flipDn = (trendDir = -1) and (prevTrend =  1)
    
    //==========================================================
    // 7.5 RSI + PIVOTS (para score de señales)
    //==========================================================
    rsiVal = rsi[rsiLen](close)
    
    // Pivots high/low simétricos (ventana 2*pivotLen+1)
    once lastPivotHigh = 0
    once lastPivotLow  = 0
    if barindex >= 2*pivotLen then
       if high[pivotLen] = highest[2*pivotLen+1](high) then
          lastPivotHigh = high[pivotLen]
       endif
       if low[pivotLen]  = lowest[2*pivotLen+1](low) then
          lastPivotLow  = low[pivotLen]
       endif
    endif
    
    //==========================================================
    // 7.6 SIGNAL SCORE (6 componentes)
    //==========================================================
    bypassScore = 12.0
    
    // Componente 1: momentum (mov en dirección contraria 3 barras previas)
    dirMoveBuy  = close[3] - close
    dirMoveSell = close - close[3]
    if atrValue > 0 then
       momRatioBuy  = dirMoveBuy  / atrValue
       momRatioSell = dirMoveSell / atrValue
    else
       momRatioBuy  = 0
       momRatioSell = 0
    endif
    // mapClamp(x, 0.3, 2.0, 0, 17) → t = (x-0.3)/1.7 clamp, * 17
    tMomBuy      = min(1.0, max(0.0, (momRatioBuy  - 0.3) / 1.7))
    tMomSell     = min(1.0, max(0.0, (momRatioSell - 0.3) / 1.7))
    momScoreBuy  = tMomBuy  * 17.0
    momScoreSell = tMomSell * 17.0
    
    // Componente 2: efficiency ratio mapClamp(er, 0.15, 0.7, 0, 17)
    tEr     = min(1.0, max(0.0, (erValue - 0.15) / 0.55))
    erScore = tEr * 17.0
    
    // Componente 3: volumen Z mapClamp(volZ, 0, 3, 0, 17) o bypass
    if hasVol and (useVolScore = 1) then
       tVol   = min(1.0, max(0.0, volZ / 3.0))
       vScore = tVol * 17.0
    else
       vScore = bypassScore
    endif
    
    // Componente 4: RSI depth
    if useRsiScore = 1 then
       rsiWinLow  = lowest[rsiLookback](rsiVal)
       rsiWinHigh = highest[rsiLookback](rsiVal)
       rsiDepthBuy  = max(0.0, rsiOS - rsiWinLow)
       rsiDepthSell = max(0.0, rsiWinHigh - rsiOB)
       tRsiBuy      = min(1.0, max(0.0, rsiDepthBuy  / 15.0))
       tRsiSell     = min(1.0, max(0.0, rsiDepthSell / 15.0))
       rsiScoreBuy  = tRsiBuy  * 17.0
       rsiScoreSell = tRsiSell * 17.0
    else
       rsiScoreBuy  = bypassScore
       rsiScoreSell = bypassScore
    endif
    
    // Componente 5: structure (distancia al último pivot)
    if useStructScore = 1 then
       if lastPivotLow > 0 then
          pivDistBuy = abs(close - lastPivotLow)
       else
          pivDistBuy = 0
       endif
       if lastPivotHigh > 0 then
          pivDistSell = abs(lastPivotHigh - close)
       else
          pivDistSell = 0
       endif
       if atrValue > 0 then
          pivRatioBuy  = pivDistBuy  / atrValue
          pivRatioSell = pivDistSell / atrValue
       else
          pivRatioBuy  = 0
          pivRatioSell = 0
       endif
       // mapClampInv(x, 0, 1.5, 16, 6): desciende con x
       tStructBuy      = min(1.0, max(0.0, pivRatioBuy  / 1.5))
       tStructSell     = min(1.0, max(0.0, pivRatioSell / 1.5))
       structScoreBuy  = 16.0 - tStructBuy  * 10.0
       structScoreSell = 16.0 - tStructSell * 10.0
    else
       structScoreBuy  = bypassScore
       structScoreSell = bypassScore
    endif
    
    // Componente 6: break depth (profundidad de rotura del SuperTrend previo)
    breakDepthBuy  = max(0.0, stLine[1] - close[1])
    breakDepthSell = max(0.0, close[1] - stLine[1])
    if atrValue > 0 then
       breakRatioBuy  = breakDepthBuy  / atrValue
       breakRatioSell = breakDepthSell / atrValue
    else
       breakRatioBuy  = 0
       breakRatioSell = 0
    endif
    tBrkBuy       = min(1.0, max(0.0, breakRatioBuy))
    tBrkSell      = min(1.0, max(0.0, breakRatioSell))
    breakScoreBuy  = tBrkBuy  * 16.0
    breakScoreSell = tBrkSell * 16.0
    
    // Suma (máx ~102)
    buyScore  = momScoreBuy  + erScore + vScore + rsiScoreBuy  + structScoreBuy  + breakScoreBuy
    sellScore = momScoreSell + erScore + vScore + rsiScoreSell + structScoreSell + breakScoreSell
    buyScoreInt  = round(buyScore)
    sellScoreInt = round(sellScore)
    
    //==========================================================
    // 8. DYNAMIC TP R-MULTIPLES (per-bar, for live signal use)
    //==========================================================
    // Scale por blend TQI + volRatio
    tqiComp = min(1.0, max(0.0, tqi))
    volComp01 = (volRatio - 0.5) / 1.5
    volComp = min(1.0, max(0.0, volComp01))
    wTpSum = dynTpTqiW + dynTpVolW
    if wTpSum <= 0 then
       wTpSum = 1.0
    endif
    rawScale = (tqiComp * dynTpTqiW + volComp * dynTpVolW) / wTpSum
    finalScale = dynTpMinScale + rawScale * (dynTpMaxScale - dynTpMinScale)
    
    // TP base re-ordenados (garantizar tp1<tp2<tp3)
    fixedTp1R = min(tp1R, min(tp2R, tp3R))
    fixedTp3R = max(tp1R, max(tp2R, tp3R))
    fixedTp2R = tp1R + tp2R + tp3R - fixedTp1R - fixedTp3R
    
    if useDynTp = 1 then
       // Floors proporcionales
       tp1Floor = dynTpFloorR1
       if fixedTp1R > 0.01 then
          tp2Floor = dynTpFloorR1 * (fixedTp2R / fixedTp1R)
          tp3Floor = dynTpFloorR1 * (fixedTp3R / fixedTp1R)
       else
          tp2Floor = dynTpFloorR1
          tp3Floor = dynTpFloorR1
       endif
       effTp1R = min(dynTpCeilR3, max(tp1Floor, fixedTp1R * finalScale))
       effTp2R = min(dynTpCeilR3, max(tp2Floor, fixedTp2R * finalScale))
       effTp3R = min(dynTpCeilR3, max(tp3Floor, fixedTp3R * finalScale))
       // Re-sort tras scaling
       sTp1 = min(effTp1R, min(effTp2R, effTp3R))
       sTp3 = max(effTp1R, max(effTp2R, effTp3R))
       sTp2 = effTp1R + effTp2R + effTp3R - sTp1 - sTp3
       liveTp1R = sTp1
       liveTp2R = sTp2
       liveTp3R = sTp3
    else
       liveTp1R = fixedTp1R
       liveTp2R = fixedTp2R
       liveTp3R = fixedTp3R
    endif
    
    //==========================================================
    // 9. ACTIVE TRADE STATE (solo 1 señal viva a la vez)
    //==========================================================
    once tradeDir      = 0
    once tradeClosed   = 1   // 1 = no hay trade vivo; se pone a 0 al abrir
    once tradeEntryBar = 0
    once tradeEntry    = 0
    once tradeSl       = 0
    once tradeTp1      = 0
    once tradeTp2      = 0
    once tradeTp3      = 0
    once tradeTp1R     = 1.0
    once tradeTp2R     = 2.0
    once tradeTp3R     = 3.0
    once hitTp1        = 0
    once hitTp2        = 0
    once hitTp3        = 0
    once tradeCellIdx  = -1
    
    confirmedBuy  = flipUp and isWarm
    confirmedSell = flipDn and isWarm
    
    if confirmedBuy then
       tEntry = close
       // SL basado en el último pivot low (réplica Pine): el más conservador entre pivot-SL y close-SL
       if lastPivotLow > 0 then
          slBase = lastPivotLow
       else
          slBase = low
       endif
       rawSl = slBase - slAtrMult * atrValue
       minSl = close  - slAtrMult * atrValue
       tSl   = min(rawSl, minSl)
       risk  = tEntry - tSl
       tradeDir      = 1
       tradeClosed   = 0
       tradeEntryBar = barindex
       tradeEntry    = tEntry
       tradeSl       = tSl
       tradeTp1      = tEntry + risk * liveTp1R
       tradeTp2      = tEntry + risk * liveTp2R
       tradeTp3      = tEntry + risk * liveTp3R
       tradeTp1R     = liveTp1R
       tradeTp2R     = liveTp2R
       tradeTp3R     = liveTp3R
       hitTp1        = 0
       hitTp2        = 0
       hitTp3        = 0
    endif
    
    if confirmedSell then
       tEntry = close
       // SL basado en el último pivot high (réplica Pine): el más conservador entre pivot-SL y close-SL
       if lastPivotHigh > 0 then
          slBase = lastPivotHigh
       else
          slBase = high
       endif
       rawSl = slBase + slAtrMult * atrValue
       minSl = close  + slAtrMult * atrValue
       tSl   = max(rawSl, minSl)
       risk  = tSl - tEntry
       tradeDir      = -1
       tradeClosed   = 0
       tradeEntryBar = barindex
       tradeEntry    = tEntry
       tradeSl       = tSl
       tradeTp1      = tEntry - risk * liveTp1R
       tradeTp2      = tEntry - risk * liveTp2R
       tradeTp3      = tEntry - risk * liveTp3R
       tradeTp1R     = liveTp1R
       tradeTp2R     = liveTp2R
       tradeTp3R     = liveTp3R
       hitTp1        = 0
       hitTp2        = 0
       hitTp3        = 0
    endif
    
    //==========================================================
    // 10. HIT DETECTION + REALIZED R + LEARNING
    //==========================================================
    // Rolling buffer de últimas maxHistory señales cerradas (array $sigR)
    once writeIdx = 0         // puntero rotante 0..maxHistory-1
    once bufFilled = 0        // cuántos slots llenos (hasta maxHistory)
    once winStreak = 0
    once lossStreak = 0
    once maxWinStreak = 0
    once maxLossStreak = 0
    once allCount = 0
    once allRSum = 0
    once allCumR = 0
    once allPeak = 0
    once allTrough = 0
    once signalsSinceCalib = 0
    
    // Regime grid (3×3): idx = erBin*3 + volBin
    once gridC0 = 0
    once gridC1 = 0
    once gridC2 = 0
    once gridC3 = 0
    once gridC4 = 0
    once gridC5 = 0
    once gridC6 = 0
    once gridC7 = 0
    once gridC8 = 0
    once gridE0 = 0
    once gridE1 = 0
    once gridE2 = 0
    once gridE3 = 0
    once gridE4 = 0
    once gridE5 = 0
    once gridE6 = 0
    once gridE7 = 0
    once gridE8 = 0
    
    // Bin del regime actual (para clasificar la señal que se abre)
    if erValue < erLow then
       curErBin = 0
    elsif erValue < erHigh then
       curErBin = 1
    else
       curErBin = 2
    endif
    if volRatio < volLow then
       curVolBin = 0
    elsif volRatio < volHigh then
       curVolBin = 1
    else
       curVolBin = 2
    endif
    curCell = curErBin * 3 + curVolBin
    
    // Memorizar cell del trade cuando abre
    if confirmedBuy or confirmedSell then
       tradeCellIdx = curCell
    endif
    
    if (tradeDir <> 0) and (tradeClosed = 0) and (barindex > tradeEntryBar) then
       if tradeDir = 1 then
          tp1Reached = high >= tradeTp1
          tp2Reached = high >= tradeTp2
          tp3Reached = high >= tradeTp3
          slHit      = low  <= tradeSl
       else
          tp1Reached = low <= tradeTp1
          tp2Reached = low <= tradeTp2
          tp3Reached = low <= tradeTp3
          slHit      = high >= tradeSl
       endif
       
       if tp1Reached and (hitTp1 = 0) then
          hitTp1 = 1
       endif
       if tp2Reached and (hitTp2 = 0) then
          hitTp2 = 1
       endif
       if tp3Reached and (hitTp3 = 0) then
          hitTp3 = 1
       endif
       
       tradeAge = barindex - tradeEntryBar
       timeoutHit = tradeAge >= tradeMaxAge
       
       if (hitTp3 = 1) or slHit or timeoutHit then
          // Calcular realized R (fórmula Pine: 1/3 por tramo)
          if hitTp3 = 1 then
             realizedR = (tradeTp1R + tradeTp2R + tradeTp3R) / 3.0
          elsif slHit then
             taken = 0
             remaining = 1.0
             if hitTp1 = 1 then
                taken = taken + (1.0/3.0) * tradeTp1R
                remaining = remaining - (1.0/3.0)
             endif
             if hitTp2 = 1 then
                taken = taken + (1.0/3.0) * tradeTp2R
                remaining = remaining - (1.0/3.0)
             endif
             realizedR = taken + remaining * (-1.0)
          else
             // timeout: solo suma los TPs tocados
             taken = 0
             if hitTp1 = 1 then
                taken = taken + (1.0/3.0) * tradeTp1R
             endif
             if hitTp2 = 1 then
                taken = taken + (1.0/3.0) * tradeTp2R
             endif
             if hitTp3 = 1 then
                taken = taken + (1.0/3.0) * tradeTp3R
             endif
             realizedR = taken
          endif
          // Clamp
          realizedR = max(-1.0, min(tradeTp3R, realizedR))
          
          // Push al buffer rotante
          $sigR[writeIdx] = realizedR
          writeIdx = writeIdx + 1
          if writeIdx >= maxHistory then
             writeIdx = 0
          endif
          if bufFilled < maxHistory then
             bufFilled = bufFilled + 1
          endif
          
          // Stats acumuladas
          allRSum = allRSum + realizedR
          allCount = allCount + 1
          allCumR = allCumR + realizedR
          if allCumR > allPeak then
             allPeak = allCumR
          endif
          curDD = allCumR - allPeak
          if curDD < allTrough then
             allTrough = curDD
          endif
          if realizedR > 0 then
             winStreak = winStreak + 1
             lossStreak = 0
             if winStreak > maxWinStreak then
                maxWinStreak = winStreak
             endif
          else
             lossStreak = lossStreak + 1
             winStreak = 0
             if lossStreak > maxLossStreak then
                maxLossStreak = lossStreak
             endif
          endif
          
          // Grid 3×3 EWMA update (despiadadamente manual por falta de arrays anidados)
          if tradeCellIdx = 0 then
             gridC0 = gridC0 + 1
             if gridC0 = 1 then
                gridE0 = realizedR
             else
                gridE0 = gridE0*(1-ewmaAlpha) + realizedR*ewmaAlpha
             endif
          endif
          if tradeCellIdx = 1 then
             gridC1 = gridC1 + 1
             if gridC1 = 1 then
                gridE1 = realizedR
             else
                gridE1 = gridE1*(1-ewmaAlpha) + realizedR*ewmaAlpha
             endif
          endif
          if tradeCellIdx = 2 then
             gridC2 = gridC2 + 1
             if gridC2 = 1 then
                gridE2 = realizedR
             else
                gridE2 = gridE2*(1-ewmaAlpha) + realizedR*ewmaAlpha
             endif
          endif
          if tradeCellIdx = 3 then
             gridC3 = gridC3 + 1
             if gridC3 = 1 then
                gridE3 = realizedR
             else
                gridE3 = gridE3*(1-ewmaAlpha) + realizedR*ewmaAlpha
             endif
          endif
          if tradeCellIdx = 4 then
             gridC4 = gridC4 + 1
             if gridC4 = 1 then
                gridE4 = realizedR
             else
                gridE4 = gridE4*(1-ewmaAlpha) + realizedR*ewmaAlpha
             endif
          endif
          if tradeCellIdx = 5 then
             gridC5 = gridC5 + 1
             if gridC5 = 1 then
                gridE5 = realizedR
             else
                gridE5 = gridE5*(1-ewmaAlpha) + realizedR*ewmaAlpha
             endif
          endif
          if tradeCellIdx = 6 then
             gridC6 = gridC6 + 1
             if gridC6 = 1 then
                gridE6 = realizedR
             else
                gridE6 = gridE6*(1-ewmaAlpha) + realizedR*ewmaAlpha
             endif
          endif
          if tradeCellIdx = 7 then
             gridC7 = gridC7 + 1
             if gridC7 = 1 then
                gridE7 = realizedR
             else
                gridE7 = gridE7*(1-ewmaAlpha) + realizedR*ewmaAlpha
             endif
          endif
          if tradeCellIdx = 8 then
             gridC8 = gridC8 + 1
             if gridC8 = 1 then
                gridE8 = realizedR
             else
                gridE8 = gridE8*(1-ewmaAlpha) + realizedR*ewmaAlpha
             endif
          endif
          
          // Auto-calibración (simplificación 1: determinista histórico)
          signalsSinceCalib = signalsSinceCalib + 1
          if (useAutoCalib = 1) and (bufFilled >= calibWindow) and (signalsSinceCalib >= calibCooldown) then
             // Avg R de los últimos calibWindow samples del buffer
             sumR = 0
             cnt  = 0
             n = calibWindow
             if n > bufFilled then
                n = bufFilled
             endif
             // lee hacia atrás desde writeIdx (que apunta al próximo slot libre)
             for k = 1 to n do
                idx = writeIdx - k
                if idx < 0 then
                   idx = idx + maxHistory
                endif
                sumR = sumR + $sigR[idx]
                cnt = cnt + 1
             next
             if cnt > 0 then
                postAvgR = sumR / cnt
                if postAvgR < calibBadR then
                   if effQStrength > qualityStrength then
                      drift = 0 - calibStepQ
                   else
                      drift = calibStepQ
                   endif
                   effQStrength = min(calibMaxQ, max(calibMinQ, effQStrength + drift))
                   signalsSinceCalib = 0
                elsif postAvgR > calibGoodR then
                   signalsSinceCalib = 0
                endif
             endif
          endif
          
          // Cerrar trade (mantener tradeDir para que las líneas persistan en el dibujo)
          tradeClosed = 1
          tradeCellIdx = -1
       endif
    endif
    
    if useAutoCalib = 0 then
       effQStrength = qualityStrength
    endif
    
    //==========================================================
    // 11. ROLLING STATS (win-rate, avg R, window DD)
    //==========================================================
    n = calibWindow
    if n > bufFilled then
       n = bufFilled
    endif
    sumR2 = 0
    wins = 0
    runR = 0
    minRun = 0
    for k = 1 to n do
       idx = writeIdx - k
       if idx < 0 then
          idx = idx + maxHistory
       endif
       rVal = $sigR[idx]
       sumR2 = sumR2 + rVal
       if rVal > 0 then
          wins = wins + 1
       endif
       runR = runR + rVal
       if runR < minRun then
          minRun = runR
       endif
    next
    if n > 0 then
       rollWinRate = wins / n
       rollAvgR    = sumR2 / n
    else
       rollWinRate = 0
       rollAvgR    = 0
    endif
    rollWindowDD = minRun
    
    //==========================================================
    // 12. DRAW SIGNAL LABELS
    //==========================================================
    if showSignals = 1 then
       if confirmedBuy then
          // Flecha pegada al mínimo
          drawtext("▲", barindex, low - 0.15*rawAtr) coloured(0, 230, 118, 255)
          // Score junto a la flecha, debajo de stLine (que está debajo del precio en compra)
          drawtext("BUY #buyScoreInt#", barindex, stLine - 0.3*rawAtr) coloured(0, 230, 118, 255)
       endif
       if confirmedSell then
          // Flecha pegada al máximo
          drawtext("▼", barindex, high + 0.15*rawAtr) coloured(255, 82, 82, 255)
          // Score junto a la flecha, encima de stLine (que está encima del precio en venta)
          drawtext("SELL #sellScoreInt#", barindex, stLine + 0.3*rawAtr) coloured(255, 82, 82, 255)
       endif
    endif
    
    //==========================================================
    // 13. DRAW TP/SL LINES + etiquetas de precio al final
    //==========================================================
    if tradeDir <> 0 and islastbarupdate then
       xEnd   = barindex + labelOffsetBars
       xLabel = xEnd + 3
       // Redondeo a 2 decimales para texto (evita cola de floats feos)
       entryFmt = round(tradeEntry * 100) / 100
       slFmt    = round(tradeSl    * 100) / 100
       tp1Fmt   = round(tradeTp1   * 100) / 100
       tp2Fmt   = round(tradeTp2   * 100) / 100
       tp3Fmt   = round(tradeTp3   * 100) / 100
       
       // Entry
       drawsegment(tradeEntryBar, tradeEntry, xEnd, tradeEntry) coloured(150, 150, 150, 200)
       drawtext("Entry #entryFmt#", xLabel, tradeEntry) coloured(150, 150, 150, 255)
       // SL
       drawsegment(tradeEntryBar, tradeSl, xEnd, tradeSl) coloured(255, 23, 68, 255)
       drawtext("SL #slFmt#", xLabel, tradeSl) coloured(255, 23, 68, 255)
       // TPs (color distinto si ya tocado + marca ✓)
       if hitTp1 = 1 then
          drawsegment(tradeEntryBar, tradeTp1, xEnd, tradeTp1) coloured(64, 224, 208, 255)
          drawtext("TP1 #tp1Fmt# ✓", xLabel, tradeTp1) coloured(64, 224, 208, 255)
       else
          drawsegment(tradeEntryBar, tradeTp1, xEnd, tradeTp1) coloured(0, 230, 118, 200)
          drawtext("TP1 #tp1Fmt#", xLabel, tradeTp1) coloured(0, 230, 118, 255)
       endif
       if hitTp2 = 1 then
          drawsegment(tradeEntryBar, tradeTp2, xEnd, tradeTp2) coloured(64, 224, 208, 255)
          drawtext("TP2 #tp2Fmt# ✓", xLabel, tradeTp2) coloured(64, 224, 208, 255)
       else
          drawsegment(tradeEntryBar, tradeTp2, xEnd, tradeTp2) coloured(0, 230, 118, 200)
          drawtext("TP2 #tp2Fmt#", xLabel, tradeTp2) coloured(0, 230, 118, 255)
       endif
       if hitTp3 = 1 then
          drawsegment(tradeEntryBar, tradeTp3, xEnd, tradeTp3) coloured(64, 224, 208, 255)
          drawtext("TP3 #tp3Fmt# ✓", xLabel, tradeTp3) coloured(64, 224, 208, 255)
       else
          drawsegment(tradeEntryBar, tradeTp3, xEnd, tradeTp3) coloured(0, 230, 118, 255)
          drawtext("TP3 #tp3Fmt#", xLabel, tradeTp3) coloured(0, 230, 118, 255)
       endif
    endif
    
    //==========================================================
    // 14. DASHBOARD (fixed top-right, anchor)
    //==========================================================
    if showDash = 1 and islastbarupdate then
       // Header
       drawtext("SATS  v1.9", -200, -10) anchor(topright, xshift, yshift) coloured(255,255,255,255)
       // Trend
       if trendDir = 1 then
          drawtext("Trend: Bullish ▲", -200, -30) anchor(topright, xshift, yshift) coloured(0, 230, 118, 255)
       else
          drawtext("Trend: Bearish ▼", -200, -30) anchor(topright, xshift, yshift) coloured(255, 82, 82, 255)
       endif
       // TQI
       if tqi > 0.6 then
          tqR = 0
          tqG = 230
          tqB = 118
       elsif tqi > 0.35 then
          tqR = 255
          tqG = 235
          tqB = 59
       else
          tqR = 255
          tqG = 82
          tqB = 82
       endif
       drawtext("TQI: #tqi#", -200, -50) anchor(topright, xshift, yshift) coloured(tqR, tqG, tqB, 255)
       // Q.Strength (efectivo, puede diferir del input por calibración)
       drawtext("Q.Str: #effQStrength#", -200, -70) anchor(topright, xshift, yshift) coloured(220,220,220,255)
       // Regime ER
       if erValue >= erHigh then
          drawtext("Regime: Trending", -200, -90) anchor(topright, xshift, yshift) coloured(0, 230, 118, 255)
       elsif erValue >= erLow then
          drawtext("Regime: Mixed", -200, -90) anchor(topright, xshift, yshift) coloured(255, 235, 59, 255)
       else
          drawtext("Regime: Choppy", -200, -90) anchor(topright, xshift, yshift) coloured(255, 82, 82, 255)
       endif
       // Vol regime
       if volRatio < volLow then
          drawtext("Vol: Low", -200, -110) anchor(topright, xshift, yshift) coloured(150,150,255,255)
       elsif volRatio < volHigh then
          drawtext("Vol: Normal", -200, -110) anchor(topright, xshift, yshift) coloured(220,220,220,255)
       else
          drawtext("Vol: High", -200, -110) anchor(topright, xshift, yshift) coloured(255, 180, 100, 255)
       endif
       drawtext("ER: #erValue#", -200, -130) anchor(topright, xshift, yshift) coloured(220,220,220,255)
       drawtext("VolRatio: #volRatio#", -200, -150) anchor(topright, xshift, yshift) coloured(220,220,220,255)
       // TP mode
       if useDynTp = 1 then
          drawtext("TP: Dynamic ×#finalScale#", -200, -170) anchor(topright, xshift, yshift) coloured(100,200,255,255)
       else
          drawtext("TP: Fixed", -200, -170) anchor(topright, xshift, yshift) coloured(220,220,220,255)
       endif
       drawtext("R live: #liveTp1R# / #liveTp2R# / #liveTp3R#", -200, -190) anchor(topright, xshift, yshift) coloured(220,220,220,255)
       // Stats
       drawtext("Signals: #bufFilled#", -200, -220) anchor(topright, xshift, yshift) coloured(200,200,200,255)
       if bufFilled >= 5 then
          if rollWinRate >= 0.5 then
             wrR = 0
             wrG = 230
             wrB = 118
          else
             wrR = 255
             wrG = 82
             wrB = 82
          endif
       else
          wrR = 150
          wrG = 150
          wrB = 150
       endif
       wrPct = rollWinRate * 100
       drawtext("WinRate: #wrPct#%", -200, -240) anchor(topright, xshift, yshift) coloured(wrR, wrG, wrB, 255)
       if bufFilled >= 5 then
          if rollAvgR > 0 then
             arR = 0
             arG = 230
             arB = 118
          else
             arR = 255
             arG = 82
             arB = 82
          endif
       else
          arR = 150
          arG = 150
          arB = 150
       endif
       drawtext("AvgR: #rollAvgR#", -200, -260) anchor(topright, xshift, yshift) coloured(arR, arG, arB, 255)
       drawtext("WindowDD: #rollWindowDD#R", -200, -280) anchor(topright, xshift, yshift) coloured(220,220,220,255)
       drawtext("AllDD: #allTrough#R", -200, -300) anchor(topright, xshift, yshift) coloured(220,220,220,255)
       drawtext("Streak W:#winStreak# / max #maxWinStreak#", -200, -320) anchor(topright, xshift, yshift) coloured(0,230,118,255)
       drawtext("Streak L:#lossStreak# / max #maxLossStreak#", -200, -340) anchor(topright, xshift, yshift) coloured(255,82,82,255)
       // Current regime edge (de la celda actual)
       if curCell = 0 then
          regC = gridC0
          regE = gridE0
       elsif curCell = 1 then
          regC = gridC1
          regE = gridE1
       elsif curCell = 2 then
          regC = gridC2
          regE = gridE2
       elsif curCell = 3 then
          regC = gridC3
          regE = gridE3
       elsif curCell = 4 then
          regC = gridC4
          regE = gridE4
       elsif curCell = 5 then
          regC = gridC5
          regE = gridE5
       elsif curCell = 6 then
          regC = gridC6
          regE = gridE6
       elsif curCell = 7 then
          regC = gridC7
          regE = gridE7
       else
          regC = gridC8
          regE = gridE8
       endif
       drawtext("RegimeEdge: #regE#R (n=#regC#)", -200, -360) anchor(topright, xshift, yshift) coloured(220,220,220,255)
    endif
    
    //==========================================================
    // 15. PLOT: SuperTrend (patrón canónico PRT — ver PRC_Supertrend-TV)
    //==========================================================
    // UNA sola variable con coloured(r,g,b) dinámico. PRT pinta por tramos correctamente.
    if trendDir = 1 then
       stR = 0
       stG = 230
       stB = 118
    else
       stR = 255
       stG = 82
       stB = 82
    endif
    
    if isWarm then
       plotLine = stLine
    else
       plotLine = undefined
    endif
    
    return plotLine coloured(stR, stG, stB) style(line, 2) as "SuperTrend"
    


    ahenry thanked this post
    #260411 quote
    adeelq79adeelq79
    Participant
    Senior

    Hi Ivan, this is amazing thanks. However the ‘buy’ and ‘sell’ labels dont seem to print on the chart. Any ideas?

    #260525 quote
    Iván GonzálezIván González
    Moderator
    Legend
    #260544 quote
    adeelq79adeelq79
    Participant
    Senior

    Got it, it works on shares but not indicies like DOW or DAX.

    #264735 quote
    adeelq79adeelq79
    Participant
    Senior

    Hi Ivan,


    Is thee anything I can try to get this working on Indicies like the DOW?

Viewing 6 posts - 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.
ProRealAI ProRealAI New

Stuck on this ProBuilder code?

Describe what this topic is trying to build, in plain English, and ProRealAI writes the ProRealTime™ indicator, screener or system for you.

Available in 7 languages
Try ProRealAI

TradingView to ProRealTime Translation Center

New Reply
Author
author-avatar
ahenry @ahenry Participant
Summary

This topic contains 5 replies,
has 3 voices, and was last updated by adeelq79adeelq79
2 months ago.

Topic Details
Forum: TradingView to ProRealTime Translation Center Forum
Started: 04/18/2026
Status: Active
Attachments: 1 files
ProRealCode ProRealCode
Loading...