Пример #1
0
def _update_activation_config(to_update_data, current_config, config_file_path,
                              config_file, deactivate_others):
    from octobot_commons.tentacles_management.class_inspector import get_class_from_string, evaluator_parent_inspection
    something_changed = False
    for element_name, activated in to_update_data.items():
        if element_name in current_config:
            active = activated if isinstance(
                activated, bool) else activated.lower() == "true"
            current_activation = current_config[element_name]
            if current_activation != active:
                get_logger().info(
                    f"{config_file} updated: {element_name} "
                    f"{'activated' if active else 'deactivated'}")
                current_config[element_name] = active
                something_changed = True
    if deactivate_others:
        import evaluator.Strategies as strategies
        for element_name, activated in current_config.items():
            if element_name not in to_update_data:
                if current_config[element_name]:
                    # do not deactivate strategies
                    config_class = get_class_from_string(
                        element_name, strategies.StrategiesEvaluator,
                        strategies, evaluator_parent_inspection)
                    if config_class is None:
                        get_logger().info(
                            f"{config_file} updated: {element_name} "
                            f"{'deactivated'}")
                        current_config[element_name] = False
                        something_changed = True
    if something_changed:
        with open(config_file_path, "w+") as config_file_w:
            config_file_w.write(dump_json(current_config))
Пример #2
0
def get_class(config, class_type) -> object:
    classes = get_classes(config, class_type)
    if classes and len(classes) > 1:
        get_logger(__name__).warning(
            f"More than one instance of {class_type} available, "
            f"using {classes[0]}.")
    return classes[0]
Пример #3
0
    def check_last_prices(self,
                          last_prices,
                          price_to_check,
                          inferior,
                          simulated_time=False) -> bool:
        if last_prices:
            prices = [
                p[ECOC.PRICE.value] for p in last_prices
                if not math.isnan(p[ECOC.PRICE.value]) and (
                    p[ECOC.TIMESTAMP.value] >= self.creation_time
                    or simulated_time)
            ]

            if prices:
                if inferior:
                    if float(min(prices)) < price_to_check:
                        get_logger(self.get_name()).debug(
                            f"{self.symbol} last prices: {prices}, "
                            f"ask for {'inferior' if inferior else 'superior'} "
                            f"to {price_to_check}")
                        return True
                else:
                    if float(max(prices)) > price_to_check:
                        get_logger(self.get_name()).debug(
                            f"{self.symbol} last prices: {prices}, "
                            f"ask for {'inferior' if inferior else 'superior'} "
                            f"to {price_to_check}")
                        return True
        return False
Пример #4
0
def parse_order_type(raw_order):
    try:
        side: TradeOrderSide = TradeOrderSide(
            raw_order[ExchangeConstantsOrderColumns.SIDE.value])
        order_type: TradeOrderType = TradeOrderType(
            raw_order[ExchangeConstantsOrderColumns.TYPE.value])

        if side == TradeOrderSide.BUY:
            if order_type == TradeOrderType.LIMIT or order_type == TradeOrderType.LIMIT_MAKER:
                order_type = TraderOrderType.BUY_LIMIT
            elif order_type == TradeOrderType.MARKET:
                order_type = TraderOrderType.BUY_MARKET
            else:
                order_type = _get_sell_and_buy_types(order_type)
        elif side == TradeOrderSide.SELL:
            if order_type == TradeOrderType.LIMIT or order_type == TradeOrderType.LIMIT_MAKER:
                order_type = TraderOrderType.SELL_LIMIT
            elif order_type == TradeOrderType.MARKET:
                order_type = TraderOrderType.SELL_MARKET
            else:
                order_type = _get_sell_and_buy_types(order_type)
        return side, order_type
    except KeyError:
        get_logger(
            Order.__class__.__name__).error("Failed to parse order type")
        return None, None
Пример #5
0
async def _handle_creation(bot_id, action, data):
    if action == OctoBotChannelTradingActions.EXCHANGE.value:
        try:
            config = data[OctoBotChannelTradingDataKeys.EXCHANGE_CONFIG.value]
            exchange_builder = create_exchange_builder(config,
                                                       data[OctoBotChannelTradingDataKeys.EXCHANGE_NAME.value]) \
                .has_matrix(data[OctoBotChannelTradingDataKeys.MATRIX_ID.value]) \
                .use_tentacles_setup_config(data[OctoBotChannelTradingDataKeys.TENTACLES_SETUP_CONFIG.value]) \
                .set_bot_id(bot_id) \
                .is_rest_only()
            if is_trader_enabled_in_config(config):
                exchange_builder.is_real()
            elif is_trader_simulator_enabled_in_config(config):
                exchange_builder.is_simulated()
            backtesting = data[OctoBotChannelTradingDataKeys.BACKTESTING.value]
            if backtesting is not None:
                exchange_builder.is_backtesting(backtesting)
            await exchange_builder.build()
            await get_chan_at_id(OctoBotChannelsName.OCTOBOT_CHANNEL.value, bot_id).get_internal_producer() \
                .send(bot_id=bot_id,
                      subject=OctoBotChannelSubjects.NOTIFICATION.value,
                      action=action,
                      data={OctoBotChannelTradingDataKeys.EXCHANGE_ID.value: exchange_builder.exchange_manager.id})
        except Exception as e:
            get_logger(OCTOBOT_CHANNEL_TRADING_CONSUMER_LOGGER_TAG).error(f"Error when creating new exchange {e}")
def _is_docker_available() -> bool:
    try:
        _get_client()
        return True
    except docker.errors.NotFound:
        get_logger().error("Docker service not found")
    return False
Пример #7
0
def create_venv_if_necessary(venv_path):
    venv_abs_path = os.path.abspath(venv_path)
    if not _is_venv_installed(venv_path=venv_path):
        get_logger().info(f"Creating a virtual env in {venv_abs_path}")
        _create_venv(venv_path=venv_path)
    else:
        get_logger().info(f"Using virtual env in {venv_abs_path}")
Пример #8
0
async def _handle_creation(bot_id, action, data):
    if action == OctoBotChannelTradingActions.EXCHANGE.value:
        try:
            config = data[OctoBotChannelTradingDataKeys.EXCHANGE_CONFIG.value]
            exchange_builder = create_exchange_builder(config,
                                                       data[OctoBotChannelTradingDataKeys.EXCHANGE_NAME.value]) \
                .has_matrix(data[OctoBotChannelTradingDataKeys.MATRIX_ID.value]) \
                .use_tentacles_setup_config(data[OctoBotChannelTradingDataKeys.TENTACLES_SETUP_CONFIG.value]) \
                .set_bot_id(bot_id)
            _set_exchange_type_details(
                exchange_builder, config,
                data[OctoBotChannelTradingDataKeys.BACKTESTING.value])
            await exchange_builder.build()
            await get_chan_at_id(OctoBotChannelsName.OCTOBOT_CHANNEL.value, bot_id).get_internal_producer() \
                .send(bot_id=bot_id,
                      subject=OctoBotChannelSubjects.NOTIFICATION.value,
                      action=action,
                      data={OctoBotChannelTradingDataKeys.EXCHANGE_ID.value: exchange_builder.exchange_manager.id})
        except TradingModeIncompatibility as e:
            get_logger(OCTOBOT_CHANNEL_TRADING_CONSUMER_LOGGER_TAG).error(
                f"Error when initializing trading mode, {data[OctoBotChannelTradingDataKeys.EXCHANGE_NAME.value]} "
                f"exchange connection is closed to increase performances: {e}")
        except Exception as e:
            get_logger(OCTOBOT_CHANNEL_TRADING_CONSUMER_LOGGER_TAG).error(
                f"Error when creating new exchange: {e}")
Пример #9
0
    async def on_fill_complete(self):
        """
        Post fill actions
        """
        try:
            # compute order fees
            self.fee = self.get_computed_fee()

            get_logger(self.get_logger_name()).debug(
                f"{self.symbol} of size {self.origin_quantity} {self.currency} "
                f"filled {self.filled_quantity} {self.currency} "
                f"on {self.exchange_manager.exchange_name} "
                f"at {self.filled_price}")

            await get_chan(ORDERS_CHANNEL, self.exchange_manager.id).get_internal_producer() \
                .send(cryptocurrency=self.currency,
                      symbol=self.symbol,
                      order=self.to_dict(),
                      is_from_bot=True,
                      is_closed=True,
                      is_updated=False)
            await self.exchange_manager.trader.close_filled_order(self)
        except Exception as e:
            get_logger(self.get_logger_name()).exception(
                e, True, f"Fail to execute fill complete action : {e}.")
Пример #10
0
async def create_trading_mode(
        trading_mode_class: AbstractTradingMode.__class__,
        config: dict,
        exchange_manager: ExchangeManager,
        cryptocurrency: str = None,
        symbol: str = None,
        time_frame: object = None,
        bot_id: str = None) -> AbstractTradingMode:
    try:
        trading_mode: AbstractTradingMode = trading_mode_class(
            config, exchange_manager)
        trading_mode.cryptocurrency = cryptocurrency
        trading_mode.symbol = symbol
        trading_mode.time_frame = time_frame
        trading_mode.bot_id = bot_id
        await trading_mode.initialize()
        get_logger(f"{LOGGER_TAG}[{exchange_manager.exchange_name}]") \
            .debug(f"{trading_mode.get_name()} started for "
                   f"[cryptocurrency={cryptocurrency if cryptocurrency else CONFIG_WILDCARD},"
                   f" symbol={symbol if symbol else CONFIG_WILDCARD},"
                   f" time_frame={time_frame if time_frame else CONFIG_WILDCARD}]")
        return trading_mode
    except RuntimeError as e:
        get_logger(LOGGER_TAG).error(e.args[0])
        raise e
Пример #11
0
def _get_tentacles_values(evaluations, tentacle_type_node, exchange):
    try:
        from octobot_evaluators.api.matrix import get_children_list, has_children, get_value
    except ImportError:
        get_logger("InterfaceUtil").error(
            "_get_tentacles_values requires OctoBot-Evaluators package installed"
        )
        return {}
    for tentacle_name, tentacle_name_node in get_children_list(
            tentacle_type_node).items():
        evaluations[exchange][tentacle_name] = {}
        for cryptocurrency, cc_node in get_children_list(
                tentacle_name_node).items():
            evaluations[exchange][tentacle_name][cryptocurrency] = {}
            if has_children(cc_node):
                for symbol, symbol_node in get_children_list(cc_node).items():
                    if has_children(symbol_node):
                        evaluations[exchange][tentacle_name][symbol] = {}
                        for time_frame, time_frame_node in get_children_list(
                                symbol_node).items():
                            evaluations[exchange][tentacle_name][symbol][time_frame] = \
                                get_value(time_frame_node)
                    else:
                        evaluations[exchange][tentacle_name][
                            symbol] = get_value(symbol_node)
            else:
                evaluations[exchange][tentacle_name][
                    cryptocurrency] = get_value(cc_node)
def get_activated_trading_mode(
        config, tentacles_setup_config) -> AbstractTradingMode.__class__:
    if tentacles_setup_config is not None:
        try:
            trading_modes = [
                tentacle_class for tentacle_class in get_activated_tentacles(
                    tentacles_setup_config)
                if get_deep_class_from_parent_subclasses(
                    tentacle_class, AbstractTradingMode)
            ]

            if len(trading_modes) > 1:
                raise ConfigTradingError(
                    f"More than one activated trading mode found in your tentacle configuration, "
                    f"please activate only one")

            elif trading_modes:
                trading_mode_class = get_deep_class_from_parent_subclasses(
                    trading_modes[0], AbstractTradingMode)

                if trading_mode_class is not None:
                    return get_class(config, trading_mode_class)
        except ModuleNotFoundError as e:
            get_logger("get_activated_trading_mode").error(
                f"Error when loading the activated trading mode: {e}")

    raise ConfigTradingError(
        f"Please ensure your tentacles configuration file is valid and at least one trading "
        f"mode is activated")
Пример #13
0
async def run_independent_backtesting(data_files,
                                      timeout=10,
                                      use_loggers=True,
                                      run_on_common_part_only=True):
    independent_backtesting = None
    try:
        config_to_use = load_test_config()
        if use_loggers:
            init_logger()
        independent_backtesting = create_independent_backtesting(
            config_to_use,
            load_test_tentacles_config(),
            data_files,
            "",
            run_on_common_part_only=run_on_common_part_only)
        await initialize_and_run_independent_backtesting(
            independent_backtesting, log_errors=False)
        await independent_backtesting.join_backtesting_updater(timeout)
        return independent_backtesting
    except MissingTimeFrame:
        # ignore this exception: is due to missing of the only required time frame
        return independent_backtesting
    except asyncio.TimeoutError as e:
        get_logger().exception(
            e, True,
            f"Timeout after waiting for backtesting for {timeout} seconds.")
        # stop backtesting to prevent zombie tasks
        await stop_independent_backtesting(independent_backtesting)
        raise
    except Exception as e:
        get_logger().exception(e, True, str(e))
        # stop backtesting to prevent zombie tasks
        await stop_independent_backtesting(independent_backtesting)
        raise
Пример #14
0
 def get_class(config, class_type):
     classes = AdvancedManager.get_classes(config, class_type)
     if classes and len(classes) > 1:
         get_logger(AdvancedManager.__name__).warning(
             f"More than one instance of {class_type} available, "
             f"using {classes[0]}.")
     return classes[0]
async def _start_service_feed(service_feed, edited_config):
    if not await start_service_feed(service_feed, False, edited_config):
        get_logger(OCTOBOT_CHANNEL_SERVICE_CONSUMER_LOGGER_TAG).error(
            f"Failed to start {service_feed.get_name()}. Evaluators requiring this service feed "
            f"might not work properly")
        return False
    return True
Пример #16
0
def get_activated_trading_mode(config):
    if CONFIG_TRADING_TENTACLES in config:
        try:
            trading_modes = [
                class_str for class_str, activated in
                config[CONFIG_TRADING_TENTACLES].items()
                if activated and get_deep_class_from_parent_subclasses(
                    class_str, AbstractTradingMode)
            ]

            if len(trading_modes) > 1:
                raise ConfigTradingError(
                    f"More than one activated trading mode found in your {CONFIG_TRADING_FILE_PATH} file, "
                    f"please activate only one")

            elif trading_modes:
                trading_mode_class = get_deep_class_from_parent_subclasses(
                    trading_modes[0], AbstractTradingMode)

                if trading_mode_class is not None:
                    return get_class(config, trading_mode_class)
        except ModuleNotFoundError as e:
            get_logger("get_activated_trading_mode").error(
                f"Error when loading a trading mode: {e} "
                f"referenced in {CONFIG_TRADING_FILE_PATH} file")

    raise ConfigTradingError(
        f"Please ensure your {CONFIG_TRADING_FILE_PATH} file is valid and at least one trading "
        f"mode is activated")
Пример #17
0
    def update_from_raw(self, raw_order):
        if self.side is None or self.order_type is None:
            try:
                self._update_type_from_raw(raw_order)
                if self.taker_or_maker is None:
                    self._update_taker_maker()
            except KeyError:
                get_logger(self.__class__.__name__).warning(
                    "Failed to parse order side and type")

        return self.update(
            symbol=str(
                raw_order.get(ExchangeConstantsOrderColumns.SYMBOL.value,
                              None)),
            current_price=raw_order.get(
                ExchangeConstantsOrderColumns.PRICE.value, 0.0),
            quantity=raw_order.get(ExchangeConstantsOrderColumns.AMOUNT.value,
                                   0.0),
            price=raw_order.get(ExchangeConstantsOrderColumns.PRICE.value,
                                0.0),
            status=parse_order_status(raw_order),
            order_id=str(
                raw_order.get(ExchangeConstantsOrderColumns.ID.value, None)),
            quantity_filled=raw_order.get(
                ExchangeConstantsOrderColumns.FILLED.value, 0.0),
            filled_price=raw_order.get(
                ExchangeConstantsOrderColumns.PRICE.value, 0.0),
            total_cost=raw_order.get(ExchangeConstantsOrderColumns.COST.value,
                                     0.0),
            fee=raw_order.get(ExchangeConstantsOrderColumns.FEE.value, None),
            timestamp=raw_order.get(
                ExchangeConstantsOrderColumns.TIMESTAMP.value, None))
Пример #18
0
 async def _on_price_hit(self):
     """
     Is called when the trailing price is hit
     """
     prices_manager = self.exchange_manager.exchange_symbols_data. \
         get_exchange_symbol_data(self.symbol).prices_manager
     get_logger(self.get_logger_name()).debug(f"New price hit {prices_manager.mark_price}, replacing stop...")
     await self._reset_events(prices_manager.mark_price, prices_manager.mark_price_set_time)
Пример #19
0
def _handle_exception(exception, resource_key, catch_exception,
                      default_response):
    if catch_exception:
        get_logger("ExternalResourcesManager") \
            .error(f"Exception when calling get_external_resource for {resource_key} key: {exception}")
        return default_response
    else:
        raise exception
Пример #20
0
def get_single_deepest_child_class(clazz) -> object:
    children_classes = clazz.__subclasses__()
    if len(children_classes) == 0:
        return clazz
    if len(children_classes) > 1:
        get_logger(__name__).error(
            f"More than one child class of {clazz}, expecting one, "
            f"using {children_classes[0]}")
    return get_single_deepest_child_class(children_classes[0])
Пример #21
0
    def del_exchange(self, exchange_name, exchange_manager_id) -> None:
        try:
            self.exchanges[exchange_name].pop(exchange_manager_id, None)

            if not self.exchanges[exchange_name]:
                self.exchanges.pop(exchange_name, None)
        except KeyError:
            get_logger(self.__class__.__name__).warning(f"Can't del exchange {exchange_name} "
                                                        f"with id {exchange_manager_id}")
Пример #22
0
 async def on_fill(self, force_fill=False, is_from_exchange_data=False):
     if self.is_open():
         self.state = FillOrderState(
             self, is_from_exchange_data=is_from_exchange_data)
         await self.state.initialize(forced=force_fill)
     else:
         get_logger(self.get_logger_name()).debug(
             f"Trying to fill a previously filled or canceled order: "
             f"ignored fill call for {self}")
Пример #23
0
async def create_trading_mode(config, exchange_manager) -> None:
    try:
        trading_mode = get_activated_trading_mode(config)(config,
                                                          exchange_manager)
        await trading_mode.initialize()
        get_logger(f"{LOGGER_TAG}[{exchange_manager.exchange.name}]")\
            .debug(f"Using {trading_mode.get_name()} trading mode")
    except RuntimeError as e:
        get_logger(LOGGER_TAG).error(e.args[0])
        raise e
Пример #24
0
def create_advanced_types_list(clazz, config) -> list:
    advanced_class_list = [
        class_type for subclass in clazz.__subclasses__()
        for class_type in get_classes(config, subclass)
    ]

    if not __check_duplicate(advanced_class_list):
        get_logger(__name__).warning("Duplicate class name.")

    return advanced_class_list
def parse_time_frames(time_frames_string_list):
    result_list = []
    for time_frame_string in time_frames_string_list:
        try:
            result_list.append(TimeFrames(time_frame_string))
        except ValueError:
            get_logger(LOGGER_TAG).error(
                "No time frame available for: '{0}'. Available time "
                "frames are: {1}. '{0}' time frame requirement "
                "ignored.".format(time_frame_string,
                                  [t.value for t in TimeFrames]))
    return result_list
Пример #26
0
def install(image_name=OCTOBOT_IMAGE,
            image_tag=OCTOBOT_STABLE_TAG,
            container_name=OCTOBOT_CONTAINER_NAME,
            use_arm_image=False):
    if _is_docker_available() and not _is_container_running(container_name=container_name):
        if use_arm_image:
            image_name = OCTOBOT_PI_IMAGE
        _pull_octobot_image(_get_complete_image(image_name, image_tag))
        _run_octobot_container(_get_complete_image(image_name, image_tag),
                               container_name=container_name)
    else:
        get_logger().error("Docker container already exists")
Пример #27
0
def _run_on_octobot_container(args: list,
                              image_name=OCTOBOT_IMAGE,
                              image_tag=OCTOBOT_STABLE_TAG,
                              container_name=OCTOBOT_CONTAINER_NAME,
                              use_arm_image=False):
    if _is_docker_available() and _is_container_running(container_name=container_name):
        if use_arm_image:
            image_name = OCTOBOT_PI_IMAGE
        return _run_octobot_container(_get_complete_image(image_name, image_tag),
                                      container_name=container_name,
                                      args=args)
    else:
        get_logger().error("Docker container not found")
Пример #28
0
    def create_advanced_evaluator_types_list(evaluator_class, config):
        evaluator_advanced_eval_class_list = []
        for evaluator_subclass in evaluator_class.__subclasses__():
            for eval_class in evaluator_subclass.__subclasses__():
                for eval_class_type in AdvancedManager.get_classes(
                        config, eval_class):
                    evaluator_advanced_eval_class_list.append(eval_class_type)

        if not AdvancedManager._check_duplicate(
                evaluator_advanced_eval_class_list):
            get_logger(
                AdvancedManager.__name__).warning("Duplicate evaluator name.")

        return evaluator_advanced_eval_class_list
Пример #29
0
def clear_dictionaries_by_keys(dict_dest, dict_src):
    for key in dict_src:
        src_val = dict_src[key]
        if key in dict_dest:
            dest_val = dict_dest[key]
            if src_val == DELETE_ELEMENT_VALUE:
                dict_dest.pop(key)
            elif isinstance(dest_val, dict) and isinstance(src_val, dict):
                dict_dest[key] = clear_dictionaries_by_keys(dest_val, src_val)
            else:
                get_logger().error(
                    f"Conflict when deleting dict element with key : {key}")

    return dict_dest
Пример #30
0
def get_matrix_list():
    try:
        from octobot_evaluators.api.matrix import get_matrix, get_node_children_by_names, get_children_list
    except ImportError:
        get_logger("InterfaceUtil").error(
            "get_matrix_list requires OctoBot-Evaluators package installed")
        return {}
    evaluations = {}
    matrix = get_matrix(get_bot_api().get_matrix_id())
    for exchange, exchange_node in get_node_children_by_names(matrix).items():
        evaluations[exchange] = {}
        for tentacle_type_node in get_children_list(exchange_node).values():
            _get_tentacles_values(evaluations, tentacle_type_node, exchange)
    return evaluations