Safe Supertrend Strategy (No Repaint)Overview
The Safe Supertrend is a repaint-free version of the popular Supertrend trend-following indicator.
Most Supertrend indicators appear perfect on historical charts because they flip intrabar and then repaint after the candle closes.
This version fixes that by using close-of-bar confirmation only, making every trend flip 100% stable, safe, and non-repainting.
Why This Supertrend Doesn’t Repaint
Most Supertrend indicators calculate their trend direction using the current bar’s data.
But during a live candle:
ATR expands and contracts
The upper/lower bands move
Price moves above/below the band temporarily
A false flip appears → then disappears when the candle closes
That is classic repainting.
This indicator avoids all of that by using:
close > upper
close < lower
This means:
Trend direction flips only based on the previous candle,
No intrabar calculations,
No flickering signals,
No “perfect but fake” historical performance.
Every signal you see on the chart is exactly what was available in real-time.
How It Works
Calculates ATR (Average True Range) and SMA centerline
Builds upper and lower volatility bands
Confirms trend flips only after the previous bar closes
Plots clear bull and bear reversal signals
Works on all markets (crypto, stocks, forex, indices)
No repainting, no recalc, no misleading flips.
Bullish Signal (Trend Up)
A bullish trend begins only when:
The previous candle closes above the upper ATR band,
And this flip is fully confirmed.
A green triangle marks the start of a new uptrend.
Bearish Signal (Trend Down)
A bearish trend begins only when:
The previous candle closes below the lower ATR band,
And the downtrend is confirmed.
A red triangle signals the start of a new downtrend.
Inputs
ATR Length - default 10
ATR Multiplier - default 3.0
Works on all timeframes and market
Simple, but powerful.
Why Use This Version Instead of a Regular Supertrend?
Most Supertrends:
Look great historically
But repaint continuously on live charts
Give false trend flips intrabar
Cannot be reliably used in strategies
This version:
Uses strict previous-bar logic
Never repaints trend direction
Works perfectly in live trading
Backtests accurately
Is ideal for algorithmic strategies
Ideal For:
Trend-following strategies
Breakout trading
Algo trading systems
Reversal detection
Filtering market noise
Swing trading & scalping
Final Note
This is a safer, more reliable Supertrend designed for real-world use — not perfect-looking repaint illusions.
If you use Supertrend in your trading system, this no-repaint version ensures your signals are trustworthy and consistent.
Version6
Safe Supertrend Strategy (No Repaint)Overview
The Safe Supertrend is a repaint-free version of the popular Supertrend trend-following indicator.
Most Supertrend indicators appear perfect on historical charts because they flip intrabar and then repaint after the candle closes.
This version fixes that by using close-of-bar confirmation only, making every trend flip 100% stable, safe, and non-repainting.
Why This Supertrend Doesn’t Repaint
Most Supertrend indicators calculate their trend direction using the current bar’s data.
But during a live candle:
ATR expands and contracts
The upper/lower bands move
Price moves above/below the band temporarily
A false flip appears → then disappears when the candle closes
That is classic repainting.
This indicator avoids all of that by using:
close > upper
close < lower
This means:
Trend direction flips only based on the previous candle,
No intrabar calculations,
No flickering signals,
No “perfect but fake” historical performance.
Every signal you see on the chart is exactly what was available in real-time.
How It Works
Calculates ATR (Average True Range) and SMA centerline
Builds upper and lower volatility bands
Confirms trend flips only after the previous bar closes
Plots clear bull and bear reversal signals
Works on all markets (crypto, stocks, forex, indices)
No repainting, no recalc, no misleading flips.
Bullish Signal (Trend Up)
A bullish trend begins only when:
The previous candle closes above the upper ATR band,
And this flip is fully confirmed.
A green triangle marks the start of a new uptrend.
Bearish Signal (Trend Down)
A bearish trend begins only when:
The previous candle closes below the lower ATR band,
And the downtrend is confirmed.
A red triangle signals the start of a new downtrend.
Inputs
ATR Length - default 10
ATR Multiplier - default 3.0
Works on all timeframes and market
Simple, but powerful.
Why Use This Version Instead of a Regular Supertrend?
Most Supertrends:
Look great historically
But repaint continuously on live charts
Give false trend flips intrabar
Cannot be reliably used in strategies
This version:
Uses strict previous-bar logic
Never repaints trend direction
Works perfectly in live trading
Backtests accurately
Is ideal for algorithmic strategies
Ideal For:
Trend-following strategies
Breakout trading
Algo trading systems
Reversal detection
Filtering market noise
Swing trading & scalping
Final Note
This is a safer, more reliable Supertrend designed for real-world use — not perfect-looking repaint illusions.
If you use Supertrend in your trading system, this no-repaint version ensures your signals are trustworthy and consistent.
PseudoPlotLibrary "PseudoPlot"
PseudoPlot: behave like plot and fill using polyline
This library enables line plotting by polyline like plot() and fill().
The core of polyline() is array of chart.point array, polyline() is called in its method.
Moreover, plotarea() makes a box in main chart, plotting data within the box is enabled.
It works so slowy to manage array of chart.point, so limit the target to visible area of the chart.
Due to polyline specifications, na and expression can not be used for colors.
1. pseudoplot
pseudoplot() behaves like plot().
//use plot()
plot(close)
//use pseudoplot()
pseudoplot(close)
Pseudoplot has label. Label is enabled when title argument is set.
In the example bellow, "close value" label is shown with line.
The label is shown at right of the line when recent bar is visible.
It is shown at 15% from the left of visible area when recent bar is not visible.
Just set "" if you don't need label.
//use plot()
plot(close,"close value")
//use pseudoplot
pseudoplot(close, "close value")
Arguments are designed in an order as similar as possible to plot.
plot(series, title, color, linewidth, style, trackprice, histbase, offset, join, editable, show_last, display, format, precision, force_overlay) → plot
pseudoplot(series, title, ,linecolor ,linewidth, linestyle, labelbg, labeltext, labelsize, shorttitle, format, xpos_from_left, overlay) → pseudo_plot
2. pseudofill
pseudofill() behaves like fill().
The label is shown(text only) at right of the line when recent bar is visible.
It is shown at 10% from the left of visible area when recent bar is not visible.
Just set "" if you don't need label.
//use plot() and fill()
p1=plot(open)
p2=plot(close)
fill(p1,p2)
//use pseudofill()
pseudofill(open,close)
Arguments are designed in an order as similar as possible to fill.
fill(hline1, hline2, color, title, editable, fillgaps, display) → void
pseudofill(series1, series2, fillcolor, title, linecolor, linewidth, linestyle, labeltext, labelsize, shorttitle, format, xpos_from_left, overlay) → pseudo_plot
3. plotarea and its methods
plotarea() makes a box in main chart. You can set the box position to top or bottom, and
the box height in percentage of the range of visible high and low prices.
x-coordinate of the box is from chart.left_visible_bar_time to chart.right_visible_bar_time,
y-coordinate is highest and lowest price of visible bars.
pseudoplot() and pseudofill() work as method of plotarea(box).
Usage is almost same as the function version, just set min and max value, y-coodinate is remapped automatically.
hline() is also available. The y-coordinate of hline is specified as a percentage from the bottom.
plotarea() and its associated methods are overlay=true as default.
Depending on the drawing order of the objects, plot may become invisible, so the bgcolor of plotarea should be na or tranceparent.
//1. make a plotarea
// bgcolor should be na or transparent color.
area=plotarea("bottom",30,"plotarea",bgcolor=na)
//2. plot in a plotarea
//(min=0, max=100 is omitted as it is the default.)
area.pseudoplot(ta.rsi(close,14))
//3. draw hlines
area.hline(30,linestyle="dotted",linewidth=2)
area.hline(70,linestyle="dotted",linewidth=2)
4. Data structure and sub methods
Array management is most imporant part of using polyline.
I don't know the proper way to handle array, so it is managed by array and array as intermediate data.
(type xy_arrays to manage bar_time and price as independent arrays.)
method cparray() pack arrays to array, when array includes both chart.left_visible_bar_time and chart.right_visible_bar.time.
Calling polyline is implemented as methods of array of chart.point.
Method creates polyline object if array is not empty.
method polyline(linecolor, linewidth, linestyle, overlay) → series polyline
method polyline_fill(fillcolor, linecolor, linewidth, linestyle, overlay) → series polyline
Also calling label is implemented as methods of array of chart.point.
Method creates label ofject if array is not empty.
Label is located at right edge of the chart when recent bar is visible, located at left side when recent bar is invisible.
label(title, labelbg, labeltext, labelsize, format, shorttitle, xpos_from_left, overlay) → series label
label_for_fill(title, labeltext, labelsize, format, shorttitle, xpos_from_left, overlay) → series label
visible_xyInit(series)
make arrays of visible x(bar_time) and y(price/value).
Parameters:
series (float) : (float) series variable
Returns: (xy_arrays)
method remap(this, bottom, top, min, max)
Namespace types: xy_arrays
Parameters:
this (xy_arrays)
bottom (float) : (float) bottom price to ajust.
top (float) : (float) top price to ajust.
min (float) : (float) min of src value.
max (float) : (float) max of src value.
Returns: (xy_arrays)
method polyline(this, linecolor, linewidth, linestyle, overlay)
Namespace types: array
Parameters:
this (array)
linecolor (color) : (color) color of polyline.
linewidth (int) : (int) width of polyline.
linestyle (string) : (string) linestyle of polyline. default is line.style_solid("solid"), others line.style_dashed("dashed"), line.style_dotted("dotted").
overlay (bool) : (bool) force_overlay of polyline. default is false.
Returns: (polyline)
method polyline_fill(this, fillcolor, linecolor, linewidth, linestyle, overlay)
Namespace types: array
Parameters:
this (array)
fillcolor (color)
linecolor (color) : (color) color of polyline.
linewidth (int) : (int) width of polyline.
linestyle (string) : (string) linestyle of polyline. default is line.style_solid("solid"), others line.style_dashed("dashed"), line.style_dotted("dotted").
overlay (bool) : (bool) force_overlay of polyline. default is false.
Returns: (polyline)
method label(this, title, labelbg, labeltext, labelsize, format, shorttitle, xpos_from_left, overlay)
Namespace types: array
Parameters:
this (array)
title (string) : (string) label text.
labelbg (color) : (color) color of label bg.
labeltext (color) : (color) color of label text.
labelsize (int) : (int) size of label.
format (string) : (string) textformat of label. default is text.format_none("none"). others text.format_bold("bold"), text.format_italic("italic"), text.format_bold+text.format_italic("bold+italic").
shorttitle (string) : (string) another label text for recent bar is not visible.
xpos_from_left (int) : (int) another label x-position(percentage from left of chart width), when recent bar is not visible. default is 15%.
overlay (bool) : (bool) force_overlay of label. default is false.
Returns: (label)
method label_for_fill(this, title, labeltext, labelsize, format, shorttitle, xpos_from_left, overlay)
Namespace types: array
Parameters:
this (array)
title (string) : (string) label text.
labeltext (color) : (color) color of label text.
labelsize (int) : (int) size of label.
format (string) : (string) textformat of label. default is text.format_none("none"). others text.format_bold("bold"), text.format_italic("italic"), text.format_bold+text.format_italic("bold+italic").
shorttitle (string) : (string) another label text for recent bar is not visible.
xpos_from_left (int) : (int) another label x-position(percentage from left of chart width), when recent bar is not visible. default is 10%.
overlay (bool) : (bool) force_overlay of label. default is false.
Returns: (label)
pseudoplot(series, title, linecolor, linewidth, linestyle, labelbg, labeltext, labelsize, shorttitle, format, xpos_from_left, overlay)
polyline like plot with label
Parameters:
series (float) : (float) series variable to plot.
title (string) : (string) title if need label. default value is ""(disable label).
linecolor (color) : (color) color of line.
linewidth (int) : (int) width of line.
linestyle (string) : (string) style of plotting line. default is "solid", others "dashed", "dotted".
labelbg (color) : (color) color of label bg.
labeltext (color) : (color) color of label text.
labelsize (int) : (int) size of label text.
shorttitle (string) : (string) another label text for recent bar is not visible.
format (string) : (string) textformat of label. default is text.format_none("none"). others text.format_bold("bold"), text.format_italic("italic"), text.format_bold+text.format_italic("bold+italic").
xpos_from_left (int) : (int) another label x-position(percentage from left of chart width), when recent bar is not visible. default is 15%.
overlay (bool) : (bool) force_overlay of polyline and label.
Returns: (pseudo_plot)
method pseudoplot(this, series, title, linecolor, linewidth, linestyle, labelbg, labeltext, labelsize, shorttitle, format, xpos_from_left, min, max, overlay)
Namespace types: series box
Parameters:
this (box)
series (float) : (float) series variable to plot.
title (string) : (string) title if need label. default value is ""(disable label).
linecolor (color) : (color) color of line.
linewidth (int) : (int) width of line.
linestyle (string) : (string) style of plotting line. default is "solid", others "dashed", "dotted".
labelbg (color) : (color) color of label bg.
labeltext (color) : (color) color of label text.
labelsize (int) : (int) size of label text.
shorttitle (string) : (string) another label text for recent bar is not visible.
format (string) : (string) textformat of label. default is text.format_none("none"). others text.format_bold("bold"), text.format_italic("italic"), text.format_bold+text.format_italic("bold+italic").
xpos_from_left (int) : (int) another label x-position(percentage from left of chart width), when recent bar is not visible. default is 15%.
min (float)
max (float)
overlay (bool) : (bool) force_overlay of polyline and label.
Returns: (pseudo_plot)
pseudofill(series1, series2, fillcolor, title, linecolor, linewidth, linestyle, labeltext, labelsize, shorttitle, format, xpos_from_left, overlay)
fill by polyline
Parameters:
series1 (float) : (float) series variable to plot.
series2 (float) : (float) series variable to plot.
fillcolor (color) : (color) color of fill.
title (string)
linecolor (color) : (color) color of line.
linewidth (int) : (int) width of line.
linestyle (string) : (string) style of plotting line. default is "solid", others "dashed", "dotted".
labeltext (color)
labelsize (int)
shorttitle (string)
format (string) : (string) textformat of label. default is text.format_none("none"). others text.format_bold("bold"), text.format_italic("italic"), text.format_bold+text.format_italic("bold+italic").
xpos_from_left (int) : (int) another label x-position(percentage from left of chart width), when recent bar is not visible. default is 15%.
overlay (bool) : (bool) force_overlay of polyline and label.
Returns: (pseudoplot)
method pseudofill(this, series1, series2, fillcolor, title, linecolor, linewidth, linestyle, labeltext, labelsize, shorttitle, format, xpos_from_left, min, max, overlay)
Namespace types: series box
Parameters:
this (box)
series1 (float) : (float) series variable to plot.
series2 (float) : (float) series variable to plot.
fillcolor (color) : (color) color of fill.
title (string)
linecolor (color) : (color) color of line.
linewidth (int) : (int) width of line.
linestyle (string) : (string) style of plotting line. default is "solid", others "dashed", "dotted".
labeltext (color)
labelsize (int)
shorttitle (string)
format (string) : (string) textformat of label. default is text.format_none("none"). others text.format_bold("bold"), text.format_italic("italic"), text.format_bold+text.format_italic("bold+italic").
xpos_from_left (int) : (int) another label x-position(percentage from left of chart width), when recent bar is not visible. default is 15%.
min (float)
max (float)
overlay (bool) : (bool) force_overlay of polyline and label.
Returns: (pseudo_plot)
plotarea(pos, height, title, bordercolor, borderwidth, bgcolor, textsize, textcolor, format, overlay)
subplot area in main chart
Parameters:
pos (string) : (string) position of subplot area, bottom or top.
height (int) : (float) percentage of visible chart heght.
title (string) : (string) text of area box.
bordercolor (color) : (color) color of border.
borderwidth (int) : (int) width of border.
bgcolor (color) : (string) color of area bg.
textsize (int)
textcolor (color)
format (string)
overlay (bool) : (bool) force_overlay of polyline and label.
Returns: (box)
method hline(this, ypos_from_bottom, linecolor, linestyle, linewidth, overlay)
Namespace types: series box
Parameters:
this (box)
ypos_from_bottom (float) : (float) percentage of box height from the bottom of box.(bottom is 0%, top is 100%).
linecolor (color) : (color) color of line.
linestyle (string) : (string) style of line.
linewidth (int) : (int) width of line.
overlay (bool) : (bool) force_overlay of polyline and label.
Returns: (line)
pseudo_plot
polyline and label.
Fields:
p (series polyline)
l (series label)
xy_arrays
x(bartime) and y(price or value) arrays.
Fields:
t (array)
p (array)
libTFLibrary "libTF"
libTF: Find higher/lower TF automatically
This library to find higher/lower TF from current timeframe(timeframe.period) for Pine Script version6(or higher).
Basic Algorithm
Using a timeframe scale Array and timeframe.in_seconds() function to find higher/lower timeframe.
Return value is na if could not find TF in the timeframe scale.
The timeframe scale could be changed by the parameter 'scale'(CSV).
How to use
1. Set higher/lower TF
higher()/lower() function returns higher/lower TF.
Default timeframe scale is "1, 5, 15, 60, 240, 1D, 1M, 3M, 12M".
example:
htf1 = higher()
htf2 = higher(htf1)
ltf1 = lower()
ltf2 = lower(ltf1)
2. Set higher/lower TF using your timeframe scale
The timeframe scale could be changed by the parameter.
example:
myscale="1,60,1D,1M,12M"
htf1 = higher(timeframe.period,myscale)
htf2 = higher(htf1,myscale)
ltf1 = lower(timeframe.period,myscale)
ltf2 = lower(ltf1,myscale)
3. How to use with request.*() function
na value is set if no higher/lower TF in timeframe scale.
It returns current timeframe's value, when na value as timeframe parameter in request.*().
As bellow, if it should be na when timeframe is na.
example:
return_value_request_htf1 = na(htf1)?na:request.security(syminfo.tickerid,htf1,timeframe.period)
return_value_request_ltf1 = na(ltf1)?na:request.security(syminfo.tickerid,ltf1,timeframe.period)
higher(tf, scale)
higher: find higher TF from TF string.
Parameters:
tf (string) : default value is timeframe.period.
scale (string) : TF scale in CSV. default is "1,5,15,60,240,1D,1W,1M,3M,12M".
Returns: higher TF string.
lower(tf, scale)
lower: find lower TF from TF string.
Parameters:
tf (string) : default value is timeframe.period.
scale (string) : TF scale in CSV. defalut is "1,5,15,60,240,1D,1W,1M,3M,12M".
Returns: lower TF string.



