def _initialize_markets(self, market_names: List[Tuple[str, str]]): ethereum_rpc_url = global_config_map.get("ethereum_rpc_url").value binance_api_key = global_config_map.get("binance_api_key").value binance_api_secret = global_config_map.get("binance_api_secret").value for market_name, symbol in market_names: market = None if market_name == "ddex": market = DDEXMarket(wallet=self.wallet, web3_url=ethereum_rpc_url, order_book_tracker_data_source_type=OrderBookTrackerDataSourceType.EXCHANGE_API, symbols=[symbol]) elif market_name == "binance": market = BinanceMarket(web3_url=ethereum_rpc_url, binance_api_key=binance_api_key, binance_api_secret=binance_api_secret, order_book_tracker_data_source_type=OrderBookTrackerDataSourceType.EXCHANGE_API, symbols=[symbol]) elif market_name == "radar_relay": market = RadarRelayMarket(wallet=self.wallet, web3_url=ethereum_rpc_url, symbols=[symbol]) self.markets[market_name]: MarketBase = market
async def main(): await create_yml_files() read_configs_from_yml() hb = HummingbotApplication() with patch_stdout(log_field=hb.app.log_field): init_logging("hummingbot_logs.yml", override_log_level=global_config_map.get("log_level").value) tasks: List[Coroutine] = [hb.run()] if global_config_map.get("debug_console").value: management_port: int = detect_available_port(8211) tasks.append(start_management_console(locals(), host="localhost", port=management_port)) await asyncio.gather(*tasks)
async def inner_loop(_keys: List[str]): for key in _keys: current_strategy: str = in_memory_config_map.get( "strategy").value strategy_cm: Dict[str, ConfigVar] = get_strategy_config_map( current_strategy) if key in in_memory_config_map: cv: ConfigVar = in_memory_config_map.get(key) elif key in global_config_map: cv: ConfigVar = global_config_map.get(key) else: cv: ConfigVar = strategy_cm.get(key) if key == "wallet": wallets = list_wallets() if len(wallets) > 0: value = await self._unlock_wallet() else: value = await self._create_or_import_wallet() logging.getLogger("hummingbot.public_eth_address").info( value) elif key == "strategy_file_path": value = await self._import_or_create_strategy_config() else: value = await single_prompt(cv) cv.value = parse_cvar_value(cv, value) if not self.config_complete: await inner_loop(self._get_empty_configs())
def status(self) -> bool: if self.config_complete: self.app.log(" - Config complete") else: self.app.log(' x Pending config. Please enter "config" before starting the bot.') return False eth_node_valid = check_web3(global_config_map.get("ethereum_rpc_url").value) if eth_node_valid: self.app.log(" - Ethereum node running and current") else: self.app.log(' x Bad ethereum rpc url. Your node may be syncing. ' 'Please re-configure by entering "config ethereum_rpc_url"') return False loading_markets: List[str] = [] for market_name, market in self.markets.items(): if not market.ready: loading_markets.append(market_name) if self.strategy is None: return True elif len(loading_markets) > 0: for loading_market in loading_markets: self.app.log(f" x Waiting for {loading_market} market to get ready for trading. " f"Please keep the bot running and try to start again in a few minutes") return False else: self.app.log(" - All markets ready") if self.strategy is not None: self.app.log("\n" + self.strategy.format_status()) return False
def _initialize_wallet(self, token_symbols: List[str]): ethereum_rpc_url = global_config_map.get("ethereum_rpc_url").value erc20_token_addresses = get_erc20_token_addresses(token_symbols) self.wallet: Web3Wallet = Web3Wallet(private_key=self.acct.privateKey, backend_urls=[ethereum_rpc_url], erc20_token_addresses=erc20_token_addresses, chain=EthereumChain.MAIN_NET)
async def main(): await create_yml_files() init_logging("hummingbot_logs.yml") read_configs_from_yml() hb = HummingbotApplication() hb.acct = unlock_wallet(public_key=WALLET_PUBLIC_KEY, password=WALLET_PASSWORD) with patch_stdout(log_field=hb.app.log_field): init_logging( "hummingbot_logs.yml", override_log_level=global_config_map.get("log_level").value) logging.getLogger().info("____DEV_MODE__start_directly__") in_memory_config_map.get("strategy").value = STRATEGY in_memory_config_map.get("strategy").validate(STRATEGY) in_memory_config_map.get("strategy_file_path").value = STRATEGY_PATH in_memory_config_map.get("strategy_file_path").validate(STRATEGY_PATH) global_config_map.get("wallet").value = WALLET_PUBLIC_KEY tasks: List[Coroutine] = [hb.run()] await asyncio.gather(*tasks)
def status(self) -> bool: self.app.log("\n Preliminary checks:") if self.config_complete: self.app.log(" - Config check: Config complete") else: self.app.log( ' x Config check: Pending config. Please enter "config" before starting the bot.' ) return False eth_node_valid = check_web3( global_config_map.get("ethereum_rpc_url").value) if eth_node_valid: self.app.log(" - Node check: Ethereum node running and current") else: self.app.log( ' x Node check: Bad ethereum rpc url. Your node may be syncing. ' 'Please re-configure by entering "config ethereum_rpc_url"') return False if self.wallet is not None: has_minimum_eth = self.wallet.get_balance("ETH") > 0.01 if has_minimum_eth: self.app.log( " - Min ETH check: Minimum ETH requirement satisfied") else: self.app.log( " x Min ETH check: Not enough ETH in wallet. " "A small amount of Ether is required for sending transactions on Decentralized Exchanges" ) loading_markets: List[str] = [] for market_name, market in self.markets.items(): if not market.ready: loading_markets.append(market_name) if self.strategy is None: return True elif len(loading_markets) > 0: for loading_market in loading_markets: self.app.log( f" x Market check: Waiting for {loading_market} market to get ready for trading. " f"Please keep the bot running and try to start again in a few minutes" ) return False self.app.log(" - Market check: All markets ready") self.app.log(self.strategy.format_status() + "\n") return True
async def inner_loop(_keys: List[str]): for key in _keys: current_strategy: str = in_memory_config_map.get("strategy").value strategy_cm: Dict[str, ConfigVar] = get_strategy_config_map(current_strategy) if key in in_memory_config_map: cv: ConfigVar = in_memory_config_map.get(key) elif key in global_config_map: cv: ConfigVar = global_config_map.get(key) else: cv: ConfigVar = strategy_cm.get(key) value = await single_prompt(cv) cv.value = parse_cvar_value(cv, value) if not self.config_complete: await inner_loop(self._get_empty_configs())
async def _create_or_import_wallet(self): choice = await self.app.prompt(prompt=global_config_map.get("wallet").prompt) if choice == "import": private_key = await self.app.prompt(prompt="Your wallet private key >>> ", is_password=True) password = await self.app.prompt(prompt="A password to protect your wallet key >>> ", is_password=True) self.acct = import_and_save_wallet(password, private_key) self.app.log("Wallet %s imported into hummingbot" % (self.acct.address,)) elif choice == "create": password = await self.app.prompt(prompt="A password to protect your wallet key >>> ", is_password=True) self.acct = create_and_save_wallet(password) self.app.log("New wallet %s created" % (self.acct.address,)) else: self.app.log('Invalid choice. Please enter "create" or "import".') result = await self._create_or_import_wallet() return result return self.acct.address
def _initialize_markets(self, market_names: List[Tuple[str, str]]): ethereum_rpc_url = global_config_map.get("ethereum_rpc_url").value for market_name, symbol in market_names: if market_name == "ddex" and self.wallet: market = DDEXMarket( wallet=self.wallet, web3_url=ethereum_rpc_url, order_book_tracker_data_source_type= OrderBookTrackerDataSourceType.EXCHANGE_API, symbols=[symbol]) elif market_name == "binance": binance_api_key = global_config_map.get( "binance_api_key").value binance_api_secret = global_config_map.get( "binance_api_secret").value market = BinanceMarket( web3_url=ethereum_rpc_url, binance_api_key=binance_api_key, binance_api_secret=binance_api_secret, order_book_tracker_data_source_type= OrderBookTrackerDataSourceType.EXCHANGE_API, symbols=[symbol]) elif market_name == "radar_relay" and self.wallet: market = RadarRelayMarket(wallet=self.wallet, web3_url=ethereum_rpc_url, symbols=[symbol]) elif market_name == "coinbase_pro": coinbase_pro_api_key = global_config_map.get( "coinbase_pro_api_key").value coinbase_pro_secret_key = global_config_map.get( "coinbase_pro_secret_key").value coinbase_pro_passphrase = global_config_map.get( "coinbase_pro_passphrase").value market = CoinbaseProMarket( web3_url=ethereum_rpc_url, coinbase_pro_api_key=coinbase_pro_api_key, coinbase_pro_secret_key=coinbase_pro_secret_key, coinbase_pro_passphrase=coinbase_pro_passphrase, symbols=[symbol]) else: raise ValueError(f"Market name {market_name} is invalid.") self.markets[market_name]: MarketBase = market
async def _cancel_outstanding_orders(self) -> bool: on_chain_cancel_on_exit = global_config_map.get("on_chain_cancel_on_exit").value success = True self.app.log("Cancelling outstanding orders...") for market_name, market in self.markets.items(): # By default, the bot does not cancel orders on exit on Radar Relay, since all open orders will # expire in a short window if not on_chain_cancel_on_exit and market_name == "radar_relay": continue cancellation_results = await market.cancel_all(self.KILL_TIMEOUT) uncancelled = list(filter(lambda cr: cr.success is False, cancellation_results)) if len(uncancelled) > 0: success = False uncancelled_order_ids = list(map(lambda cr: cr.order_id, uncancelled)) self.app.log("\nFailed to cancel the following orders on %s:\n%s" % ( market_name, '\n'.join(uncancelled_order_ids) )) if success: self.app.log("All outstanding orders cancelled.") return success
async def start_market_making(self, strategy_name: str): strategy_cm = get_strategy_config_map(strategy_name) if strategy_name == "cross_exchange_market_making": maker_market = strategy_cm.get("maker_market").value.lower() taker_market = strategy_cm.get("taker_market").value.lower() raw_maker_symbol = strategy_cm.get( "maker_market_symbol").value.upper() raw_taker_symbol = strategy_cm.get( "taker_market_symbol").value.upper() min_profitability = strategy_cm.get("min_profitability").value trade_size_override = strategy_cm.get("trade_size_override").value strategy_report_interval = global_config_map.get( "strategy_report_interval").value limit_order_min_expiration = strategy_cm.get( "limit_order_min_expiration").value cancel_order_threshold = strategy_cm.get( "cancel_order_threshold").value active_order_canceling = strategy_cm.get( "active_order_canceling").value top_depth_tolerance_rules = [(re.compile(re_str), value) for re_str, value in strategy_cm.get( "top_depth_tolerance").value] top_depth_tolerance = 0.0 for regex, tolerance_value in top_depth_tolerance_rules: if regex.match(raw_maker_symbol) is not None: top_depth_tolerance = tolerance_value try: maker_assets: Tuple[str, str] = SymbolSplitter.split( maker_market, raw_maker_symbol) taker_assets: Tuple[str, str] = SymbolSplitter.split( taker_market, raw_taker_symbol) except ValueError as e: self.app.log(str(e)) return market_names: List[Tuple[str, str]] = [(maker_market, raw_maker_symbol), (taker_market, raw_taker_symbol)] self._initialize_wallet( token_symbols=list(set(maker_assets + taker_assets))) self._initialize_markets(market_names) self.market_pair = CrossExchangeMarketPair( *([self.markets[maker_market], raw_maker_symbol] + list(maker_assets) + [self.markets[taker_market], raw_taker_symbol] + list(taker_assets) + [top_depth_tolerance])) strategy_logging_options = ( CrossExchangeMarketMakingStrategy.OPTION_LOG_CREATE_ORDER | CrossExchangeMarketMakingStrategy.OPTION_LOG_ADJUST_ORDER | CrossExchangeMarketMakingStrategy.OPTION_LOG_MAKER_ORDER_FILLED | CrossExchangeMarketMakingStrategy.OPTION_LOG_REMOVING_ORDER | CrossExchangeMarketMakingStrategy.OPTION_LOG_STATUS_REPORT | CrossExchangeMarketMakingStrategy.OPTION_LOG_MAKER_ORDER_HEDGED ) self.strategy = CrossExchangeMarketMakingStrategy( market_pairs=[self.market_pair], min_profitability=min_profitability, status_report_interval=strategy_report_interval, logging_options=strategy_logging_options, trade_size_override=trade_size_override, limit_order_min_expiration=limit_order_min_expiration, cancel_order_threshold=cancel_order_threshold, active_order_canceling=active_order_canceling) elif strategy_name == "arbitrage": primary_market = strategy_cm.get("primary_market").value.lower() secondary_market = strategy_cm.get( "secondary_market").value.lower() raw_primary_symbol = strategy_cm.get( "primary_market_symbol").value.upper() raw_secondary_symbol = strategy_cm.get( "secondary_market_symbol").value.upper() min_profitability = strategy_cm.get("min_profitability").value try: primary_assets: Tuple[str, str] = SymbolSplitter.split( primary_market, raw_primary_symbol) secondary_assets: Tuple[str, str] = SymbolSplitter.split( secondary_market, raw_secondary_symbol) except ValueError as e: self.app.log(str(e)) return market_names: List[Tuple[str, str]] = [ (primary_market, raw_primary_symbol), (secondary_market, raw_secondary_symbol) ] self._initialize_wallet( token_symbols=list(set(primary_assets + secondary_assets))) self._initialize_markets(market_names) self.market_pair = ArbitrageMarketPair( *([self.markets[primary_market], raw_primary_symbol] + list(primary_assets) + [self.markets[secondary_market], raw_secondary_symbol] + list(secondary_assets))) strategy_logging_options = ArbitrageStrategy.OPTION_LOG_ALL self.strategy = ArbitrageStrategy( market_pairs=[self.market_pair], min_profitability=min_profitability, logging_options=strategy_logging_options) else: raise NotImplementedError try: self.clock = Clock(ClockMode.REALTIME) if self.wallet is not None: self.clock.add_iterator(self.wallet) for market in self.markets.values(): if market is not None: self.clock.add_iterator(market) self.clock.add_iterator(self.strategy) self.strategy_task: asyncio.Task = asyncio.ensure_future( self.clock.run()) self.app.log( f"\n'{strategy_name}' strategy started.\n" f"You can use the `status` command to query the progress.") except Exception as e: self.logger().error(str(e), exc_info=True)