Пример #1
0
    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.acct: Optional[LocalAccount] = None
        self.markets: Dict[str, MarketBase] = {}
        self.wallet: Optional[Web3Wallet] = 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.reporting_module: Optional[ReportAggregator] = None
        self.data_feed: Optional[DataFeedBase] = None
        self.notifiers: List[NotifierBase] = []
        self.kill_switch: Optional[KillSwitch] = None
        self.liquidity_bounty: Optional[LiquidityBounty] = None
        self._initialize_liquidity_bounty()
        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
Пример #2
0
    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.acct: Optional[LocalAccount] = None
        self.markets: Dict[str, MarketBase] = {}
        self.wallet: Optional[Web3Wallet] = None
        self.strategy_task: Optional[asyncio.Task] = None
        self.strategy: Optional[CrossExchangeMarketMakingStrategy] = None
        self.market_pair: Optional[CrossExchangeMarketPair] = None
        self.clock: Optional[Clock] = None

        self.assets: Optional[Set[str]] = set()
        self.starting_balances = {}
        self.placeholder_mode = False
        self.log_queue_listener: Optional[
            logging.handlers.QueueListener] = None
        self.reporting_module: Optional[ReportAggregator] = None
        self.data_feed: Optional[DataFeedBase] = None
        self.stop_loss_tracker: Optional[StopLossTracker] = None
        self._app_warnings: Deque[ApplicationWarning] = deque()
        self._trading_required: bool = True
Пример #3
0
    async def prompt_for_configuration(self,  # type: HummingbotApplication
                                       file_name):
        self.app.clear_input()
        self.placeholder_mode = True
        self.app.hide_input = True
        required_exchanges.clear()

        strategy_config = ConfigVar(key="strategy",
                                    prompt="What is your market making strategy? >>> ",
                                    validator=validate_strategy)
        await self.prompt_a_config(strategy_config)
        if self.app.to_stop_config:
            self.app.to_stop_config = False
            return
        strategy = strategy_config.value
        config_map = get_strategy_config_map(strategy)
        self._notify(f"Please see https://docs.hummingbot.io/strategies/{strategy.replace('_', '-')}/ "
                     f"while setting up these below configuration.")
        # assign default values and reset those not required
        for config in config_map.values():
            if config.required:
                config.value = config.default
            else:
                config.value = None
        for config in config_map.values():
            if config.prompt_on_new and config.required:
                if not self.app.to_stop_config:
                    await self.prompt_a_config(config)
                else:
                    self.app.to_stop_config = False
                    return
            else:
                config.value = config.default

        # catch a last key binding to stop config, if any
        if self.app.to_stop_config:
            self.app.to_stop_config = False
            return

        if file_name is None:
            file_name = await self.prompt_new_file_name(strategy)
            if self.app.to_stop_config:
                self.app.to_stop_config = False
                self.app.set_text("")
                return
        self.app.change_prompt(prompt=">>> ")
        strategy_path = os.path.join(CONF_FILE_PATH, file_name)
        template = get_strategy_template_path(strategy)
        shutil.copy(template, strategy_path)
        save_to_yml(strategy_path, config_map)
        self.strategy_file_name = file_name
        self.strategy_name = strategy
        # Reload completer here otherwise the new file will not appear
        self.app.input_field.completer = load_completer(self)
        self._notify(f"A new config file {self.strategy_file_name} created.")
        self.placeholder_mode = False
        self.app.hide_input = False
        if await self.status_check_all():
            self._notify("\nEnter \"start\" to start market making.")
Пример #4
0
    async def update_gateway_config_key_list(self):
        try:
            config_list: List[str] = []
            config_dict: Dict[str, Any] = await self._fetch_gateway_configs()
            build_config_namespace_keys(config_list, config_dict)

            self.gateway_config_keys = config_list
            self._app.app.input_field.completer = load_completer(self._app)
        except Exception:
            self.logger().error(
                "Error fetching gateway configs. Please check that Gateway service is online. ",
                exc_info=True)
Пример #5
0
    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()
Пример #6
0
    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
Пример #7
0
    async def prompt_for_configuration(
        self,  # type: HummingbotApplication
        file_name,
    ):
        self.app.clear_input()
        self.placeholder_mode = True
        self.app.hide_input = True
        required_exchanges.clear()

        strategy = await self.get_strategy_name()

        if self.app.to_stop_config:
            return

        config_map = get_strategy_config_map(strategy)
        self.notify(f"Please see https://docs.hummingbot.io/strategies/{strategy.replace('_', '-')}/ "
                    f"while setting up these below configuration.")

        if isinstance(config_map, ClientConfigAdapter):
            await self.prompt_for_model_config(config_map)
            if not self.app.to_stop_config:
                file_name = await self.save_config_to_file(file_name, config_map)
        elif config_map is not None:
            file_name = await self.prompt_for_configuration_legacy(file_name, strategy, config_map)
        else:
            self.app.to_stop_config = True

        if self.app.to_stop_config:
            return

        save_previous_strategy_value(file_name, self.client_config_map)
        self.strategy_file_name = file_name
        self.strategy_name = strategy
        self.strategy_config_map = config_map
        # Reload completer here otherwise the new file will not appear
        self.app.input_field.completer = load_completer(self)
        self.notify(f"A new config file has been created: {self.strategy_file_name}")
        self.placeholder_mode = False
        self.app.hide_input = False

        await self.verify_status()
Пример #8
0
    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()
Пример #9
0
    async def _gateway_connect(
            self,           # type: HummingbotApplication
            connector: str = None
    ):
        with begin_placeholder_mode(self):
            gateway_connections_conf: List[Dict[str, str]] = GatewayConnectionSetting.load()
            if connector is None:
                if len(gateway_connections_conf) < 1:
                    self.notify("No existing connection.\n")
                else:
                    connector_df: pd.DataFrame = build_connector_display(gateway_connections_conf)
                    self.notify(connector_df.to_string(index=False))
            else:
                # get available networks
                connector_configs: Dict[str, Any] = await GatewayHttpClient.get_instance().get_connectors()
                connector_config: List[Dict[str, Any]] = [
                    d for d in connector_configs["connectors"] if d["name"] == connector
                ]
                if len(connector_config) < 1:
                    self.notify(f"No available blockchain networks available for the connector '{connector}'.")
                    return
                available_networks: List[Dict[str, Any]] = connector_config[0]["available_networks"]
                trading_type: str = connector_config[0]["trading_type"][0]

                # ask user to select a chain. Automatically select if there is only one.
                chains: List[str] = [d['chain'] for d in available_networks]
                chain: str
                if len(chains) == 1:
                    chain = chains[0]
                else:
                    # chains as options
                    while True:
                        chain = await self.app.prompt(
                            prompt=f"Which chain do you want {connector} to connect to?({', '.join(chains)}) >>> "
                        )
                        if self.app.to_stop_config:
                            self.app.to_stop_config = False
                            return

                        if chain in GATEWAY_CONNECTORS:
                            break
                        self.notify(f"{chain} chain not supported.\n")

                # ask user to select a network. Automatically select if there is only one.
                networks: List[str] = list(
                    itertools.chain.from_iterable([d['networks'] for d in available_networks if d['chain'] == chain])
                )
                network: str

                if len(networks) == 1:
                    network = networks[0]
                else:
                    while True:
                        self.app.input_field.completer.set_gateway_networks(networks)
                        network = await self.app.prompt(
                            prompt=f"Which network do you want {connector} to connect to? ({', '.join(networks)}) >>> "
                        )
                        if self.app.to_stop_config:
                            return
                        if network in networks:
                            break
                        self.notify("Error: Invalid network")

                # get wallets for the selected chain
                wallets_response: List[Dict[str, Any]] = await GatewayHttpClient.get_instance().get_wallets()
                matching_wallets: List[Dict[str, Any]] = [w for w in wallets_response if w["chain"] == chain]
                wallets: List[str]
                if len(matching_wallets) < 1:
                    wallets = []
                else:
                    wallets = matching_wallets[0]['walletAddresses']

                # if the user has no wallet, ask them to select one
                if len(wallets) < 1:
                    self.app.clear_input()
                    self.placeholder_mode = True
                    wallet_private_key = await self.app.prompt(
                        prompt=f"Enter your {chain}-{network} wallet private key >>> ",
                        is_password=True
                    )
                    self.app.clear_input()
                    if self.app.to_stop_config:
                        return
                    response: Dict[str, Any] = await GatewayHttpClient.get_instance().add_wallet(
                        chain, network, wallet_private_key
                    )
                    wallet_address: str = response["address"]

                # the user has a wallet. Ask if they want to use it or create a new one.
                else:
                    # print table
                    while True:
                        use_existing_wallet: str = await self.app.prompt(
                            prompt=f"Do you want to connect to {chain}-{network} with one of your existing wallets on "
                                   f"Gateway? (Yes/No) >>> "
                        )
                        if self.app.to_stop_config:
                            return
                        if use_existing_wallet in ["Y", "y", "Yes", "yes", "N", "n", "No", "no"]:
                            break
                        self.notify("Invalid input. Please try again or exit config [CTRL + x].\n")

                    self.app.clear_input()
                    # they use an existing wallet
                    if use_existing_wallet is not None and use_existing_wallet in ["Y", "y", "Yes", "yes"]:
                        native_token: str = native_tokens[chain]
                        wallet_table: List[Dict[str, Any]] = []
                        for w in wallets:
                            balances: Dict[str, Any] = await GatewayHttpClient.get_instance().get_balances(
                                chain, network, w, [native_token]
                            )
                            wallet_table.append({"balance": balances['balances'][native_token], "address": w})

                        wallet_df: pd.DataFrame = build_wallet_display(native_token, wallet_table)
                        self.notify(wallet_df.to_string(index=False))
                        self.app.input_field.completer.set_list_gateway_wallets_parameters(wallets_response, chain)

                        while True:
                            wallet_address: str = await self.app.prompt(prompt="Select a gateway wallet >>> ")
                            if self.app.to_stop_config:
                                return
                            if wallet_address in wallets:
                                self.notify(f"You have selected {wallet_address}")
                                break
                            self.notify("Error: Invalid wallet address")

                    # they want to create a new wallet even though they have other ones
                    else:
                        while True:
                            try:
                                wallet_private_key: str = await self.app.prompt(
                                    prompt=f"Enter your {chain}-{network} wallet private key >>> ",
                                    is_password=True
                                )
                                self.app.clear_input()
                                if self.app.to_stop_config:
                                    return

                                response: Dict[str, Any] = await GatewayHttpClient.get_instance().add_wallet(
                                    chain, network, wallet_private_key
                                )
                                wallet_address = response["address"]
                                break
                            except Exception:
                                self.notify("Error adding wallet. Check private key.\n")

                self.app.clear_input()

                # write wallets to Gateway connectors settings.
                GatewayConnectionSetting.upsert_connector_spec(connector, chain, network, trading_type, wallet_address)
                self.notify(f"The {connector} connector now uses wallet {wallet_address} on {chain}-{network}")

                # update AllConnectorSettings and fee overrides.
                AllConnectorSettings.create_connector_settings()
                AllConnectorSettings.initialize_paper_trade_settings(global_config_map.get("paper_trade_exchanges").value)
                await refresh_trade_fees_config()

                # Reload completer here to include newly added gateway connectors
                self.app.input_field.completer = load_completer(self)
Пример #10
0
    async def prompt_for_configuration(
            self,  # type: HummingbotApplication
            file_name):
        self.app.clear_input()
        self.placeholder_mode = True
        self.app.hide_input = True
        required_exchanges.clear()

        strategy_config = ConfigVar(
            key="strategy",
            prompt="What is your market making strategy? >>> ",
            validator=validate_strategy)
        await self.prompt_a_config(strategy_config)
        if self.app.to_stop_config:
            self.stop_config()
            return
        strategy = strategy_config.value
        config_map = get_strategy_config_map(strategy)
        config_map_backup = copy.deepcopy(config_map)
        self._notify(
            f"Please see https://docs.hummingbot.io/strategies/{strategy.replace('_', '-')}/ "
            f"while setting up these below configuration.")
        # assign default values and reset those not required
        for config in config_map.values():
            if config.required:
                config.value = config.default
            else:
                config.value = None
        for config in config_map.values():
            if config.prompt_on_new and config.required:
                if not self.app.to_stop_config:
                    await self.prompt_a_config(config)
                else:
                    break
            else:
                config.value = config.default

        if self.app.to_stop_config:
            self.stop_config(config_map, config_map_backup)
            return

        if file_name is None:
            file_name = await self.prompt_new_file_name(strategy)
            if self.app.to_stop_config:
                self.stop_config(config_map, config_map_backup)
                self.app.set_text("")
                return
        self.app.change_prompt(prompt=">>> ")
        strategy_path = os.path.join(CONF_FILE_PATH, file_name)
        template = get_strategy_template_path(strategy)
        shutil.copy(template, strategy_path)
        save_to_yml(strategy_path, config_map)
        self.strategy_file_name = file_name
        self.strategy_name = strategy
        # Reload completer here otherwise the new file will not appear
        self.app.input_field.completer = load_completer(self)
        self._notify(f"A new config file {self.strategy_file_name} created.")
        self.placeholder_mode = False
        self.app.hide_input = False
        try:
            timeout = float(global_config_map["create_command_timeout"].value)
            all_status_go = await asyncio.wait_for(self.status_check_all(),
                                                   timeout)
        except asyncio.TimeoutError:
            self._notify(
                "\nA network error prevented the connection check to complete. See logs for more details."
            )
            self.strategy_file_name = None
            self.strategy_name = None
            raise
        if all_status_go:
            self._notify("\nEnter \"start\" to start market making.")