range-filter-signals/tests/reference.py
Allan Niñal Allan Niñal 018c36a70a Range Filter Signals: free MT5 and MT4 indicator source, Python reference, tests and README
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 16:07:16 +08:00
56 lines
2.1 KiB
Python
# 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