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
|