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 _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_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 _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 _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, 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(""" 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, 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, 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 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) -> 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, 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) -> 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 _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, 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 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: 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 Samco module subscription", options) client_id = click.prompt( "Client ID", cls._get_default(lean_config, "samco-client-id")) client_password = logger.prompt_password( "Client Password", cls._get_default(lean_config, "samco-client-password")) year_of_birth = click.prompt( "Year of Birth", cls._get_default(lean_config, "samco-year-of-birth")) logger.info(""" The product type must be set to MIS if you are targeting intraday products, CNC if you are targeting delivery products or NRML if you are targeting carry forward products. """.strip()) product_type = click.prompt("Product type", cls._get_default(lean_config, "samco-product-type"), type=click.Choice(["MIS", "CNC", "NRML"], case_sensitive=False)) logger.info(""" The trading segment must be set to EQUITY if you are trading equities on NSE or BSE, or COMMODITY if you are trading commodities on MCX. """.strip()) trading_segment = click.prompt( "Trading segment", cls._get_default(lean_config, "samco-trading-segment"), type=click.Choice(["EQUITY", "COMMODITY"], case_sensitive=False)) return SamcoBrokerage(organization_id, client_id, client_password, year_of_birth, 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)
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) exchange_name = click.prompt( "FTX Exchange [FTX|FTXUS]", cls._get_default(lean_config, "ftx-exchange-name")) 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()) prefix = exchange.prefix() api_key = click.prompt( "API key", cls._get_default(lean_config, f'{prefix}-api-key')) api_secret = logger.prompt_password( "API secret", cls._get_default(lean_config, f'{prefix}-api-secret')) account_tier = logger.prompt_list( "Select the Account Tier", exchange.account_tier_options(), cls._get_default(lean_config, f'{prefix}-account-tier')) return FTXBrokerage(organization_id, api_key, api_secret, account_tier, exchange_name)
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 Kraken module subscription", options ) 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", cls._get_default(lean_config, "kraken-api-key")) api_secret = logger.prompt_password("API secret", cls._get_default(lean_config, "kraken-api-secret")) verification_tier = logger.prompt_list("Select the Verification Tier", [Option(id="Starter", label="Starter"), Option(id="Intermediate", label="Intermediate"), Option(id="Pro", label="Pro")], cls._get_default(lean_config, "kraken-verification-tier") ) return KrakenBrokerage(organization_id, api_key, api_secret, verification_tier)
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 Zerodha module subscription", options ) logger.info("You need API credentials for Kite Connect (https://kite.trade/) to use the Zerodha brokerage.") api_key = click.prompt("API key", cls._get_default(lean_config, "zerodha-api-key")) access_token = logger.prompt_password("Access token", cls._get_default(lean_config, "zerodha-access-token")) logger.info(""" The product type must be set to MIS if you are targeting intraday products, CNC if you are targeting delivery products or NRML if you are targeting carry forward products. """.strip()) product_type = click.prompt( "Product type", cls._get_default(lean_config, "zerodha-product-type"), type=click.Choice(["MIS", "CNC", "NRML"], case_sensitive=False) ) logger.info(""" The trading segment must be set to EQUITY if you are trading equities on NSE or BSE, or COMMODITY if you are trading commodities on MCX. """.strip()) trading_segment = click.prompt( "Trading segment", cls._get_default(lean_config, "zerodha-trading-segment"), type=click.Choice(["EQUITY", "COMMODITY"], case_sensitive=False) ) return ZerodhaBrokerage(organization_id, api_key, access_token, product_type, trading_segment)
def test_info_logs_message(capsys: CaptureFixture) -> None: logger = Logger() logger.info("Message") assert_stdout_stderr(capsys, "Message\n", "")