class EhlersWayBandpass(Function):
    def __init__(self, input_, period, delta):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)
        self.__delta = FunctionInput(delta)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= min(len(self.__period), len(
                self.__delta)) or len(self) + 5 > len(self.__input):
            raise StopIteration

        self.inputs.sync({self.__input: 5})

        period = self.__period.consume()
        delta = self.__delta.consume()

        beta = math.cos(2 * math.pi / period)
        gamma = 1 / math.cos(4 * math.pi * delta / period)
        alpha = gamma - math.sqrt(gamma * gamma - 1)

        i = self.__input.consumed
        bp2 = self._values[-min(len(self), 2)] if len(self) >= 1 else 0.5 * (
            1 - alpha) * (self.__input[i - 2] - self.__input[i - 4])
        bp1 = self._values[-1] if len(self) >= 2 else 0.5 * (1 - alpha) * (
            self.__input[i - 1] - self.__input[i - 3]) + beta * (1 +
                                                                 alpha) * bp2
        bp = 0.5 * (1 - alpha) * (self.__input[i] - self.__input[i - 2]
                                  ) + beta * (1 + alpha) * bp1 - alpha * bp2

        self._values.append(bp)
        self.__input.consume()
Exemple #2
0
class ZScore(Function):
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.__period) or len(self) + int(
                self.__period.max) > len(self.__input):
            raise StopIteration

        self.inputs.sync({self.__input: int(self.__period.max)})

        latest_input = self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))

        input_ = self.__input[self.__input.consumed -
                              period:self.__input.consumed]
        mean = np.mean(input_)
        std = np.std(input_)

        self._values.append((latest_input - mean) / std)
Exemple #3
0
class Ema(Function):
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        Function.__init__(self)

    def _first(self):
        self.inputs.update()

        if len(self.__period) == 0 or int(self.__period.max) > len(self.__input):
            raise StopIteration

        self.inputs.sync({self.__input: int(self.__period.max)})

        self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))

        self._values.append(np.mean(self.__input[self.__input.consumed - period:self.__input.consumed]))

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.__period) or len(self) + int(self.__period.max) > len(self.__input):
            raise StopIteration

        input_ = self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))

        weight = 2 / (period + 1)

        self._values.append((input_ - self._values[-1]) * weight + self._values[-1])
Exemple #4
0
class Low(Function):
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        self.__last_boundary = 0
        self.__last_period = None
        self.lows = []

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.__period) or len(self) + int(
                self.__period.max) > len(self.__input):
            raise StopIteration

        self.inputs.sync({self.__input: int(self.__period.max)})

        self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))

        if self.__last_period is None:
            self.__last_period = period

        if (len(self) - self.__last_boundary) % self.__last_period > 0:
            self._values.append(self._values[-1])
        else:
            self.__last_boundary = len(self)
            self._values.append(
                min(self.__input[self.__input.consumed -
                                 self.__last_period:self.__input.consumed]))
            self.__last_period = period
            self.lows.append((self._values[-1], self.__last_boundary))
Exemple #5
0
class StandardDeviation(Function):
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        self.__mean = 0.0
        self.__error_sum = 0.0
        self.__variance = 0.0

        Function.__init__(self)

    def _first(self):
        self.inputs.update()

        if len(self.__period) == 0 or int(self.__period.max) > len(
                self.__input):
            raise StopIteration

        self.inputs.sync({self.__input: int(self.__period.max)})

        self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))

        input_ = np.array(self.__input[self.__input.consumed -
                                       period:self.__input.consumed])
        self.__mean = np.mean(input_)
        self.__error_sum = np.sum((input_ - self.__mean)**2)
        self.__variance = self.__error_sum / period

        self._values.append(np.sqrt(self.__variance))

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.__period) or len(self) + int(
                self.__period.max) > len(self.__input):
            raise StopIteration

        value_discard = self.__input[self.__input.consumed - 1]
        value_new = self.__input.consume()
        period_discard = int(
            min(self.__period[self.__period.consumed - 1], self.__period.max))
        period_new = int(min(self.__period.consume(), self.__period.max))

        delta_new_discard = value_new - value_discard
        delta_discard_mean = value_discard - self.__mean

        delta_new_mean_before = value_new - self.__mean
        self.__mean += delta_new_discard / period_new
        delta_new_mean_after = value_new - self.__mean

        self.__error_sum -= (
            (delta_discard_mean * delta_discard_mean -
             delta_new_mean_before * delta_new_mean_after) * period_discard +
            delta_new_discard * delta_new_mean_after) / (period_discard - 1)
        self.__variance = abs(self.__error_sum / period_new)

        self._values.append(np.sqrt(self.__variance))
Exemple #6
0
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        self.__last_boundary = 0
        self.__last_period = None
        self.lows = []

        Function.__init__(self)
Exemple #7
0
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        self.__mean = 0.0
        self.__error_sum = 0.0
        self.__variance = 0.0

        Function.__init__(self)
Exemple #8
0
    def __init__(self, input_, period, zrange, alpha):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)
        self.__zrange = FunctionInput(zrange)
        self.__alpha = FunctionInput(alpha)

        self.__zscore = FunctionInput(ZScore(input_, period))

        self.__entropy = 1.0
        self.__ema = 0

        Function.__init__(self)
Exemple #9
0
class Rsi(Function):
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        self.__slope = FunctionInput(Slope(input_))
        self.__average_gain = None
        self.__average_loss = None

        Function.__init__(self)

    def _first(self):
        self.inputs.update()

        if len(self.__period) == 0 or int(self.__period.max) > len(
                self.__slope):
            raise StopIteration

        self.inputs.sync({self.__slope: int(self.__period.max)})

        self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))
        self.__slope.consume()

        self.__average_gain = np.mean([
            max(d, 0) for d in self.__slope[self.__slope.consumed -
                                            period:self.__slope.consumed]
        ])
        self.__average_loss = np.mean([
            min(d, 0) for d in self.__slope[self.__slope.consumed -
                                            period:self.__slope.consumed]
        ])

        self._values.append(
            100 - 100 / (1 + self.__average_gain / -self.__average_loss)
        )  # XXX We'll need some kind of zero division protection

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.__period) or len(self) + int(
                self.__period.max) > len(self.__slope):
            raise StopIteration

        self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))
        slope = self.__slope.consume()

        self.__average_gain = (self.__average_gain *
                               (period - 1) + max(slope, 0)) / period
        self.__average_loss = (self.__average_loss *
                               (period - 1) + min(slope, 0)) / period

        self._values.append(100 - 100 /
                            (1 + self.__average_gain / -self.__average_loss))
Exemple #10
0
class ChangePeriod(Function):
    def __init__(self, input_, change, period):
        self.__input = FunctionInput(input_)
        self.__change = FunctionInput(change)
        self.__period = FunctionInput(period)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= min(len(self.__change), len(
                self.__period)) or len(self) + int(self.__period.max) > len(
                    self.__input):
            raise StopIteration

        self.inputs.sync({self.__input: int(self.__period.max)})

        self.__input.consume()
        change = self.__change.consume()
        period = int(min(self.__period.consume(), self.__period.max))

        frequencies = np.fft.rfftfreq(period)[::-1]

        samples = np.array(self.__input[self.__input.consumed -
                                        period:self.__input.consumed])
        min_ = np.min(samples)
        range_ = np.max(samples) - min_

        fourier_transform = np.fft.rfft(2 * (samples - min_) / range_ -
                                        1) / (0.5 * period)

        magnitude = np.abs(fourier_transform)[::-1]

        target_magnitude = np.mean(samples) * abs(0.5 * change) / range_

        if target_magnitude <= np.max(magnitude):
            if target_magnitude > magnitude[0]:
                for i, m in enumerate(magnitude):
                    if m >= target_magnitude:
                        x = (m - target_magnitude) / (m - magnitude[i - 1])
                        frequency = frequencies[i - 1] * x + frequencies[i] * (
                            1 - x)
                        self._values.append(min(1 / frequency, period))
                        break
            else:
                self._values.append(1 / frequencies[0])
        else:
            self._values.append(period)
Exemple #11
0
    def __init__(self, input_, std_dev_period, band_min, band_max, band_count,
                 interpolate):
        self.__input = FunctionInput(input_)
        self.__interpolate = interpolate

        self.__band_periods = np.geomspace(band_min, band_max, band_count)
        self.__bands = list(
            FunctionInput(
                StandardDeviation(EhlersWayBandpass(input_, period, 0.5),
                                  std_dev_period))
            for period in self.__band_periods)
        for i, band in enumerate(self.__bands):
            setattr(self, "_DominantBand__band{}".format(i), band)

        Function.__init__(self)
Exemple #12
0
class Slope(Function):
    def __init__(self, input_):
        self.__input = FunctionInput(input_)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) + 2 > len(self.__input):
            raise StopIteration

        self.inputs.sync({self.__input: 2})

        self._values.append(self.__input[self.__input.consumed] -
                            self.__input[self.__input.consumed - 1])
        self.__input.consume()
    def __init__(self, input_, pooling_period, period_count, multiplier):
        self.__period_count = FunctionInput(period_count)
        self.__multiplier = FunctionInput(multiplier)

        self.__low = FunctionInput(Low(Skip(input_, 1), pooling_period))
        self.__atr = FunctionInput(Atr(input_, pooling_period, period_count))

        self.__current_period = 0
        self.__current_period_count = None

        Function.__init__(self)
Exemple #14
0
class AroonOscillator(Function):
    def __init__(self, input_, period):
        self.__up = FunctionInput(AroonUp(input_, period))
        self.__down = FunctionInput(AroonDown(input_, period))

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.__up):
            raise StopIteration

        self.inputs.sync()

        up = self.__up.consume()
        down = self.__down.consume()

        self._values.append(up - down)
Exemple #15
0
class Subtract(Function):
    def __init__(self, input1, input2):
        self.input1 = FunctionInput(input1)
        self.input2 = FunctionInput(input2)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.input1) or len(self) >= len(self.input2):
            raise StopIteration

        self.inputs.sync()

        a = self.input1.consume()
        b = self.input2.consume()

        self._values.append(a - b)
class ChandelierExitLong(Function):
    def __init__(self, input_, pooling_period, period_count, multiplier):
        self.__period_count = FunctionInput(period_count)
        self.__multiplier = FunctionInput(multiplier)

        self.__high = FunctionInput(High(Skip(input_, 1), pooling_period))
        self.__atr = FunctionInput(Atr(input_, pooling_period, period_count))

        self.__current_period = 0
        self.__current_period_count = None

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= min(len(self.__atr), len(self.__high),
                            len(self.__multiplier)):
            raise StopIteration

        self.inputs.sync()

        period_count = int(
            min(self.__period_count.consume(), self.__period_count.max))
        self.__high.consume()
        atr = self.__atr.consume()
        multiplier = self.__multiplier.consume()

        current_period = max(period + self.__current_period for period, (
            high,
            index) in enumerate(self.__high.highs[self.__current_period:])
                             if index < self.__high.consumed)
        if self.__current_period != current_period:
            self.__current_period = current_period
            self.__current_period_count = period_count

        period_high = max(
            high for high, _ in self.__high.highs[self.__current_period -
                                                  self.__current_period_count +
                                                  1:self.__current_period + 1])
        self._values.append(period_high - atr * multiplier)
Exemple #17
0
class Divide(Function):
    def __init__(self, input1, input2):
        self.input1 = FunctionInput(input1)
        self.input2 = FunctionInput(input2)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.input1) or len(self) >= len(self.input2):
            raise StopIteration

        self.inputs.sync()

        a = self.input1.consume()
        b = self.input2.consume()

        b = b if b != 0 else 0.00000001

        self._values.append(a / b)
Exemple #18
0
class Lerp(Function):
    def __init__(self, input1, input2, x):
        self.input1 = FunctionInput(input1)
        self.input2 = FunctionInput(input2)
        self.x = FunctionInput(x)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= min(len(self.input1), len(self.input2), len(self.x)):
            raise StopIteration

        self.inputs.sync()

        a = self.input1.consume()
        b = self.input2.consume()
        x = self.x.consume()

        self._values.append(a * (1 - x) + b * x)
Exemple #19
0
class DominantBand(Function):
    def __init__(self, input_, std_dev_period, band_min, band_max, band_count,
                 interpolate):
        self.__input = FunctionInput(input_)
        self.__interpolate = interpolate

        self.__band_periods = np.geomspace(band_min, band_max, band_count)
        self.__bands = list(
            FunctionInput(
                StandardDeviation(EhlersWayBandpass(input_, period, 0.5),
                                  std_dev_period))
            for period in self.__band_periods)
        for i, band in enumerate(self.__bands):
            setattr(self, "_DominantBand__band{}".format(i), band)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.__bands[0]):
            raise StopIteration

        self.inputs.sync()

        self.__input.consume()
        std_devs = [band.consume() for band in self.__bands]

        value = 0
        if self.__interpolate:
            value = 1
            normalized_std_devs = np.array(std_devs) / np.sum(std_devs)
            for i in range(0, len(self.__bands)):
                value *= self.__band_periods[i]**normalized_std_devs[i]
        else:
            value = self.__band_periods[np.argmax(std_devs)]

        self._values.append(value)
Exemple #20
0
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        self.__slope = FunctionInput(Slope(input_))
        self.__average_gain = None
        self.__average_loss = None

        Function.__init__(self)
Exemple #21
0
class AroonDown(Function):
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.__period) or len(self) + int(self.__period.max) > len(self.__input):
            raise StopIteration

        self.inputs.sync({self.__input: int(self.__period.max)})

        self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))

        low = (None, None)
        for i in range(self.__input.consumed - period - 1, self.__input.consumed):
            if low[0] is not None and self.__input[i] < low[0] or low[0] is None:
                low = (self.__input[i], self.__input.consumed - i)

        self._values.append(100 * (period - low[1]) / period)
Exemple #22
0
class Skip(Function):
    def __init__(self, input_, skip):
        self.__input = FunctionInput(input_)
        self.__skip = int(skip)

        Function.__init__(self)

    def _next(self):
        self.inputs.update()

        if len(self) + self.__skip > len(self.__input):
            raise StopIteration

        self.inputs.sync({self.__input: self.__skip})

        self._values.append(self.__input.consume())
Exemple #23
0
    def __init__(self, input_, pooling_period, period_count):
        self.__input = FunctionInput(input_)
        self.__pooling_period = FunctionInput(pooling_period)
        self.__period_count = FunctionInput(period_count)

        self.__last_pool_boundary = None
        self.__last_pooling_period = None
        self.__trs = []
        self.atrs = []

        Function.__init__(self)
    def __init__(self, input_, period, delta):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)
        self.__delta = FunctionInput(delta)

        Function.__init__(self)
Exemple #25
0
class EntropyEma(Function):
    def __init__(self, input_, period, zrange, alpha):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)
        self.__zrange = FunctionInput(zrange)
        self.__alpha = FunctionInput(alpha)

        self.__zscore = FunctionInput(ZScore(input_, period))

        self.__entropy = 1.0
        self.__ema = 0

        Function.__init__(self)

    def _first(self):
        self.inputs.update()

        if len(self.__period) == 0 or int(self.__period.max) > len(self.__input): # XXX Add other inputs
            raise StopIteration

        self.inputs.sync({self.__input: int(self.__period.max)})

        self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))
        self.__zrange.consume()
        self.__alpha.consume()

        self.__ema = np.mean(self.__input[self.__input.consumed - period:self.__input.consumed])
        self._values.append(self.__entropy)

    def _next(self):
        self.inputs.update()

        if len(self) >= len(self.__period) or len(self) + int(self.__period.max) > len(self.__input): # XXX
            raise StopIteration

        input_ = self.__input.consume()
        period = int(min(self.__period.consume(), self.__period.max))
        zrange = self.__zrange.consume()
        alpha = self.__alpha.consume()

        old_z = self.__zscore[self.__zscore.consumed - 1]
        z = self.__zscore.consume()

        action = max((abs(z) - abs(old_z)) / zrange, 0)
        if action > 0:
            self.__entropy = max(self.__entropy - action, 0)
        else:
            self.__entropy = 1 - (1 - self.__entropy) * alpha

        weight = 2 / (period + 1)

        #self._values.append((input_ - self._values[-1]) * weight + self._values[-1])
        self._values.append(self.__entropy)
Exemple #26
0
class Atr(Function):
    def __init__(self, input_, pooling_period, period_count):
        self.__input = FunctionInput(input_)
        self.__pooling_period = FunctionInput(pooling_period)
        self.__period_count = FunctionInput(period_count)

        self.__last_pool_boundary = None
        self.__last_pooling_period = None
        self.__trs = []
        self.atrs = []

        Function.__init__(self)

    def _first(self):
        self.inputs.update()

        if min(len(self.__pooling_period), len(self.__period_count)
               ) == 0 or int(self.__pooling_period.max) * int(
                   self.__period_count.max) + 1 > len(self.__input):
            raise StopIteration

        self.inputs.sync({
            self.__input:
            int(self.__pooling_period.max) * int(self.__period_count.max) + 1
        })

        self.__input.consume()
        pooling_period = int(
            min(self.__pooling_period.consume(), self.__pooling_period.max))
        period_count = int(
            max(min(self.__period_count.consume(), self.__period_count.max),
                1))

        for period in range(period_count):
            input_ = self.__input[self.__input.consumed -
                                  (period_count - period) *
                                  pooling_period:self.__input.consumed -
                                  (period_count - period - 1) * pooling_period]
            high = max(input_)
            low = min(input_)
            close = self.__input[self.__input.consumed -
                                 (period_count - period) * pooling_period - 1]

            self.__trs.append(
                max(high - low, abs(high - close), abs(low - close)))

        self.__last_pool_boundary = 0
        self.__last_pooling_period = pooling_period
        self._values.append(np.mean(self.__trs))
        self.atrs.append(self._values[-1])

    def _next(self):
        self.inputs.update()

        if len(self) >= min(
                len(self.__pooling_period), len(self.__period_count)
        ) or len(self) + int(self.__pooling_period.max) * int(
                self.__period_count.max) + 1 > len(self.__input):
            raise StopIteration

        self.__input.consume()
        pooling_period = int(
            min(self.__pooling_period.consume(), self.__pooling_period.max))
        period_count = int(
            max(min(self.__period_count.consume(), self.__period_count.max),
                1))

        if len(self) - self.__last_pool_boundary < self.__last_pooling_period:
            self._values.append(self._values[-1])
        else:
            input_ = self.__input[self.__input.consumed -
                                  self.__last_pooling_period:self.__input.
                                  consumed]
            high = max(input_)
            low = min(input_)
            close = self.__input[self.__input.consumed -
                                 self.__last_pooling_period - 1]

            self.__last_pool_boundary = len(self)
            self.__last_pooling_period = pooling_period
            self.__trs.append(
                max(high - low, abs(high - close), abs(low - close)))
            self._values.append(
                (self._values[-1] *
                 (period_count - 1) + self.__trs[-1]) / period_count)
            self.atrs.append(self._values[-1])
Exemple #27
0
 def __init__(self, value):
     FunctionInput.__init__(self, value)
Exemple #28
0
    def __init__(self, input_, skip):
        self.__input = FunctionInput(input_)
        self.__skip = int(skip)

        Function.__init__(self)
Exemple #29
0
    def __init__(self, input_, period):
        self.__input = FunctionInput(input_)
        self.__period = FunctionInput(period)

        Function.__init__(self)
Exemple #30
0
    def __init__(self, input_):
        self.__input = FunctionInput(input_)

        Function.__init__(self)