Self-Aware Trend System [WillyAlgoTrader]

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #260317 quote
    ahenry
    Participant
    Junior

    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ález
    Moderator
    Master

    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"
    


    #260411 quote
    adeelq79
    Participant
    Average

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

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

TradingView to ProRealTime Translation Center

New Reply
Author
author-avatar
ahenry @ahenry Participant
Summary

This topic contains 2 replies,
has 3 voices, and was last updated by adeelq79
11 hours, 58 minutes ago.

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