Reputation: 11
I created a function that computes an adaptive ATR with the period coming from estimations using fft on a certain window. the highpass and supersmoother functions come from Jhon Ehlers work; they select data with cycles periods between 10 and 48 observations.
def dominant_cycle(close):
close = highpass_filter(close)
close = close[-int(np.floor(len(close) / 2)):]
close = super_smoother(close)
close = close / np.std(close)
ft = np.fft.fft(close)
FFT = pd.DataFrame()
FFT['amp'] = np.sqrt(ft.real**2 + ft.imag**2) / (len(close) / 2)
plt.plot(FFT['amp'])
FFT['freq'] = np.fft.fftfreq(ft.size, d=1)
max_ = FFT.iloc[FFT['amp'].idxmax()]
max_freq = max_['freq']
print(max_)
# Check if max_freq is zero to avoid division by zero
if max_freq == 0:
return 48
cycle = np.floor(0.5 / max_freq)
if cycle < 10:
return 10
elif cycle > 48:
return 48
else:
return cycle
def adaptive_atr(data, window=100):
high = np.array(data['High'])
low = np.array(data['Low'])
close = np.array(data['Close'])
period=np.zeros_like(close)
atr = np.zeros_like(close)
center=np.zeros_like(close)
center[:window]=close[:window]
atr[window-1] = np.mean(np.maximum.reduce([high[:window] - low[:window],
np.abs(high[:window] - np.roll(close, 1)[:window]),
np.abs(low[:window] - np.roll(close, 1)[:window])]))
for i in range(window, len(data)):
period[i] = dominant_cycle(close[i - window + 1:i])
# Calculate true ranges
tr1 = high[i] - low[i]
tr2 = np.abs(high[i] - np.roll(close, 1)[i])
tr3 = np.abs(low[i] - np.roll(close, 1)[i])
tr = max(tr1, tr2, tr3)
atr[i] = (atr[i - 1] * (period[i] - 1) + tr) / period[i]
center[i]=(center[i - 1] * (period[i] - 1) + close[i]) / period[i]
return atr,center,period
What do you think? how can I improve? should I compute the fft of the autocorrelation vector? should I use the Goertzel alg? Thank you :)
Upvotes: 1
Views: 50