Indicator · Pine Script v4 · On the chart

Range Filter [DW]

by theupslidedown· code credited to DonovanWall

The Range Filter indicator filters out minor price fluctuations directly on the price chart to provide a clearer view of underlying market trends.

View on GitHub

GitHub stars2on the repository
Pine versionv4older, still runs
Lines of code199
Settings9inputs
LicenceNone statedfile: MPL-2.0
Last update3 years ago17 Feb 2023

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

199 lines of Pine Script v4 from rangefilter.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

rangefilter.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © DonovanWall

//██████╗ ██╗    ██╗
//██╔══██╗██║    ██║
//██║  ██║██║ █╗ ██║
//██║  ██║██║███╗██║
//██████╔╝╚███╔███╔╝
//╚═════╝  ╚══╝╚══╝ 

//@version=4
study(title="Range Filter [DW] [UT-backtester]", shorttitle="RF [DW]", overlay=true)

//This is an experimental study designed to filter out minor price action for a clearer view of trends.

//Inspired by the QQE's volatility filter, this filter applies the process directly to price rather than to a smoothed RSI.

//First, a smooth average price range is calculated for the basis of the filter and multiplied by a specified amount.
//Next, the filter is calculated by gating price movements that do not exceed the specified range.
//Lastly the target ranges are plotted to display the prices that will trigger filter movement.

//Custom bar colors are included. The color scheme is based on the filtered price trend.

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Updates:

// -> Migrated to v4.
// -> Range Filter and the bands are now calculated in a singular function.
// -> There are now two different calculation methods for the filter. Select the type you want to use via the "Filter Type" input. Type 1 is the original formula.
// -> Multiple range sizing methods are now available. You can choose from the following scales:
//    - Points
//    - Pips (Works best with forex pairs, obviously)
//    - Ticks
//    - % of Price
//    - ATR
//    - Average Change (Default. This is the original sizing method.)
//    - Standard Deviation
//    - Absolute (Absolute numerical value)
// -> Range smoothing is now optional, and you can specify your smoothing length. Smoothing only affects dynamic scales (ATR, Average Change, and Standard Deviation).
// -> Filter movement can now be determined using wicks or close. This can be specified via the "Movement Source" input.
// -> Stability Fix: Added correction for NaN values to stabilize initial states.
// -> Reorganized the script structure.
// -> Revamped the color scheme.

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Updates:

// - The Range Filter functions have now been rebuilt using Pine's awesome new array functions.

// - Standard deviation calculation has been adjusted to calculate the same as TV's built in stdev() function.

// - Rewritten filter direction and bar color variables.

// - Included an external output variable for trend information that can easily be sent to other scripts without hardcoding.
//   The output format is 1 for bullish, and -1 for bearish.
//   To use this external variable with another script, simply select it from your other script's source dropdown tab.

// - Added the ability to average range filter values based on a user defined number of filter changes.
//   This averaging method utilized the Conditional Sampling EMA function I introduced in my Resampling Filter Pack and only takes a new sample when the filter changes its value.
//   This opens up a whole new world of possible filter outputs.

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Functions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Conditional Sampling EMA Function 
Cond_EMA(x, cond, n)=>
    var val     = array.new_float(0)
    var ema_val = array.new_float(1)
    if cond
        array.push(val, x)
        if array.size(val) > 1
            array.remove(val, 0)
        if na(array.get(ema_val, 0))
            array.fill(ema_val, array.get(val, 0))
        array.set(ema_val, 0, (array.get(val, 0) - array.get(ema_val, 0))*(2/(n + 1)) + array.get(ema_val, 0))
    EMA = array.get(ema_val, 0)
    EMA

//Conditional Sampling SMA Function
Cond_SMA(x, cond, n)=>
    var vals = array.new_float(0)
    if cond
        array.push(vals, x)
        if array.size(vals) > n
            array.remove(vals, 0)
    SMA = array.avg(vals)
    SMA

//Standard Deviation Function
Stdev(x, n)=>
    sqrt(Cond_SMA(pow(x, 2), 1, n) - pow(Cond_SMA(x, 1, n), 2))

//Range Size Function
rng_size(x, scale, qty, n)=> 
    ATR      = Cond_EMA(tr(true), 1, n)
    AC       = Cond_EMA(abs(x - x[1]), 1, n)
    SD       = Stdev(x, n)
    rng_size = scale=="Pips" ? qty*0.0001 : scale=="Points" ? qty*syminfo.pointvalue : scale=="% of Price" ? close*qty/100 : scale=="ATR" ? qty*ATR :
               scale=="Average Change" ? qty*AC : scale=="Standard Deviation" ? qty*SD : scale=="Ticks" ? qty*syminfo.mintick : qty   

//Two Type Range Filter Function
rng_filt(h, l, rng_, n, type, smooth, sn, av_rf, av_n)=>
    rng_smooth = Cond_EMA(rng_, 1, sn)
    r          = smooth ? rng_smooth : rng_
    var rfilt  = array.new_float(2, (h + l)/2)
    array.set(rfilt, 1, array.get(rfilt, 0))
    if type=="Type 1"
        if h - r > array.get(rfilt, 1)
            array.set(rfilt, 0, h - r)
        if l + r < array.get(rfilt, 1)
            array.set(rfilt, 0, l + r)
    if type=="Type 2"
        if h >= array.get(rfilt, 1) + r
            array.set(rfilt, 0, array.get(rfilt, 1) + floor(abs(h - array.get(rfilt, 1))/r)*r)
        if l <= array.get(rfilt, 1) - r
            array.set(rfilt, 0, array.get(rfilt, 1) - floor(abs(l - array.get(rfilt, 1))/r)*r)
    rng_filt1 = array.get(rfilt, 0)
    hi_band1  = rng_filt1 + r
    lo_band1  = rng_filt1 - r
    rng_filt2 = Cond_EMA(rng_filt1, rng_filt1 != rng_filt1[1], av_n)
    hi_band2  = Cond_EMA(hi_band1, rng_filt1 != rng_filt1[1], av_n)
    lo_band2  = Cond_EMA(lo_band1, rng_filt1 != rng_filt1[1], av_n)
    rng_filt  = av_rf ? rng_filt2 : rng_filt1
    hi_band   = av_rf ? hi_band2 : hi_band1
    lo_band   = av_rf ? lo_band2 : lo_band1
    [hi_band, lo_band, rng_filt]
 
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Type
f_type = input(defval="Type 1", options=["Type 1", "Type 2"], title="Filter Type")

//Movement Source
mov_src = input(defval="Close", options=["Wicks", "Close"], title="Movement Source")

//Range Size Inputs
rng_qty   = input(defval=2.618, minval=0.0000001, title="Range Size")
rng_scale = input(defval="Average Change", options=["Points", "Pips", "Ticks", "% of Price", "ATR", "Average Change", "Standard Deviation", "Absolute"], title="Range Scale")

//Range Period
rng_per = input(defval=14, minval=1, title="Range Period (for ATR, Average Change, and Standard Deviation)")

//Range Smoothing Inputs
smooth_range = input(defval=true, title="Smooth Range")
smooth_per   = input(defval=27, minval=1, title="Smoothing Period")

//Filter Value Averaging Inputs
av_vals    = input(defval=false, title="Average Filter Changes")
av_samples = input(defval=2, minval=1, title="Number Of Changes To Average")

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//High And Low Values
h_val = mov_src=="Wicks" ? high : close
l_val = mov_src=="Wicks" ? low : close

//Range Filter Values
[h_band, l_band, filt] = rng_filt(h_val, l_val, rng_size((h_val + l_val)/2, rng_scale, rng_qty, rng_per), rng_per, f_type, smooth_range, smooth_per, av_vals, av_samples)

//Direction Conditions
var fdir = 0.0
fdir    := filt > filt[1] ? 1 : filt < filt[1] ? -1 : fdir
upward   = fdir==1 ? 1 : 0
downward = fdir==-1 ? 1 : 0

//Colors
filt_color = upward ? #05ff9b : downward ? #ff0583 : #cccccc
bar_color  = upward and (close > filt) ? (close > close[1] ? #05ff9b : #00b36b) :
             downward and (close < filt) ? (close < close[1] ? #ff0583 : #b8005d) : #cccccc

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Plot
filt_plot = plot(filt, color=filt_color, linewidth=3, transp=0, title="Filter")

//Band Plots
h_band_plot = plot(h_band, color=#05ff9b, transp=100, title="High Band")
l_band_plot = plot(l_band, color=#ff0583, transp=100, title="Low Band")

//Band Fills
fill(h_band_plot, filt_plot, color=#00b36b, transp=85, title="High Band Fill")
fill(l_band_plot, filt_plot, color=#b8005d, transp=85, title="Low Band Fill")

//Bar Color
barcolor(bar_color)

//External Trend Output
plot(fdir, transp=100, editable=false, display=display.none, title="External Output - Trend Signal")


strategy = fdir
plot(strategy, "Strategy Signal", display=display.none)

Overview

Inspired by QQE volatility concepts, it calculates a smooth range using methods such as ATR, Average Change, Standard Deviation, or fixed units like pips and percentages. Price movements that fall within the threshold are gated, and target ranges are plotted alongside trend-based custom bar coloring. User settings allow tuning the filter type, movement source, range multiplier, smoothing periods, and change-averaging samples.

Details

Published by

theupslidedown on GitHub

Code credit

DonovanWall, as written in the script's header

Type

Indicator, Pine Script v4

Draws

On the price chart

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Filter TypestringType 1f_type
Movement SourcestringClosemov_src
Range Sizefloat2.618rng_qty
Range ScalestringAverage Changerng_scale
Range Period (for ATR, Average Change, and Standard Deviation)int14rng_per
Smooth Rangebooltruesmooth_range
Smoothing Periodint27smooth_per
Average Filter Changesboolfalseav_vals
Number Of Changes To Averageint2av_samples
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

Chandelier Exit

by everget
947 stars

This indicator plots an ATR-based Chandelier Exit trailing stop on the price chart. It tracks a long stop under recent highs and a short stop above recent lows, then switches direction when price crosses the opposite stop. Buy and sell labels mark those flips.

Indicator v6 Volatility & bandsTrend Repaints
Updated 12 days ago · GPL-3.0 GitHub repository of Chandelier Exit

The Momentum Setup is a multi-indicator visual tool designed for trend and momentum analysis directly on the price chart. It combines Relative Strength Index (RSI), Money Flow Index (MFI), Commodity Channel Index (CCI), Supertrend, and a 250-bar percentage cha

Indicator v5 Oscillators & momentumTrend
Updated 1 year ago · MPL-2.0 GitHub repository of Momentum Setup - Ankush Bajaj Momentum Investing Setup
330 stars

Range Filter [Alorse] is a technical indicator overlay for TradingView designed to filter market volatility and identify price trends. It calculates a smoothed range based on historical volatility using a configurable sampling period and multiplier applied to

Indicator v5 TrendVolatility & bands
Updated 2 months ago · None stated GitHub repository of Range Filter [Alorse]
318 stars

This indicator calculates an ATR trailing stop line derived from the highest high minus an average true range multiple over a specified lookback period. It plots the trailing stop line directly on the price chart and colors price bars based on whether the clos

Indicator v5 TrendVolatility & bands
Updated 2 months ago · MIT GitHub repository of ATR Trailing Stoploss

NVDA Trend Ribbon

by longsurf-ai
280 stars

This indicator plots three exponential moving averages and ATR volatility envelopes on the price chart. It compares the fast and slow EMAs to shade a trend ribbon and marks confirmed upward and downward crossovers with triangle labels. Settings change the thre

Indicator v6 TrendMoving averages
Updated 3 days ago · MIT GitHub repository of NVDA Trend Ribbon

[RS]Donchian Fans

by ricardosantos79
261 stars

This indicator plots Donchian Channel boundary lines along with dynamic fan projections directly on the price chart. It calculates the highest high, lowest low, and median price over a customizable lookback period. Whenever price establishes a new channel high

Indicator v4 Support & resistanceTrend
Updated 4 years ago · None stated GitHub repository of [RS]Donchian Fans

More Trend scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers