From 4a59d9d07e9aae81090b8c2fe7dbb5c5b17bb1ae Mon Sep 17 00:00:00 2001 From: mraniki <8766259+mraniki@users.noreply.github.com> Date: Mon, 7 Aug 2023 20:23:09 +0200 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=93=9D=20updated=20docstring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tt/plugins/default_plugins/ __init__.py | 5 + .../default_plugins/cex_exchange_plugin.py | 119 +++++++++++++++-- tt/plugins/plugin_manager.py | 123 ++++++++++++++++-- tt/utils.py | 23 +++- 4 files changed, 248 insertions(+), 22 deletions(-) diff --git a/tt/plugins/default_plugins/ __init__.py b/tt/plugins/default_plugins/ __init__.py index e69de29bb..5c5f26ce1 100644 --- a/tt/plugins/default_plugins/ __init__.py +++ b/tt/plugins/default_plugins/ __init__.py @@ -0,0 +1,5 @@ +""" + Plugins location + +""" + diff --git a/tt/plugins/default_plugins/cex_exchange_plugin.py b/tt/plugins/default_plugins/cex_exchange_plugin.py index cf861ff88..a778fe7d1 100644 --- a/tt/plugins/default_plugins/cex_exchange_plugin.py +++ b/tt/plugins/default_plugins/cex_exchange_plugin.py @@ -9,7 +9,16 @@ class CexExchangePlugin(BasePlugin): - """CEX Plugin""" + """ + Class CexExchangePlugin to support CEX Exchange + + Args: + None + + Returns: + None + + """ name = os.path.splitext(os.path.basename(__file__))[0] def __init__(self): super().__init__() @@ -34,7 +43,17 @@ def should_handle(self, message): return self.enabled async def handle_message(self, msg): - """Handles incoming messages""" + """ + Handles incoming messages + to route to the respective function + + Args: + msg (str): The incoming message + + Returns: + None + + """ if not self.enabled: return @@ -69,7 +88,18 @@ async def handle_message(self, msg): class CexExchange(): - """CEX Object""" + """ + CEX Object to support CEX + via CCXT library to be reviewed + to be stored in different file/package + + Args: + None + + Returns: + None + + """ def __init__(self): if settings.cex_name: client = getattr(ccxt, settings.cex_name) @@ -86,25 +116,61 @@ def __init__(self): self.commands = settings.ccxt_commands async def get_info(self): - """info_message""" + """ + info_message + + """ exchange_name = self.cex.id account_info = self.cex.uid - #account_info = self.cex.fetchAccounts().get('main') + # account_info = self.cex.fetchAccounts().get('main') + # method not implemented yet return f"💱 {exchange_name}\n🪪 {account_info}" async def get_help(self): + """ + Get the help information for the current instance. + + Returns: + A string containing the available commands. + """ return (f"{self.commands}\n") async def get_quote(self, symbol): - """return main asset balance.""" + """ + return main asset balance. + + Args: + symbol + + Returns: + quote + """ + return f"🏦 {self.cex.fetchTicker(symbol).get('last')}" async def get_trading_asset_balance(self): - """return main asset balance.""" + """ + return main asset balance. + + Args: + None + + Returns: + balance + """ return self.cex.fetchBalance()[f"{settings.trading_asset}"]["free"] async def get_account_balance(self): - """return account balance.""" + """ + return account balance. + + Args: + None + + Returns: + balance + + """ raw_balance = self.cex.fetch_free_balance() filtered_balance = {k: v for k, v in raw_balance.items() @@ -118,7 +184,16 @@ async def get_account_balance(self): return balance async def get_account_position(self): - """return account position.""" + """ + return account position. + + Args: + None + + Returns: + position + + """ open_positions = self.cex.fetch_positions() open_positions = [p for p in open_positions if p['type'] == 'open'] position = "📊 Position\n" + str(open_positions) @@ -126,11 +201,33 @@ async def get_account_position(self): return position async def get_account_pnl(self): - """return account pnl.""" + """ + return account pnl. + + Args: + None + + Returns: + pnl + """ + return 0 async def execute_order(self, order_params): - """Execute order.""" + """ + Execute order + + Args: + order_params (dict): + action(str) + instrument(str) + quantity(int) + + Returns: + trade_confirmation(dict) + + """ + action = order_params.get('action') instrument = order_params.get('instrument') quantity = order_params.get('quantity', settings.trading_risk_amount) diff --git a/tt/plugins/plugin_manager.py b/tt/plugins/plugin_manager.py index 66159f63f..ecb03f103 100644 --- a/tt/plugins/plugin_manager.py +++ b/tt/plugins/plugin_manager.py @@ -8,13 +8,34 @@ class PluginManager: - """🔌 Plugin Manager """ + """ + 🔌 Plugin Manager use to load, start and + dispatch message to the plugins + + Args: + plugin_directory (str): Directory of plugins + + Returns: + None + + """ + def __init__(self, plugin_directory=None): self.plugin_directory = plugin_directory or settings.plugin_directory self.plugins = [] def load_plugins(self): - """ Load plugins from directory """ + """ + 🔌Load plugins from directory + + Returns: + None + + Raises: + Exception + + + """ package = importlib.import_module(self.plugin_directory) logger.debug("Loading plugins from: {}", package) for _, plugin_name, _ in pkgutil.iter_modules(package.__path__): @@ -27,7 +48,17 @@ def load_plugins(self): logger.warning("Error loading plugin {}: {}", plugin_name, e) def load_plugin(self, module, plugin_name): - """ Load a plugin from a module """ + """ + Load a plugin from a module + + Args: + module (Module): Module + plugin_name (str): Plugin name + + Returns: + None + + """ logger.debug("plugin_name: {}", plugin_name) for name, obj in module.__dict__.items(): if (isinstance(obj, type) @@ -38,18 +69,44 @@ def load_plugin(self, module, plugin_name): logger.debug("Plugin loaded: {}", name) async def start_all_plugins(self): - """ Start all plugins """ + """ + Start all plugins + Start the scheduler + + Returns: + None + + + """ for plugin in self.plugins: await self.start_plugin(plugin) scheduler.start() async def start_plugin(self, plugin): - """ Start a plugin """ + """ + Start a plugin + + Args: + plugin (Plugin): Plugin + + Returns: + None + + """ await plugin.start() async def process_message(self, message): - """ Send message to plugins """ + """ + Send message to plugins + + Args: + message (str): Message + + Returns: + None + + """ for plugin in self.plugins: try: if plugin.should_handle(message): @@ -63,6 +120,18 @@ async def process_message(self, message): class BasePlugin: """ ⚡ Base Plugin Class + use to be inherited by Talky Plugins + especially the scheduling, notification and + message handling. + + Args: + None + + Returns: + None + + + """ def __init__(self): self.enabled = False @@ -78,6 +147,16 @@ async def send_notification(self, message): pass def should_handle(self, message): + """ + Returns True if the plugin should handle the message + + Args: + message (str): Message + + Returns: + bool + + """ return (not message.startswith(settings.bot_ignore) if self.enabled else False) @@ -86,8 +165,19 @@ async def plugin_notify_schedule_task( user_name=None, frequency=8, function=None): - """Handles task notification - every X hours. Defaulted to 8 hours""" + """ + Handles task notification + every X hours. Defaulted to 8 hours + + Args: + user_name (str): User name + frequency (int): Frequency + function (function): Function + + Returns: + None + """ + if function: self.scheduler.add_task( name=user_name, @@ -104,8 +194,21 @@ async def plugin_notify_cron_task( user_hours="6,12,18", user_timezone="UTC", function=None): - """Handles task cron scheduling for notification - Monday to Friday at 6AM, 12PM and 6PM UTC""" + """ + Handles task cron scheduling for notification + Monday to Friday at 6AM, 12PM and 6PM UTC + + Args: + user_name (str): User name + user_day_of_week (str): Day of week + user_hours (str): Hours + user_timezone (str): Timezone + function (function): Function + + Returns: + None + + """ if function: self.scheduler.add_task( name=user_name, diff --git a/tt/utils.py b/tt/utils.py index 6df6cd87a..caabf8490 100644 --- a/tt/utils.py +++ b/tt/utils.py @@ -37,6 +37,11 @@ async def run_bot(): """ 🤖 Run the chat bot & the plugins. + Returns: + None + + Refer to iamlistening documentation for more information + """ listener = Listener() plugin_manager = PluginManager() @@ -46,6 +51,12 @@ async def run_bot(): async def start_plugins(plugin_manager): """ 🔌 Start all plugins. + + Returns: + None + + Refer to chat manager for the pl + """ if settings.plugin_enabled: plugin_manager.load_plugins() @@ -55,7 +66,17 @@ async def start_plugins(plugin_manager): async def start_bot(listener, plugin_manager, max_iterations=None): """ - 👂 Start the chat listener and dispatch to plugins + 👂 Start the chat listener and + dispatch messages to plugins + + Args: + listener (Listener): Listener + plugin_manager (PluginManager): PluginManager + max_iterations (int): Max iterations + + Returns: + None + """ await listener.start() await start_plugins(plugin_manager) From 77354b3302bcfb47d56370a892eda17e8afb0a97 Mon Sep 17 00:00:00 2001 From: mraniki Date: Mon, 7 Aug 2023 22:25:57 +0200 Subject: [PATCH 2/3] :arrow_up: dep --- pyproject.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ac6c9a68e..cf5a6af79 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,11 +49,11 @@ fastapi = "^0.101.0" ping3 = "^4.0.4" playwright = "^1.36.0" ccxt = "^4.0.0" -dxsp = "^4.2.3" -findmyorder = "^1.6.1" -iamlistening = "^3.1.0" -talkytrend = "^1.12.3" -myllm = "^1.0.0" +dxsp = "^4.2.10" +findmyorder = "^1.7.11" +iamlistening = "^3.2.0" +talkytrend = "^1.12.11" +myllm = "^1.2.8" [tool.poetry.group.dev.dependencies] From fb06f6c22fa5bdca75d82adcdb4bf51f382cdc97 Mon Sep 17 00:00:00 2001 From: mraniki Date: Mon, 7 Aug 2023 20:28:31 +0000 Subject: [PATCH 3/3] Update Requirements --- .requirements/requirements.txt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.requirements/requirements.txt b/.requirements/requirements.txt index ed243d91c..50cf6a0fa 100644 --- a/.requirements/requirements.txt +++ b/.requirements/requirements.txt @@ -26,7 +26,7 @@ cryptography==41.0.3 ; python_version >= "3.10" and python_version < "4.0" curl-cffi==0.5.7 ; python_version >= "3.10" and python_version < "4.0" cytoolz==0.12.2 ; python_version >= "3.10" and python_version < "4" and implementation_name == "cpython" decorator==5.1.1 ; python_version >= "3.10" and python_version < "4.0" -dxsp==4.2.6 ; python_version >= "3.10" and python_version < "4.0" +dxsp==4.2.10 ; python_version >= "3.10" and python_version < "4.0" dynaconf==3.2.0 ; python_version >= "3.10" and python_version < "4.0" emoji==2.7.0 ; python_version >= "3.10" and python_version < "4.0" eth-abi==4.1.0 ; python_version >= "3.10" and python_version < "4" @@ -40,11 +40,11 @@ eth-typing==3.4.0 ; python_version >= "3.10" and python_version < "4" eth-utils==2.2.0 ; python_version >= "3.10" and python_version < "4" exceptiongroup==1.1.2 ; python_version >= "3.10" and python_version < "3.11" fastapi==0.101.0 ; python_version >= "3.10" and python_version < "4.0" -findmyorder==1.7.8 ; python_version >= "3.10" and python_version < "4.0" +findmyorder==1.7.11 ; python_version >= "3.10" and python_version < "4.0" frozendict==2.3.8 ; python_version >= "3.10" and python_version < "4.0" frozenlist==1.4.0 ; python_version >= "3.10" and python_version < "4.0" future==0.18.3 ; python_version >= "3.10" and python_version < "4.0" -g4f==0.0.1.3 ; python_version >= "3.10" and python_version < "4.0" +g4f==0.0.1.4 ; python_version >= "3.10" and python_version < "4.0" greenlet==2.0.2 ; python_version >= "3.10" and python_version < "4.0" grpcio==1.56.2 ; python_version >= "3.10" and python_version < "4.0" guilded-py==1.10.0 ; python_version >= "3.10" and python_version < "4.0" @@ -56,9 +56,10 @@ html5lib==1.1 ; python_version >= "3.10" and python_version < "4.0" httpcore==0.17.3 ; python_version >= "3.10" and python_version < "4.0" httpx==0.24.1 ; python_version >= "3.10" and python_version < "4.0" hyperframe==6.0.1 ; python_version >= "3.10" and python_version < "4.0" -iamlistening==3.1.4 ; python_version >= "3.10" and python_version < "4.0" +iamlistening==3.2.0 ; python_version >= "3.10" and python_version < "4.0" idna==3.4 ; python_version >= "3.10" and python_version < "4.0" jeepney==0.8.0 ; python_version >= "3.10" and (sys_platform == "bsd" or sys_platform == "linux") and python_version < "4.0" +js2py==0.74 ; python_version >= "3.10" and python_version < "4.0" jsonschema-specifications==2023.7.1 ; python_version >= "3.10" and python_version < "4.0" jsonschema==4.19.0 ; python_version >= "3.10" and python_version < "4.0" logbook==1.6.0 ; python_version >= "3.10" and python_version < "4.0" @@ -71,7 +72,7 @@ mastodon-py==1.8.1 ; python_version >= "3.10" and python_version < "4.0" matrix-nio==0.20.2 ; python_version >= "3.10" and python_version < "4.0" multidict==6.0.4 ; python_version >= "3.10" and python_version < "4.0" multitasking==0.0.11 ; python_version >= "3.10" and python_version < "4.0" -myllm==1.1.0 ; python_version >= "3.10" and python_version < "4.0" +myllm==1.2.8 ; python_version >= "3.10" and python_version < "4.0" numpy==1.25.2 ; python_version >= "3.10" and python_version < "4.0" oauthlib==3.2.2 ; python_version >= "3.10" and python_version < "4.0" packaging==23.1 ; python_version >= "3.10" and python_version < "4.0" @@ -94,6 +95,7 @@ pydantic-core==2.4.0 ; python_version >= "3.10" and python_version < "4.0" pydantic==2.1.1 ; python_version >= "3.10" and python_version < "4.0" pyee==9.0.4 ; python_version >= "3.10" and python_version < "4.0" pyexecjs==1.5.1 ; python_version >= "3.10" and python_version < "4.0" +pyjsparser==2.7.1 ; python_version >= "3.10" and python_version < "4.0" pyparsing==3.1.1 ; python_version >= "3.10" and python_version < "4.0" python-cryptography-fernet-wrapper==1.0.4 ; python_version >= "3.10" and python_version < "4.0" python-dateutil==2.8.2 ; python_version >= "3.10" and python_version < "4.0" @@ -101,6 +103,7 @@ python-dotenv==1.0.0 ; python_version >= "3.10" and python_version < "4.0" python-magic-bin==0.4.14 ; python_version >= "3.10" and python_version < "4.0" and platform_system == "Windows" python-magic==0.4.27 ; python_version >= "3.10" and python_version < "4.0" and platform_system != "Windows" python-socks[asyncio]==2.3.0 ; python_version >= "3.10" and python_version < "4.0" +pythorhead==0.15.4 ; python_version >= "3.10" and python_version < "3.12" pytz-deprecation-shim==0.1.0.post0 ; python_version >= "3.10" and python_version < "4.0" pytz==2023.3 ; python_version >= "3.10" and python_version < "4.0" pyunormalize==15.0.0 ; python_version >= "3.10" and python_version < "4.0" @@ -121,7 +124,7 @@ six==1.16.0 ; python_version >= "3.10" and python_version < "4.0" sniffio==1.3.0 ; python_version >= "3.10" and python_version < "4.0" soupsieve==2.4.1 ; python_version >= "3.10" and python_version < "4.0" starlette==0.27.0 ; python_version >= "3.10" and python_version < "4.0" -talkytrend==1.12.10 ; python_version >= "3.10" and python_version < "4.0" +talkytrend==1.12.11 ; python_version >= "3.10" and python_version < "4.0" telethon==1.29.2 ; python_version >= "3.10" and python_version < "4.0" tinode-grpc==0.22.3 ; python_version >= "3.10" and python_version < "4.0" toml==0.10.2 ; python_version >= "3.10" and python_version < "4.0"