def install_packages(path_or_url=None, version=None, authenticator=None): message = "Tentacles installed" success = True if path_or_url and version: path_or_url = _add_version_to_tentacles_package_path( path_or_url, version) for package_url in [path_or_url] if path_or_url else \ tentacles_manager_api.get_registered_tentacle_packages( interfaces_util.get_bot_api().get_edited_tentacles_config()).values(): if not package_url == tentacles_manager_constants.UNKNOWN_TENTACLES_PACKAGE_LOCATION: if not call_tentacle_manager( tentacles_manager_api.install_all_tentacles, package_url, setup_config=interfaces_util.get_bot_api( ).get_edited_tentacles_config(), aiohttp_session=interfaces_util.get_bot_api( ).get_aiohttp_session(), bot_install_dir=octobot_constants.OCTOBOT_FOLDER, authenticator=authenticator): success = False else: message = "Tentacles installed however it is impossible to re-install tentacles with unknown package origin" # reload profiles to display newly installed ones if any interfaces_util.get_edited_config(dict_only=False).load_profiles() if success: return message return False
def community(): authenticator = interfaces_util.get_bot_api().get_community_auth() logged_in_email = None use_preview = not authenticator.can_authenticate() try: logged_in_email = authenticator.get_logged_in_email() except (authentication.AuthenticationRequired, authentication.UnavailableError): pass except Exception as e: flask.flash(f"Error when contacting the community server: {e}", "error") if logged_in_email is None and not use_preview: return flask.redirect('community_login') tentacles_packages = models.get_account_tentacles_packages( authenticator) if logged_in_email else [] default_image = flask.url_for( 'static', filename="img/community/tentacles_packages_previews/octobot.png") return flask.render_template( 'community.html', use_preview=use_preview, preview_tentacles_packages=models.get_preview_tentacles_packages( flask.url_for), current_logged_in_email=logged_in_email, role=authenticator.supports.support_role, is_donor=bool(authenticator.supports.donations), tentacles_packages=tentacles_packages, current_bots_stats=models.get_current_octobots_stats(), default_tentacles_package_image=default_image)
def start_optimizer(strategy, time_frames, evaluators, risks): try: tools = web_interface_root.WebInterface.tools optimizer = tools[constants.BOT_TOOLS_STRATEGY_OPTIMIZER] if optimizer is not None and octobot_api.is_optimizer_computing( optimizer): return False, "Optimizer already running" independent_backtesting = tools[constants.BOT_TOOLS_BACKTESTING] if independent_backtesting and octobot_api.is_independent_backtesting_in_progress( independent_backtesting): return False, "A backtesting is already running" else: formatted_time_frames = time_frame_manager.parse_time_frames( time_frames) float_risks = [float(risk) for risk in risks] temp_independent_backtesting = octobot_api.create_independent_backtesting( interfaces_util.get_global_config(), None, []) optimizer_config = interfaces_util.run_in_bot_async_executor( octobot_api.initialize_independent_backtesting_config( temp_independent_backtesting)) optimizer = octobot_api.create_strategy_optimizer( optimizer_config, interfaces_util.get_bot_api().get_edited_tentacles_config(), strategy) tools[constants.BOT_TOOLS_STRATEGY_OPTIMIZER] = optimizer thread = threading.Thread( target=octobot_api.find_optimal_configuration, args=(optimizer, evaluators, formatted_time_frames, float_risks), name=f"{optimizer.get_name()}-WebInterface-runner") thread.start() return True, "Optimizer started" except Exception as e: LOGGER.exception(e, True, f"Error when starting optimizer: {e}") raise e
def is_compatible_account(exchange_name: str, api_key, api_sec, api_pass) -> dict: to_check_config = copy.deepcopy(interfaces_util.get_edited_config()[commons_constants.CONFIG_EXCHANGES].get(exchange_name, {})) if _is_real_exchange_value(api_key): to_check_config[commons_constants.CONFIG_EXCHANGE_KEY] = configuration.encrypt(api_key).decode() if _is_real_exchange_value(api_sec): to_check_config[commons_constants.CONFIG_EXCHANGE_SECRET] = configuration.encrypt(api_sec).decode() if _is_real_exchange_value(api_pass): to_check_config[commons_constants.CONFIG_EXCHANGE_PASSWORD] = configuration.encrypt(api_pass).decode() is_compatible = False is_sponsoring = trading_api.is_sponsoring(exchange_name) is_configured = False authenticator = interfaces_util.get_bot_api().get_community_auth() is_supporter = authenticator.supports.is_supporting() error = None if _is_possible_exchange_config(to_check_config): is_configured = True is_compatible, error = interfaces_util.run_in_bot_async_executor( trading_api.is_compatible_account( exchange_name, to_check_config, interfaces_util.get_edited_tentacles_config() ) ) return { "exchange": exchange_name, "compatible": is_compatible, "supporter_account": is_supporter, "configured": is_configured, "supporting": is_sponsoring, "error_message": error }
def start_backtesting_using_specific_files(files, source, reset_tentacle_config=False, run_on_common_part_only=True): try: tools = web_interface_root.WebInterface.tools previous_independent_backtesting = tools[constants.BOT_TOOLS_BACKTESTING] if tools[constants.BOT_TOOLS_STRATEGY_OPTIMIZER] and octobot_api.is_optimizer_in_progress( tools[constants.BOT_TOOLS_STRATEGY_OPTIMIZER]): return False, "Optimizer already running" elif previous_independent_backtesting and \ octobot_api.is_independent_backtesting_in_progress(previous_independent_backtesting): return False, "A backtesting is already running" else: if previous_independent_backtesting: interfaces_util.run_in_bot_main_loop( octobot_api.stop_independent_backtesting(previous_independent_backtesting)) if reset_tentacle_config: tentacles_config = interfaces_util.get_edited_config(dict_only=False).get_tentacles_config_path() tentacles_setup_config = tentacles_manager_api.get_tentacles_setup_config(tentacles_config) else: tentacles_setup_config = interfaces_util.get_bot_api().get_edited_tentacles_config() config = interfaces_util.get_global_config() independent_backtesting = octobot_api.create_independent_backtesting(config, tentacles_setup_config, files, run_on_common_part_only=run_on_common_part_only) interfaces_util.run_in_bot_main_loop( octobot_api.initialize_and_run_independent_backtesting(independent_backtesting), blocking=False) tools[constants.BOT_TOOLS_BACKTESTING] = independent_backtesting tools[constants.BOT_TOOLS_BACKTESTING_SOURCE] = source return True, "Backtesting started" except Exception as e: LOGGER.exception(e, False) return False, f"Error when starting backtesting: {e}"
def community_login(): authenticator = interfaces_util.get_bot_api().get_community_auth() logged_in_email = form = None try: logged_in_email = authenticator.get_logged_in_email() except community.AuthenticationRequired: pass except Exception as e: flask.flash(f"Error when contacting the community server: {e}", "error") if logged_in_email is None: form = CommunityLoginForm( flask.request.form) if flask.request.form else CommunityLoginForm( ) if form.validate_on_submit(): try: authenticator.login(form.email.data, form.password.data) logged_in_email = form.email.data flask.flash(f"Authenticated as {form.email.data}", "success") except community.FailedAuthentication: flask.flash(f"Invalid email or password", "error") except Exception as e: flask.flash(f"Error during authentication: {e}", "error") return flask.render_template('community_login.html', form=form, current_logged_in_email=logged_in_email, community_url=constants.OCTOBOT_COMMUNITY_URL)
def user_command(): request_data = flask.request.get_json() interfaces_util.run_in_bot_main_loop( services_api.send_user_command( interfaces_util.get_bot_api().get_bot_id(), request_data["subject"], request_data["action"], request_data["data"])) return flask.jsonify(request_data)
def reset_packages(): if call_tentacle_manager(tentacles_manager_api.uninstall_all_tentacles, setup_config=interfaces_util.get_bot_api(). get_edited_tentacles_config(), use_confirm_prompt=False): return "Reset successful" else: return None
def update_packages(): message = "Tentacles updated" success = True for package_url in tentacles_manager_api.get_registered_tentacle_packages( interfaces_util.get_bot_api().get_edited_tentacles_config( )).values(): if package_url != tentacles_manager_constants.UNKNOWN_TENTACLES_PACKAGE_LOCATION: if not call_tentacle_manager( tentacles_manager_api.update_all_tentacles, package_url, aiohttp_session=interfaces_util.get_bot_api( ).get_aiohttp_session()): success = False else: message = "Tentacles updated however it is impossible to update tentacles with unknown package origin" if success: return message return False
def get_evaluators_list(strategy_name): if strategy_name: strategy_class = tentacles_management.get_class_from_string( strategy_name, evaluators.StrategyEvaluator, TentaclesStrategies, tentacles_management.evaluator_parent_inspection) found_evaluators = evaluators_api.get_relevant_TAs_for_strategy( strategy_class, interfaces_util.get_bot_api().get_tentacles_setup_config()) return set(evaluator.get_name() for evaluator in found_evaluators) else: return []
def manage_metrics(enable_metrics): current_edited_config = interfaces_util.get_edited_config(dict_only=False) if commons_constants.CONFIG_METRICS not in current_edited_config.config: current_edited_config.config[commons_constants.CONFIG_METRICS] = { commons_constants.CONFIG_ENABLED_OPTION: enable_metrics} else: current_edited_config.config[commons_constants.CONFIG_METRICS][ commons_constants.CONFIG_ENABLED_OPTION] = enable_metrics if enable_metrics and community.CommunityManager.should_register_bot(current_edited_config): community.CommunityManager.background_get_id_and_register_bot(interfaces_util.get_bot_api()) current_edited_config.save()
def install_packages(path_or_url=None): message = "Tentacles installed" success = True for package_url in [path_or_url] if path_or_url else \ tentacles_manager_api.get_registered_tentacle_packages( interfaces_util.get_bot_api().get_edited_tentacles_config()).values(): if not package_url == tentacles_manager_constants.UNKNOWN_TENTACLES_PACKAGE_LOCATION: if not call_tentacle_manager( tentacles_manager_api.install_all_tentacles, package_url, setup_config=interfaces_util.get_bot_api( ).get_edited_tentacles_config(), aiohttp_session=interfaces_util.get_bot_api( ).get_aiohttp_session(), bot_install_dir=octobot_constants.OCTOBOT_FOLDER): success = False else: message = "Tentacles installed however it is impossible to re-install tentacles with unknown package origin" if success: return message return False
def get_time_frames_list(strategy_name): if strategy_name: strategy_class = tentacles_management.get_class_from_string( strategy_name, evaluators.StrategyEvaluator, TentaclesStrategies, tentacles_management.evaluator_parent_inspection) return [ tf.value for tf in strategy_class.get_required_time_frames( interfaces_util.get_global_config(), interfaces_util.get_bot_api().get_tentacles_setup_config()) ] else: return []
def _handle_package_operation(update_type): if update_type == "add_package": request_data = flask.request.get_json() success = False if request_data: version = None url_key = "url" if url_key in request_data: path_or_url = request_data[url_key] version = request_data.get("version", None) action = "register_and_install" else: path_or_url, action = next(iter(request_data.items())) path_or_url = path_or_url.strip() if action == "register_and_install": installation_result = models.install_packages( path_or_url, version, authenticator=interfaces_util.get_bot_api( ).get_community_auth()) if installation_result: return util.get_rest_reply( flask.jsonify(installation_result)) else: return util.get_rest_reply( 'Impossible to install the given tentacles package, #TODO in 0.4.', 500) if not success: return util.get_rest_reply('{"operation": "ko"}', 500) elif update_type in [ "install_packages", "update_packages", "reset_packages" ]: packages_operation_result = {} if update_type == "install_packages": packages_operation_result = models.install_packages() elif update_type == "update_packages": packages_operation_result = models.update_packages() elif update_type == "reset_packages": packages_operation_result = models.reset_packages() if packages_operation_result is not None: return util.get_rest_reply( flask.jsonify(packages_operation_result)) else: action = update_type.split("_")[0] return util.get_rest_reply( f'Impossible to {action} packages, check the logs for more information.', 500)
def collect_data_file(exchange, symbol): success = False try: result = interfaces_util.run_in_bot_async_executor( backtesting_api.collect_exchange_historical_data(exchange, interfaces_util.get_bot_api().get_edited_tentacles_config(), [symbol])) success = True except Exception as e: result = f"data collector error: {e}" if success: return success, f"{result} saved" else: return success, f"Can't collect data for {symbol} on {exchange} ({result})"
async def _background_collect_exchange_historical_data(exchange, symbols, time_frames, start_timestamp, end_timestamp): data_collector_instance = backtesting_api.exchange_historical_data_collector_factory( exchange, interfaces_util.get_bot_api().get_edited_tentacles_config(), symbols if isinstance(symbols, list) else [symbols], time_frames=time_frames, start_timestamp=start_timestamp, end_timestamp=end_timestamp) web_interface_root.WebInterface.tools[ constants.BOT_TOOLS_DATA_COLLECTOR] = data_collector_instance coro = _start_collect_and_notify(data_collector_instance) threading.Thread(target=asyncio.run, args=(coro, ), name=f"DataCollector{symbols}").start()
def update_modules(modules): success = True for url in [ octobot_constants.DEFAULT_TENTACLES_URL, # tentacles_manager_api.get_compiled_tentacles_url( # octobot_constants.DEFAULT_COMPILED_TENTACLES_URL, # octobot_constants.TENTACLES_REQUIRED_VERSION # ) ]: try: call_tentacle_manager(tentacles_manager_api.update_tentacles, modules, url, aiohttp_session=interfaces_util.get_bot_api( ).get_aiohttp_session(), quite_mode=True) except Exception: success = False if success: return f"{len(modules)} Tentacles updated" return None
def get_currency_price_graph_update(exchange_id, symbol, time_frame, list_arrays=True, backtesting=False, minimal_candles=False, ignore_trades=False): bot_api = interfaces_util.get_bot_api() # TODO: handle on the fly backtesting price graph # if backtesting and WebInterface and WebInterface.tools[BOT_TOOLS_BACKTESTING]: # bot = WebInterface.tools[BOT_TOOLS_BACKTESTING].get_bot() symbol = parse_get_symbol(symbol) in_backtesting = backtesting_api.is_backtesting_enabled( interfaces_util.get_global_config()) or backtesting exchange_manager = trading_api.get_exchange_manager_from_exchange_id( exchange_id) if time_frame is not None: try: symbol_data = trading_api.get_symbol_data(exchange_manager, symbol, allow_creation=False) limit = 1 if minimal_candles else -1 historical_candles = trading_api.get_symbol_historical_candles( symbol_data, time_frame, limit=limit) kline = [math.nan] if trading_api.has_symbol_klines(symbol_data, time_frame): kline = trading_api.get_symbol_klines(symbol_data, time_frame) if historical_candles is not None: return _create_candles_data(symbol, time_frame, historical_candles, kline, bot_api, list_arrays, in_backtesting, ignore_trades) except KeyError: traded_pairs = trading_api.get_trading_pairs(exchange_manager) if not traded_pairs or symbol in traded_pairs: # not started yet return None else: return {"error": f"no data for {symbol}"} return None
def stop_bot(): interfaces_util.get_bot_api().stop_bot()
def get_config_activated_trading_mode(): return trading_api.get_activated_trading_mode( interfaces_util.get_bot_api().get_edited_tentacles_config())
def community_logout(): interfaces_util.get_bot_api().get_community_auth().logout() return flask.redirect(flask.url_for('community_login'))
def update_bot(): interfaces_util.get_bot_api().update_bot()
def get_tentacles_packages(): return tentacles_manager_api.get_registered_tentacle_packages( interfaces_util.get_bot_api().get_edited_tentacles_config())
def restart_bot(): interfaces_util.get_bot_api().restart_bot()