def __init__(self, config): self.start_time = time.time() self.config = config self.startup_config = copy.deepcopy(config) self.edited_config = copy.deepcopy(config) self.ready = False self.watcher = None # tools: used for alternative operations on a bot on the fly (ex: backtesting started from web interface) self.tools = { BOT_TOOLS_BACKTESTING: None, BOT_TOOLS_STRATEGY_OPTIMIZER: None, BOT_TOOLS_RECORDER: None, } # Logger self.logger = get_logger(self.__class__.__name__) # Advanced AdvancedManager.init_advanced_classes_if_necessary(self.config) # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[ CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() # Init time frames using enabled strategies EvaluatorCreator.init_time_frames_from_strategies(self.config) self.time_frames = TimeFrameManager.get_config_time_frame(self.config) # Init relevant evaluator names list using enabled strategies self.relevant_evaluators = EvaluatorCreator.get_relevant_evaluators_from_strategies( self.config) # Backtesting self.backtesting_enabled = Backtesting.enabled(self.config) # Add services to self.config[CONFIG_CATEGORY_SERVICES] ServiceCreator.create_services(self.config, self.backtesting_enabled) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) # Notify starting if self.config[CONFIG_NOTIFICATION_INSTANCE].enabled( CONFIG_NOTIFICATION_GLOBAL_INFO): self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all( NOTIFICATION_STARTING_MESSAGE, False) self.symbol_threads_manager = {} self.exchange_traders = {} self.exchange_trader_simulators = {} self.trading_mode = None self.exchange_trading_modes = {} self.exchanges_list = {} self.symbol_evaluator_list = {} self.crypto_currency_evaluator_list = {} self.dispatchers_list = [] self.symbol_time_frame_updater_threads = []
def __init__(self, config): self.start_time = time.time() self.config = config self.startup_config = copy.deepcopy(config) self.edited_config = copy.deepcopy(config) self.ready = False self.watcher = None self.current_loop_thread = None # tools: used for alternative operations on a bot on the fly (ex: backtesting started from web interface) self.tools = { BOT_TOOLS_BACKTESTING: None, BOT_TOOLS_STRATEGY_OPTIMIZER: None, BOT_TOOLS_RECORDER: None, } # Logger self.logger = get_logger(self.__class__.__name__) # Advanced AdvancedManager.init_advanced_classes_if_necessary(self.config) # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[ CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() # Init time frames using enabled strategies EvaluatorCreator.init_time_frames_from_strategies(self.config) self.time_frames = TimeFrameManager.get_config_time_frame(self.config) # Init relevant evaluator names list using enabled strategies self.relevant_evaluators = EvaluatorCreator.get_relevant_evaluators_from_strategies( self.config) # Backtesting self.backtesting_enabled = Backtesting.enabled(self.config) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) self.symbol_tasks_manager = {} self.exchange_traders = {} self.exchange_trader_simulators = {} self.trading_mode = None self.exchange_trading_modes = {} self.exchanges_list = {} self.symbol_evaluator_list = {} self.crypto_currency_evaluator_list = {} self.dispatchers_list = [] self.global_updaters_by_exchange = {} self.async_loop = None self.social_eval_tasks = [] self.real_time_eval_tasks = [] self.main_task_group = None
def __init__(self, config): self.start_time = time.time() self.config = config self.ready = False # Logger self.logger = logging.getLogger(self.__class__.__name__) # Advanced AdvancedManager.create_class_list(self.config) # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[ CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() # Init time frames using enabled strategies EvaluatorCreator.init_time_frames_from_strategies(self.config) self.time_frames = TimeFrameManager.get_config_time_frame(self.config) # Init relevant evaluator names list using enabled strategies self.relevant_evaluators = EvaluatorCreator.get_relevant_evaluators_from_strategies( self.config) # Add services to self.config[CONFIG_CATEGORY_SERVICES] ServiceCreator.create_services(self.config) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) # Notify starting if self.config[CONFIG_NOTIFICATION_INSTANCE].enabled( CONFIG_NOTIFICATION_GLOBAL_INFO): self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all( NOTIFICATION_STARTING_MESSAGE) # Backtesting self.backtesting_enabled = None self.symbol_threads_manager = {} self.exchange_traders = {} self.exchange_trader_simulators = {} self.exchanges_list = {} self.symbol_evaluator_list = {} self.crypto_currency_evaluator_list = {} self.dispatchers_list = [] self.symbol_time_frame_updater_threads = []
def __init__(self): # Logger fileConfig('config/logging_config.ini') self.logger = logging.getLogger(self.__class__.__name__) sys.excepthook = self.log_uncaught_exceptions # Version self.logger.info("Version : {0}".format(VERSION)) # Config self.logger.info("Load config file...") self.config = load_config() # Advanced AdvancedManager.create_class_list(self.config) # Interfaces self.web_app = WebApp(self.config) if self.web_app.enabled(): self.web_app.start() # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[ CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() # TODO : CONFIG TEMP LOCATION self.time_frames = [ TimeFrames.THIRTY_MINUTES, TimeFrames.ONE_HOUR, TimeFrames.FOUR_HOURS, TimeFrames.ONE_DAY ] self.exchanges = [ccxt.binance] # Add services to self.config[CONFIG_CATEGORY_SERVICES] ServiceCreator.create_services(self.config) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) self.symbols_threads_manager = [] self.exchange_traders = {} self.exchange_trader_simulators = {} self.exchanges_list = {} self.symbol_evaluator_list = [] self.dispatchers_list = []
def __init__(self, config): self.start_time = time.time() self.config = config self.ready = False # Logger self.logger = logging.getLogger(self.__class__.__name__) # Advanced AdvancedManager.create_class_list(self.config) # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() self.time_frames = TimeFrameManager.get_config_time_frame(self.config) # Add services to self.config[CONFIG_CATEGORY_SERVICES] ServiceCreator.create_services(self.config) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) # Notify starting self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all(NOTIFICATION_STARTING_MESSAGE) # Backtesting self.backtesting_enabled = None self.symbol_threads_manager = {} self.exchange_traders = {} self.exchange_trader_simulators = {} self.exchanges_list = {} self.symbol_evaluator_list = {} self.crypto_currency_evaluator_list = {} self.dispatchers_list = [] self.symbol_time_frame_updater_threads = []
class OctoBot: """ Constructor : - Load configs """ def __init__(self, config): self.start_time = time.time() self.config = config self.startup_config = copy.deepcopy(config) self.edited_config = copy.deepcopy(config) self.ready = False self.watcher = None # tools: used for alternative operations on a bot on the fly (ex: backtesting started from web interface) self.tools = { BOT_TOOLS_BACKTESTING: None, BOT_TOOLS_STRATEGY_OPTIMIZER: None, BOT_TOOLS_RECORDER: None, } # Logger self.logger = get_logger(self.__class__.__name__) # Advanced AdvancedManager.init_advanced_classes_if_necessary(self.config) # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[ CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() # Init time frames using enabled strategies EvaluatorCreator.init_time_frames_from_strategies(self.config) self.time_frames = TimeFrameManager.get_config_time_frame(self.config) # Init relevant evaluator names list using enabled strategies self.relevant_evaluators = EvaluatorCreator.get_relevant_evaluators_from_strategies( self.config) # Backtesting self.backtesting_enabled = Backtesting.enabled(self.config) # Add services to self.config[CONFIG_CATEGORY_SERVICES] ServiceCreator.create_services(self.config, self.backtesting_enabled) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) # Notify starting if self.config[CONFIG_NOTIFICATION_INSTANCE].enabled( CONFIG_NOTIFICATION_GLOBAL_INFO): self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all( NOTIFICATION_STARTING_MESSAGE, False) self.symbol_threads_manager = {} self.exchange_traders = {} self.exchange_trader_simulators = {} self.trading_mode = None self.exchange_trading_modes = {} self.exchanges_list = {} self.symbol_evaluator_list = {} self.crypto_currency_evaluator_list = {} self.dispatchers_list = [] self.symbol_time_frame_updater_threads = [] def create_exchange_traders(self): available_exchanges = ccxt.exchanges for exchange_class_string in self.config[CONFIG_EXCHANGES]: if exchange_class_string in available_exchanges: exchange_type = getattr(ccxt, exchange_class_string) # Backtesting Exchange if self.backtesting_enabled: exchange_manager = ExchangeManager(self.config, exchange_type, is_simulated=True) else: # Real Exchange exchange_manager = ExchangeManager(self.config, exchange_type, is_simulated=False) exchange_inst = exchange_manager.get_exchange() self.exchanges_list[exchange_inst.get_name()] = exchange_inst # create trader instance for this exchange exchange_trader = Trader(self.config, exchange_inst) self.exchange_traders[ exchange_inst.get_name()] = exchange_trader # create trader simulator instance for this exchange exchange_trader_simulator = TraderSimulator( self.config, exchange_inst) self.exchange_trader_simulators[ exchange_inst.get_name()] = exchange_trader_simulator # create trading mode try: self.trading_mode = get_activated_trading_mode( self.config)(self.config, exchange_inst) self.exchange_trading_modes[ exchange_inst.get_name()] = self.trading_mode self.logger.debug( f"Using {self.trading_mode.get_name()} trading mode") except RuntimeError as e: self.logger.error(e.args[0]) raise e else: self.logger.error( f"{exchange_class_string} exchange not found") def create_evaluation_threads(self): self.logger.info("Evaluation threads creation...") # create dispatchers self.dispatchers_list = EvaluatorCreator.create_dispatchers( self.config) # create Social and TA evaluators for crypto_currency, crypto_currency_data in self.config[ CONFIG_CRYPTO_CURRENCIES].items(): # create crypto_currency evaluator crypto_currency_evaluator = CryptocurrencyEvaluator( self.config, crypto_currency, self.dispatchers_list, self.relevant_evaluators) self.crypto_currency_evaluator_list[ crypto_currency] = crypto_currency_evaluator # create TA evaluators for symbol in crypto_currency_data[CONFIG_CRYPTO_PAIRS]: # create symbol evaluator symbol_evaluator = SymbolEvaluator(self.config, symbol, crypto_currency_evaluator) symbol_evaluator.set_traders(self.exchange_traders) symbol_evaluator.set_trader_simulators( self.exchange_trader_simulators) crypto_currency_evaluator.add_symbol_evaluator( symbol, symbol_evaluator) self.symbol_evaluator_list[symbol] = symbol_evaluator for exchange in self.exchanges_list.values(): if exchange.get_exchange_manager().enabled(): # Verify that symbol exists on this exchange if symbol in exchange.get_exchange_manager( ).get_traded_pairs(): self._create_symbol_threads_managers( exchange, symbol_evaluator) # notify that exchange doesn't support this symbol else: if not self.backtesting_enabled: self.logger.warning( f"{exchange.get_name()} doesn't support {symbol}" ) self._check_required_evaluators() def _create_symbol_threads_managers(self, exchange, symbol_evaluator): if Backtesting.enabled(self.config): real_time_ta_eval_list = [] else: # Create real time TA evaluators real_time_ta_eval_list = EvaluatorCreator.create_real_time_ta_evals( self.config, exchange, symbol_evaluator.get_symbol(), self.relevant_evaluators) symbol_time_frame_updater_thread = SymbolTimeFramesDataUpdaterThread() for time_frame in self.time_frames: if exchange.get_exchange_manager().time_frame_exists( time_frame.value, symbol_evaluator.get_symbol()): self.symbol_threads_manager[ time_frame] = EvaluatorThreadsManager( self.config, time_frame, symbol_time_frame_updater_thread, symbol_evaluator, exchange, self.exchange_trading_modes[exchange.get_name()], real_time_ta_eval_list, self.relevant_evaluators) else: self.logger.warning( f"{exchange.get_name()} exchange is not supporting the required time frame: " f"'{time_frame.value}' for {symbol_evaluator.get_symbol()}." ) self.symbol_time_frame_updater_threads.append( symbol_time_frame_updater_thread) def _check_required_evaluators(self): if self.symbol_threads_manager: etm = next(iter(self.symbol_threads_manager.values())) ta_list = etm.get_evaluator().get_ta_eval_list() if self.relevant_evaluators != CONFIG_EVALUATORS_WILDCARD: for required_eval in self.relevant_evaluators: required_class = get_class_from_string( required_eval, TAEvaluator, TA, evaluator_parent_inspection) if required_class and not self._class_is_in_list( ta_list, required_class): self.logger.error( f"Missing technical analysis evaluator {required_class.get_name()} for " f"current strategy. Activate it in OctoBot advanced configuration interface " f"to allow activated strategy(ies) to work properly." ) def start_threads(self): if self.performance_analyser: self.performance_analyser.start() for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values( ): crypto_currency_evaluator.start_threads() for manager in self.symbol_threads_manager.values(): manager.start_threads() for thread in self.symbol_time_frame_updater_threads: if self.watcher is not None: thread.set_watcher(self.watcher) thread.start() for thread in self.dispatchers_list: thread.start() self.ready = True self.logger.info("Evaluation threads started...") def join_threads(self): for manager in self.symbol_threads_manager: self.symbol_threads_manager[manager].join_threads() for thread in self.symbol_time_frame_updater_threads: thread.join() for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values( ): crypto_currency_evaluator.join_threads() for trader in self.exchange_traders.values(): trader.join_order_manager() for trader_simulator in self.exchange_trader_simulators.values(): trader_simulator.join_order_manager() for thread in self.dispatchers_list: thread.join() if self.performance_analyser: self.performance_analyser.join() def stop_threads(self): # Notify stopping if self.config[CONFIG_NOTIFICATION_INSTANCE].enabled( CONFIG_NOTIFICATION_GLOBAL_INFO): self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all( NOTIFICATION_STOPPING_MESSAGE) self.logger.info("Stopping threads ...") for thread in self.symbol_time_frame_updater_threads: thread.stop() for manager in self.symbol_threads_manager.values(): manager.stop_threads() for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values( ): crypto_currency_evaluator.stop_threads() for trader in self.exchange_traders.values(): trader.stop_order_manager() for trader_simulator in self.exchange_trader_simulators.values(): trader_simulator.stop_order_manager() for thread in self.dispatchers_list: thread.stop() if self.performance_analyser: self.performance_analyser.stop() # stop services for service_instance in ServiceCreator.get_service_instances( self.config): try: service_instance.stop() except Exception as e: raise e # stop exchanges threads for exchange in self.exchanges_list.values(): exchange.stop() self.logger.info("Threads stopped.") @staticmethod def _class_is_in_list(class_list, required_klass): return any(required_klass in klass.get_parent_evaluator_classes() for klass in class_list) def set_watcher(self, watcher): self.watcher = watcher def get_symbols_threads_manager(self): return self.symbol_threads_manager def get_exchange_traders(self): return self.exchange_traders def get_exchange_trader_simulators(self): return self.exchange_trader_simulators def get_exchange_trading_modes(self): return self.exchange_trading_modes def get_exchanges_list(self): return self.exchanges_list def get_symbol_evaluator_list(self): return self.symbol_evaluator_list def get_symbols_list(self): return self.symbol_evaluator_list.keys() def get_crypto_currency_evaluator_list(self): return self.crypto_currency_evaluator_list def get_dispatchers_list(self): return self.dispatchers_list def get_symbol_time_frame_updater_threads(self): return self.symbol_time_frame_updater_threads def get_start_time(self): return self.start_time def is_ready(self): return self.ready def get_config(self): return self.config def get_startup_config(self): return self.startup_config def get_edited_config(self): return self.edited_config def get_tools(self): return self.tools def get_trading_mode(self): return self.trading_mode
class OctoBot: """ Constructor : - Load configs """ def __init__(self, config): self.start_time = time.time() self.config = config self.ready = False # Logger self.logger = logging.getLogger(self.__class__.__name__) # Advanced AdvancedManager.create_class_list(self.config) # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[ CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() # Init time frames using enabled strategies EvaluatorCreator.init_time_frames_from_strategies(self.config) self.time_frames = TimeFrameManager.get_config_time_frame(self.config) # Init relevant evaluator names list using enabled strategies self.relevant_evaluators = EvaluatorCreator.get_relevant_evaluators_from_strategies( self.config) # Add services to self.config[CONFIG_CATEGORY_SERVICES] ServiceCreator.create_services(self.config) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) # Notify starting if self.config[CONFIG_NOTIFICATION_INSTANCE].enabled( CONFIG_NOTIFICATION_GLOBAL_INFO): self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all( NOTIFICATION_STARTING_MESSAGE) # Backtesting self.backtesting_enabled = None self.symbol_threads_manager = {} self.exchange_traders = {} self.exchange_trader_simulators = {} self.exchanges_list = {} self.symbol_evaluator_list = {} self.crypto_currency_evaluator_list = {} self.dispatchers_list = [] self.symbol_time_frame_updater_threads = [] def create_exchange_traders(self): self.backtesting_enabled = Backtesting.enabled(self.config) available_exchanges = ccxt.exchanges for exchange_class_string in self.config[CONFIG_EXCHANGES]: if exchange_class_string in available_exchanges: exchange_type = getattr(ccxt, exchange_class_string) # Backtesting Exchange if self.backtesting_enabled: exchange_manager = ExchangeManager(self.config, exchange_type, is_simulated=True) else: # True Exchange exchange_manager = ExchangeManager(self.config, exchange_type, is_simulated=False) exchange_inst = exchange_manager.get_exchange() self.exchanges_list[exchange_inst.get_name()] = exchange_inst # create trader instance for this exchange exchange_trader = Trader(self.config, exchange_inst) self.exchange_traders[ exchange_inst.get_name()] = exchange_trader # create trader simulator instance for this exchange exchange_trader_simulator = TraderSimulator( self.config, exchange_inst) self.exchange_trader_simulators[ exchange_inst.get_name()] = exchange_trader_simulator else: self.logger.error( "{0} exchange not found".format(exchange_class_string)) def create_evaluation_threads(self): self.logger.info("Evaluation threads creation...") # create dispatchers self.dispatchers_list = EvaluatorCreator.create_dispatchers( self.config) # create Social and TA evaluators for crypto_currency, crypto_currency_data in self.config[ CONFIG_CRYPTO_CURRENCIES].items(): # create crypto_currency evaluator crypto_currency_evaluator = CryptocurrencyEvaluator( self.config, crypto_currency, self.dispatchers_list, self.relevant_evaluators) self.crypto_currency_evaluator_list[ crypto_currency] = crypto_currency_evaluator # create TA evaluators for symbol in crypto_currency_data[CONFIG_CRYPTO_PAIRS]: # create symbol evaluator symbol_evaluator = SymbolEvaluator(self.config, symbol, crypto_currency_evaluator) symbol_evaluator.set_traders(self.exchange_traders) symbol_evaluator.set_trader_simulators( self.exchange_trader_simulators) crypto_currency_evaluator.add_symbol_evaluator( symbol, symbol_evaluator) self.symbol_evaluator_list[symbol] = symbol_evaluator for exchange in self.exchanges_list.values(): if exchange.get_exchange_manager().enabled(): # Verify that symbol exists on this exchange if symbol in exchange.get_exchange_manager( ).get_traded_pairs(): self._create_symbol_threads_managers( exchange, symbol_evaluator) # notify that exchange doesn't support this symbol else: if not self.backtesting_enabled: self.logger.warning( "{0} doesn't support {1}".format( exchange.get_name(), symbol)) def _create_symbol_threads_managers(self, exchange, symbol_evaluator): # Create real time TA evaluators real_time_ta_eval_list = EvaluatorCreator.create_real_time_ta_evals( self.config, exchange, symbol_evaluator.get_symbol(), self.relevant_evaluators) symbol_time_frame_updater_thread = SymbolTimeFramesDataUpdaterThread() for time_frame in self.time_frames: if exchange.get_exchange_manager().time_frame_exists( time_frame.value): self.symbol_threads_manager[ time_frame] = EvaluatorThreadsManager( self.config, time_frame, symbol_time_frame_updater_thread, symbol_evaluator, exchange, real_time_ta_eval_list, self.relevant_evaluators) self.symbol_time_frame_updater_threads.append( symbol_time_frame_updater_thread) def start_threads(self): if self.performance_analyser: self.performance_analyser.start() for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values( ): crypto_currency_evaluator.start_threads() for manager in self.symbol_threads_manager.values(): manager.start_threads() for thread in self.symbol_time_frame_updater_threads: thread.start() for thread in self.dispatchers_list: thread.start() self.ready = True self.logger.info("Evaluation threads started...") def join_threads(self): for manager in self.symbol_threads_manager: self.symbol_threads_manager[manager].join_threads() for thread in self.symbol_time_frame_updater_threads: thread.join() for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values( ): crypto_currency_evaluator.join_threads() for trader in self.exchange_traders.values(): trader.join_order_manager() for trader_simulator in self.exchange_trader_simulators.values(): trader_simulator.join_order_manager() for thread in self.dispatchers_list: thread.join() if self.performance_analyser: self.performance_analyser.join() def stop_threads(self): # Notify stopping if self.config[CONFIG_NOTIFICATION_INSTANCE].enabled( CONFIG_NOTIFICATION_GLOBAL_INFO): self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all( NOTIFICATION_STOPPING_MESSAGE) self.logger.info("Stopping threads ...") for thread in self.symbol_time_frame_updater_threads: thread.stop() for manager in self.symbol_threads_manager.values(): manager.stop_threads() for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values( ): crypto_currency_evaluator.stop_threads() for trader in self.exchange_traders.values(): trader.stop_order_manager() for trader_simulator in self.exchange_trader_simulators.values(): trader_simulator.stop_order_manager() for thread in self.dispatchers_list: thread.stop() if self.performance_analyser: self.performance_analyser.stop() # stop services for service_instance in ServiceCreator.get_service_instances( self.config): try: service_instance.stop() except Exception as e: raise e # stop exchanges threads for exchange in self.exchanges_list.values(): exchange.stop() self.logger.info("Threads stopped.") def get_symbols_threads_manager(self): return self.symbol_threads_manager def get_exchange_traders(self): return self.exchange_traders def get_exchange_trader_simulators(self): return self.exchange_trader_simulators def get_exchanges_list(self): return self.exchanges_list def get_symbol_evaluator_list(self): return self.symbol_evaluator_list def get_crypto_currency_evaluator_list(self): return self.crypto_currency_evaluator_list def get_dispatchers_list(self): return self.dispatchers_list def get_symbol_time_frame_updater_threads(self): return self.symbol_time_frame_updater_threads def get_start_time(self): return self.start_time def is_ready(self): return self.ready
class OctoBot: """ Constructor : - Load configs """ def __init__(self, config): self.start_time = time.time() self.config = config self.startup_config = copy.deepcopy(config) self.edited_config = copy.deepcopy(config) self.ready = False self.watcher = None self.current_loop_thread = None # tools: used for alternative operations on a bot on the fly (ex: backtesting started from web interface) self.tools = { BOT_TOOLS_BACKTESTING: None, BOT_TOOLS_STRATEGY_OPTIMIZER: None, BOT_TOOLS_RECORDER: None, } # Logger self.logger = get_logger(self.__class__.__name__) # Advanced AdvancedManager.init_advanced_classes_if_necessary(self.config) # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[ CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() # Init time frames using enabled strategies EvaluatorCreator.init_time_frames_from_strategies(self.config) self.time_frames = TimeFrameManager.get_config_time_frame(self.config) # Init relevant evaluator names list using enabled strategies self.relevant_evaluators = EvaluatorCreator.get_relevant_evaluators_from_strategies( self.config) # Backtesting self.backtesting_enabled = Backtesting.enabled(self.config) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) self.symbol_tasks_manager = {} self.exchange_traders = {} self.exchange_trader_simulators = {} self.trading_mode = None self.exchange_trading_modes = {} self.exchanges_list = {} self.symbol_evaluator_list = {} self.crypto_currency_evaluator_list = {} self.dispatchers_list = [] self.global_updaters_by_exchange = {} self.async_loop = None self.social_eval_tasks = [] self.real_time_eval_tasks = [] self.main_task_group = None async def create_services(self): # Add services to self.config[CONFIG_CATEGORY_SERVICES] await ServiceCreator.create_services(self.config, self.backtesting_enabled) # Notify starting if self.config[CONFIG_NOTIFICATION_INSTANCE].enabled( CONFIG_NOTIFICATION_GLOBAL_INFO): await self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all( NOTIFICATION_STARTING_MESSAGE, False) async def create_exchange_traders(self, ignore_config=False): self.async_loop = asyncio.get_running_loop() available_exchanges = ccxt.exchanges for exchange_class_string in self.config[CONFIG_EXCHANGES]: if exchange_class_string in available_exchanges: exchange_type = getattr(ccxt, exchange_class_string) # Backtesting Exchange if self.backtesting_enabled: exchange_manager = ExchangeManager(self.config, exchange_type, is_simulated=True) else: # Real Exchange exchange_manager = ExchangeManager( self.config, exchange_type, is_simulated=False, ignore_config=ignore_config) await exchange_manager.initialize() exchange_inst = exchange_manager.get_exchange() self.exchanges_list[exchange_inst.get_name()] = exchange_inst self.global_updaters_by_exchange[exchange_inst.get_name( )] = GlobalPriceUpdater(exchange_inst) # create trader instance for this exchange exchange_trader = Trader(self.config, exchange_inst) await exchange_trader.initialize() self.exchange_traders[ exchange_inst.get_name()] = exchange_trader # create trader simulator instance for this exchange exchange_trader_simulator = TraderSimulator( self.config, exchange_inst) await exchange_trader_simulator.initialize() self.exchange_trader_simulators[ exchange_inst.get_name()] = exchange_trader_simulator if not (exchange_trader_simulator.enabled(self.config) or exchange_trader.enabled(self.config)): self.logger.error( f"No trader simulator nor real trader activated on {exchange_inst.get_name()}" ) # create trading mode try: self.trading_mode = get_activated_trading_mode( self.config)(self.config, exchange_inst) self.exchange_trading_modes[ exchange_inst.get_name()] = self.trading_mode self.logger.debug( f"Using {self.trading_mode.get_name()} trading mode") except RuntimeError as e: self.logger.error(e.args[0]) raise e else: self.logger.error( f"{exchange_class_string} exchange not found") def create_evaluation_tasks(self): self.logger.info("Evaluation threads creation...") # create dispatchers self.dispatchers_list = EvaluatorCreator.create_dispatchers( self.config, self.async_loop) # create Social and TA evaluators for crypto_currency, crypto_currency_data in self.config[ CONFIG_CRYPTO_CURRENCIES].items(): # create crypto_currency evaluator crypto_currency_evaluator = CryptocurrencyEvaluator( self.config, crypto_currency, self.dispatchers_list, self.relevant_evaluators) self.crypto_currency_evaluator_list[ crypto_currency] = crypto_currency_evaluator self.social_eval_tasks = self.social_eval_tasks + crypto_currency_evaluator.get_social_tasked_eval_list( ) # create TA evaluators for symbol in crypto_currency_data[CONFIG_CRYPTO_PAIRS]: # create symbol evaluator symbol_evaluator = SymbolEvaluator(self.config, symbol, crypto_currency_evaluator) symbol_evaluator.set_traders(self.exchange_traders) symbol_evaluator.set_trader_simulators( self.exchange_trader_simulators) crypto_currency_evaluator.add_symbol_evaluator( symbol, symbol_evaluator) self.symbol_evaluator_list[symbol] = symbol_evaluator for exchange in self.exchanges_list.values(): global_price_updater = self.global_updaters_by_exchange[ exchange.get_name()] if exchange.get_exchange_manager().enabled(): # Verify that symbol exists on this exchange if symbol in exchange.get_exchange_manager( ).get_traded_pairs(): self._create_symbol_threads_managers( exchange, symbol_evaluator, global_price_updater) # notify that exchange doesn't support this symbol else: if not self.backtesting_enabled: self.logger.warning( f"{exchange.get_name()} doesn't support {symbol}" ) self._check_required_evaluators() def _create_symbol_threads_managers(self, exchange, symbol_evaluator, global_price_updater): if Backtesting.enabled(self.config): real_time_ta_eval_list = [] else: # Create real time TA evaluators real_time_ta_eval_list = EvaluatorCreator.create_real_time_ta_evals( self.config, exchange, symbol_evaluator.get_symbol(), self.relevant_evaluators) self.real_time_eval_tasks = self.real_time_eval_tasks + real_time_ta_eval_list for time_frame in self.time_frames: if exchange.get_exchange_manager().time_frame_exists( time_frame.value, symbol_evaluator.get_symbol()): self.symbol_tasks_manager[time_frame] = \ EvaluatorTaskManager(self.config, time_frame, global_price_updater, symbol_evaluator, exchange, self.exchange_trading_modes[exchange.get_name()], real_time_ta_eval_list, self.async_loop, self.relevant_evaluators) else: self.logger.warning( f"{exchange.get_name()} exchange is not supporting the required time frame: " f"'{time_frame.value}' for {symbol_evaluator.get_symbol()}." ) def _check_required_evaluators(self): if self.symbol_tasks_manager: etm = next(iter(self.symbol_tasks_manager.values())) ta_list = etm.get_evaluator().get_ta_eval_list() if self.relevant_evaluators != CONFIG_EVALUATORS_WILDCARD: for required_eval in self.relevant_evaluators: required_class = get_class_from_string( required_eval, TAEvaluator, TA, evaluator_parent_inspection) if required_class and not self._class_is_in_list( ta_list, required_class): self.logger.error( f"Missing technical analysis evaluator {required_class.get_name()} for " f"current strategy. Activate it in OctoBot advanced configuration interface " f"to allow activated strategy(ies) to work properly." ) async def start_tasks(self, run_in_new_thread=False): task_list = [] if self.performance_analyser: task_list.append(self.performance_analyser.start_monitoring()) for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values( ): task_list.append( crypto_currency_evaluator.get_social_evaluator_refresh_task()) for trader in self.exchange_traders.values(): task_list.append(trader.launch()) for trader_simulator in self.exchange_trader_simulators.values(): task_list.append(trader_simulator.launch()) for updater in self.global_updaters_by_exchange.values(): if self.watcher is not None: updater.set_watcher(self.watcher) task_list.append(updater.start_update_loop()) for real_time_eval in self.real_time_eval_tasks: task_list.append(real_time_eval.start_task()) for social_eval in self.social_eval_tasks: task_list.append(social_eval.start_task()) for thread in self.dispatchers_list: thread.start() self.logger.info("Evaluation tasks started...") self.ready = True self.main_task_group = asyncio.gather(*task_list) if run_in_new_thread: self._create_new_asyncio_main_loop() else: self.current_loop_thread = threading.current_thread() await self.main_task_group def join_threads(self): for thread in self.dispatchers_list: thread.join() def stop_threads(self): stop_coroutines = [] # Notify stopping if self.config[CONFIG_NOTIFICATION_INSTANCE].enabled( CONFIG_NOTIFICATION_GLOBAL_INFO): # To be improved with a full async implementation # To be done : "asyncio.run" --> replaced by a simple await # PR discussion : https://github.com/Drakkar-Software/OctoBot/pull/563#discussion_r248088266 stop_coroutines.append( self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all( NOTIFICATION_STOPPING_MESSAGE)) self.logger.info("Stopping threads ...") if self.main_task_group: self.main_task_group.cancel() for thread in self.dispatchers_list: thread.stop() # stop services for service_instance in ServiceCreator.get_service_instances( self.config): try: service_instance.stop() except Exception as e: raise e # stop exchanges threads for exchange in self.exchanges_list.values(): stop_coroutines.append(exchange.stop()) loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) asyncio.run(get_gather_wrapper(stop_coroutines)) self.logger.info("Threads stopped.") @staticmethod def _class_is_in_list(class_list, required_klass): return any(required_klass in klass.get_parent_evaluator_classes() for klass in class_list) def run_in_main_asyncio_loop(self, coroutine): # restart a new loop if necessary (for backtesting analysis) if Backtesting.enabled(self.config) and self.async_loop.is_closed(): self.logger.debug("Main loop is closed, starting a new main loop.") self._create_new_asyncio_main_loop() return run_coroutine_in_asyncio_loop(coroutine, self.async_loop) def _create_new_asyncio_main_loop(self): self.async_loop = asyncio.new_event_loop() self.async_loop.set_debug(FORCE_ASYNCIO_DEBUG_OPTION) asyncio.set_event_loop(self.async_loop) self.current_loop_thread = threading.Thread( target=self.async_loop.run_forever) self.current_loop_thread.start() def set_watcher(self, watcher): self.watcher = watcher def get_symbols_tasks_manager(self): return self.symbol_tasks_manager def get_exchange_traders(self): return self.exchange_traders def get_exchange_trader_simulators(self): return self.exchange_trader_simulators def get_exchange_trading_modes(self): return self.exchange_trading_modes def get_exchanges_list(self): return self.exchanges_list def get_symbol_evaluator_list(self): return self.symbol_evaluator_list def get_symbols_list(self): return self.symbol_evaluator_list.keys() def get_crypto_currency_evaluator_list(self): return self.crypto_currency_evaluator_list def get_dispatchers_list(self): return self.dispatchers_list def get_global_updaters_by_exchange(self): return self.global_updaters_by_exchange def get_start_time(self): return self.start_time def is_ready(self): return self.ready def get_config(self): return self.config def get_startup_config(self): return self.startup_config def get_edited_config(self): return self.edited_config def get_tools(self): return self.tools def get_trading_mode(self): return self.trading_mode def get_async_loop(self): return self.async_loop
def _create_performance_analyser(self): if CONFIG_DEBUG_OPTION_PERF in self.octobot.get_config() \ and self.octobot.get_config()[CONFIG_DEBUG_OPTION_PERF]: return PerformanceAnalyser()
class CryptoBot: """ Constructor : - Load configs """ def __init__(self, config): self.start_time = time.time() self.config = config self.ready = False # Logger self.logger = logging.getLogger(self.__class__.__name__) # Advanced AdvancedManager.create_class_list(self.config) # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() self.time_frames = TimeFrameManager.get_config_time_frame(self.config) # Add services to self.config[CONFIG_CATEGORY_SERVICES] ServiceCreator.create_services(self.config) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) # Notify starting self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all(NOTIFICATION_STARTING_MESSAGE) # Backtesting self.backtesting_enabled = None self.symbol_threads_manager = {} self.exchange_traders = {} self.exchange_trader_simulators = {} self.exchanges_list = {} self.symbol_evaluator_list = {} self.crypto_currency_evaluator_list = {} self.dispatchers_list = [] self.symbol_time_frame_updater_threads = [] def create_exchange_traders(self): self.backtesting_enabled = Backtesting.enabled(self.config) available_exchanges = ccxt.exchanges for exchange_class_string in self.config[CONFIG_EXCHANGES]: if exchange_class_string in available_exchanges: exchange_type = getattr(ccxt, exchange_class_string) # Backtesting Exchange if self.backtesting_enabled: exchange_inst = ExchangeSimulator(self.config, exchange_type) else: # True Exchange exchange_inst = Exchange(self.config, exchange_type) self.exchanges_list[exchange_inst.get_name()] = exchange_inst # create trader instance for this exchange exchange_trader = Trader(self.config, exchange_inst) self.exchange_traders[exchange_inst.get_name()] = exchange_trader # create trader simulator instance for this exchange exchange_trader_simulator = TraderSimulator(self.config, exchange_inst) self.exchange_trader_simulators[exchange_inst.get_name()] = exchange_trader_simulator else: self.logger.error("{0} exchange not found".format(exchange_class_string)) def create_evaluation_threads(self): self.logger.info("Evaluation threads creation...") # create dispatchers self.dispatchers_list = EvaluatorCreator.create_dispatchers(self.config) # create Social and TA evaluators for crypto_currency, crypto_currency_data in self.config[CONFIG_CRYPTO_CURRENCIES].items(): # create crypto_currency evaluator crypto_currency_evaluator = CryptocurrencyEvaluator(self.config, crypto_currency, self.dispatchers_list) self.crypto_currency_evaluator_list[crypto_currency] = crypto_currency_evaluator # create TA evaluators for symbol in crypto_currency_data[CONFIG_CRYPTO_PAIRS]: # create symbol evaluator symbol_evaluator = SymbolEvaluator(self.config, symbol, crypto_currency_evaluator) symbol_evaluator.set_traders(self.exchange_traders) symbol_evaluator.set_trader_simulators(self.exchange_trader_simulators) crypto_currency_evaluator.add_symbol_evaluator(symbol, symbol_evaluator) self.symbol_evaluator_list[symbol] = symbol_evaluator for exchange in self.exchanges_list.values(): if exchange.enabled(): # Verify that symbol exists on this exchange if symbol in exchange.get_traded_pairs(): self._create_symbol_threads_managers(symbol, exchange, symbol_evaluator) # notify that exchange doesn't support this symbol else: if not self.backtesting_enabled: self.logger.warning("{0} doesn't support {1}".format(exchange.get_name(), symbol)) def _create_symbol_threads_managers(self, symbol, exchange, symbol_evaluator): # Create real time TA evaluators real_time_ta_eval_list = EvaluatorCreator.create_real_time_ta_evals(self.config, exchange, symbol) symbol_time_frame_updater_thread = SymbolTimeFramesDataUpdaterThread() for time_frame in self.time_frames: if exchange.time_frame_exists(time_frame.value): self.symbol_threads_manager[time_frame] = EvaluatorThreadsManager(self.config, symbol, time_frame, symbol_time_frame_updater_thread, symbol_evaluator, exchange, real_time_ta_eval_list) self.symbol_time_frame_updater_threads.append(symbol_time_frame_updater_thread) def start_threads(self): if self.performance_analyser: self.performance_analyser.start() for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values(): crypto_currency_evaluator.start_threads() for manager in self.symbol_threads_manager.values(): manager.start_threads() for thread in self.symbol_time_frame_updater_threads: thread.start() for thread in self.dispatchers_list: thread.start() self.ready = True self.logger.info("Evaluation threads started...") def join_threads(self): for manager in self.symbol_threads_manager: self.symbol_threads_manager[manager].join_threads() for thread in self.symbol_time_frame_updater_threads: thread.join() for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values(): crypto_currency_evaluator.join_threads() for trader in self.exchange_traders.values(): trader.join_order_manager() for trader_simulator in self.exchange_trader_simulators.values(): trader_simulator.join_order_manager() for thread in self.dispatchers_list: thread.join() if self.performance_analyser: self.performance_analyser.join() def stop_threads(self): # Notify stopping self.config[CONFIG_NOTIFICATION_INSTANCE].notify_with_all(NOTIFICATION_STOPPING_MESSAGE) self.logger.info("Stopping threads ...") for thread in self.symbol_time_frame_updater_threads: thread.stop() for manager in self.symbol_threads_manager.values(): manager.stop_threads() for crypto_currency_evaluator in self.crypto_currency_evaluator_list.values(): crypto_currency_evaluator.stop_threads() for trader in self.exchange_traders.values(): trader.stop_order_manager() for trader_simulator in self.exchange_trader_simulators.values(): trader_simulator.stop_order_manager() for thread in self.dispatchers_list: thread.stop() if self.performance_analyser: self.performance_analyser.stop() # stop services for service_instance in ServiceCreator.get_service_instances(self.config): try: service_instance.stop() except Exception as e: raise e self.logger.info("Threads stopped.") def get_symbols_threads_manager(self): return self.symbol_threads_manager def get_exchange_traders(self): return self.exchange_traders def get_exchange_trader_simulators(self): return self.exchange_trader_simulators def get_exchanges_list(self): return self.exchanges_list def get_symbol_evaluator_list(self): return self.symbol_evaluator_list def get_crypto_currency_evaluator_list(self): return self.crypto_currency_evaluator_list def get_dispatchers_list(self): return self.dispatchers_list def get_symbol_time_frame_updater_threads(self): return self.symbol_time_frame_updater_threads def get_start_time(self): return self.start_time def is_ready(self): return self.ready
class Crypto_Bot: """ Constructor : - Load configs """ def __init__(self): # Logger fileConfig('config/logging_config.ini') self.logger = logging.getLogger(self.__class__.__name__) sys.excepthook = self.log_uncaught_exceptions # Version self.logger.info("Version : {0}".format(VERSION)) # Config self.logger.info("Load config file...") self.config = load_config() # Advanced AdvancedManager.create_class_list(self.config) # Interfaces self.web_app = WebApp(self.config) if self.web_app.enabled(): self.web_app.start() # Debug tools self.performance_analyser = None if CONFIG_DEBUG_OPTION_PERF in self.config and self.config[ CONFIG_DEBUG_OPTION_PERF]: self.performance_analyser = PerformanceAnalyser() # TODO : CONFIG TEMP LOCATION self.time_frames = [ TimeFrames.THIRTY_MINUTES, TimeFrames.ONE_HOUR, TimeFrames.FOUR_HOURS, TimeFrames.ONE_DAY ] self.exchanges = [ccxt.binance] # Add services to self.config[CONFIG_CATEGORY_SERVICES] ServiceCreator.create_services(self.config) # Notifier self.config[CONFIG_NOTIFICATION_INSTANCE] = Notification(self.config) self.symbols_threads_manager = [] self.exchange_traders = {} self.exchange_trader_simulators = {} self.exchanges_list = {} self.symbol_evaluator_list = [] self.dispatchers_list = [] def create_exchange_traders(self): for exchange_type in self.exchanges: exchange_inst = Exchange(self.config, exchange_type) # create trader instance for this exchange exchange_trader = Trader(self.config, exchange_inst) exchange_trader_simulator = TraderSimulator( self.config, exchange_inst) self.exchanges_list[exchange_type.__name__] = exchange_inst self.exchange_traders[exchange_type.__name__] = exchange_trader self.exchange_trader_simulators[ exchange_type.__name__] = exchange_trader_simulator def create_evaluation_threads(self): self.logger.info("Evaluation threads creation...") # create dispatchers self.dispatchers_list = EvaluatorCreator.create_dispatchers( self.config) # create Social and TA evaluators for crypto_currency, crypto_currency_data in self.config[ CONFIG_CRYPTO_CURRENCIES].items(): # create symbol evaluator symbol_evaluator = Symbol_Evaluator(self.config, crypto_currency, self.dispatchers_list) symbol_evaluator.set_traders(self.exchange_traders) symbol_evaluator.set_trader_simulators( self.exchange_trader_simulators) self.symbol_evaluator_list.append(symbol_evaluator) # create TA evaluators for symbol in crypto_currency_data[CONFIG_CRYPTO_PAIRS]: for exchange_type in self.exchanges: exchange = self.exchanges_list[exchange_type.__name__] if exchange.enabled(): # Verify that symbol exists on this exchange if exchange.symbol_exists(symbol): self.create_symbol_threads_managers( symbol, exchange, symbol_evaluator) # notify that exchange doesn't support this symbol else: self.logger.warning( "{0} doesn't support {1}".format( exchange_type.__name__, symbol)) def create_symbol_threads_managers(self, symbol, exchange, symbol_evaluator): # Create real time TA evaluators real_time_ta_eval_list = EvaluatorCreator.create_real_time_ta_evals( self.config, exchange, symbol) for time_frame in self.time_frames: if exchange.time_frame_exists(time_frame.value): self.symbols_threads_manager.append( EvaluatorThreadsManager(self.config, symbol, time_frame, symbol_evaluator, exchange, real_time_ta_eval_list)) def start_threads(self): if self.performance_analyser: self.performance_analyser.start() for symbol_evaluator in self.symbol_evaluator_list: symbol_evaluator.start_threads() for manager in self.symbols_threads_manager: manager.start_threads() for thread in self.dispatchers_list: thread.start() self.logger.info("Evaluation threads started...") def join_threads(self): for manager in self.symbols_threads_manager: manager.join_threads() for symbol_evaluator in self.symbol_evaluator_list: symbol_evaluator.join_threads() for trader in self.exchange_traders: self.exchange_traders[trader].join_order_manager() for trader_simulator in self.exchange_trader_simulators: self.exchange_trader_simulators[ trader_simulator].join_order_manager() for thread in self.dispatchers_list: thread.join() if self.performance_analyser: self.performance_analyser.join() def stop_threads(self): self.logger.info("Stopping threads ...") for manager in self.symbols_threads_manager: manager.stop_threads() for symbol_evaluator in self.symbol_evaluator_list: symbol_evaluator.stop_threads() for trader in self.exchange_traders: self.exchange_traders[trader].stop_order_manager() for trader_simulator in self.exchange_trader_simulators: self.exchange_trader_simulators[ trader_simulator].stop_order_manager() for thread in self.dispatchers_list: thread.stop() if self.performance_analyser: self.performance_analyser.stop() if self.web_app.enabled(): self.web_app.stop() @staticmethod def log_uncaught_exceptions(ex_cls, ex, tb): logging.exception(''.join(traceback.format_tb(tb))) logging.exception('{0}: {1}'.format(ex_cls, ex))