Skip to content

Commit cee8a99

Browse files
committed
Added KeltnerChannels
1 parent f4c7a23 commit cee8a99

File tree

1 file changed

+110
-2
lines changed

1 file changed

+110
-2
lines changed

src/rtta.pyx

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ cdef class Delay:
103103

104104

105105
cdef class EMA:
106-
"""SMA - Simple Moving Average
106+
"""EMA - Exponential moving average
107107
108108
Args:
109-
window(int): n period
109+
window(int): decay rate
110110
fillna(bool): if True, fill nan values
111111
"""
112112

@@ -165,6 +165,49 @@ cdef class EMA:
165165
self.last_value = l
166166
return retval
167167

168+
cdef class EWMA:
169+
"""EWMA - Exponentailly Weighted Moving Average
170+
171+
EWMA (Exponentially Weighted Moving Average) is a statistical
172+
technique that smooths time series data by applying exponentially
173+
decreasing weights to past observations, giving more importance to
174+
recent values. It’s commonly used in forecasting and process
175+
control to detect trends or shifts over time.
176+
177+
Args:
178+
window(int): decay rate
179+
fillna(bool): if True, fill nan values
180+
"""
181+
182+
cdef double alpha
183+
cdef double last
184+
cdef bint first
185+
186+
def __init__(self, alpha=None, span=None, com=None, bint fillna=False):
187+
if sum(x is not None for x in (alpha, span, com)) != 1:
188+
raise ValueError("You must define one of alpha, span or com");
189+
if alpha is not None:
190+
self.alpha = alpha
191+
elif span is not None:
192+
self.alpha = 2 / (span + 1)
193+
elif com is not None:
194+
self.alpha = 1 / (com + 1)
195+
196+
self.first = True
197+
198+
if 0 < self.alpha <= 1:
199+
return
200+
raise ValueError("EWMA's alpha parameter must be in the range 0<⍺<=1")
201+
202+
cpdef double update(self, double value):
203+
if self.first:
204+
self.last = value
205+
self.first = False
206+
else:
207+
self.last = self.alpha * value + (1 - self.alpha) * self.last
208+
return self.last
209+
210+
168211
cdef class Kama():
169212
"""
170213
Args:
@@ -227,8 +270,73 @@ cdef class Kama():
227270
output_view[i] = self.update(input_view[i])
228271
return retval
229272

273+
cdef class KeltnerChannel():
274+
"""KeltnerChannel - Keltner Channels
275+
Keltner Channels are a trend-following tool that helps spot
276+
potential reversals by tracking price breakouts and the direction
277+
of the channel. When the market is moving sideways, they can also
278+
indicate overbought or oversold conditions.
279+
280+
Args:
281+
window: n period
282+
fillna: True/False
283+
multiplier: Defaults to 2
284+
"""
285+
cdef EWMA middle
286+
cdef ATR atr
287+
cdef double multiplier
288+
cdef bint start
230289

290+
def __init__(self, span=20, window_atr=20, fillna=False, multiplier = 2):
291+
self.atr = ATR(window_atr)
292+
self.middle = EWMA(span=span)
293+
self.multiplier = multiplier
294+
self.start = True
295+
296+
def update(self, double close, double high, double low):
297+
cdef double atr = self.atr.update(close, high, low)
298+
cdef double tp = self.middle.update(close)
299+
return (
300+
tp,
301+
tp + (self.multiplier * atr),
302+
tp - (self.multiplier * atr)
303+
)
304+
305+
306+
cdef class KeltnerChannelOriginal():
307+
"""KeltnerChannel - Keltner Channels
308+
Keltner Channels are a trend-following tool that helps spot
309+
potential reversals by tracking price breakouts and the direction
310+
of the channel. When the market is moving sideways, they can also
311+
indicate overbought or oversold conditions.
231312
313+
Args:
314+
window: n period
315+
window_atr: n atr period. Only used if origin is False
316+
fillna: True/False
317+
multiplier: Defaults to 2
318+
"""
319+
320+
cdef int window
321+
cdef bint fillna
322+
cdef double multiplier
323+
324+
cdef SMA high
325+
cdef SMA middle
326+
cdef SMA low
327+
328+
def __init__(self, window=20, fillna=False):
329+
self.high = SMA(window, fillna=fillna)
330+
self.middle = SMA(window, fillna=fillna)
331+
self.low = SMA(window, fillna=fillna)
332+
333+
cpdef update(self, double close, double high, double low):
334+
return (
335+
self.middle.update((high + close + low) / 3.0),
336+
self.high.update((high * 4 + close - 2 * low) / 3.0),
337+
self.low.update((close + 4 * low - 2*high) / 3.0)
338+
)
339+
232340

233341
cdef class MACD():
234342
"""MCAD - Moving average convergence divergence.

0 commit comments

Comments
 (0)