コード例 #1
0
    def get_moving_average_analysis(data, current_moving_average, time_period):

        time_period_unit_moving_average = tulipy.sma(data, time_period)

        # equalize array size
        min_len_arrays = min(len(time_period_unit_moving_average), len(current_moving_average))

        # compute difference between 1 unit values and others ( >0 means currently up the other one)
        values_difference = (current_moving_average[-min_len_arrays:] - time_period_unit_moving_average[-min_len_arrays:])
        values_difference = DataUtil.drop_nan(values_difference)

        if len(values_difference):
            # indexes where current_unit_moving_average crosses time_period_unit_moving_average
            crossing_indexes = TrendAnalysis.get_threshold_change_indexes(values_difference, 0)

            multiplier = 1 if values_difference[-1] > 0 else -1

            # check at least some data crossed 0
            if crossing_indexes:
                normalized_data = DataUtil.normalize_data(values_difference)
                current_value = min(abs(normalized_data[-1])*2, 1)
                if math.isnan(current_value):
                    return 0
                # check <= values_difference.count()-1if current value is max/min
                if current_value == 0 or current_value == 1:
                    chances_to_be_max = TrendAnalysis.get_estimation_of_move_state_relatively_to_previous_moves_length(
                                                                                                    crossing_indexes,
                                                                                                    values_difference)
                    return multiplier*current_value*chances_to_be_max
                # other case: maxima already reached => return distance to max
                else:
                    return multiplier*current_value

        # just crossed the average => neutral
        return 0
コード例 #2
0
    def eval_impl(self):
        self.eval_note = START_PENDING_EVAL_NOTE
        long_period_length = 26
        if len(self.data[PriceIndexes.IND_PRICE_CLOSE.value]) >= long_period_length:
            macd, macd_signal, macd_hist = tulipy.macd(self.data[PriceIndexes.IND_PRICE_CLOSE.value], 12,
                                                       long_period_length, 9)

            # on macd hist => M pattern: bearish movement, W pattern: bullish movement
            #                 max on hist: optimal sell or buy
            macd_hist = DataUtil.drop_nan(macd_hist)
            zero_crossing_indexes = TrendAnalysis.get_threshold_change_indexes(macd_hist, 0)
            last_index = len(macd_hist) - 1
            pattern, start_index, end_index = PatternAnalyser.find_pattern(macd_hist, zero_crossing_indexes,
                                                                           last_index)

            if pattern != PatternAnalyser.UNKNOWN_PATTERN:

                # set sign (-1 buy or 1 sell)
                sign_multiplier = -1 if pattern == "W" or pattern == "V" else 1

                # set pattern time frame => W and M are on 2 time frames, others 1
                pattern_move_time = 2 if (pattern == "W" or pattern == "M") and end_index == last_index else 1

                # set weight according to the max value of the pattern and the current value
                current_pattern_start = start_index
                price_weight = macd_hist[-1] / macd_hist[current_pattern_start:].max() if sign_multiplier == 1 \
                    else macd_hist[-1] / macd_hist[current_pattern_start:].min()

                if not math.isnan(price_weight):
                    self._analyse_pattern(pattern, macd_hist, zero_crossing_indexes, price_weight,
                                          pattern_move_time, sign_multiplier)
コード例 #3
0
 def get_average_strategy_eval(self, exchange, active_only=False):
     eval_list = [
         s.get_eval_note()
         for s in self.get_strategies_eval_list(exchange, active_only)
         if isinstance(s.get_eval_note(), (int, float))
     ]
     return DataUtil.mean(eval_list)
コード例 #4
0
    async def eval_impl(self):
        self.eval_note = False
        short_period = 35  # standard with klinger
        long_period = 55  # standard with klinger
        ema_signal_period = 13  # standard ema signal for klinger
        kvo = tulipy.kvo(self.data[PriceIndexes.IND_PRICE_HIGH.value],
                         self.data[PriceIndexes.IND_PRICE_LOW.value],
                         self.data[PriceIndexes.IND_PRICE_CLOSE.value],
                         self.data[PriceIndexes.IND_PRICE_VOL.value],
                         short_period, long_period)
        kvo = DataUtil.drop_nan(kvo)
        if len(kvo) >= ema_signal_period:

            kvo_ema = tulipy.ema(kvo, ema_signal_period)
            ema_difference = kvo - kvo_ema

            if len(ema_difference) > 1:
                zero_crossing_indexes = TrendAnalysis.get_threshold_change_indexes(
                    ema_difference, 0)
                max_elements = 7
                to_consider_kvo = min(
                    max_elements,
                    len(ema_difference) - zero_crossing_indexes[-1])
                self.eval_note = TrendAnalysis.min_has_just_been_reached(
                    ema_difference[-to_consider_kvo:],
                    acceptance_window=0.9,
                    delay=1)
コード例 #5
0
    def eval_impl(self):
        self.eval_note = START_PENDING_EVAL_NOTE
        period_length = 14
        if len(self.data[
                PriceIndexes.IND_PRICE_HIGH.value]) > period_length + 10:
            min_adx = 7.5
            max_adx = 45
            neutral_adx = 25
            adx = tulipy.adx(self.data[PriceIndexes.IND_PRICE_HIGH.value],
                             self.data[PriceIndexes.IND_PRICE_LOW.value],
                             self.data[PriceIndexes.IND_PRICE_CLOSE.value],
                             period_length)
            instant_ema = tulipy.ema(
                self.data[PriceIndexes.IND_PRICE_CLOSE.value], 2)
            slow_ema = tulipy.ema(
                self.data[PriceIndexes.IND_PRICE_CLOSE.value], 20)
            adx = DataUtil.drop_nan(adx)

            if len(adx):
                current_adx = adx[-1]
                current_slows_ema = slow_ema[-1]
                current_instant_ema = instant_ema[-1]

                multiplier = -1 if current_instant_ema < current_slows_ema else 1

                # strong adx => strong trend
                if current_adx > neutral_adx:
                    # if max adx already reached => when ADX forms a top and begins to turn down, you should look for a
                    # retracement that causes the price to move toward its 20-day exponential moving average (EMA).
                    adx_last_values = adx[-15:]
                    adx_last_value = adx_last_values[-1]

                    local_max_adx = adx_last_values.max()
                    # max already reached => trend will slow down
                    if adx_last_value < local_max_adx:

                        self.eval_note = multiplier * (
                            current_adx - neutral_adx) / (local_max_adx -
                                                          neutral_adx)

                    # max not reached => trend will continue, return chances to be max now
                    else:
                        crossing_indexes = TrendAnalysis.get_threshold_change_indexes(
                            adx, neutral_adx)
                        chances_to_be_max = \
                            TrendAnalysis.get_estimation_of_move_state_relatively_to_previous_moves_length(
                                crossing_indexes, adx) if len(crossing_indexes) > 2 \
                                else 0.75
                        proximity_to_max = min(1, current_adx / max_adx)
                        self.eval_note = multiplier * proximity_to_max * chances_to_be_max

                # weak adx => change to come
                else:
                    self.eval_note = multiplier * min(1, (
                        (neutral_adx - current_adx) / (neutral_adx - min_adx)))
コード例 #6
0
 def get_progress(self):
     if not self.min_time_frame_to_consider:
         return 0
     else:
         progresses = []
         for symbol in self.time_frame_get_times:
             if symbol in self.min_time_frame_to_consider:
                 current = self.time_frame_get_times[symbol][self.min_time_frame_to_consider[symbol]]
                 nb_max = len(self.data[symbol][self.min_time_frame_to_consider[symbol]])
                 progresses.append(current / nb_max)
         return int(DataUtil.mean(progresses) * 100)
コード例 #7
0
 def _get_rsi_averages(self):
     # compute the slow and fast RSI average
     if len(self.data[
             PriceIndexes.IND_PRICE_CLOSE.value]) > self.period_length:
         rsi_v = tulipy.rsi(self.data[PriceIndexes.IND_PRICE_CLOSE.value],
                            period=self.period_length)
         rsi_v = DataUtil.drop_nan(rsi_v)
         if len(rsi_v):
             slow_average = numpy.mean(rsi_v[-self.slow_eval_count:])
             fast_average = numpy.mean(rsi_v[-self.fast_eval_count:])
             return slow_average, fast_average, rsi_v
     return None, None, None
コード例 #8
0
    def _find_optimal_configuration_using_results(self):
        for time_frame in self.all_time_frames:
            time_frame_sorted_results = self.get_sorted_results(self.run_results, time_frame)
            self.sorted_results_by_time_frame[time_frame.value] = time_frame_sorted_results

        results_through_all_time_frame = {}
        for results in self.sorted_results_by_time_frame.values():
            for rank, result in enumerate(results):
                result_summary = result.get_config_summary()
                if result_summary not in results_through_all_time_frame:
                    results_through_all_time_frame[result_summary] = [[], 0]
                results_through_all_time_frame[result_summary][RANK] += rank
                results_through_all_time_frame[result_summary][TRADES] += result.trades_counts

        result_list = [(result, trades_and_rank[RANK], DataUtil.mean(trades_and_rank[TRADES]))
                       for result, trades_and_rank in results_through_all_time_frame.items()]
        self.sorted_results_through_all_time_frame = sorted(result_list, key=lambda res: res[RANK])
コード例 #9
0
    def eval_impl(self):
        eval_proposition = START_PENDING_EVAL_NOTE
        short_period = 35  # standard with klinger
        long_period = 55  # standard with klinger
        ema_signal_period = 13  # standard ema signal for klinger
        kvo = tulipy.kvo(self.data[PriceIndexes.IND_PRICE_HIGH.value],
                         self.data[PriceIndexes.IND_PRICE_LOW.value],
                         self.data[PriceIndexes.IND_PRICE_CLOSE.value],
                         self.data[PriceIndexes.IND_PRICE_VOL.value],
                         short_period, long_period)
        kvo = DataUtil.drop_nan(kvo)
        if len(kvo) >= ema_signal_period:
            kvo_ema = tulipy.ema(kvo, ema_signal_period)

            ema_difference = kvo - kvo_ema

            if len(ema_difference) > 1:
                zero_crossing_indexes = TrendAnalysis.get_threshold_change_indexes(
                    ema_difference, 0)

                current_difference = ema_difference[-1]
                significant_move_threshold = numpy.std(ema_difference)

                factor = 0.2

                if TrendAnalysis.peak_has_been_reached_already(
                        ema_difference[zero_crossing_indexes[-1]:]):
                    if abs(current_difference) > significant_move_threshold:
                        factor = 1
                    else:
                        factor = 0.5

                eval_proposition = current_difference * factor / significant_move_threshold

                if abs(eval_proposition) > 1:
                    eval_proposition = 1 if eval_proposition > 0 else -1

        self.eval_note = eval_proposition
コード例 #10
0
    def _create_orders(self, lower_bound, upper_bound, side, sorted_orders,
                       portfolio, current_price, missing_orders, state):

        if lower_bound >= upper_bound:
            self.logger.warning(f"No {side} orders for {self.symbol} possible: current price beyond boundaries.")
            return []

        orders = []
        selling = side == TradeOrderSide.SELL

        currency, market = split_symbol(self.symbol)
        order_limiting_currency = currency if selling else market

        order_limiting_currency_amount = portfolio[order_limiting_currency][Portfolio.AVAILABLE] \
            if order_limiting_currency in portfolio else 0
        if state == self.NEW:
            # create staggered orders

            starting_bound = lower_bound * (1 + self.spread / 2) if selling else upper_bound * (1 - self.spread / 2)
            self.flat_spread = AbstractTradingModeCreator.adapt_price(self.symbol_market,
                                                                      current_price * self.spread)
            orders_count, average_order_quantity = \
                self._get_order_count_and_average_quantity(current_price, selling, lower_bound,
                                                           upper_bound, order_limiting_currency_amount,
                                                           currency=order_limiting_currency)
            for i in range(orders_count):
                price = self._get_price_from_iteration(starting_bound, selling, i)
                if price is not None:
                    quantity = self._get_quantity_from_iteration(average_order_quantity, self.mode,
                                                                 side, i, orders_count, price)
                    if quantity is not None:
                        orders.append(OrderData(side, quantity, price, self.symbol))
            if not orders:
                self.logger.error(f"Not enough {order_limiting_currency} to create {side.name} orders. "
                                  f"For the strategy to work better, add {order_limiting_currency} funds or "
                                  f"change change the strategy settings to make less but bigger orders.")
            else:
                orders.reverse()

        if state == self.FILL:
            # complete missing orders
            if missing_orders:
                max_quant_per_order = order_limiting_currency_amount / len(missing_orders)
                missing_orders_around_spread = []
                for missing_order_price, missing_order_side in missing_orders:
                    if missing_order_side == side:
                        previous_o = None
                        following_o = None
                        for o in sorted_orders:
                            if previous_o is None:
                                previous_o = o
                            elif o.origin_price > missing_order_price:
                                following_o = o
                                break
                            else:
                                previous_o = o
                        if previous_o.side == following_o.side:
                            # missing order between similar orders
                            quantity = min(DataUtil.mean([previous_o.origin_quantity, following_o.origin_quantity]),
                                           max_quant_per_order / missing_order_price)
                            orders.append(OrderData(missing_order_side, quantity,
                                                    missing_order_price, self.symbol, False))
                            self.logger.debug(f"Creating missing orders not around spread: {orders[-1]}")
                        else:
                            missing_orders_around_spread.append((missing_order_price, missing_order_side))

                if missing_orders_around_spread:
                    # missing order next to spread
                    starting_bound = upper_bound if selling else lower_bound
                    increment_window = self.flat_increment/2
                    order_limiting_currency_available_amount = \
                        portfolio[order_limiting_currency][Portfolio.AVAILABLE] \
                        if order_limiting_currency in portfolio else 0
                    portfolio_total = portfolio[order_limiting_currency][Portfolio.TOTAL] \
                        if order_limiting_currency in portfolio else 0
                    order_limiting_currency_amount = portfolio_total
                    if order_limiting_currency_available_amount:
                        orders_count, average_order_quantity = \
                            self._get_order_count_and_average_quantity(current_price, selling, lower_bound,
                                                                       upper_bound, portfolio_total,
                                                                       currency=order_limiting_currency)
                        for missing_order_price, missing_order_side in missing_orders_around_spread:
                            limiting_amount_from_this_order = order_limiting_currency_amount
                            price = starting_bound
                            found_order = False
                            i = 0
                            while not found_order and i < orders_count:
                                quantity = self._get_quantity_from_iteration(average_order_quantity, self.mode,
                                                                             side, i, orders_count,
                                                                             price)
                                limiting_currency_quantity = quantity if selling else quantity / price
                                if price is not None and limiting_amount_from_this_order > 0 and \
                                        price-increment_window <= missing_order_price <= price+increment_window:

                                    if limiting_currency_quantity > limiting_amount_from_this_order or \
                                            limiting_currency_quantity > order_limiting_currency_available_amount:
                                        limiting_currency_quantity = min(limiting_amount_from_this_order,
                                                                         order_limiting_currency_available_amount)
                                    found_order = True
                                    if limiting_currency_quantity is not None:
                                        orders.append(OrderData(side, limiting_currency_quantity, price,
                                                                self.symbol, False))
                                        self.logger.debug(f"Creating missing order around spread {orders[-1]}")
                                price = price - self.flat_increment if selling else price + self.flat_increment
                                limiting_amount_from_this_order -= limiting_currency_quantity
                                i += 1

        elif state == self.ERROR:
            self.logger.error("Impossible to create staggered orders when incompatible order are already in place. "
                              "Cancel these orders of you want to use this trading mode.")
        return orders
コード例 #11
0
 def get_average_trades_count(self):
     return DataUtil.mean(self.trades_counts)
コード例 #12
0
 def get_average_score(self):
     bot_profitabilities = [
         profitability_result[self.BOT_PROFITABILITY] - profitability_result[self.MARKET_PROFITABILITY]
         for profitability_result in self.run_profitabilities]
     return DataUtil.mean(bot_profitabilities)