ProRealCode - Trading & Coding with ProRealTime™
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!
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!
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 filtersbarindex > 2//----------------------------------------------// // Cloud //----------------------------------------------// medPrice=(high+low)/2 colorbetween(trail,medPrice,r,g,b,20) //----------------------------------------------// // return //----------------------------------------------// return trail style(line,3) coloured(r,g,b)
Thanks for your support, (Muchas grasias!!)
Fractal Trail Algorithm Conversion
This topic contains 3 replies,
has 2 voices, and was last updated by jogtt
1 year ago.
| Forum: | ProBuilder: Indicators & Custom Tools |
| Language: | English |
| Started: | 02/04/2025 |
| Status: | Active |
| Attachments: | 3 files |
The information collected on this form is stored in a computer file by ProRealCode to create and access your ProRealCode profile. This data is kept in a secure database for the duration of the member's membership. They will be kept as long as you use our services and will be automatically deleted after 3 years of inactivity. Your personal data is used to create your private profile on ProRealCode. This data is maintained by SAS ProRealCode, 407 rue Freycinet, 59151 Arleux, France. If you subscribe to our newsletters, your email address is provided to our service provider "MailChimp" located in the United States, with whom we have signed a confidentiality agreement. This company is also compliant with the EU/Swiss Privacy Shield, and the GDPR. For any request for correction or deletion concerning your data, you can directly contact the ProRealCode team by email at privacy@prorealcode.com If you would like to lodge a complaint regarding the use of your personal data, you can contact your data protection supervisory authority.