Fractal Trail Algorithm Conversion

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #243428 quote
    jogtt
    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
    jogtt
    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ález
    Moderator
    Master

    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 and jogtt thanked this post
    #244606 quote
    jogtt
    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.

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 jogtt
1 year ago.

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