def find_min_time_frame(time_frames, min_time_frame=None): """ Find the minimum time frame :param time_frames: the time frame list :param min_time_frame: the min time frame :return: the minimal time frame """ time_frame_list = time_frames if time_frames and isinstance(next(iter(time_frames)), enums.TimeFrames): time_frame_list = [t.value for t in time_frames] if (not time_frame_list ): # if exchange has no time frame list, returns minimal time frame return TimeFramesRank[0] min_index = 0 if min_time_frame: min_index = TimeFramesRank.index(min_time_frame) # TimeFramesRank is the ordered list of timeframes for index, time_frame in enumerate(TimeFramesRank): tf_val = time_frame.value if index >= min_index and tf_val in time_frame_list: try: return enums.TimeFrames(tf_val) except ValueError: pass return min_time_frame
def _load_all_available_timeframes(self): allowed_timeframes = set(tf.value for tf in commons_enums.TimeFrames) self.time_frames = [ commons_enums.TimeFrames(time_frame) for time_frame in self.exchange_manager.client_time_frames if time_frame in allowed_timeframes ]
async def strategy_matrix_callback(self, matrix_id, evaluator_name, evaluator_type, eval_note, eval_note_type, exchange_name, cryptocurrency, symbol, time_frame): # if this callback is from a technical evaluator: ensure strategy should be notified at this moment if evaluator_type == enums.EvaluatorMatrixTypes.TA.value: # ensure this time frame is within the strategy's time frames if common_enums.TimeFrames(time_frame) not in self.strategy_time_frames or \ not self.is_technical_evaluator_cycle_complete(matrix_id, evaluator_name, evaluator_type, exchange_name, cryptocurrency, symbol, time_frame): # do not call the strategy return await self.matrix_callback( matrix_id, evaluator_name, evaluator_type, eval_note, eval_note_type, exchange_name, cryptocurrency, symbol, time_frame )
def get_symbol_time_candles(symbol_data, time_frame, limit, include_in_construction): tf = enums.TimeFrames(time_frame) if include_in_construction: return _add_in_construction_data( symbol_data.symbol_candles[tf].get_symbol_time_candles(limit), symbol_data, tf, enums.PriceIndexes.IND_PRICE_TIME.value) return symbol_data.symbol_candles[tf].get_symbol_time_candles(limit)
def get_timeframes_list(exchanges): timeframes_list = [] allowed_timeframes = set(tf.value for tf in commons_enums.TimeFrames) for exchange in exchanges: if exchange not in exchange_symbol_fetch_blacklist: timeframes_list += interfaces_util.run_in_bot_async_executor( trading_api.get_exchange_available_time_frames(exchange)) return [commons_enums.TimeFrames(time_frame) for time_frame in list(set(timeframes_list)) if time_frame in allowed_timeframes]
def init_config_time_frame_for_tests(config): """ Append time frames to config for tests :param config: the test config :return: the test config with time frames """ result = [] for time_frame in config[constants.CONFIG_TIME_FRAME]: result.append(enums.TimeFrames(time_frame)) config[constants.CONFIG_TIME_FRAME] = result
def _get_time_frame(exchange_name, exchange_id): try: return time_frame_manager.get_display_time_frame( interfaces_util.get_global_config(), commons_enums.TimeFrames(constants.DEFAULT_TIMEFRAME)) except IndexError: # second try with watched timeframes, there might be a real-time time frame available return trading_api.get_watched_timeframes( trading_api.get_exchange_manager_from_exchange_name_and_id( exchange_name, exchange_id))[0]
def get_eval_time(full_candle=None, time_frame=None, partial_candle=None, kline=None): if full_candle is not None and time_frame is not None: # add one full time frame seconds since a full candle is available when the next has started return full_candle[enums.PriceIndexes.IND_PRICE_TIME.value] + \ enums.TimeFramesMinutes[enums.TimeFrames(time_frame)] * constants.MINUTE_TO_SECONDS if partial_candle is not None: return partial_candle[enums.PriceIndexes.IND_PRICE_TIME.value] if kline is not None: return kline[enums.PriceIndexes.IND_PRICE_TIME.value] raise ValueError("Invalid arguments")
async def get_database_description(database): description = (await database.select(enums.DataTables.DESCRIPTION, size=1))[0] version = description[1] if version == "1.0": return { enums.DataFormatKeys.TIMESTAMP.value: description[0], enums.DataFormatKeys.VERSION.value: description[1], enums.DataFormatKeys.EXCHANGE.value: description[2], enums.DataFormatKeys.SYMBOLS.value: json.loads(description[3]), enums.DataFormatKeys.TIME_FRAMES.value: [common_enums.TimeFrames(tf) for tf in json.loads(description[4])] } else: raise RuntimeError(f"Unknown datafile version: {version}")
async def candle(self, candle_data: cryptofeed_types.Candle, receipt_timestamp: float): """ Cryptofeed candle callback :param candle_data: the candle object defined in cryptofeed.types.Candle :param receipt_timestamp: received timestamp """ symbol = self.get_pair_from_exchange(candle_data.symbol) time_frame = commons_enums.TimeFrames(candle_data.interval) candle = [ candle_data.start, float(candle_data.open), float(candle_data.high), float(candle_data.low), float(candle_data.close), float(candle_data.volume), ] ticker = { Ectc.HIGH.value: float(candle_data.high), Ectc.LOW.value: float(candle_data.low), Ectc.BID.value: None, Ectc.BID_VOLUME.value: None, Ectc.ASK.value: None, Ectc.ASK_VOLUME.value: None, Ectc.OPEN.value: float(candle_data.open), Ectc.CLOSE.value: float(candle_data.close), Ectc.LAST.value: float(candle_data.close), Ectc.PREVIOUS_CLOSE.value: None, Ectc.BASE_VOLUME.value: float(candle_data.volume), Ectc.TIMESTAMP.value: candle_data.timestamp, } if candle_data.symbol not in self.watched_pairs: if not candle_data.closed: await self.push_to_channel(trading_constants.KLINE_CHANNEL, time_frame=time_frame, symbol=symbol, kline=candle) else: await self.push_to_channel(trading_constants.OHLCV_CHANNEL, time_frame=time_frame, symbol=symbol, candle=candle) # Push a new ticker if necessary : only push on the min timeframe if time_frame is self.min_timeframe: await self.push_to_channel(trading_constants.TICKER_CHANNEL, symbol=symbol, ticker=ticker)
def _inner_get_available_node_paths(self, matrix_id, evaluator_type, exchange_name, cryptocurrency, symbol, use_cache=True): return [ matrix.get_matrix_default_value_path(tentacle_name=evaluator, tentacle_type=evaluator_type, exchange_name=exchange_name, cryptocurrency=cryptocurrency, symbol=symbol, time_frame=time_frame) for time_frame in self.get_available_time_frames(matrix_id, exchange_name, evaluator_type, cryptocurrency, symbol, use_cache=use_cache) if common_enums.TimeFrames(time_frame) in self.strategy_time_frames for evaluator in self._get_available_evaluators(matrix_id, exchange_name, evaluator_type, use_cache=use_cache) ]
async def get_database_description(database): description = (await database.select(enums.DataTables.DESCRIPTION, size=1))[0] version = description[1] if version == "1.0": return { enums.DataFormatKeys.TIMESTAMP.value: description[0], enums.DataFormatKeys.VERSION.value: description[1], enums.DataFormatKeys.EXCHANGE.value: description[2], enums.DataFormatKeys.SYMBOLS.value: json.loads(description[3]), enums.DataFormatKeys.TIME_FRAMES.value: [common_enums.TimeFrames(tf) for tf in json.loads(description[4])], enums.DataFormatKeys.START_TIMESTAMP.value: 0, enums.DataFormatKeys.END_TIMESTAMP.value: 0, enums.DataFormatKeys.CANDLES_LENGTH.value: int((await database.select_count(enums.ExchangeDataTables.OHLCV, ["*"],\ time_frame=tmf_manager.find_min_time_frame([common_enums.TimeFrames(tf) for tf in json.loads(description[4])]).value))[0][0] / len(json.loads(description[3]))) } elif version == "1.1": return { enums.DataFormatKeys.TIMESTAMP.value: description[0], enums.DataFormatKeys.VERSION.value: description[1], enums.DataFormatKeys.EXCHANGE.value: description[2], enums.DataFormatKeys.SYMBOLS.value: json.loads(description[3]), enums.DataFormatKeys.TIME_FRAMES.value: [common_enums.TimeFrames(tf) for tf in json.loads(description[4])], enums.DataFormatKeys.START_TIMESTAMP.value: description[5], enums.DataFormatKeys.END_TIMESTAMP.value: description[6], enums.DataFormatKeys.CANDLES_LENGTH.value: int((await database.select_count(enums.ExchangeDataTables.OHLCV, ["*"],\ time_frame=tmf_manager.find_min_time_frame([common_enums.TimeFrames(tf) for tf in json.loads(description[4])]).value))[0][0] / len(json.loads(description[3]))) } else: raise RuntimeError(f"Unknown datafile version: {version}")
def parse_time_frames(time_frames_string_list): """ Parse a time frame list as string :param time_frames_string_list: the time frame list as string :return: the parsed time frame list """ result_list = [] for time_frame_string in time_frames_string_list: try: result_list.append(enums.TimeFrames(time_frame_string)) except ValueError: logging_util.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 enums.TimeFrames])) return result_list
async def candle(self, feed, symbol, start, stop, interval, trades, open_price, close_price, high_price, low_price, volume, closed, timestamp, receipt_timestamp): if symbol: symbol = self.get_pair_from_exchange(symbol) time_frame = commons_enums.TimeFrames(interval) candle = [ start, float(open_price), float(high_price), float(low_price), float(close_price), float(volume), ] ticker = { Ectc.HIGH.value: float(high_price), Ectc.LOW.value: float(low_price), Ectc.BID.value: None, Ectc.BID_VOLUME.value: None, Ectc.ASK.value: None, Ectc.ASK_VOLUME.value: None, Ectc.OPEN.value: float(open_price), Ectc.CLOSE.value: float(close_price), Ectc.LAST.value: float(close_price), Ectc.PREVIOUS_CLOSE.value: None, Ectc.BASE_VOLUME.value: float(volume), Ectc.TIMESTAMP.value: timestamp, } if not closed: await self.push_to_channel(trading_constants.KLINE_CHANNEL, time_frame=time_frame, symbol=symbol, kline=candle) else: await self.push_to_channel(trading_constants.OHLCV_CHANNEL, time_frame=time_frame, symbol=symbol, candle=candle) # Push a new ticker if necessary : only push on the min timeframe if time_frame is self.min_timeframe: await self.push_to_channel(trading_constants.TICKER_CHANNEL, symbol=symbol, ticker=ticker)
async def can_convert(self, ) -> bool: self.exchange_name, self.symbol, self.time_data = LegacyDataConverter._interpret_file_name( self.file_to_convert) if None in (self.exchange_name, self.symbol, self.time_data): return False self.file_content = self._read_data_file() if not self.file_content: return False for time_frame, candles_data in self.file_content.items(): try: # check time frame validity time_frame = commons_enums.TimeFrames(time_frame) # check candle data validity if isinstance(candles_data, list) and len(candles_data) == 6: # check candle data non-emptiness if all(data for data in candles_data): self.time_frames.append(time_frame) except ValueError: pass return bool(self.time_frames)
def _get_tentacle_registration_topic(self, all_symbols_by_crypto_currencies, time_frames, real_time_time_frames): currencies, symbols, _ = super()._get_tentacle_registration_topic( all_symbols_by_crypto_currencies, time_frames, real_time_time_frames) to_handle_time_frames = [] if self.time_frame is None: self.logger.error( "Missing self.time_frame value, impossible to initialize this evaluator." ) else: ideal_time_frame = common_enums.TimeFrames(self.time_frame) to_handle_time_frame = util.get_shortest_time_frame( ideal_time_frame, real_time_time_frames, time_frames) if ideal_time_frame != to_handle_time_frame: self.logger.warning( f"Missing {ideal_time_frame.name} time frame in available time frames, " f"using {to_handle_time_frame.name} instead.") to_handle_time_frames = [to_handle_time_frame] # by default time frame registration only for the timeframe of this real-time evaluator return currencies, symbols, to_handle_time_frames
def is_tentacle_value_valid(matrix_id, tentacle_path, timestamp=0, delta=10) -> bool: """ Check if the node is ready to be used WARNING: This method only works with complete default tentacle path :param matrix_id: the matrix id :param tentacle_path: the tentacle node path :param timestamp: the timestamp to use :param delta: the authorized delta to be valid (in seconds) :return: True if the node is valid else False """ if timestamp == 0: timestamp = time.time() try: return timestamp - ( get_tentacle_node(matrix_id, tentacle_path).node_value_time + common_enums.TimeFramesMinutes[common_enums.TimeFrames( tentacle_path[-1])] * common_constants.MINUTE_TO_SECONDS + delta) < 0 except (IndexError, ValueError): return False
async def candle(self, feed, symbol, start, stop, interval, trades, open_price, close_price, high_price, low_price, volume, closed, timestamp, receipt_timestamp): if symbol: symbol = self.get_pair_from_exchange(symbol) time_frame = commons_enums.TimeFrames(interval) candle = [ timestamp, float(open_price), float(high_price), float(low_price), float(close_price), float(volume), ] if not closed: await self.push_to_channel(trading_constants.KLINE_CHANNEL, time_frame=time_frame, symbol=symbol, kline=candle) else: await self.push_to_channel(trading_constants.OHLCV_CHANNEL, time_frame=time_frame, symbol=symbol, candle=candle)
def __init__(self): super().__init__() self.evaluation_time_frame = \ commons_enums.TimeFrames(tentacles_manager_api.get_tentacle_config(self.__class__)[ evaluator_constants.STRATEGIES_REQUIRED_TIME_FRAME][0]).value