ProRealCode - Trading & Coding with ProRealTime™
Hi everyone,
I recently came across a very interesting indicator that combines a trailing stop loss with a built-in profit target. While the pine script for this indicator seems well-written, it’s quite complex.
I was wondering if there’s a similar indicator already available in PRT’s library? I’m familiar with the existing trailing stop indicators based on ATR in PRT library, but I’m looking for something that also incorporates a profit target functionality similar to one below.
Does anyone here have experience with creating or using such an indicator on PRT? Any suggestions would be greatly appreciated!
https://www.tradingview.com/script/gUXnDioT-Interactive-ATR-Stop-Loss-TANHEF/@version=5
indicator(title='Interactive ATR Stop Loss', shorttitle='Interactive ATR', overlay=true)
//INPUTS - Interactive
tt_Interact = "Click location to begin ATR Trailing Stoploss. Below price for long stop, and above price for short stop. \nDrag 🔵 to modify afterwards."
tt_closeType= "Criteria used to determine if stop-loss has been hit.\n\nWick: low/high wicks outside of trailing stop \nClose: close outside of trailing stop"
yBarPrice = input.price(0.0, title='Start Point', inline='Above/Below bar to start', group='Interactive ATR', confirm=true)
xBarTime = input.time(0, title='', inline='Above/Below bar to start', group='Interactive ATR', confirm=true, tooltip=tt_Interact)
closeType = input.string("Wick", title="Trigger",options=["Wick","Close"], inline='ATRclose', group="Interactive ATR", tooltip=tt_closeType)
//INPUTS - Price Target
tt_PriceTarget = "Profit target can be set on the opposite side of price in compared to the trailing stoploss. The trailing stop loss will continue plotting until it is hit, even if the profit target is hit first. The profit target can be set as an exact price or a Risk/Reward ratio. The Risk/Reward ratio calculates from the close price to the ATR stoploss value."
displayPriceTarget = input(false, title="Profit Target", inline="PriceTarget", group="Interactive ATR", tooltip=tt_PriceTarget)
priceTargetType = input.string('R:R', title="", inline='PriceTarget', group="Interactive ATR", options=['R:R','Price'])
priceTargetMult = input.float(1.5, title="", inline="PriceTarget", group="Interactive ATR", step=0.1)
//INPUTS - Display Settings
tt_DisplayInteractive = "Display ATR Trailing - Interactive: Displays \nFill: stoploss areas for Interactive ATR \nShape: display shape when trailing stop hit\nLabel: label including ATR trailing value and status"
tt_DisplayBandsATR = "Display ATR Bands: Normal Upper & Lower\n"
displayTrailATR = input(true, title="Display ATR Trailing - Interactive", inline='TrailingATR', group="Display")
fillArea = input(true, title="Fill", inline='TrailingATR', group="Display")
displayShapes = input(true, title='Shape', inline='TrailingATR', group="Display")
displayLabel = input(true, title='Label', inline='TrailingATR', group="Display", tooltip=tt_DisplayInteractive)
displayBandsATR = input(false, title="Display ATR Bands", inline='BandsATR', group="Display", tooltip=tt_DisplayBandsATR)
//INPUTS - ATR Settings
length = input.int(14, minval=1, title='Length', inline="inputsATR", group="ATR Settings")
multiplier = input.float(3.0,step=0.5, title='Multiplier', inline="inputsATR", group="ATR Settings")
maTypeInput = input.string("SMMA (RMA)",title="MA Type", inline="inputsATR", group="ATR Settings", options=["SMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"])
src1 = input(close, title="Source (Upper band)",inline='1', group="ATR Settings")
src2 = input(close, title="Source (Lower band)",inline='2', group="ATR Settings")
//INPUTS - Styles
tt_colTrailing = "Trailing ATR colors\nDisplayable via 'Display ATR Trailing - Interactive'"
tt_colNormalATR = "Normal ATR bands colors\nDisplayable via 'Display ATR Bands'"
colTrailing = input(color.new(color.blue,0), title='Trailing', inline='Colors', group="Styles")
colLossFill = input.color(color.new(color.red,20), title='Loss Fill', inline='Colors', group="Styles", tooltip=tt_colTrailing)
colProfitFill = input.color(color.new(color.lime,20), title='Profit Fill', inline='Colors', group="Styles")
colShort = input.color(color.new(color.purple,20), title='Upper Band', inline='Colors2', group="Styles")
colLong = input.color(color.new(color.teal,20), title='Lower Band', inline='Colors2', group="Styles", tooltip=tt_colNormalATR)
labelSize = input.string(size.normal, title="Label Size", inline="labelSize", group="Styles", options=[size.auto, size.tiny, size.small, size.normal, size.large, size.huge])
//CALCULATE - MA
calcMA(source, length, type) =>
switch type
"SMA" => ta.sma(source, length)
"EMA" => ta.ema(source, length)
"SMMA (RMA)" => ta.rma(source, length)
"WMA" => ta.wma(source, length)
"VWMA" => ta.vwma(source, length)
a = calcMA(ta.tr(true), length, maTypeInput) * multiplier
upper = calcMA(ta.tr(true), length, maTypeInput) * multiplier + src1
lower = src2 - calcMA(ta.tr(true), length, maTypeInput) * multiplier
//CALCULATE - Trailing ATR
var startNow = false //Start Plotting TrailingStop Loss
var aboveClose = false //Above or below (True = long , False = short)
var aboveClose_ProfitTarget = false
var waitForFirstProfitTargetHit = true
var upperTrailing = 0.0
var lowerTrailing = 0.0
var currentlyTrailing = false
var startMinute = int(na) //Start minute (for alerts)
var startHour = int(na) //Start hour (for alerts)
var startDay = int(na) //Start day (for alerts)
var priceTargetVal = float(na) //For price target value (from either R:R or Price input)
//Check first bar of trailing stoploss, also if short or long stoploss
if xBarTime == time
startNow := true
aboveClose := yBarPrice < close ? true : false
startMinute := minute
startHour := hour
startDay := dayofmonth
//Start stoploss and set trailing value
if startNow and startNow[1] == false
currentlyTrailing := true
upperTrailing := upper
lowerTrailing := lower
if priceTargetType == 'R:R'
priceTargetVal := aboveClose ? close+((close-lowerTrailing)*priceTargetMult) : close-((upperTrailing-close)*priceTargetMult)
else
priceTargetVal := priceTargetMult
if aboveClose
if lower > low
labelATR = label.new(bar_index, yBarPrice, text='Overlapping\nATR and Bar', textalign = text.align_left, color=color.new(color.blue,100), textcolor=color.blue, xloc=xloc.bar_index, yloc=yloc.price,size=labelSize, tooltip='Either place on another bar or modify ATR Settings')
label.set_style(labelATR, aboveClose ? label.style_label_up : label.style_label_down)
else
if upper < high
labelATR = label.new(bar_index, yBarPrice, text='Overlapping\nATR and Bar', textalign = text.align_left, color=color.new(color.blue,100), textcolor=color.blue, xloc=xloc.bar_index, yloc=yloc.price,size=labelSize, tooltip='Either place on another bar or modify ATR Settings')
label.set_style(labelATR, aboveClose ? label.style_label_up : label.style_label_down)
//Update ATR Trailing Stop Value
if currentlyTrailing
if aboveClose == false
if upperTrailing > upper
upperTrailing := upper
if aboveClose
if lowerTrailing < lower
lowerTrailing := lower
//PLOT - Draggable Start Point
plot(xBarTime == time ? yBarPrice : na,style=plot.style_circles, color=color.blue, linewidth=5, title="🔵Start Point (Draggable Circle)")
//PLOT - Trailing Stop-loss
plotUpperTrailing = plot(displayTrailATR and currentlyTrailing and aboveClose == false ? upperTrailing : na, title="Upper Trailing", color=colTrailing) //Upper Trail
plotLowerTrailing = plot(displayTrailATR and currentlyTrailing and aboveClose ? lowerTrailing : na, title="Lower Trailing", color=colTrailing) //Lower Trail
placeholder = plot(currentlyTrailing ? hlc3 : na, editable=false, title="Placeholder", color=color.new(color.blue,100)) //Placeholder
profitHit = false
//Stop the upper/lower trailing after found
if closeType == "Wick"
//Trailing
if high > upperTrailing and aboveClose == false
currentlyTrailing := false
if low < lowerTrailing and aboveClose
currentlyTrailing := false
//Profit Target
if (ta.cross(high,priceTargetVal) or ta.cross(low,priceTargetVal)) and currentlyTrailing
waitForFirstProfitTargetHit := false
profitHit := true
if closeType == "Close"
//Trailing
if close[1] > upperTrailing and aboveClose == false
currentlyTrailing := false
if close[1] < lowerTrailing and aboveClose
currentlyTrailing := false
//Profit Target
if (ta.cross(close,priceTargetVal)) and currentlyTrailing
waitForFirstProfitTargetHit := false
profitHit := true
//PLOT - Fill (only while active, removes when triggered)
fill(plotUpperTrailing,placeholder,color=close < upperTrailing ? color.new(colLossFill,80) : na,display=fillArea ? display.all : display.none)
fill(plotLowerTrailing,placeholder,color=close > lowerTrailing ? color.new(colLossFill,80) : na,display=fillArea ? display.all : display.none)
//PLOT - Price Target
plotTarget = plot(displayPriceTarget and currentlyTrailing and waitForFirstProfitTargetHit[1] ? priceTargetVal : na, title="Price Target")
fill(placeholder, plotTarget, color=waitForFirstProfitTargetHit[1] ? color.new(colProfitFill,80) : na,display=fillArea ? display.all : display.none)
//PLOT - Shape (Stoploss Hit)
plotchar(displayTrailATR and aboveClose and displayShapes and currentlyTrailing[1] and currentlyTrailing == false, title="Symbol - Long Stop", char='⚠️', location=location.belowbar, size=size.small)
plotchar(displayTrailATR and aboveClose == false and displayShapes and currentlyTrailing[1] and currentlyTrailing == false, title="Symbol - Short Stop", char='⚠️', location=location.abovebar, size=size.small)
//PLOT - Shape (Target Hit)
plotchar(displayTrailATR and aboveClose and displayShapes and displayPriceTarget and profitHit and waitForFirstProfitTargetHit[1], title="Symbol - Long Profit", char='🎯', location=location.abovebar, size=size.small)
plotchar(displayTrailATR and aboveClose == false and displayShapes and displayPriceTarget and profitHit and waitForFirstProfitTargetHit[1], title="Symbol - Short Profit", char='🎯', location=location.belowbar, size=size.small)
//PLOT - Normal ATR Bands
plotUpper = plot(displayBandsATR ? upper : na, title='ATR Band - Upper', color=colShort)
plotLower = plot(displayBandsATR ? lower : na, title='ATR Band - Lower', color=colLong)
//LABEL - Get text
labelState = ""
if currentlyTrailing == false
labelState := "⚠️"
else
labelState := displayPriceTarget ? '⌛\nProfit Target: ' + str.tostring(math.round_to_mintick(priceTargetVal),'#.################') : ''
labelState := aboveClose ? labelState + '\nLoss Distance: ' + str.tostring(((lowerTrailing[1]/close)-1)*100,'#.###') + '%' : labelState + '\nLoss Distance: ' + str.tostring(((upperTrailing[1]/close)-1)*100,'#.###') + '%'
if displayPriceTarget and waitForFirstProfitTargetHit
labelState := aboveClose ? labelState + '\nProfit Distance: ' + str.tostring(((priceTargetVal/close)-1)*100,'#.###') + '%' : labelState + '\nProfit Distance: ' + str.tostring(((priceTargetVal/close)-1)*100,'#.###') + '%'
else if displayPriceTarget
labelState := labelState + '\nProfit Distance: 🎯'
labelPrice = aboveClose ? lowerTrailing : upperTrailing
profitText = string(na)
labelText = 'ATR: ' + str.tostring(math.round_to_mintick(labelPrice),'#.################') + labelState
//LABEL - Display
directionCol = aboveClose ? colProfitFill : colLossFill
var labelATR = label.new(na, na, '', textalign = text.align_left, textcolor = color.blue, style = label.style_label_left,xloc=xloc.bar_index, yloc=yloc.price,size=labelSize)
label.set_xy(labelATR, displayTrailATR and displayLabel ? bar_index+3 : na, close[1])
label.set_color(labelATR, directionCol)
label.set_text(labelATR, labelText)
//INPUTS - Alerts
tt_alert = "Check alerts to use. Go to 'Create Alert' and set the condition to 'Interactive ATR', select create. "
tt_alertDetails = "\n\nAdditional details can be added to the message using these words in between Curly (Brace) Brackets:\n {{trail}} = ATR trailing stop-loss (price) \n {{upper}} = Upper ATR band (price) \n {{lower}} = Lower ATR band (price) \n {{band}} = Lower or Upper trailing (word) \n {{type}} = Long or Short stop-loss (word) \n {{traildistance}} = Trailing Distance (%) \n {{targetdistance}} = Target Distance (%) \n {{starttime}} = Start time of trailing (day:hour:minute) \n {{target}} = Price target (price) \n {{trigger}} = Wick or Close Trigger input option (input) \n {{atrlength}} = ATR length (input) \n {{atrmultiplier}} = ATR multiplier (input) \n {{atrma}} = ATR MA type (input) \n {{ticker}} = Ticker of chart (word) \n {{exchange}} = Exchange of chart (word) \n {{description}} = Description of ticker (words) \n {{close}} = Bar close (price) \n {{open}} = Bar open (price) \n {{high}} = Bar high (price) \n {{low}} = Bar low (price) \n {{hl2}} = Bar HL2 (price) \n {{volume}} = Bar volume (value) \n {{time}} = Current time (day:hour:minute) \n {{interval}} = Chart timeframe \n {{newline}} = New line for text"
tt_alertTrailingHit = "\n\nTrailing Hit: alert interactive trailing ATR hit."
tt_alertTrailingEx = "\n\nExample Alert Message Input: \n {{band}} ATR Trailing Stop Hit at {{trail}} ({{type}}){{newline}}{{ticker}}\n\nExample Alert Message Output: \n Lower ATR Trailing Stop Hit at 25 (Long)\n BTCUSD"
tt_alertPriceTarget = "\n\nTarget Hit: alert price target hit (while trailing not hit)."
tt_alertTargetEx = "\n\nExample Alert Message Input: \n Price crossing target of {{target}} ({{type}}){{newline}}{{ticker}} ATR Trailing Stop Not Hit\n\nExample Alert Message Output: \n Price crossing target of 100 (Long)\n BTCUSD ATR Trailing Stop Not Hit"
o_trailing = "{{band}} ATR Trailing Stop Hit at {{trail}} ({{type}}){{newline}}{{ticker}}"
o_target = "Price crossing target of {{target}} ({{type}}){{newline}}{{ticker}} ATR Trailing Stop Not Hit"
Alert_TrailingHit = input(true, title="Alert Trailing Stop Hit", inline='AlertTrailingHit', group="Alert", tooltip=tt_alert + tt_alertTrailingHit + tt_alertDetails + tt_alertTrailingEx)
Alert_TrailingHitText = input.string(o_trailing, title=' - Message', inline='AlertTrailingHit', group="Alert")
Alert_PriceTarget = input(false, title="Alert Price Target Hit", inline='AlertProfitHit', group="Alert", tooltip=tt_alert + tt_alertPriceTarget + tt_alertDetails + tt_alertTargetEx)
Alert_PriceTargetText = input.string(o_target, title=' - Message', inline='AlertProfitHit', group="Alert")
//allOptions = "{{trail}} {{upper}} {{lower}} {{band}} {{type}} {{traildistance}} {{targetdistance}} {{target}} {{trigger}} {{atrlength}} {{atrmultiplier}} {{atrma}} {{ticker}} {{exchange}} {{description}} {{close}} {{open}} {{high}} {{low}} {{hl2}} {{volume}} {{time}} {{starttime}} {{interval}} {{newline}}"
//CALCULATE - Timeframe text for alert ('fixes' letter consistancy between different timeframes)
calcTimeframeText(_src) =>
result = _src
if str.contains(_src,'S')
result := str.replace(_src,'S','s',0)
else if str.contains(_src,'D') or str.contains(_src,'W') or str.contains(_src,'M')
result := _src
else
result := str.tonumber(_src) < 60 ? _src + 'm' : str.tostring(str.tonumber(_src)/60) + 'h'
//CALCULATE - Curly brackets text into current data
//One reason this code was added due to the preference of using alert() instead of alertcondition() which requires additional selection when setting up alerts.
//This function allows for alert() to return messages with retreived values via curly brackets, that alertcondition() can do by default.
//Additional indicator specific values can also be retreived, such as {{trail}} , {{band}} , {{type}} , {{trigger}} , {{target}} , {{newline}} , and more.
checkAlertText(_text) =>
result = _text
//Calculated values specific to this indicator
result := str.replace(result, '{{trail}}', str.tostring(math.round_to_mintick(aboveClose ? lowerTrailing : upperTrailing),'#.################'))
result := str.replace(result, '{{upper}}', str.tostring(math.round_to_mintick(upper),'#.################'))
result := str.replace(result, '{{lower}}', str.tostring(math.round_to_mintick(lower),'#.################'))
result := str.replace(result, '{{band}}', aboveClose ? 'Lower' : 'Upper')
result := str.replace(result, '{{type}}', aboveClose ? 'Long' : 'Short')
result := str.replace(result, '{{traildistance}}', aboveClose ? str.tostring(((lowerTrailing[1]/close)-1)*100,'#.###') + '%' : str.tostring(((upperTrailing[1]/close)-1)*100,'#.###') + '%')
result := str.replace(result, '{{targetdistance}}', aboveClose ? str.tostring(((priceTargetVal/close)-1)*100,'#.###') + '%' : str.tostring(((priceTargetVal/close)-1)*100,'#.###') + '%')
result := str.replace(result, '{{starttime}}', str.tostring(startDay,'#') + ':' + str.tostring(startHour,'#') + ':' + str.tostring(startMinute,'#'))
//Input values specific to this indicator
result := str.replace(result, '{{target}}', str.tostring(math.round_to_mintick(priceTargetVal),'#.################'))
result := str.replace(result, '{{trigger}}', closeType)
result := str.replace(result, '{{atrlength}}', str.tostring(length,'#'))
result := str.replace(result, '{{atrmultiplier}}', str.tostring(multiplier,'#'))
result := str.replace(result, '{{atrma}}', maTypeInput)
//Common to any indicator
result := str.replace(result, '{{ticker}}', syminfo.ticker)
result := str.replace(result, '{{exchange}}', syminfo.prefix(syminfo.tickerid))
result := str.replace(result, '{{description}}', syminfo.description)
result := str.replace(result, '{{close}}', str.tostring(math.round_to_mintick(close),'#.################'))
result := str.replace(result, '{{open}}', str.tostring(math.round_to_mintick(open),'#.################'))
result := str.replace(result, '{{high}}', str.tostring(math.round_to_mintick(high),'#.################'))
result := str.replace(result, '{{low}}', str.tostring(math.round_to_mintick(low),'#.################'))
result := str.replace(result, '{{hl2}}', str.tostring(math.round_to_mintick(hl2),'#.################'))
result := str.replace(result, '{{volume}}', str.tostring(math.round_to_mintick(volume),'#.################'))
result := str.replace(result, '{{time}}', str.tostring(dayofmonth,'#') + ':' + str.tostring(hour,'#') + ':' + str.tostring(minute,'#'))
result := str.replace(result, '{{interval}}', calcTimeframeText(timeframe.period))
result := str.replace(result, '{{newline}}', '\n')
//CALCULATE - ALERTS
if Alert_TrailingHit
if currentlyTrailing[1] and currentlyTrailing == false
alert(checkAlertText(Alert_TrailingHitText),alert.freq_once_per_bar)
if Alert_PriceTarget
if currentlyTrailing and ta.cross(priceTargetVal,close)
alert(checkAlertText(Alert_PriceTargetText),alert.freq_once_per_bar)
Hi,
The indicator below is the “ATR Trailing Stop” from the library (https://www.prorealcode.com/prorealtime-indicators/another-atr-trailing-stop/ ) with a small extension to show a “Take Profit”…
You can set the TPL (TakeProfitLong) and TPS (TakeProfitShort) in points in the “Settings window”…
The “p” is the period of the ATR
De “mult” is de multiplier van de ATR
atr = AverageTrueRange[p](close) * mult
If BarIndex<=10 then
Dist=Average[10](Range)*0.5
EndIf
once trend=1
Once TPLong=0
Once TPShort=0
if trend=1 then
hh=max(hh,close)
ll=hh
if atr<atr[1] then
hhlevel=hh-atr
if hhlevel>ts then
ts=hhlevel
endif
endif
r=0
g=168
else
ll=min(ll,close)
hh=ll
if atr<atr[1] then
lllevel=ll+atr
if lllevel<ts then
ts=lllevel
endif
endif
r=255
g=0
endif
if close crosses over ts then
trend=1
if mode>0 then
ts=ll
endif
elsif close crosses under ts then
trend=-1
if mode>0 then
ts=hh
endif
endif
If Close Crosses Over TS then
BarIndexLong=BarIndex
TPShort=0
HighLong=High
EndIf
If Close[1] Crosses Over TS[1] then
OpenTPLong=Open
TPLong=Open+TPL
EndIf
If TPLong>0 then
DrawSegment(BarIndexLong,TPLong,BarIndex,TPLong)Style(Line,2)Coloured("Green")
DrawSegment(BarIndexLong,HighLong,BarIndexLong,TPLong)Style(Line,2)Coloured("Green")
DrawText("TakeProfit#TPLong#",BarIndexLong+4,TPLong+Dist,SansSerif,Bold,16)Coloured("Green")
EndIf
If Close Crosses Under TS then
BarIndexShort=BarIndex
TPLong=0
LowShort=Low
EndIf
If Close[1] Crosses Under TS[1] then
OpenTPShort=Open
TPShort=Open-TPS
EndIf
If TPShort>0 then
DrawSegment(BarIndexShort,TPShort,BarIndex,TPShort)Style(Line,2)Coloured("Red")
DrawSegment(BarIndexShort,LowShort,BarIndexShort,TPShort)Style(Line,2)Coloured("Red")
DrawText("TakeProfit#TPShort#",BarIndexShort+4,TPShort-Dist,SansSerif,Bold,16)Coloured("Red")
EndIf
return ts coloured(r,g,0) style(line,3)
From the original “leaflet”…
The ATR trailing stop has 2 modes: (“mode” setting)
Trailing Stop Loss with Profit Taking
This topic contains 3 replies,
has 2 voices, and was last updated by JS
1 year, 10 months ago.
| Forum: | ProBuilder: Indicators & Custom Tools |
| Language: | English |
| Started: | 04/05/2024 |
| Status: | Active |
| Attachments: | 2 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.