Fractal Trail Algorithm Conversion

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #243428 quote
    jogttjogtt
    Participant
    New

    Hi All,

    I have found a very interesting Fractal Trail Algorithm based on Williams Fractals. The code is in Pine v5.0 and available for TradingView. You can find a comprehensive description in the following link:

    https://es.tradingview.com/script/kAAGPpsC-Fractal-Trail-UAlgo/

    I have attempted translating the code into Pro Real Code with the help of Chat GPT. Nonetheless, the results I am getting for the same assets and parameters are different in both TW and PRT as you can see in the images attached, so I reckon I am not properly capturing the indicator’s logic. This is what I have so far:

    // --- Fractal Trail Indicator for ProRealTime (ProBuilder) --- 
    
    // --- User Inputs ---
    WilliamsLeftRange  = 2  // Number of bars to the left
    WilliamsRightRange = 2  // Number of bars to the right
    WilliamsStopBuffer = 0  // Stop buffer percentage
    
    // --- Fractal Detection ---
    FractalHigh = 0
    FractalLow = 0
    
    // --- Identify High Fractal (Delayed Confirmation) ---
    IF High[WilliamsRightRange] >= Highest[WilliamsLeftRange + WilliamsRightRange](High) AND High[WilliamsRightRange] <> High[WilliamsRightRange+1] THEN
        FractalHigh = High[WilliamsRightRange]
    ENDIF
    
    // --- Identify Low Fractal (Delayed Confirmation) ---
    IF Low[WilliamsRightRange] <= Lowest[WilliamsLeftRange + WilliamsRightRange](Low) AND Low[WilliamsRightRange] <> Low[WilliamsRightRange+1] THEN
        FractalLow = Low[WilliamsRightRange]
    ENDIF
    
    // --- Apply Stop Buffer (Only After Fractal Confirmation) ---
    FractalLowBuffered  = FractalLow * (1 - WilliamsStopBuffer / 100)
    FractalHighBuffered = FractalHigh * (1 + WilliamsStopBuffer / 100)
    
    // --- Persistent Stop Logic ---
    ONCE ActiveStop = 0
    ONCE TrendDirection = 0  // 1 = Long, -1 = Short, 0 = Neutral
    
    // --- Ensure Stops Persist & Only Move in Favorable Direction ---
    IF FractalLow > 0 THEN
        IF TrendDirection <> 1 THEN  
            ActiveStop = FractalLowBuffered  // Flip to long stop only if not already long
            TrendDirection = 1
        ELSE  
            ActiveStop = MAX(ActiveStop, FractalLowBuffered)  // Update only if it moves up
        ENDIF
    ENDIF
    
    IF FractalHigh > 0 THEN
        IF TrendDirection <> -1 THEN  
            ActiveStop = FractalHighBuffered  // Flip to short stop only if not already short
            TrendDirection = -1
        ELSE  
            ActiveStop = MIN(ActiveStop, FractalHighBuffered)  // Update only if it moves down
        ENDIF
    ENDIF
    
    // --- Plot Only the Active Stop ---
    RETURN ActiveStop AS "Fractal Trailing Stop"
    

    Would anyone be interested in checking the code I have produced or translating the code directly into Pro Real Code?

    Many thanks in advance for your support!

    Capture_PRT_Fractal.png Capture_PRT_Fractal.png Capture_tw_Fractal.png Capture_tw_Fractal.png
    #243588 quote
    jogttjogtt
    Participant
    New

    Anyone could give me hand with the code conversion, please? For your convenience, I am attaching below the original code from TradingView together with another caption of the indicator:

    // This Pine Script™ code is subject to the terms of the Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
    // © UAlgo
    //@version=5
    indicator(title=’Fractal Trail [UAlgo]’, shorttitle=’Fractal Trail [UAlgo]’, overlay=true)

    bool showWilliamsFractals = input.bool(defval=true, title=’Show All Williams Fractals’, group=”Fractal Trail [UAlgo]”, tooltip=’Places triangle indicators to mark each Williams fractal position’)
    bool showWilliamsStops = input.bool(defval=true, title=’Show Williams Trail’, tooltip=’Creates a dynamic trailing stop based on the latest identified fractal’, group=”Fractal Trail [UAlgo]”)
    int williamsLeftRange = input.int(defval=2, minval=1, maxval=50, title=’Williams Fractal Range Left/Right’, group=”Fractal Trail [UAlgo]”, tooltip=’Specifies the number of previous bars to analyze for the range. Standard setting is two bars in both directions.’,inline = “range”)
    int williamsRightRange = input.int(defval=2, minval=1, maxval=50, title=’ ‘, tooltip=’Determines the number of forward bars to examine for the range. Best practice suggests matching the backward range value.’, group=”Fractal Trail [UAlgo]”,inline = “range”)
    float williamsStopBuffer = input.float(defval=0, minval=0, maxval=20, step=0.5, title=’Trail Buffer Percent (%)’, group=”Fractal Trail [UAlgo]”, tooltip=’Sets a percentage-based safety margin between the fractal price and the trailing stop’)
    string flipInput = input.string(title=’Trail Invalidation Source’, defval=’Close’, options=[‘Close’, ‘Wick’], tooltip=’Determines whether the trail flips based on candle closing prices or extreme points (high/low)’, group=”Fractal Trail [UAlgo]”)
    color upTrailColor = input.color(defval=color.rgb(40, 218, 150), title=’Up/Down Trail Color’, group=”Fractal Trail [UAlgo]”,inline = “trailC”)
    color dnTrailColor = input.color(defval=color.new(color.blue, 0), title=’ ‘, group=”Fractal Trail [UAlgo]”,inline = “trailC”)
    color fillColorUp = color.new(color.rgb(40, 218, 150), 80)
    color fillColorDn = color.new(color.blue, 80)

    f_IsWilliamsFractal(_leftRange, _rightRange, _type) =>
    _isFractal = _type == ‘high’ and high[_rightRange] >= ta.highest(high, _leftRange + _rightRange + 1) or _type == ‘low’ and low[_rightRange] <= ta.lowest(low, _leftRange + _rightRange + 1)
    _fractalValue = _isFractal and _type == ‘high’ ? high[_rightRange] : _isFractal and _type == ‘low’ ? low[_rightRange] : na
    [_isFractal, _fractalValue]

    [isHighFractal, highFractalPrice] = f_IsWilliamsFractal(williamsLeftRange, williamsRightRange, ‘high’)
    [isLowFractal, lowFractalPrice] = f_IsWilliamsFractal(williamsLeftRange, williamsRightRange, ‘low’)

    isHighFractal := isHighFractal[1] ? false : isHighFractal
    isLowFractal := isLowFractal[1] ? false : isLowFractal

    highFractalOffset = 0 – williamsRightRange
    color white10 = color.new(color.white, 10)
    plotshape(isHighFractal and showWilliamsFractals, title=’Shape for Williams High’, style=shape.triangledown, location=location.abovebar, color=white10, size=size.tiny, offset=highFractalOffset)
    lowFractalOffset = 0 – williamsRightRange
    plotshape(isLowFractal and showWilliamsFractals, title=’Shape for Williams Low’, style=shape.triangleup, location=location.belowbar, color=white10, size=size.tiny, offset=lowFractalOffset)

    f_addPercentBuffer(_input, _buffer, _direction) =>
    _direction == ‘plus’ ? _input * (1 + _buffer / 100) : _direction == ‘minus’ ? _input * (1 – _buffer / 100) : na

    lowFractalPriceBuffered = f_addPercentBuffer(lowFractalPrice, williamsStopBuffer, ‘minus’)
    highFractalPriceBuffered = f_addPercentBuffer(highFractalPrice, williamsStopBuffer, ‘plus’)

    f_persistAndReset(_trigger, _source) =>
    var float _output = 0.0
    _output := _trigger ? _source : _output[1]
    _output

    longStopPrice = f_persistAndReset(isLowFractal, lowFractalPriceBuffered)
    shortStopPrice = f_persistAndReset(isHighFractal, highFractalPriceBuffered)

    f_trail(_source, _trail, _direction) =>
    _direction == ‘down’ and _source >= _trail[1] ? _trail : _direction == ‘up’ and _source <= _trail[1] ? _trail : _source

    var float longStopPriceTrail = longStopPrice
    var float shortStopPriceTrail = shortStopPrice

    shortStopPriceTrail := f_trail(shortStopPrice, shortStopPriceTrail, ‘down’)
    longStopPriceTrail := f_trail(longStopPrice, longStopPriceTrail, ‘up’)

    f_flip(_flipInput, _longTrail, _shortTrail, _longReset, _shortReset) =>
    var bool _flipLongNow = false
    var bool _flipShortNow = false
    var bool _isLong = true
    var bool _isShort = true
    float _flipLongSource = _flipInput == ‘Close’ ? close : _flipInput == ‘Wick’ ? high : na
    float _flipShortSource = _flipInput == ‘Close’ ? close : _flipInput == ‘Wick’ ? low : na
    _flipLongNow := _isShort[1] and _flipLongSource > _shortTrail ? true : false
    _flipShortNow := _isLong[1] and _flipShortSource < _longTrail ? true : false
    _flipLongNow := _flipShortNow and _flipLongNow and close > _longTrail ? true : _flipShortNow and _flipLongNow and close <= _longTrail ? false : _flipLongNow
    _flipShortNow := _flipLongNow and _flipShortNow and close < _shortTrail ? true : _flipShortNow and _flipLongNow and close >= _shortTrail ? false : _flipShortNow
    _isLong := _flipLongNow ? true : _flipShortNow ? false : na(_isLong[1]) ? true : _isLong[1]
    _isShort := _flipShortNow ? true : _flipLongNow ? false : na(_isShort[1]) ? true : _isShort[1]
    _longTrailOutput = _longTrail
    _shortTrailOutput = _shortTrail
    _longTrailOutput := _isLong and not _isLong[1] ? _longReset : _longTrailOutput
    _shortTrailOutput := _isShort and not _isShort[1] ? _shortReset : _shortTrailOutput
    float _longTrailPlot = _isLong ? _longTrailOutput : _isLong and _isShort ? _longTrailOutput : na
    float _shortTrailPlot = _isShort ? _shortTrailOutput : _isLong and _isShort ? _shortTrailOutput : na
    [_longTrailOutput, _shortTrailOutput, _longTrailPlot, _shortTrailPlot]

    f_getFlipResetWilliamsLong(_longTrail, _buffer, _isLowFractal, _rightRange) =>
    _barIndexWhenLastFractalConfirmed = ta.valuewhen(_isLowFractal, bar_index, 0)
    _barsSinceLastFractalConfirmed = bar_index – _barIndexWhenLastFractalConfirmed
    int _barsToGoBack = _barsSinceLastFractalConfirmed + _rightRange
    float _lowestLow = low
    for i = 0 to _barsToGoBack by 1
    _lowestLow := math.min(low[i], _lowestLow)
    _lowestLow
    _lowestLowAdjusted = _lowestLow * (1 – _buffer / 100)
    _lowestLowAdjusted

    f_getFlipResetWilliamsShort(_shortTrail, _buffer, _isHighFractal, _leftRange) =>
    _barIndexWhenLastFractalConfirmed = ta.valuewhen(_isHighFractal, bar_index, 0)
    _barsSinceLastFractalConfirmed = bar_index – _barIndexWhenLastFractalConfirmed
    int _barsToGoBack = _barsSinceLastFractalConfirmed + _leftRange
    float _highestHigh = high
    for i = 0 to _barsToGoBack by 1
    _highestHigh := math.max(high[i], _highestHigh)
    _highestHigh
    _highestHighAdjusted = _highestHigh * (1 + _buffer / 100)
    _highestHighAdjusted

    longStopPrice := f_getFlipResetWilliamsLong(longStopPrice, williamsStopBuffer, isLowFractal, williamsRightRange)
    shortStopPrice := f_getFlipResetWilliamsShort(shortStopPrice, williamsStopBuffer, isHighFractal, williamsLeftRange)

    [longStopPriceTrailTemp, shortStopPriceTrailTemp, longStopPriceTrailPlot, shortStopPriceTrailPlot] = f_flip(flipInput, longStopPriceTrail, shortStopPriceTrail, longStopPrice, shortStopPrice)

    longStopPriceTrail := longStopPriceTrailTemp
    shortStopPriceTrail := shortStopPriceTrailTemp

    shortStopPriceTrailPlotDisplay = showWilliamsStops ? shortStopPriceTrailPlot : na
    longStopPriceTrailPlotDisplay = showWilliamsStops ? longStopPriceTrailPlot : na

    plot(shortStopPriceTrailPlotDisplay, ‘Williams Trailing Stop High Price’, color=dnTrailColor, style=plot.style_linebr, linewidth=3)
    plot(shortStopPriceTrailPlotDisplay, ‘Williams Trailing Stop High Price Highlight’, color=dnTrailColor, style=plot.style_linebr, linewidth=1)
    plot(longStopPriceTrailPlotDisplay, ‘Williams Trailing Stop Low Price’, color=upTrailColor, style=plot.style_linebr, linewidth=3)
    plot(longStopPriceTrailPlotDisplay, ‘Williams Trailing Stop Low Price Highlight’, color=upTrailColor, style=plot.style_linebr, linewidth=1)

    pricefill = plot(hl2, ‘Midline’, color=color.gray, display=display.none)

    isUptrend = close < shortStopPriceTrailPlotDisplay
    isDowntrend = close > longStopPriceTrailPlotDisplay

    fillColor = isUptrend ? color.new(fillColorDn, 85) : color.new(fillColorUp, 85)
    fillPrice = isUptrend ? shortStopPriceTrailPlotDisplay : longStopPriceTrailPlotDisplay

    fill(plot(fillPrice, title=’Williams Trailing Stop Fill High’), pricefill, color=fillColor)

    alertCrossLongStop = na(longStopPriceTrailPlot) and not na(longStopPriceTrailPlot[1])
    alertCrossShortStop = na(shortStopPriceTrailPlot) and not na(shortStopPriceTrailPlot[1])
    alertcondition(alertCrossLongStop, title=’Crossed Williams Long Stop’, message=’Alert from Williams Fractal Trailing Stops: \n {{ticker}} price crossed long stop’)
    alertcondition(alertCrossShortStop, title=’Crossed Williams Short Stop’, message=’Alert from Williams Fractal Trailing Stops: \n {{ticker}} price crossed short stop’)

    alertcondition(isHighFractal, title=’High Printed’, message=’Alert from Williams Fractal Trailing Stops: \n {{ticker}} Williams High has been confirmed’)
    alertcondition(isLowFractal, title=’Low Printed’, message=’Alert from Williams Fractal Trailing Stops: \n {{ticker}} Williams Low has been confirmed’)

    Thanks!

    BTC_TD_Fractal.png BTC_TD_Fractal.png
    #244384 quote
    Iván GonzálezIván González
    Moderator
    Legend

    Here it is:

    //PRC_Fractal Trail Indicator
    //version = 0
    //26.02.2025
    //Iván González @ www.prorealcode.com
    //Sharing ProRealTime knowledge
    //----------------------------------------------//
    // CONFIGURATION PARAMETERS
    //----------------------------------------------//
    WilliamsLeftRange  = 2  // Number of bars to the left
    WilliamsRightRange = 2  // Number of bars to the right
    WilliamsStopBuffer = 0  // Stop margin percentage
    showWilliamsFractals = 1 // Display Williams Fractals
    flipInput = 1            // 1 -> Source = close, 0 -> Source = wick
    
    //----------------------------------------------//
    // INITIALIZATION OF VARIABLES
    //----------------------------------------------//
    once ShortStopPrice = high
    once LongStopPrice = low
    once ShortStopPriceTrail = ShortStopPrice
    once LongStopPriceTrail = LongStopPrice
    
    if barindex > 2 then  // Avoid errors in the first bars
    
    //----------------------------------------------//
    // FRACTAL DETECTION
    //----------------------------------------------//
    
    // Detect High Fractal (local maximum)
    isHighFractal = high[WilliamsRightRange] >= highest[WilliamsLeftRange + WilliamsRightRange + 1](high)
    if isHighFractal then
    HighFractalPrice = high[WilliamsRightRange]
    else
    HighFractalPrice = undefined
    endif
    if isHighFractal[1] then
    isHighFractal = 0
    endif
    
    // Detect Low Fractal (local minimum)
    isLowFractal = low[WilliamsRightRange] <= lowest[WilliamsLeftRange + WilliamsRightRange + 1](low)
    if isLowFractal then
    LowFractalPrice = low[WilliamsRightRange]
    else
    LowFractalPrice = undefined
    endif
    if isLowFractal[1] then
    isLowFractal = 0
    endif
    
    //----------------------------------------------//
    // FRACTAL VISUALIZATION ON THE CHART
    //----------------------------------------------//
    highFractalOffset = WilliamsRightRange
    if isHighFractal and showWilliamsFractals then
    drawtext("▼", barindex[highFractalOffset], high[highFractalOffset] + 0.15 * tr) coloured("grey",50)
    endif
    
    lowFractalOffset = WilliamsRightRange
    if isLowFractal and showWilliamsFractals then
    drawtext("▲", barindex[lowFractalOffset], low[lowFractalOffset] - 0.15 * tr) coloured("grey",50)
    endif
    
    //----------------------------------------------//
    // STOP LEVEL CALCULATION WITH BUFFER
    //----------------------------------------------//
    LowFractalPriceBuffered = LowFractalPrice * (1 - WilliamsStopBuffer / 100)
    HighFractalPriceBuffered = HighFractalPrice * (1 + WilliamsStopBuffer / 100)
    
    // Update stop levels when a new fractal is detected
    if isLowFractal then
    LongStopPrice = LowFractalPriceBuffered
    endif
    if isHighFractal then
    ShortStopPrice = HighFractalPriceBuffered
    endif
    
    //----------------------------------------------//
    // TRAILING STOP CALCULATION
    //----------------------------------------------//
    
    // The short stop only moves downward
    if ShortStopPrice < ShortStopPriceTrail[1] then
    ShortStopPriceTrail = ShortStopPrice
    else
    ShortStopPriceTrail = ShortStopPriceTrail[1]
    endif
    
    // The long stop only moves upward
    if LongStopPrice > LongStopPriceTrail[1] then
    LongStopPriceTrail = LongStopPrice
    else
    LongStopPriceTrail = LongStopPriceTrail[1]
    endif
    
    //----------------------------------------------//
    // FILTER TO PREVENT STOP REVERSALS
    //----------------------------------------------//
    // Adjust stop levels if there are sudden trend changes
    
    barsSinceLastLowFractalConfirmed = barssince(isLowFractal)
    lowestLow = low
    for i = 0 to barsSinceLastLowFractalConfirmed + WilliamsRightRange do
    lowestLow = min(low[i], lowestLow)
    next
    lowestLowAdjusted = lowestLow * (1 - WilliamsStopBuffer / 100)
    LongStopPrice = lowestLowAdjusted
    
    barsSinceLastHighFractalConfirmed = barssince(isHighFractal)
    highestHigh = high
    for i = 0 to barsSinceLastHighFractalConfirmed + WilliamsLeftRange do
    highestHigh = max(high[i], highestHigh)
    next
    highestHighAdjusted = highestHigh * (1 + WilliamsStopBuffer / 100)
    ShortStopPrice = highestHighAdjusted
    
    //----------------------------------------------//
    // TREND DEFINITION AND TRAIL STOP SELECTION
    //----------------------------------------------//
    if ShortStopPrice > ShortStopPrice[1] then
    trail = LongStopPrice
    trend = 1
    r = 40
    g = 218
    b = 150
    elsif LongStopPrice < LongStopPrice[1] then
    trail = ShortStopPrice
    trend = 0
    r = 0
    g = 0
    b = 255
    elsif trend = 1 and trend = trend[1] then
    trail = LongStopPrice
    else
    trail = ShortStopPrice
    endif
    
    endif  // Close the block that filters barindex > 2
    //----------------------------------------------//
    //  Cloud
    //----------------------------------------------//
    medPrice=(high+low)/2
    colorbetween(trail,medPrice,r,g,b,20)
    
    //----------------------------------------------//
    //  return
    //----------------------------------------------//
    return trail style(line,3) coloured(r,g,b)
    robertogozzi, jogtt and Tsunehiro Kanno thanked this post
    #244606 quote
    jogttjogtt
    Participant
    New

    Thanks for your support,  (Muchas grasias!!)

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

Fractal Trail Algorithm Conversion


ProBuilder: Indicators & Custom Tools

New Reply
Author
author-avatar
jogtt @jogtt Participant
Summary

This topic contains 3 replies,
has 2 voices, and was last updated by jogttjogtt
1 year, 6 months ago.

Topic Details
Forum: ProBuilder: Indicators & Custom Tools
Language: English
Started: 02/04/2025
Status: Active
Attachments: 3 files
ProRealCode ProRealCode
Loading...