def __init__(self, client_config_map: Optional[ClientConfigAdapter] = None): self.client_config_map: Union[ClientConfigMap, ClientConfigAdapter] = ( # type-hint enables IDE auto-complete client_config_map or load_client_config_map_from_file() ) # This is to start fetching trading pairs for auto-complete TradingPairFetcher.get_instance(self.client_config_map) self.ev_loop: asyncio.AbstractEventLoop = asyncio.get_event_loop() self.markets: Dict[str, ExchangeBase] = {} # strategy file name and name get assigned value after import or create command self._strategy_file_name: Optional[str] = None self.strategy_name: Optional[str] = None self._strategy_config_map: Optional[BaseStrategyConfigMap] = None self.strategy_task: Optional[asyncio.Task] = None self.strategy: Optional[StrategyBase] = None self.market_pair: Optional[CrossExchangeMarketPair] = None self.market_trading_pair_tuples: List[MarketTradingPairTuple] = [] self.clock: Optional[Clock] = None self.market_trading_pairs_map = {} self.token_list = {} self.init_time: float = time.time() self.start_time: Optional[int] = None self.placeholder_mode = False self.log_queue_listener: Optional[logging.handlers.QueueListener] = None self.data_feed: Optional[DataFeedBase] = None self.notifiers: List[NotifierBase] = [] self.kill_switch: Optional[KillSwitch] = None self._app_warnings: Deque[ApplicationWarning] = deque() self._trading_required: bool = True self._last_started_strategy_file: Optional[str] = None self.trade_fill_db: Optional[SQLConnectionManager] = None self.markets_recorder: Optional[MarketsRecorder] = None self._pmm_script_iterator = None self._binance_connector = None self._shared_client = None # gateway variables and monitor self._gateway_monitor = GatewayStatusMonitor(self) command_tabs = self.init_command_tabs() self.parser: ThrowingArgumentParser = load_parser(self, command_tabs) self.app = HummingbotCLI( self.client_config_map, input_handler=self._handle_command, bindings=load_key_bindings(self), completer=load_completer(self), command_tabs=command_tabs ) self._init_gateway_monitor()
def test_fetched_connector_trading_pairs( self, _, mock_connector_settings, mock_import_module, ): mock_connector_settings.return_value = { "mock_exchange_1": self.MockConnectorSetting(name="mockConnector"), "mock_paper_trade": self.MockConnectorSetting(name="mock_paper_trade", parent_name="mockConnector") } mock_import_module.return_value = self.MockConnectorDataSourceModule() trading_pair_fetcher = TradingPairFetcher() self.async_run_with_timeout( self.wait_until_trading_pair_fetcher_ready(trading_pair_fetcher), 1.0) trading_pairs = trading_pair_fetcher.trading_pairs self.assertEqual(2, len(trading_pairs)) self.assertEqual(trading_pairs, { "mockConnector": "MOCK-HBOT", "mock_paper_trade": "MOCK-HBOT" })
def valid_token_or_trading_pair_array(market: str, input_list: Any): try: if isinstance(input_list, str): if len(input_list) == 0: return True filtered: filter = filter(lambda x: x not in ['[', ']', '"', "'"], list(input_list)) input_list = "".join(filtered).split(",") input_list = [s.strip() for s in input_list ] # remove leading and trailing whitespaces single_token_inputs = list(filter(is_token, input_list)) trading_pair_inputs = list( filter(lambda x: not is_token(x), input_list)) known_trading_pairs = TradingPairFetcher.get_instance( ).trading_pairs.get(market, []) if len(known_trading_pairs) == 0: return True else: from hummingbot.client.hummingbot_application import MARKET_CLASSES market_class = MARKET_CLASSES[market] valid_token_set: Set[str] = set() for known_trading_pair in known_trading_pairs: try: base, quote = market_class.split_symbol(known_trading_pair) valid_token_set.update([base, quote]) except Exception: # Add this catch to prevent trading_pairs with bad format to break the validator continue return all([token[1:-1] in valid_token_set for token in single_token_inputs]) and \ all([trading_pair in known_trading_pairs for trading_pair in trading_pair_inputs]) except Exception: return False
def validate_market_trading_pair(market: str, value: str) -> Optional[str]: # Since trading pair validation and autocomplete are UI optimizations that do not impact bot performances, # in case of network issues or slow wifi, this check returns true and does not prevent users from proceeding, trading_pair_fetcher: TradingPairFetcher = TradingPairFetcher.get_instance() if trading_pair_fetcher.ready: if value not in trading_pair_fetcher.trading_pairs.get(market): return f"{value} is not an active market on {market}."
def _trading_pair_completer(self) -> Completer: trading_pair_fetcher = TradingPairFetcher.get_instance() for exchange in sorted(list(CONNECTOR_SETTINGS.keys()), key=len, reverse=True): if exchange in self.prompt_text: market = exchange break trading_pairs = trading_pair_fetcher.trading_pairs.get(market, []) if trading_pair_fetcher.ready else [] return WordCompleter(trading_pairs, ignore_case=True, sentence=True)
def _trading_pair_completer(self) -> Completer: trading_pair_fetcher = TradingPairFetcher.get_instance() market = "" for exchange in sorted(list(AllConnectorSettings.get_connector_settings().keys()), key=len, reverse=True): if exchange in self.prompt_text: market = exchange break trading_pairs = trading_pair_fetcher.trading_pairs.get(market, []) if trading_pair_fetcher.ready and market else [] return WordCompleter(trading_pairs, ignore_case=True, sentence=True)
def _trading_pair_completer(self) -> Completer: trading_pair_fetcher = TradingPairFetcher.get_instance() market = None for exchange in EXCHANGES: if exchange in self.prompt_text: market = exchange break trading_pairs = trading_pair_fetcher.trading_pairs.get(market, []) if trading_pair_fetcher.ready else [] return WordCompleter(trading_pairs, ignore_case=True)
def is_valid_market_trading_pair(market: str, value: str) -> bool: # Since trading pair validation and autocomplete are UI optimizations that do not impact bot performances, # in case of network issues or slow wifi, this check returns true and does not prevent users from proceeding, trading_pair_fetcher: TradingPairFetcher = TradingPairFetcher.get_instance() if trading_pair_fetcher.ready: trading_pairs = trading_pair_fetcher.trading_pairs.get(market, []) return value in trading_pair_fetcher.trading_pairs.get(market) if len(trading_pairs) > 0 else True else: return True
def __init__(self): # This is to start fetching trading pairs for auto-complete TradingPairFetcher.get_instance() self.ev_loop: asyncio.BaseEventLoop = asyncio.get_event_loop() # # Enable main thread debug mode to make sure Callbacks taking longer than 50ms are logged. # self.ev_loop.set_debug(True) # self.ev_loop.slow_callback_duration = 0.001 # 1ms self.parser: ThrowingArgumentParser = load_parser(self) self.app = HummingbotCLI(input_handler=self._handle_command, bindings=load_key_bindings(self), completer=load_completer(self)) self.markets: Dict[str, ExchangeBase] = {} self.wallet: Optional[Web3Wallet] = None # strategy file name and name get assigned value after import or create command self._strategy_file_name: str = None self.strategy_name: str = None self.strategy_task: Optional[asyncio.Task] = None self.strategy: Optional[StrategyBase] = None self.market_pair: Optional[CrossExchangeMarketPair] = None self.market_trading_pair_tuples: List[MarketTradingPairTuple] = [] self.clock: Optional[Clock] = None self.market_trading_pairs_map = {} self.token_list = {} self.init_time: float = time.time() self.start_time: Optional[int] = None self.assets: Optional[Set[str]] = set() self.placeholder_mode = False self.log_queue_listener: Optional[ logging.handlers.QueueListener] = None self.data_feed: Optional[DataFeedBase] = None self.notifiers: List[NotifierBase] = [] self.kill_switch: Optional[KillSwitch] = None self._app_warnings: Deque[ApplicationWarning] = deque() self._trading_required: bool = True self._last_started_strategy_file: Optional[str] = None self.trade_fill_db: Optional[SQLConnectionManager] = None self.markets_recorder: Optional[MarketsRecorder] = None self._script_iterator = None self._binance_connector = None
def test_fetched_connector_trading_pairs(self): with patch('hummingbot.core.utils.trading_pair_fetcher.CONNECTOR_SETTINGS', {"mock_exchange_1": self.MockConnectorSetting()}) as _, \ patch('hummingbot.core.utils.trading_pair_fetcher.importlib.import_module', return_value=self.MockConnectorDataSourceModule()) as _, \ patch('hummingbot.core.utils.trading_pair_fetcher.TradingPairFetcher._sf_shared_instance', None): from hummingbot.core.utils.trading_pair_fetcher import TradingPairFetcher trading_pair_fetcher = TradingPairFetcher() asyncio.get_event_loop().run_until_complete( self.wait_until_trading_pair_fetcher_ready( trading_pair_fetcher)) trading_pairs = trading_pair_fetcher.trading_pairs self.assertEqual(trading_pairs, {'mockConnector': 'MOCK-HBOT'})
def validate_market_trading_pair(market: str, value: str) -> Optional[str]: """ Since trading pair validation and autocomplete are UI optimizations that do not impact bot performances, in case of network issues or slow wifi, this check returns true and does not prevent users from proceeding, """ from hummingbot.core.utils.trading_pair_fetcher import TradingPairFetcher trading_pair_fetcher: TradingPairFetcher = TradingPairFetcher.get_instance() if trading_pair_fetcher.ready: trading_pairs = trading_pair_fetcher.trading_pairs.get(market, []) if len(trading_pairs) == 0: return None elif value not in trading_pairs: return f"{value} is not an active market on {market}."
def __init__(self): self.ev_loop: asyncio.BaseEventLoop = asyncio.get_event_loop() self.parser: ThrowingArgumentParser = load_parser(self) self.app = HummingbotCLI(input_handler=self._handle_command, bindings=load_key_bindings(self), completer=load_completer(self)) self.markets: Dict[str, ExchangeBase] = {} self.wallet: Optional[Web3Wallet] = None # strategy file name and name get assigned value after import or create command self.strategy_file_name: str = None self.strategy_name: str = None self.strategy_task: Optional[asyncio.Task] = None self.strategy: Optional[StrategyBase] = None self.market_pair: Optional[CrossExchangeMarketPair] = None self.market_trading_pair_tuples: List[MarketTradingPairTuple] = [] self.clock: Optional[Clock] = None self.init_time: int = int(time.time() * 1e3) self.start_time: Optional[int] = None self.assets: Optional[Set[str]] = set() self.starting_balances = {} self.placeholder_mode = False self.log_queue_listener: Optional[ logging.handlers.QueueListener] = None self.data_feed: Optional[DataFeedBase] = None self.notifiers: List[NotifierBase] = [] self.kill_switch: Optional[KillSwitch] = None self._app_warnings: Deque[ApplicationWarning] = deque() self._trading_required: bool = True self.trade_fill_db: SQLConnectionManager = SQLConnectionManager.get_trade_fills_instance( ) self.markets_recorder: Optional[MarketsRecorder] = None self._script_iterator = None # This is to start fetching trading pairs for auto-complete TradingPairFetcher.get_instance()
def get_completer(): trading_pair_fetcher = TradingPairFetcher.get_instance() prompt_text = hb.app.prompt_text if "exchange name" in prompt_text: return list(EXCHANGES) elif "trading pair" in prompt_text and trading_pair_fetcher.ready: market = None for exchange in EXCHANGES: if exchange in prompt_text: market = exchange break return trading_pair_fetcher.trading_pairs[ market] if market != None else [] else: return []
def test_fetched_connector_trading_pairs(self, _, mock_connector_settings): connector = AsyncMock() connector.all_trading_pairs.return_value = ["MOCK-HBOT"] mock_connector_settings.return_value = { "mock_exchange_1": self.MockConnectorSetting(name="mockConnector", connector=connector), "mock_paper_trade": self.MockConnectorSetting(name="mock_paper_trade", parent_name="mock_exchange_1") } client_config_map = ClientConfigAdapter(ClientConfigMap()) trading_pair_fetcher = TradingPairFetcher(client_config_map) self.async_run_with_timeout( self.wait_until_trading_pair_fetcher_ready(trading_pair_fetcher), 1.0) trading_pairs = trading_pair_fetcher.trading_pairs self.assertEqual(2, len(trading_pairs)) self.assertEqual( { "mockConnector": ["MOCK-HBOT"], "mock_paper_trade": ["MOCK-HBOT"] }, trading_pairs)
from os.path import ( realpath, join, ) from typing import List from hummingbot import get_strategy_list from hummingbot.core.utils.trading_pair_fetcher import TradingPairFetcher # Global variables required_exchanges: List[str] = [] trading_pair_fetcher = TradingPairFetcher.get_instance() # Global static values KEYFILE_PREFIX = "key_file_" KEYFILE_POSTFIX = ".json" ENCYPTED_CONF_PREFIX = "encrypted_" ENCYPTED_CONF_POSTFIX = ".json" GLOBAL_CONFIG_PATH = "conf/conf_global.yml" TRADE_FEES_CONFIG_PATH = "conf/conf_fee_overrides.yml" TOKEN_ADDRESSES_FILE_PATH = realpath(join(__file__, "../../wallet/ethereum/erc20_tokens.json")) DEFAULT_KEY_FILE_PATH = "conf/" DEFAULT_LOG_FILE_PATH = "logs/" DEFAULT_ETHEREUM_RPC_URL = "https://mainnet.coinalpha.com/hummingbot-test-node" TEMPLATE_PATH = realpath(join(__file__, "../../templates/")) CONF_FILE_PATH = "conf/" CONF_PREFIX = "conf_" CONF_POSTFIX = "_strategy" EXCHANGES = { "bamboo_relay",
def test_trading_pair_fetcher_returns_same_instance_when_get_new_instance_once_initialized( self): instance = TradingPairFetcher.get_instance() self.assertIs(instance, TradingPairFetcher.get_instance())
def test_trading_pair_fetcher_returns_same_instance_when_get_new_instance_once_initialized( self): from hummingbot.core.utils.trading_pair_fetcher import TradingPairFetcher instance = TradingPairFetcher.get_instance() self.assertIs(instance, TradingPairFetcher.get_instance())
def test_fetch_all(self, mock_api, all_connector_settings_mock): all_connector_settings_mock.return_value = { "binance": ConnectorSetting(name='binance', type=ConnectorType.Exchange, example_pair='ZRX-ETH', centralised=True, use_ethereum_wallet=False, trade_fee_schema=TradeFeeSchema( percent_fee_token=None, maker_percent_fee_decimal=Decimal('0.001'), taker_percent_fee_decimal=Decimal('0.001'), buy_percent_fee_deducted_from_returns=False, maker_fixed_fees=[], taker_fixed_fees=[]), config_keys={ 'binance_api_key': ConfigVar(key='binance_api_key', prompt=""), 'binance_api_secret': ConfigVar(key='binance_api_secret', prompt="") }, is_sub_domain=False, parent_name=None, domain_parameter=None, use_eth_gas_lookup=False) } url = binance_web_utils.public_rest_url( path_url=CONSTANTS.EXCHANGE_INFO_PATH_URL) mock_response: Dict[str, Any] = { "timezone": "UTC", "serverTime": 1639598493658, "rateLimits": [], "exchangeFilters": [], "symbols": [ { "symbol": "ETHBTC", "status": "TRADING", "baseAsset": "ETH", "baseAssetPrecision": 8, "quoteAsset": "BTC", "quotePrecision": 8, "quoteAssetPrecision": 8, "baseCommissionPrecision": 8, "quoteCommissionPrecision": 8, "orderTypes": [ "LIMIT", "LIMIT_MAKER", "MARKET", "STOP_LOSS_LIMIT", "TAKE_PROFIT_LIMIT" ], "icebergAllowed": True, "ocoAllowed": True, "quoteOrderQtyMarketAllowed": True, "isSpotTradingAllowed": True, "isMarginTradingAllowed": True, "filters": [], "permissions": ["SPOT", "MARGIN"] }, { "symbol": "LTCBTC", "status": "TRADING", "baseAsset": "LTC", "baseAssetPrecision": 8, "quoteAsset": "BTC", "quotePrecision": 8, "quoteAssetPrecision": 8, "baseCommissionPrecision": 8, "quoteCommissionPrecision": 8, "orderTypes": [ "LIMIT", "LIMIT_MAKER", "MARKET", "STOP_LOSS_LIMIT", "TAKE_PROFIT_LIMIT" ], "icebergAllowed": True, "ocoAllowed": True, "quoteOrderQtyMarketAllowed": True, "isSpotTradingAllowed": True, "isMarginTradingAllowed": True, "filters": [], "permissions": ["SPOT", "MARGIN"] }, { "symbol": "BNBBTC", "status": "TRADING", "baseAsset": "BNB", "baseAssetPrecision": 8, "quoteAsset": "BTC", "quotePrecision": 8, "quoteAssetPrecision": 8, "baseCommissionPrecision": 8, "quoteCommissionPrecision": 8, "orderTypes": [ "LIMIT", "LIMIT_MAKER", "MARKET", "STOP_LOSS_LIMIT", "TAKE_PROFIT_LIMIT" ], "icebergAllowed": True, "ocoAllowed": True, "quoteOrderQtyMarketAllowed": True, "isSpotTradingAllowed": True, "isMarginTradingAllowed": True, "filters": [], "permissions": ["MARGIN"] }, ] } mock_api.get(url, body=json.dumps(mock_response)) client_config_map = ClientConfigAdapter(ClientConfigMap()) fetcher = TradingPairFetcher(client_config_map) asyncio.get_event_loop().run_until_complete(fetcher._fetch_task) trading_pairs = fetcher.trading_pairs self.assertEqual(1, len(trading_pairs.keys())) self.assertIn("binance", trading_pairs) binance_pairs = trading_pairs["binance"] self.assertEqual(2, len(binance_pairs)) self.assertIn("ETH-BTC", binance_pairs) self.assertIn("LTC-BTC", binance_pairs) self.assertNotIn("BNB-BTC", binance_pairs)