def build(cls, lean_config: Dict[str, Any], logger: Logger) -> LeanConfigConfigurer: logger.info( "The IQFeed data feed requires an IQFeed developer account and a locally installed IQFeed client." ) default_binary = cls._get_default(lean_config, "iqfeed-iqconnect") if default_binary is not None: default_binary = Path(default_binary) else: default_binary = Path( "C:/Program Files (x86)/DTN/IQFeed/iqconnect.exe") if not default_binary.is_file(): default_binary = None iqconnect = click.prompt("IQConnect binary location", type=PathParameter(exists=True, file_okay=True, dir_okay=False), default=default_binary) username = click.prompt( "Username", cls._get_default(lean_config, "iqfeed-username")) password = logger.prompt_password( "Password", cls._get_default(lean_config, "iqfeed-password")) product_name = click.prompt( "Product id", cls._get_default(lean_config, "iqfeed-productName")) version = click.prompt("Product version", cls._get_default(lean_config, "iqfeed-version")) return IQFeedDataFeed(iqconnect, username, password, product_name, version)
def _configure_notifications( logger: Logger) -> Tuple[bool, bool, List[QCNotificationMethod]]: """Interactively configures how and when notifications should be sent. :param logger: the logger to use :return: whether notifications must be enabled for order events and insights, and the notification methods """ logger.info( "You can optionally request for your strategy to send notifications when it generates an order or emits an insight" ) logger.info( "You can use any combination of email notifications, webhook notifications and SMS notifications" ) notify_order_events = click.confirm( "Do you want to send notifications on order events?", default=False) notify_insights = click.confirm( "Do you want to send notifications on insights?", default=False) notify_methods = [] if notify_order_events or notify_insights: _log_notification_methods(notify_methods) notify_methods.append(_prompt_notification_method()) while True: _log_notification_methods(notify_methods) if not click.confirm( "Do you want to add another notification method?", default=False): break notify_methods.append(_prompt_notification_method()) return notify_order_events, notify_insights, notify_methods
def _build(cls, lean_config: Dict[str, Any], logger: Logger) -> LocalBrokerage: api_client = container.api_client() organizations = api_client.organizations.get_all() options = [Option(id=organization.id, label=organization.name) for organization in organizations] organization_id = logger.prompt_list("Select the organization with the Atreyu module subscription", options) host = click.prompt("Host", cls._get_default(lean_config, "atreyu-host")) req_port = click.prompt("Request port", cls._get_default(lean_config, "atreyu-req-port"), type=int) sub_port = click.prompt("Subscribe port", cls._get_default(lean_config, "atreyu-sub-port"), type=int) username = click.prompt("Username", cls._get_default(lean_config, "atreyu-username")) password = logger.prompt_password("Password", cls._get_default(lean_config, "atreyu-password")) client_id = click.prompt("Client id", cls._get_default(lean_config, "atreyu-client-id")) broker_mpid = click.prompt("Broker MPID", cls._get_default(lean_config, "atreyu-broker-mpid")) locate_rqd = click.prompt("Locate rqd", cls._get_default(lean_config, "atreyu-locate-rqd")) return AtreyuBrokerage(organization_id, host, req_port, sub_port, username, password, client_id, broker_mpid, locate_rqd)
def _build(cls, lean_config: Dict[str, Any], logger: Logger) -> LocalBrokerage: api_client = container.api_client() organizations = api_client.organizations.get_all() options = [ Option(id=organization.id, label=organization.name) for organization in organizations ] organization_id = logger.prompt_list( "Select the organization with the {} module subscription".format( cls.get_name()), options) logger.info(""" Create an API key by logging in and accessing the Binance API Management page (https://www.binance.com/en/my/settings/api-management). """.strip()) api_key = click.prompt( "API key", cls._get_default(lean_config, "binance-api-key")) api_secret = logger.prompt_password( "API secret", cls._get_default(lean_config, "binance-api-secret")) testnet = click.confirm("Use the testnet?") return BinanceBrokerage(organization_id, api_key, api_secret, testnet)
def _configure_credentials(cls, lean_config: Dict[str, Any], logger: Logger) -> None: logger.info(""" To use IB with LEAN you must disable two-factor authentication or only use IBKR Mobile. This is done from your IB Account Manage Account -> Settings -> User Settings -> Security -> Secure Login System. In the Secure Login System, deselect all options or only select "IB Key Security via IBKR Mobile". Interactive Brokers Lite accounts do not support API trading. """.strip()) username = click.prompt("Username", cls._get_default(lean_config, "ib-user-name")) account_id = click.prompt("Account id", cls._get_default(lean_config, "ib-account")) account_password = logger.prompt_password( "Account password", cls._get_default(lean_config, "ib-password")) agent_description = None trading_mode = None demo_slice = account_id.lower()[:2] live_slice = account_id.lower()[0] if live_slice == "d": if demo_slice == "df" or demo_slice == "du": agent_description = "Individual" trading_mode = "paper" elif demo_slice == "di": # TODO: Remove this once we know what ib-agent-description should be for Advisor accounts raise RuntimeError( "Please use the --environment option for Advisor accounts") agent_description = "Advisor" trading_mode = "paper" else: if live_slice == "f" or live_slice == "i": # TODO: Remove this once we know what ib-agent-description should be for Advisor accounts raise RuntimeError( "Please use the --environment option for Advisor accounts") agent_description = "Advisor" trading_mode = "live" elif live_slice == "u": agent_description = "Individual" trading_mode = "live" if trading_mode is None: raise MoreInfoError( f"Account id '{account_id}' does not look like a valid account id", "https://www.lean.io/docs/lean-cli/tutorials/live-trading/local-live-trading#03-Interactive-Brokers" ) lean_config["ib-user-name"] = username lean_config["ib-account"] = account_id lean_config["ib-password"] = account_password lean_config["ib-agent-description"] = agent_description lean_config["ib-trading-mode"] = trading_mode cls._save_properties(lean_config, [ "ib-user-name", "ib-account", "ib-password", "ib-agent-description", "ib-trading-mode" ])
def build(cls, logger: Logger) -> CloudBrokerage: logger.info(""" Create an API key by logging in and accessing the Bitfinex API Management page (https://www.bitfinex.com/api). """.strip()) api_key = click.prompt("API key") secret_key = logger.prompt_password("Secret key") return BitfinexBrokerage(api_key, secret_key)
def build(cls, logger: Logger) -> CloudBrokerage: logger.info(""" Create an API key by logging in and accessing the Kraken API Management page (https://www.kraken.com/u/security/api). """.strip()) api_key = click.prompt("API key") secret_key = logger.prompt_password("Secret key") verification_tier = click.prompt("Verification Tier") return KrakenBrokerage(api_key, secret_key, verification_tier)
def test_prompt_list_returns_id_of_selected_option(prompt: mock.Mock, capsys: CaptureFixture) -> None: logger = Logger() options = [Option(id=1, label="Option 1"), Option(id=2, label="Option 2"), Option(id=3, label="Option 3")] prompt.return_value = 3 selected_option = logger.prompt_list("Select an option", options) assert selected_option == 3 capsys.readouterr()
def test_prompt_returns_single_option_without_prompting_with_display_of_value(capsys: CaptureFixture) -> None: logger = Logger() options = [Option(id=1, label="Option 1")] selected_option = logger.prompt_list("Select an option", options) assert selected_option == 1 stdout, stderr = capsys.readouterr() assert "Select an option: Option 1" in stdout
def test_progress_creates_started_progress_instance(capsys: CaptureFixture) -> None: logger = Logger() progress = logger.progress() result = progress._started progress.stop() assert result capsys.readouterr()
def test_prompt_list_displays_all_options(prompt: mock.Mock, capsys: CaptureFixture) -> None: logger = Logger() options = [Option(id=1, label="Option 1"), Option(id=2, label="Option 2"), Option(id=3, label="Option 3")] prompt.return_value = 3 logger.prompt_list("Select an option", options) stdout, stderr = capsys.readouterr() assert "Option 1" in stdout assert "Option 2" in stdout assert "Option 3" in stdout
def _configure_credentials(cls, lean_config: Dict[str, Any], logger: Logger) -> None: logger.info(""" Create an API key by logging in and accessing the Bitfinex API Management page (https://www.bitfinex.com/api). """.strip()) lean_config["bitfinex-api-key"] = click.prompt("API key", cls._get_default(lean_config, "bitfinex-api-key")) lean_config["bitfinex-api-secret"] = logger.prompt_password( "API secret", cls._get_default(lean_config, "bitfinex-api-secret") ) cls._save_properties(lean_config, ["bitfinex-api-key", "bitfinex-api-secret"])
def get_settings(self, logger: Logger) -> Dict[str, str]: """Returns all settings for this brokerage, prompting the user for input when necessary. :param logger: the logger to use for printing instructions """ if self._notes is not None: logger.info(self._notes) settings = self._get_settings() settings["id"] = self._id return settings
def build(cls, logger: Logger) -> CloudBrokerage: logger.info(""" Your Tradier account id and API token can be found on your Settings/API Access page (https://dash.tradier.com/settings/api). The account id is the alpha-numeric code in a dropdown box on that page. Your account details are not saved on QuantConnect. """.strip()) account_id = click.prompt("Account id") access_token = logger.prompt_password("Access token") environment = click.prompt("Environment", type=click.Choice(["demo", "real"], case_sensitive=False)) return TradierBrokerage(account_id, access_token, environment)
def _build(cls, lean_config: Dict[str, Any], logger: Logger) -> LocalBrokerage: logger.info(""" Create an API key by logging in and accessing the Bitfinex API Management page (https://www.bitfinex.com/api). """.strip()) api_key = click.prompt( "API key", cls._get_default(lean_config, "bitfinex-api-key")) api_secret = logger.prompt_password( "API secret", cls._get_default(lean_config, "bitfinex-api-secret")) return BitfinexBrokerage(api_key, api_secret)
def build(cls, logger: Logger) -> CloudBrokerage: logger.info(""" You can generate Coinbase Pro API credentials on the API settings page (https://pro.coinbase.com/profile/api). When creating the key, make sure you authorize it for View and Trading access. """.strip()) api_key = click.prompt("API key") api_secret = logger.prompt_password("API secret") passphrase = logger.prompt_password("Passphrase") environment = "paper" if click.confirm("Use the sandbox?") else "live" return CoinbaseProBrokerage(api_key, api_secret, passphrase, environment)
def build(cls, logger: Logger) -> CloudBrokerage: exchange_name = click.prompt("FTX Exchange [FTX|FTXUS]") exchange = FTXExchange() if exchange_name.casefold() == "FTX".casefold() else FTXUSExchange() logger.info(""" Create an API key by logging in and accessing the {} Profile page (https://{}/profile). """.format(exchange.get_name(), exchange.get_domain()).strip()) api_key = click.prompt("API key") secret_key = logger.prompt_password("Secret key") account_tier = click.prompt("Account Tier") return FTXBrokerage(api_key, secret_key, account_tier, exchange_name)
def build(cls, logger: Logger) -> CloudBrokerage: logger.info(""" Your Binance real account information can be found on your API Management Settings page (https://www.binance.com/en/my/settings/api-management). Your account details are not save on QuantConnect. Demo credentials can be generated on Binance Testnet (https://testnet.binance.vision/). """.strip()) api_key = click.prompt("API key") secret_key = logger.prompt_password("Secret key") environment = click.prompt("Environment", type=click.Choice(["demo", "real"], case_sensitive=False)) return BinanceBrokerage(api_key, secret_key, environment)
def _configure_auto_restart(logger: Logger) -> bool: """Interactively configures whether automatic algorithm restarting must be enabled. :param logger: the logger to use :return: whether automatic algorithm restarting must be enabled """ logger.info( "Automatic restarting uses best efforts to restart the algorithm if it fails due to a runtime error" ) logger.info( "This can help improve its resilience to temporary errors such as a brokerage API disconnection" ) return click.confirm( "Do you want to enable automatic algorithm restarting?", default=True)
def _build(cls, lean_config: Dict[str, Any], logger: Logger) -> LocalBrokerage: logger.info(""" Your OANDA account id can be found on your OANDA Account Statement page (https://www.oanda.com/account/statement/). It follows the following format: ###-###-######-###. You can generate an API token from the Manage API Access page (https://www.oanda.com/account/tpa/personal_token). """.strip()) account_id = click.prompt("Account id", cls._get_default(lean_config, "oanda-account-id")) access_token = logger.prompt_password("Access token", cls._get_default(lean_config, "oanda-access-token")) environment = click.prompt("Environment", cls._get_default(lean_config, "oanda-environment"), type=click.Choice(["Practice", "Trade"], case_sensitive=False)) return OANDABrokerage(account_id, access_token, environment)
def test_debug_does_not_log_until_debug_logging_is_enabled( capsys: CaptureFixture) -> None: logger = Logger() logger.debug("Message 1") logger.enable_debug_logging() logger.debug("Message 2") assert_stdout_stderr(capsys, "Message 2\n", "")
def build(cls, logger: Logger) -> CloudBrokerage: logger.info(""" Your OANDA account number can be found on your OANDA Account Statement page (https://www.oanda.com/account/statement/). It follows the following format: ###-###-######-###. You can generate an API token from the Manage API Access page (https://www.oanda.com/account/tpa/personal_token). Your account details are not saved on QuantConnect. """.strip()) account_id = click.prompt("Account id") access_token = logger.prompt_password("Access token") environment = click.prompt("Environment", type=click.Choice(["demo", "real"], case_sensitive=False)) return OANDABrokerage(account_id, access_token, environment)
def build(cls, lean_config: Dict[str, Any], logger: Logger) -> LeanConfigConfigurer: brokerage = InteractiveBrokersBrokerage.build(lean_config, logger) logger.info(""" Delayed market data is used when you subscribe to data for which you don't have a market data subscription on IB. If delayed market data is disabled, live trading will stop and LEAN will shut down when this happens. """.strip()) enable_delayed_streaming_data = click.confirm( "Enable delayed market data?", cls._get_default(lean_config, "ib-enable-delayed-streaming-data")) return InteractiveBrokersDataFeed(brokerage, enable_delayed_streaming_data)
def _build(cls, lean_config: Dict[str, Any], logger: Logger) -> LocalBrokerage: logger.info(""" You can generate Coinbase Pro API credentials on the API settings page (https://pro.coinbase.com/profile/api). When creating the key, make sure you authorize it for View and Trading access. """.strip()) api_key = click.prompt("API key", cls._get_default(lean_config, "gdax-api-key")) api_secret = logger.prompt_password( "API secret", cls._get_default(lean_config, "gdax-api-secret")) passphrase = logger.prompt_password( "Passphrase", cls._get_default(lean_config, "gdax-passphrase")) sandbox = click.confirm("Use the sandbox?") return CoinbaseProBrokerage(api_key, api_secret, passphrase, sandbox)
def _build(cls, lean_config: Dict[str, Any], logger: Logger) -> LocalBrokerage: logger.info(""" Your Tradier account id and API token can be found on your Settings/API Access page (https://dash.tradier.com/settings/api). The account id is the alpha-numeric code in a dropdown box on that page. """.strip()) account_id = click.prompt( "Account id", cls._get_default(lean_config, "tradier-account-id")) access_token = logger.prompt_password( "Access token", cls._get_default(lean_config, "tradier-access-token")) use_sandbox = click.confirm( "Use the developer sandbox?", cls._get_default(lean_config, "tradier-use-sandbox")) return TradierBrokerage(account_id, access_token, use_sandbox)
def _configure_credentials(cls, lean_config: Dict[str, Any], logger: Logger) -> None: logger.info(""" You can generate Coinbase Pro API credentials on the API settings page (https://pro.coinbase.com/profile/api). When creating the key, make sure you authorize it for View and Trading access. """.strip()) lean_config["gdax-api-key"] = click.prompt( "API key", cls._get_default(lean_config, "gdax-api-key")) lean_config["gdax-api-secret"] = logger.prompt_password( "API secret", cls._get_default(lean_config, "gdax-api-secret")) lean_config["gdax-passphrase"] = logger.prompt_password( "Passphrase", cls._get_default(lean_config, "gdax-passphrase")) cls._save_properties( lean_config, ["gdax-api-key", "gdax-api-secret", "gdax-passphrase"])
def build(cls, logger: Logger) -> CloudBrokerage: logger.info(""" Create an API key by logging in and accessing the Zerodha API Management page (https://kite.trade/). """.strip()) api_key = click.prompt("API key") access_token = logger.prompt_password("Access Token") product_type = click.prompt("Product type", type=click.Choice(["MIS", "CNC", "NRML"], case_sensitive=False)) trading_segment = click.prompt("Trading segment", type=click.Choice( ["EQUITY", "COMMODITY"], case_sensitive=False)) return ZerodhaBrokerage(api_key, access_token, product_type, trading_segment)
def _build(cls, lean_config: Dict[str, Any], logger: Logger) -> LocalBrokerage: logger.info(""" To use IB with LEAN you must disable two-factor authentication or only use IBKR Mobile. This is done from your IB Account Manage Account -> Settings -> User Settings -> Security -> Secure Login System. In the Secure Login System, deselect all options or only select "IB Key Security via IBKR Mobile". Interactive Brokers Lite accounts do not support API trading. """.strip()) username = click.prompt("Username", cls._get_default(lean_config, "ib-user-name")) account_id = click.prompt("Account id", cls._get_default(lean_config, "ib-account")) account_password = logger.prompt_password( "Account password", cls._get_default(lean_config, "ib-password")) return InteractiveBrokersBrokerage(username, account_id, account_password)
def configure(cls, lean_config: Dict[str, Any], environment_name: str, logger: Logger) -> None: lean_config["environments"][environment_name]["data-queue-handler"] = \ "QuantConnect.Brokerages.InteractiveBrokers.InteractiveBrokersBrokerage" lean_config["environments"][environment_name][ "history-provider"] = "BrokerageHistoryProvider" InteractiveBrokersBrokerage.configure_credentials(lean_config, logger) logger.info(""" Delayed market data is used when you subscribe to data for which you don't have a market data subscription on IB. If delayed market data is disabled, live trading will stop and LEAN will shut down when this happens. """.strip()) lean_config["ib-enable-delayed-streaming-data"] = click.confirm( "Enable delayed market data?", cls._get_default(lean_config, "ib-enable-delayed-streaming-data")) cls._save_properties(lean_config, ["ib-enable-delayed-streaming-data"])
def build(cls, logger: Logger) -> CloudBrokerage: logger.info(""" To use IB with QuantConnect you must disable two-factor authentication or only use IBKR Mobile. This is done from your IB Account Manage Account -> Settings -> User Settings -> Security -> Secure Login System. In the Secure Login System, deselect all options or only select "IB Key Security via IBKR Mobile". Your account details are not saved on QuantConnect. Interactive Brokers Lite accounts do not support API trading. """.strip()) username = click.prompt("Username") account_id = click.prompt("Account id") account_password = logger.prompt_password("Account password") use_ib_feed = click.confirm( "Do you want to use the Interactive Brokers price data feed instead of the QuantConnect price data feed?", default=False) return InteractiveBrokersBrokerage(username, account_id, account_password, use_ib_feed)