# SPDX-License-Identifier: MPL-2.0 # This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not # distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/ # Range filter: method popularised by TradingView open-source scripts, notably "Range Filter [DW]" and its variants. """Python twin of mql5/Include/RangeFilter/RF.mqh, operation for operation (parity tests and the frequency count). from reference import run rows = run(close, period=100, mult=3.0) # per bar: filt, range, upward, downward, cond, ev """ def run(src, period=100, mult=3.0): rows = [] prev = 0.0 avrng = smrng = rng = filt = prev_filt = None up = dn = cond = 0 a1 = 2.0 / (period + 1) wper = 2 * period - 1 a2 = 2.0 / (wper + 1) for k, x in enumerate(src): ev = 0 if k >= 1: d = abs(x - prev) avrng = d if avrng is None else avrng + a1 * (d - avrng) smrng = avrng if smrng is None else smrng + a2 * (avrng - smrng) rng = smrng * mult prev_filt = filt if filt is None: filt = x else: f, r = filt, rng if x > f: filt = f if x - r < f else x - r else: filt = f if x + r > f else x + r if prev_filt is not None: if filt > prev_filt: up, dn = up + 1, 0 elif filt < prev_filt: dn, up = dn + 1, 0 moved = x != prev buy = x > filt and moved and up > 0 sell = x < filt and moved and dn > 0 p = cond if buy: cond = 1 elif sell: cond = -1 if buy and p == -1: ev = 1 elif sell and p == 1: ev = -1 prev = x rows.append(dict(filt=filt, range=rng, up=up, dn=dn, cond=cond, ev=ev, side=1 if up > 0 else (-1 if dn > 0 else 0))) return rows