From 134afd0d1ff7266db14a153132f3658dda5e73ad Mon Sep 17 00:00:00 2001 From: mraniki <8766259+mraniki@users.noreply.github.com> Date: Fri, 1 Nov 2024 08:43:02 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A5=9A=20build(deps):=20update=20ibkr?= =?UTF-8?q?.py=20and=20pyproject.toml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cefi/handler/ibkr.py | 458 +++++++++++++++++++++---------------------- pyproject.toml | 2 +- 2 files changed, 230 insertions(+), 230 deletions(-) diff --git a/cefi/handler/ibkr.py b/cefi/handler/ibkr.py index 898fe14..04416ff 100644 --- a/cefi/handler/ibkr.py +++ b/cefi/handler/ibkr.py @@ -1,234 +1,234 @@ -# """ - -# Interactive Brokers client - - -# """ - -# from ib_insync import IB, IBC, Contract, Order -# from loguru import logger - -# from ._client import CexClient - - -# class IbHandler(CexClient): -# """ -# CEX client for IBKR - - -# Args: -# None - -# Returns: -# None - -# """ - -# def __init__( -# self, -# **kwargs, -# ): -# """ -# Initializes the Broker_IBKR_Plugin class. +""" + +Interactive Brokers client + + +""" + +from ib_insync import IB, IBC, Contract, Order +from loguru import logger + +from ._client import CexClient + + +class IbHandler(CexClient): + """ + CEX client for IBKR + + + Args: + None + + Returns: + None + + """ + + def __init__( + self, + **kwargs, + ): + """ + Initializes the Broker_IBKR_Plugin class. -# This function creates an instance of the IB class from the ib_insync -# library and sets it as the 'ib' attribute of the class. -# It also sets the 'client' attribute to None as a placeholder -# for actual client details. + This function creates an instance of the IB class from the ib_insync + library and sets it as the 'ib' attribute of the class. + It also sets the 'client' attribute to None as a placeholder + for actual client details. -# To connect to the Interactive Brokers (IBKR) platform, -# the 'connect' method of the 'ib' instance is called. -# This method requires the host, port, and clientId as parameters. -# In this case, the function connects to the IBKR platform using -# the IP address "127.0.0.1", port 7497, and clientId 1. + To connect to the Interactive Brokers (IBKR) platform, + the 'connect' method of the 'ib' instance is called. + This method requires the host, port, and clientId as parameters. + In this case, the function connects to the IBKR platform using + the IP address "127.0.0.1", port 7497, and clientId 1. -# After successfully connecting to IBKR, the function logs -# a debug message using the logger module. + After successfully connecting to IBKR, the function logs + a debug message using the logger module. -# For IBC gateway setup, -# refer to https://github.com/IbcAlpha/IBC/blob/master/userguide.md + For IBC gateway setup, + refer to https://github.com/IbcAlpha/IBC/blob/master/userguide.md -# """ -# try: -# super().__init__(**kwargs) -# if self.enabled: -# if self.broker_gateway: -# ibc = IBC( -# 976, -# gateway=True, -# tradingMode="paper" if self.testmode else "live", -# userid=self.user_id, -# password=self.password, -# ) -# ibc.start() -# IB.run() -# self.client = IB() -# self.client.connect( -# host=self.host, -# port=self.port, -# clientId=self.broker_client_id or 1, -# readonly=False, -# account=self.broker_account_number or "", -# ) -# self.name = self.client.id -# self.account_number = self.client.managedAccounts()[0] -# logger.debug("Connected to IBKR {}", self.client.isConnected()) -# logger.debug("Broker_IBKR initialized with account: {}", self.account) - -# except Exception as e: -# logger.error("IBC Initialization Error {}", e) -# return None - -# async def get_info(self): -# """ -# Retrieves information from the accountValues method of the `ib` object. - -# Returns: -# The result of calling the accountValues method of the `ib` object. -# """ -# return self.client.accountValues() - -# async def get_quote(self, instrument): -# """ -# Return a quote for a instrument -# of a given ib object - - -# Args: -# cex -# instrument - -# Returns: -# quote -# """ -# try: -# instrument = await self.replace_instrument(instrument) - -# if contract := self.search_contract(instrument): -# self.client.reqMktData(contract) -# quote = self.client.ticker(contract) -# logger.debug("Quote: {}", quote) -# return quote - -# except Exception as e: -# logger.error("{} Error {}", self.name, e) - -# async def get_account_balance(self): -# """ -# return account balance - -# Args: -# None - -# Returns: -# balance - -# """ - -# return self.client.accountSummary(self.account) - -# async def get_account_position(self): -# """ -# Return account position. - -# Args: -# None - -# Returns: -# position - -# """ - -# try: -# return self.client.positions() -# except Exception as e: -# logger.error("{} Error {}", self.name, e) - -# async def pre_order_checks(self, order_params): -# """ """ -# return True - -# async def get_trading_asset_balance(self): -# """ """ -# return self.client.accountSummary(self.account_number) - -# async def execute_order(self, order_params): -# """ -# Execute order - -# Args: -# order_params (dict): -# action(str) -# instrument(str) -# quantity(int) - -# Returns: -# trade_confirmation(dict) - -# """ -# try: -# action = order_params.get("action") -# instrument = await self.replace_instrument(order_params.get("instrument")) -# quantity = order_params.get("quantity", self.trading_risk_amount) -# logger.debug("quantity {}", quantity) -# amount = await self.get_order_amount( -# quantity=quantity, -# instrument=instrument, -# is_percentage=self.trading_risk_percentage, -# ) - -# logger.debug("amount {}", amount) -# pre_order_checks = await self.pre_order_checks(order_params) -# logger.debug("pre_order_checks {}", pre_order_checks) - -# if amount and pre_order_checks: -# if contract := self.search_contract(instrument): -# order = Order() -# order.action = order_params["action"] -# order.orderType = order_params["order_type"] or "MKT" -# order.totalQuantity = amount -# trade = self.client.placeOrder(contract, order) -# return await self.get_trade_confirmation(trade, instrument, action) - -# return f"Error executing {self.name}" - -# except Exception as e: -# logger.error("{} Error {}", self.name, e) -# return f"Error executing {self.name}" - -# async def search_contract(self, instrument): -# """ -# Asynchronously searches for a contract based on the given instrument. - -# Args: -# self: The object instance. -# instrument: The instrument to search for. - -# Returns: -# Contract: The contract matching the instrument, or None if not found. -# """ -# try: -# if asset := next( -# ( -# item -# for item in self.mapping -# if item["id"] == instrument or item["alt"] == instrument -# ), -# None, -# ): -# return Contract( -# secType=asset["type"], -# symbol=asset["id"], -# -# lastTradeDateOrContractMonth=asset["lastTradeDateOrContractMonth"], -# strike=asset["strike"], -# right=asset["right"], -# multiplier=asset["multiplier"], -# exchange=asset["exchange"], -# currency=asset["currency"], -# ) -# logger.warning("Asset {} not found in mapping", instrument) -# return None - -# except Exception as e: -# logger.error("search_contract {} Error {}", instrument, e) + """ + try: + super().__init__(**kwargs) + if self.enabled: + if self.broker_gateway: + ibc = IBC( + 976, + gateway=True, + tradingMode="paper" if self.testmode else "live", + userid=self.user_id, + password=self.password, + ) + ibc.start() + IB.run() + self.client = IB() + self.client.connect( + host=self.host, + port=self.port, + clientId=self.broker_client_id or 1, + readonly=False, + account=self.broker_account_number or "", + ) + self.name = self.client.id + self.account_number = self.client.managedAccounts()[0] + logger.debug("Connected to IBKR {}", self.client.isConnected()) + logger.debug("Broker_IBKR initialized with account: {}", self.account) + + except Exception as e: + logger.error("IBC Initialization Error {}", e) + return None + + async def get_info(self): + """ + Retrieves information from the accountValues method of the `ib` object. + + Returns: + The result of calling the accountValues method of the `ib` object. + """ + return self.client.accountValues() + + async def get_quote(self, instrument): + """ + Return a quote for a instrument + of a given ib object + + + Args: + cex + instrument + + Returns: + quote + """ + try: + instrument = await self.replace_instrument(instrument) + + if contract := self.search_contract(instrument): + self.client.reqMktData(contract) + quote = self.client.ticker(contract) + logger.debug("Quote: {}", quote) + return quote + + except Exception as e: + logger.error("{} Error {}", self.name, e) + + async def get_account_balance(self): + """ + return account balance + + Args: + None + + Returns: + balance + + """ + + return self.client.accountSummary(self.account) + + async def get_account_position(self): + """ + Return account position. + + Args: + None + + Returns: + position + + """ + + try: + return self.client.positions() + except Exception as e: + logger.error("{} Error {}", self.name, e) + + async def pre_order_checks(self, order_params): + """ """ + return True + + async def get_trading_asset_balance(self): + """ """ + return self.client.accountSummary(self.account_number) + + async def execute_order(self, order_params): + """ + Execute order + + Args: + order_params (dict): + action(str) + instrument(str) + quantity(int) + + Returns: + trade_confirmation(dict) + + """ + try: + action = order_params.get("action") + instrument = await self.replace_instrument(order_params.get("instrument")) + quantity = order_params.get("quantity", self.trading_risk_amount) + logger.debug("quantity {}", quantity) + amount = await self.get_order_amount( + quantity=quantity, + instrument=instrument, + is_percentage=self.trading_risk_percentage, + ) + + logger.debug("amount {}", amount) + pre_order_checks = await self.pre_order_checks(order_params) + logger.debug("pre_order_checks {}", pre_order_checks) + + if amount and pre_order_checks: + if contract := self.search_contract(instrument): + order = Order() + order.action = order_params["action"] + order.orderType = order_params["order_type"] or "MKT" + order.totalQuantity = amount + trade = self.client.placeOrder(contract, order) + return await self.get_trade_confirmation(trade, instrument, action) + + return f"Error executing {self.name}" + + except Exception as e: + logger.error("{} Error {}", self.name, e) + return f"Error executing {self.name}" + + async def search_contract(self, instrument): + """ + Asynchronously searches for a contract based on the given instrument. + + Args: + self: The object instance. + instrument: The instrument to search for. + + Returns: + Contract: The contract matching the instrument, or None if not found. + """ + try: + if asset := next( + ( + item + for item in self.mapping + if item["id"] == instrument or item["alt"] == instrument + ), + None, + ): + return Contract( + secType=asset["type"], + symbol=asset["id"], + + lastTradeDateOrContractMonth=asset["lastTradeDateOrContractMonth"], + strike=asset["strike"], + right=asset["right"], + multiplier=asset["multiplier"], + exchange=asset["exchange"], + currency=asset["currency"], + ) + logger.warning("Asset {} not found in mapping", instrument) + return None + + except Exception as e: + logger.error("search_contract {} Error {}", instrument, e) diff --git a/pyproject.toml b/pyproject.toml index 5ebd533..34ddabe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ ccxt = "^4.2.80" capitalcom-python = "0.2.3" degiro-connector = "3.0.23" easyoanda = {version ="1.0.19", python = ">=3.11,<4.0"} -# ib_insync = "0.9.86" +ib_insync = "0.9.86" # mt5linux = "0.1.9" # pyetrade = {version ="2.1.0"} From 319f5228d4ca79bc16108a99d8e0f8c9245df353 Mon Sep 17 00:00:00 2001 From: mraniki <8766259+mraniki@users.noreply.github.com> Date: Fri, 1 Nov 2024 08:43:57 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=9A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cefi/handler/ibkr.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cefi/handler/ibkr.py b/cefi/handler/ibkr.py index 04416ff..0bd2cc4 100644 --- a/cefi/handler/ibkr.py +++ b/cefi/handler/ibkr.py @@ -188,7 +188,7 @@ async def execute_order(self, order_params): order.orderType = order_params["order_type"] or "MKT" order.totalQuantity = amount trade = self.client.placeOrder(contract, order) - return await self.get_trade_confirmation(trade, instrument, action) + return await self.get_trade_confirmation(trade, instrument, action) return f"Error executing {self.name}" @@ -219,8 +219,7 @@ async def search_contract(self, instrument): return Contract( secType=asset["type"], symbol=asset["id"], - - lastTradeDateOrContractMonth=asset["lastTradeDateOrContractMonth"], + lastTradeDateOrContractMonth=asset["lastTradeDateOrContractMonth"], strike=asset["strike"], right=asset["right"], multiplier=asset["multiplier"],