FRAMA CHANNEL

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #262924 quote
    brian gilbertbrian gilbert
    Participant
    Senior
    Good evening, here I am again: over the weekend, I came across an interesting indicator on TW called "FRAMA CHANNEL," and I’ve included both the page link and the code below. As always, thank you in advance for your help in converting it for PRT.
    https://www.tradingview.com/script/hskyfPWP-FRAMA-Channel-BigBeluga/
    
    // This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International  
    // https://creativecommons.org/licenses/by-nc-sa/4.0/
    // © BigBeluga
    
    
    
    
    //@version=5
    indicator("FRAMA Channel [BigBeluga]", overlay=true, max_labels_count = 500)
    
    
    // INPUTS --------------------------------------------------------------------------------------------------------{
    // User Inputs for FRAMA Channel
    int    N          = input.int   (26, title="Length", minval=2, step = 2, group = "Channel") // Length for FRAMA calculation
    float  distance   = input.float (1.5, "Bands Distance", step = 0.01, minval = 0.3, group = "Channel") // Distance for channel bands
    string price_vol  = input.string("Price", "Signals Data", ["Price", "Average Volume"]) // Source data for signals
    string labl_size  = input.string("Small", "Lables Size", ["Small", "Normal", "Large"])
    
    
    // Colors
    group = "Colors"
    color color1     = input.color(#27e27b, "Momentum Up", group = group, inline = "1") // Color for upward momentum
    color color2     = input.color(color.rgb(39, 114, 226), "Down", group = group, inline = "1") // Color for downward momentum
    color color3     = input.color(#a2b5ca, "Neutral", group = group) // Color for neutral state
    var color color  = color(na) // Variable to hold the current color
    
    
    bool  candles    = input.bool  (true, "Color Candles") // Toggle for coloring candles based on momentum
    
    
    // Source for FRAMA calculation
    series float price = hl2 // Use hl2 as the default source
    
    
    // Variables for FRAMA calculation
    var float Filt   = na
    var float Filt1  = na
    var float Filt2  = na
    var int   count1 = na
    var int   count2 = na
    // }
    
    
    // UDTs----------------------------------------------------------------------------------------------------------------{
    // Define a user-defined type (UDT) to store variables used in FRAMA calculation
    type vars 
        float N1
        float N2
        float N3
        float HH
        float LL
        float Dimen 
        float alpha
    
    
    // Initialize UDT instance
    v = vars.new(0., 0., 0., 0., 0., 0., 0.)
    // }
    
    
    
    
    // CALCULATIONS----------------------------------------------------------------------------------------------{
    // Perform calculations for the FRAMA Channel
    series float volatility = ta.sma(high - low, 200) // Calculate volatility using the average true range
    series float p_vol      = switch price_vol // Select the data source for signals (Price or Average Volume)
        "Price"             => close
        "Average Volume"    => math.round(math.sum(volume, 10) / 10, 2)
    
    
    // Calculate N3 for the fractal dimension
    v.N3 := (ta.highest(high, N) - ta.lowest(low, N)) / N
    
    
    // Loop to calculate N1
    v.HH := high
    v.LL := low
    
    
    for count = 0 to N / 2 - 1
        if high[count] > v.HH
            v.HH := high[count]
        if low[count] < v.LL
            v.LL := low[count]
    
    
    v.N1 := (v.HH - v.LL) / (N / 2)
    
    
    // Loop to calculate N2
    v.HH := high[N / 2]
    v.LL := low[N / 2]
    
    
    for count = N / 2 to N - 1
        if high[count] > v.HH
            v.HH := high[count]
        if low[count] < v.LL
            v.LL := low[count]
    
    
    v.N2 := (v.HH - v.LL) / (N / 2)
    
    
    // Calculate the fractal dimension
    if (v.N1 > 0 and v.N2 > 0 and v.N3 > 0)
        v.Dimen := (math.log(v.N1 + v.N2) - math.log(v.N3)) / math.log(2)
    
    
    // Calculate alpha for FRAMA
    v.alpha := math.exp(-4.6 * (v.Dimen - 1))
    v.alpha := math.max(math.min(v.alpha, 1), 0.01) // Clamp alpha between 0.01 and 1
    
    
    // Calculate the FRAMA filtered value
    Filt  := na(Filt) 
              ? price 
              : v.alpha * price + (1 - v.alpha) * Filt[1]
    
    
    Filt  := ta.sma((bar_index < N + 1) ? price : Filt, 5) // Apply SMA for smoothing
    
    
    // Calculate the channel bands
    Filt1 := Filt + volatility * distance
    Filt2 := Filt - volatility * distance
    // }
    
    
    
    
    // PLOT-------------------------------------------------------------------------------------------------------------{
    // Define conditions for plotting and coloring
    break_up = ta.crossover(hlc3, Filt1) and barstate.isconfirmed
    break_dn = ta.crossunder(hlc3, Filt2) and barstate.isconfirmed
    
    
    if ta.cross(close, Filt)
        color := color3 // Neutral color 
    
    
    // Determine the color based on breakout conditions
    switch 
        break_up => color := color1 // Upward breakout
        break_dn => color := color2 // Downward breakout
    
    
    // Set candle color if enabled
    color color_c = candles ? color : na
    
    
    // Plot the FRAMA and bands
    p0 = plot(Filt,  color = color.new(color,color == color3 ? 100 : 50),  editable = false)
    p1 = plot(Filt1, color = color.new(color,20), linewidth = 1, editable = false)
    p2 = plot(Filt2, color = color.new(color,20), linewidth = 1, editable = false)
    
    
    // Fill the area between the bands and FRAMA
    fill(p1, p0, Filt1, Filt, color.new(color, candles ? 95 : 85), na, editable = false)
    fill(p0, p2, Filt, Filt2, na, color.new(color, candles ? 95 : 85), editable = false)
    
    
    size = switch labl_size
        "Small"  => size.small
        "Normal" => size.normal
        "Large"  => size.large
    
    
    // Add labels on breakout events
    if break_up
        count2 := 0
        count1 += 1 
        if count1 == 1
            label.new(
                      x         = bar_index,
                      y         = Filt2, 
                      text      = "🢁n" + str.tostring(p_vol),
                      style     = label.style_label_up,
                      textcolor = color1, 
                      color     = color(na), 
                      size = size
                      )
    
    
    if break_dn
        count1 := 0 
        count2 += 1
        if count2 == 1
            label.new(
                      x         = bar_index,
                      y         = Filt1, 
                      text      = str.tostring(p_vol) + "n🢃",
                      style     = label.style_label_down,
                      textcolor = color2, 
                      color     = color(na), 
                      size      = size
                      )
    
    
    // Plot candles with the calculated colors
    plotcandle(
                 open, high, low, close, 
                 "Candles", 
                 color_c,
                 color_c, 
                 bordercolor = color_c, 
                 editable    = false
                 )
    // }
    
    
    


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

    Hi, here is the code:

    //----------------------------------------------
    //PRC_FRAMA Channel
    //version = 0
    //27.07.26
    //Ivan Gonzalez @ www.prorealcode.com
    //Sharing ProRealTime knowledge
    //----------------------------------------------
    // === PARAMETERS ===
    //----------------------------------------------
    N            = 26    // FRAMA length (use an EVEN value, minimum 2)
    bandDist     = 1.5   // band distance (multiple of the volatility unit)
    volPeriod    = 200   // lookback of the high-low range average
    signalData   = 0     // 0 = closing price on the label, 1 = 10-bar average volume
    showLabels   = 1     // 1 = arrows on breakouts
    colorCandles = 1     // 1 = repaint candles with the momentum colour
    //----------------------------------------------
    // === COLOURS (RGB + alpha, 0=transparent 255=opaque) ===
    //----------------------------------------------
    upR = 39     // bullish momentum
    upG = 226
    upB = 123
    dnR = 39     // bearish momentum
    dnG = 114
    dnB = 226
    nuR = 162    // neutral
    nuG = 181
    nuB = 202
    //----------------------------------------------
    // === FRACTAL DIMENSION ===
    //----------------------------------------------
    srcHL = (high + low) / 2
    half  = max(1, floor(N / 2))
    warm  = max(N, 5)
    
    
    n3 = (highest[N](high) - lowest[N](low)) / N
    n1 = (highest[half](high) - lowest[half](low)) / half
    n2 = (highest[half](high)[half] - lowest[half](low)[half]) / half
    
    
    dimen = 0
    if n1 > 0 and n2 > 0 and n3 > 0 then
        dimen = (log(n1 + n2) - log(n3)) / log(2)
    endif
    
    
    alph = exp(-4.6 * (dimen - 1))
    alph = max(min(alph, 1), 0.01)
    //----------------------------------------------
    // === ADAPTIVE FILTER + 5-BAR SMOOTHING ===
    // rawf feeds back the ALREADY smoothed filt of the previous bar
    //----------------------------------------------
    if barindex <= warm then
        rawf = srcHL
        filt = srcHL
    else
        rawf = alph * srcHL + (1 - alph) * filt[1]
        filt = (rawf + rawf[1] + rawf[2] + rawf[3] + rawf[4]) / 5
    endif
    //----------------------------------------------
    // === BANDS ===
    //----------------------------------------------
    volat  = average[volPeriod](high - low)
    bandUp = filt + volat * bandDist
    bandDn = filt - volat * bandDist
    //----------------------------------------------
    // === BREAKOUTS AND MOMENTUM STATE ===
    //----------------------------------------------
    src3 = (high + low + close) / 3
    
    
    breakUp = 0
    breakDn = 0
    if src3 crosses over bandUp then
        breakUp = 1
    endif
    if src3 crosses under bandDn then
        breakDn = 1
    endif
    
    
    if barindex <= warm then
        trendState = 0
    else
        trendState = trendState[1]
        if (close crosses over filt) or (close crosses under filt) then
            trendState = 0
        endif
        if breakUp = 1 then
            trendState = 1
        endif
        if breakDn = 1 then
            trendState = -1
        endif
    endif
    
    
    if trendState = 1 then
        cr = upR
        cg = upG
        cb = upB
    elsif trendState = -1 then
        cr = dnR
        cg = dnG
        cb = dnB
    else
        cr = nuR
        cg = nuG
        cb = nuB
    endif
    
    
    // the central line is hidden while the state is neutral
    if trendState = 0 then
        aMid = 0
    else
        aMid = 130
    endif
    
    
    if colorCandles = 1 then
        aFill = 25
    else
        aFill = 50
    endif
    //----------------------------------------------
    // === COUNTERS: only the FIRST breakout of each sequence ===
    //----------------------------------------------
    if barindex <= warm then
        cntUp = 0
        cntDn = 0
    else
        cntUp = cntUp[1]
        cntDn = cntDn[1]
        if breakUp = 1 then
            cntDn = 0
            cntUp = cntUp + 1
        endif
        if breakDn = 1 then
            cntUp = 0
            cntDn = cntDn + 1
        endif
    endif
    //----------------------------------------------
    // === LABELS ===
    //----------------------------------------------
    if signalData = 1 then
        pv = round(average[10](volume))
    else
        pv = round(close * 100) / 100
    endif
    
    
    offs = volat * 0.4
    
    
    if showLabels = 1 and breakUp = 1 and cntUp = 1 then
        drawtext("▲", barindex, bandDn - offs, SansSerif, Bold, 11) coloured(upR, upG, upB, 255)
        drawtext("#pv#", barindex, bandDn - offs * 2.2, SansSerif, Bold, 10) coloured(upR, upG, upB, 255)
    endif
    
    
    if showLabels = 1 and breakDn = 1 and cntDn = 1 then
        drawtext("#pv#", barindex, bandUp + offs * 2.2, SansSerif, Bold, 10) coloured(dnR, dnG, dnB, 255)
        drawtext("▼", barindex, bandUp + offs, SansSerif, Bold, 11) coloured(dnR, dnG, dnB, 255)
    endif
    //----------------------------------------------
    // === CANDLES AND FILL ===
    //----------------------------------------------
    if colorCandles = 1 then
        drawcandle(open, high, low, close) coloured(cr, cg, cb)
    endif
    
    
    colorbetween(bandUp, bandDn, cr, cg, cb, aFill)
    //----------------------------------------------
    return filt coloured(cr, cg, cb, aMid) style(line, 2) as "FRAMA", bandUp coloured(cr, cg, cb, 205) as "Upper band", bandDn coloured(cr, cg, cb, 205) as "Lower band"
    


    brian gilbert thanked this post
    #262944 quote
    brian gilbertbrian gilbert
    Participant
    Senior
    It’s incredible how quick and efficient you are. 
    Thanks so much, and have a great day!
    


Viewing 3 posts - 1 through 3 (of 3 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
Summary

This topic contains 2 replies,
has 2 voices, and was last updated by brian gilbertbrian gilbert
2 months ago.

Topic Details
Forum: TradingView to ProRealTime Translation Center Forum
Started: 07/26/2026
Status: Active
Attachments: No files
ProRealCode ProRealCode
Loading...