41 KiB
Siloqy Nautilus Trading Node Configuration Error
Created: 8/26/2025 8:32
Updated: 8/26/2025 8:51
Exported: 8/26/2025 8:54
Link: https://claude.ai/chat/25d9af3d-8739-475b-a8a5-074c688312eb
Prompt:
26/8/2025, 8:33:10
File: Claude-SILOQY Multi Exchange Engine Debugging.md
File: Claude-_TO_EXP! SILOQY Nautilus Integration Fix.md
- siloqy_multi_exchange_engine_Nautilus_Actor_3_12 (attached)
- ... which launches with siloqy_run_nautilus_launch (also attached) is erroring,w with:
2025-08-25T20:12:03.561627900Z [WARN] TRADER-000.TradingNode: No data_clients configuration found
2025-08-25T20:12:03.561633300Z [WARN] TRADER-000.TradingNode: No exec_clients configuration found
2025-08-25T20:12:03.561676900Z [ERROR] TRADER-000.SILOQY-LAUNCHER: Error running SILOQY system: object NoneType can't be used in 'await' expression
2025-08-25T20:12:03.561684800Z [INFO] TRADER-000.SILOQY-LAUNCHER: Shutting down SILOQY system...
2025-08-25T20:12:03.561691500Z [INFO] TRADER-000.TradingNode: STOPPING
2025-08-25T20:12:03.561753700Z [WARN] TRADER-000.DataEngine: No clients to disconnect
2025-08-25T20:12:03.561757400Z [WARN] TRADER-000.ExecEngine: No clients to disconnect
2025-08-25T20:12:03.561764600Z [INFO] TRADER-000.TradingNode: Awaiting engine disconnections (10.0s timeout)...
Diagnose.- PS. DO NOT WRITE code. You may propose solutions or pseudo. We will implement later.-
PS. I am attaching prior chat context (DO NOT assume solutions/implementations in the previous context were better - do point out inconsistencies, but, they are offered for reference.-
IMPORTANT: Siloqy Nautilus "integreation fix" chat log (file, attached) might contain a valid, working Nautilus agent implementation. CHECK.-
Response:
26/8/2025, 8:33:51
Thought process: Diagnosed Nautilus Actor configuration errors and potential async issues.
Let's carefully analyze the error message and the issues with the Nautilus Actor implementation. I'll also review the attachments to find potential solutions.
## Error Analysis:
```
2025-08-25T20:12:03.561627900Z [WARN] TRADER-000.TradingNode: No `data_clients` configuration found
2025-08-25T20:12:03.561633300Z [WARN] TRADER-000.TradingNode: No `exec_clients` configuration found
2025-08-25T20:12:03.561676900Z [ERROR] TRADER-000.SILOQY-LAUNCHER: Error running SILOQY system: object NoneType can't be used in 'await' expression
```
The key errors are:
1. No `data_clients` configuration found
2. No `exec_clients` configuration found
3. "object NoneType can't be used in 'await' expression" - This suggests we're trying to await something that is None
The error is likely in the siloqy_run_nautilus_launch file. The error suggests that either:
1. The TradingNode object doesn't have proper data_clients configured
2. There's an async function that's awaiting a None value
Let me review the attached context, specifically "SILOQY Nautilus Integration Fix" to find potential solutions.
From the SILOQY Nautilus Integration Fix chat, we have a working implementation of Nautilus Actors. This should provide insights into what might be going wrong.
Looking at the SILOQY-DOLPHIN Actor from the previous chat:
- It is configured to connect to Binance via Nautilus data clients
- It properly structures the TradingNodeConfig with data_clients configuration
- It registers the BinanceLiveDataClientFactory
The run_siloqy.py implementation seems correct with:
```python
def run_siloqy_system():
trading_config = TradingNodeConfig(
trader_id=TraderId("SILOQY-SYSTEM"),
actors=[...],
data_clients={
"BINANCE": BinanceDataClientConfig(
account_type=BinanceAccountType.SPOT,
testnet=False,
api_key=os.getenv("BINANCE_API_KEY"),
api_secret=os.getenv("BINANCE_API_SECRET")
)
}
)
node = TradingNode(config=trading_config)
node.add_data_client_factory("BINANCE", BinanceLiveDataClientFactory)
node.build()
node.run()
```
The problem with the current implementation likely includes:
1. Missing or improperly configured data_clients in the TradingNodeConfig
2. Not registering the BinanceLiveDataClientFactory correctly
3. Potentially awaiting something that is None - possibly in an on_start_async method
Now, I'll look at the first error - "No `data_clients` configuration found":
- This suggests the TradingNodeConfig is missing the data_clients dict or it's not properly configured
- We need to ensure the data_clients field is properly set with the Binance configuration
For the second error - "object NoneType can't be used in 'await' expression":
- This suggests we're trying to await a function or method that returns None
- It could be in the on_start_async method or another async method
- The error could be from an actor that's trying to await an unconfigured client
Without seeing the actual code in siloqy_multi_exchange_engine_Nautilus_Actor_3_12 and siloqy_run_nautilus_launch, I'll need to make some educated guesses based on the error and the previous working examples.
Let's focus on likely solutions:
1. Ensure data_clients is properly configured in TradingNodeConfig
2. Verify the BinanceLiveDataClientFactory is registered
3. Check all async methods for awaiting None values
4. Check the on_start_async methods in actors
Given that we're explicitly asked not to write code but to diagnose and propose solutions, I'll outline the most probable issues and suggest fixes.
I've analyzed the error logs and see a clear issue with the Nautilus configuration. Let's diagnose the root causes:
Key Issues
-
Missing Data Client Configuration:
[WARN] TRADER-000.TradingNode: No `data_clients` configuration foundThis indicates the TradingNodeConfig doesn't have properly configured data_clients, which is required for connecting to exchanges.
-
Await Error:
[ERROR] TRADER-000.SILOQY-LAUNCHER: Error running SILOQY system: object NoneType can't be used in 'await' expressionThis suggests an async method is trying to await something that's None, likely because a client or service wasn't properly initialized.
Probable Root Causes
Looking at the previous implementation in the "SILOQY Nautilus Integration Fix" chat log, there's a working pattern for Nautilus actor implementation. Comparing that to your current error:
-
TradingNodeConfig Missing Key Components:
- data_clients configuration is missing or improperly structured
- You need a properly configured BinanceDataClientConfig
-
Client Factory Registration Issue:
- The BinanceLiveDataClientFactory may not be properly registered
-
Async Method Error:
- An on_start_async or other async method is likely trying to use an uninitialized client
Proposed Solutions
-
Fix TradingNodeConfig:
- Ensure your TradingNodeConfig includes proper data_clients configuration:
data_clients={ "BINANCE": BinanceDataClientConfig( account_type=BinanceAccountType.SPOT, testnet=False, api_key=os.getenv("BINANCE_API_KEY"), api_secret=os.getenv("BINANCE_API_SECRET") ) } -
Register Factory Before Building Node:
- Ensure you're registering the factory before building:
node.add_data_client_factory("BINANCE", BinanceLiveDataClientFactory) node.build() -
Check Actor On_Start Methods:
- Review all on_start_async methods in your actors
- Make sure they're not awaiting uninitialized clients or None values
- Add proper null-checking before awaiting values
-
Environment Variable Check:
- Verify your .env file has the Binance API keys properly set
- Add validation to check if these environment variables exist before creating the config
The most likely scenario is that the launcher script isn't configuring the data_clients properly in the TradingNodeConfig, which leads to the NoneType await error when the actor tries to connect to an exchange.
Prompt:
26/8/2025, 8:38:57
File:
I am using the (attached) code, as a launcher.- REVIEW, and, if needed, provide a complete, fixed implementation of SILOQY Nautilus Actor, v3.12.- PLEASE MAKE SURE YOU BREAK OR ALTER OR "IMPROVE" NOTHING ELSE ... ... other than this fix.-
Response:
26/8/2025, 8:39:45
Thought process: Diagnosed configuration gaps in Nautilus trading node launcher.
Let me analyze the error and the provided launcher code to identify the issue.
The error message was:
```
2025-08-25T20:12:03.561627900Z [WARN] TRADER-000.TradingNode: No `data_clients` configuration found
2025-08-25T20:12:03.561633300Z [WARN] TRADER-000.TradingNode: No `exec_clients` configuration found
2025-08-25T20:12:03.561676900Z [ERROR] TRADER-000.SILOQY-LAUNCHER: Error running SILOQY system: object NoneType can't be used in 'await' expression
```
Looking at the launcher code, I can see several issues:
1. **Missing data_clients in TradingNodeConfig**: As the error states, the configuration doesn't include data_clients, which is required for connecting to exchanges.
2. **Incorrect initialization of Nautilus**: The launcher is trying to await `trading_node.build()` and later `trading_node.run_async()`, but these methods might not be awaitable or might be incorrectly implemented.
3. **No data client factory registration**: The launcher doesn't register any data client factories with `node.add_data_client_factory()`.
4. **Missing API client configuration**: There's no Binance (or other exchange) client configuration.
The launcher is trying to create a very minimal configuration:
```python
config = TradingNodeConfig(
trader_id="SILOQY-TRADER-001",
)
```
This lacks the necessary data_clients configuration which would typically include something like:
```python
data_clients={
"BINANCE": BinanceDataClientConfig(
account_type=BinanceAccountType.SPOT,
testnet=False,
api_key=os.getenv("BINANCE_API_KEY"),
api_secret=os.getenv("BINANCE_API_SECRET")
)
}
```
Also, the launcher is missing the data client factory registration:
```python
node.add_data_client_factory("BINANCE", BinanceLiveDataClientFactory)
```
Looking at the traceback, it seems that some method is trying to await something that's None, which suggests either:
1. A method that should return an awaitable is returning None, or
2. A variable that should be initialized with an awaitable is None.
The most likely suspects are the `trading_node.build()` and `trading_node.run_async()` methods, which might not be implemented as async methods or might be failing to return an awaitable.
Let me fix these issues in the launcher code.
SILOQY Launcher Fix
Looking at the error logs and your launcher code, I've identified the key issues causing the failure:
- Missing data_clients configuration: Your TradingNodeConfig is missing the required exchange connection information.
- Missing data client factory registration: You need to register the Binance data client factory.
- Incorrect usage of async methods: There's an issue with the
build()method - in Nautilus,build()is not an async method but you're awaiting it.
Here's a fixed version of your launcher that addresses these issues:
#!/usr/bin/env python3
"""
SILOQY Nautilus Launcher
Initializes Nautilus Trading framework and starts the SILOQY actor system:
- SILOQYSymbolDiscoveryActor: Symbol discovery and initial data fetching
- SILOQYMainActor: WebSocket connections and data ingestion
- DOLPHINRegimeActor: Market regime detection
- SILOQYNormalizerActor: Data normalization for Nautilus integration
"""
import asyncio
import signal
import sys
import os
from typing import List, Optional
from dotenv import load_dotenv
# Load environment variables for API keys
load_dotenv()
# Nautilus imports
try:
from nautilus_trader.config import TradingNodeConfig
from nautilus_trader.live.node import TradingNode
from nautilus_trader.model.identifiers import Venue, TraderId
from nautilus_trader.common.component import Logger, init_logging
from nautilus_trader.adapters.binance.factories import BinanceLiveDataClientFactory
from nautilus_trader.adapters.binance.config import BinanceDataClientConfig
from nautilus_trader.adapters.binance.common.enums import BinanceAccountType
NAUTILUS = True
except ImportError:
NAUTILUS = False
print("ERROR: Nautilus Trader not installed. Please install with: pip install nautilus-trader")
sys.exit(1)
# SILOQY imports
from siloqy_multi_exchange_engine_Nautilus_Actor_3_12 import (
SILOQYSymbolDiscoveryActor,
SILOQYMainActor,
DOLPHINRegimeActor,
SILOQYNormalizerActor,
RAW_TOPIC,
STRUCTURED_TOPIC,
REGIME_TOPIC,
SYMBOLS_DISCOVERED_TOPIC,
CANDLES_INITIAL_TOPIC
)
class SILOQYLauncher:
"""
Launcher for SILOQY system on Nautilus framework
"""
def __init__(self, symbols: Optional[List[str]] = None, config_path: Optional[str] = None):
"""
Initialize the launcher
Parameters:
-----------
symbols : List[str], optional
List of trading symbols to monitor. If None, discovers all symbols.
config_path : str, optional
Path to Nautilus configuration file
"""
self.symbols = symbols # Can be None for dynamic discovery
self.config_path = config_path
self.trading_node = None
self.logger = None
self.shutdown_event = asyncio.Event()
self._loop = None # Will be set when we enter the event loop
async def run(self):
"""
Main entry point for running the SILOQY system
"""
# Store event loop reference
self._loop = asyncio.get_event_loop()
# Initialize logging
init_logging()
self.logger = Logger("SILOQY-LAUNCHER")
self.logger.info("Starting SILOQY system on Nautilus framework")
# Set up signal handlers for graceful shutdown
for sig in [signal.SIGINT, signal.SIGTERM]:
signal.signal(sig, self._signal_handler)
try:
# Initialize Nautilus TradingNode
self._initialize_nautilus()
# Create and register actors (NOT async)
self._create_actors()
# Start the system
start_task = asyncio.create_task(self._start_system())
# Wait for shutdown signal
await self.shutdown_event.wait()
# Cancel the start task if it's still running
if not start_task.done():
start_task.cancel()
try:
await start_task
except asyncio.CancelledError:
pass
except Exception as e:
self.logger.error(f"Error running SILOQY system: {e}")
raise
finally:
# Graceful shutdown
await self._shutdown()
def _initialize_nautilus(self):
"""
Initialize Nautilus TradingNode and core components
Note: build() is NOT async in Nautilus, so we don't await it
"""
# Create configuration
if self.config_path:
# Load from file if provided
config = TradingNodeConfig.from_yaml(self.config_path)
else:
# Create proper configuration with data_clients
config = TradingNodeConfig(
trader_id=TraderId("SILOQY-TRADER-001"),
data_clients={
"BINANCE": BinanceDataClientConfig(
account_type=BinanceAccountType.SPOT,
testnet=False, # Use real data
api_key=os.getenv("BINANCE_API_KEY"),
api_secret=os.getenv("BINANCE_API_SECRET")
)
}
)
# Create TradingNode
self.trading_node = TradingNode(config=config)
# Register data client factory BEFORE building
self.trading_node.add_data_client_factory("BINANCE", BinanceLiveDataClientFactory)
# Build the node (NOT async)
self.trading_node.build()
self.logger.info("Nautilus TradingNode initialized")
def _create_actors(self):
"""
Create and register all SILOQY actors including discovery actor
"""
# Create actor instances
discovery_actor = SILOQYSymbolDiscoveryActor(symbols=self.symbols)
main_actor = SILOQYMainActor()
regime_actor = DOLPHINRegimeActor(max_symbols=10000) # Increased for dynamic discovery
normalizer_actor = SILOQYNormalizerActor()
# Register actors with the node
self.trading_node.add_actor(discovery_actor)
self.trading_node.add_actor(main_actor)
self.trading_node.add_actor(regime_actor)
self.trading_node.add_actor(normalizer_actor)
self.logger.info("SILOQY actors registered with TradingNode")
async def _start_system(self):
"""
Start the TradingNode and all actors
"""
# Start the node
self.trading_node.run() # This is not async in the current Nautilus API
symbol_info = f"provided {len(self.symbols)} symbols" if self.symbols else "dynamic symbol discovery"
self.logger.info(f"SILOQY system started successfully with {symbol_info}")
if self.symbols:
self.logger.info(f"Symbols: {', '.join(self.symbols[:10])}{'...' if len(self.symbols) > 10 else ''}")
async def _shutdown(self):
"""
Graceful shutdown of the system
"""
self.logger.info("Shutting down SILOQY system...")
if self.trading_node is not None:
# Stop the node
self.trading_node.stop() # This is typically not async in current Nautilus
# Dispose resources
self.trading_node.dispose()
self.logger.info("SILOQY system shutdown complete")
def _signal_handler(self, signum, frame):
"""
Handle shutdown signals - async safe version
"""
self.logger.info(f"Received signal {signum}, initiating shutdown...")
if self._loop:
self._loop.call_soon_threadsafe(self.shutdown_event.set)
else:
self.shutdown_event.set() # Fallback
def main():
"""
Entry point for the launcher
"""
# Default symbols to monitor (can be overridden with command line args)
default_symbols = [
"BTCUSDT", "ETHUSDT", "BNBUSDT", "ADAUSDT", "XRPUSDT",
"SOLUSDT", "DOGEUSDT", "DOTUSDT", "AVAXUSDT", "MATICUSDT"
]
# In a real implementation, you would parse command line arguments
# For now, we'll use None to enable dynamic discovery
symbols = None # Set to default_symbols to use specific symbols
# Create and run the launcher
launcher = SILOQYLauncher(symbols=symbols)
# Run the system
asyncio.run(launcher.run())
if __name__ == "__main__":
main()
Key Changes Made:
-
Added data_clients configuration:
- Added BinanceDataClientConfig with proper settings
- Set up environment variable loading for API keys
-
Added data client factory registration:
- Added
self.trading_node.add_data_client_factory("BINANCE", BinanceLiveDataClientFactory) - This is done before building the node
- Added
-
Fixed async/sync method calls:
- Changed
await self.trading_node.build()toself.trading_node.build() - Changed
await self.trading_node.run_async()toself.trading_node.run() - Changed
await self.trading_node.stop_async()toself.trading_node.stop()
- Changed
-
Added required imports:
- Added imports for Binance-specific Nautilus components
- Added TraderId import
- Added dotenv for environment variable loading
These changes should resolve the NoneType await error while preserving all your original functionality.
Prompt:
26/8/2025, 8:45:53
File: siloqy_multi_exchange_engine_LMDB_v3.05_NODB.py
HANG ON:
- This entire codebase is based on the attached pre-Nautilus SILOQY implementation.-
PLEASE:
- Note how the implementation interacts with Binance. AT NO POINT does it init (or, require) a Nautilus-exchange object.-
- It uses the public (no key required) BINANCE API.-
We do wish to integrate (create) a Nautilus agent but (as you will see, review the code) the entire interaction with Binance is handled by SILOQY-code itself, not via BINANCE-Nautilus objects.-
Nautilus is (is) used for everthing else (actors, bus, etc) ... ... but we handle Binance ourselves.-
Response:
26/8/2025, 8:46:40
Thought process: Diagnosed Nautilus-SILOQY integration issues, crafted targeted solution.
I need to analyze what went wrong and fix the SILOQYLauncher implementation while ensuring it works with the custom Binance integration rather than Nautilus's built-in Binance client.
Let's break down the key issues:
1. The error message shows:
```
[WARN] TRADER-000.TradingNode: No `data_clients` configuration found
[WARN] TRADER-000.TradingNode: No `exec_clients` configuration found
[ERROR] TRADER-000.SILOQY-LAUNCHER: Error running SILOQY system: object NoneType can't be used in 'await' expression
```
The most critical issue is the NoneType error in an await expression. Looking at the launcher code, I see that `await self.trading_node.build()` is trying to await a method that doesn't return a coroutine.
2. The user clarified that they're handling Binance connection themselves, not through Nautilus's exchange adapters. This means:
- We shouldn't be adding data_clients for Binance in the TradingNodeConfig
- We don't need to register BinanceLiveDataClientFactory
- The SILOQY code itself handles all the Binance API calls and WebSocket connections
Looking at the original SILOQY implementation, I can see it's using direct HTTP and WebSocket connections to Binance with their own custom adapter pattern.
Let's fix the SILOQYLauncher to work with this approach. The key fixes needed are:
1. Remove the Binance-specific data client configuration
2. Fix the async/sync method call issues - `build()` is not an async method
3. Make sure we don't interfere with SILOQY's own Binance connection handling
4. Keep the actors running on the Nautilus message bus
I'll create a fixed version focusing only on these critical issues without changing anything else.
SILOQY Launcher Fix for Custom Binance Integration
Looking at your error logs and examining the code, I've identified the key issues. The launcher is trying to use Nautilus's exchange capabilities, but your SILOQY implementation handles Binance connections directly through its own adapters.
Key Issues
- Method Call Errors: The launcher is using
awaiton methods that aren't coroutines - Missing Configuration: The TradingNode needs a minimal configuration
- Unnecessary Binance Integration: Your code doesn't need Nautilus's Binance integration
Here's a fixed implementation that respects your custom Binance handling:
#!/usr/bin/env python3
"""
SILOQY Nautilus Launcher
Initializes Nautilus Trading framework and starts the SILOQY actor system:
- SILOQYSymbolDiscoveryActor: Symbol discovery and initial data fetching
- SILOQYMainActor: WebSocket connections and data ingestion
- DOLPHINRegimeActor: Market regime detection
- SILOQYNormalizerActor: Data normalization for Nautilus integration
"""
import asyncio
import signal
import sys
from typing import List, Optional
# Nautilus imports
try:
from nautilus_trader.config import TradingNodeConfig
from nautilus_trader.live.node import TradingNode
from nautilus_trader.model.identifiers import Venue, TraderId
from nautilus_trader.common.component import Logger, init_logging
NAUTILUS = True
except ImportError:
NAUTILUS = False
print("ERROR: Nautilus Trader not installed. Please install with: pip install nautilus-trader")
sys.exit(1)
# SILOQY imports
from siloqy_multi_exchange_engine_Nautilus_Actor_3_12 import (
SILOQYSymbolDiscoveryActor,
SILOQYMainActor,
DOLPHINRegimeActor,
SILOQYNormalizerActor,
RAW_TOPIC,
STRUCTURED_TOPIC,
REGIME_TOPIC,
SYMBOLS_DISCOVERED_TOPIC,
CANDLES_INITIAL_TOPIC
)
class SILOQYLauncher:
"""
Launcher for SILOQY system on Nautilus framework
"""
def __init__(self, symbols: Optional[List[str]] = None, config_path: Optional[str] = None):
"""
Initialize the launcher
Parameters:
-----------
symbols : List[str], optional
List of trading symbols to monitor. If None, discovers all symbols.
config_path : str, optional
Path to Nautilus configuration file
"""
self.symbols = symbols # Can be None for dynamic discovery
self.config_path = config_path
self.trading_node = None
self.logger = None
self.shutdown_event = asyncio.Event()
self._loop = None # Will be set when we enter the event loop
async def run(self):
"""
Main entry point for running the SILOQY system
"""
# Store event loop reference
self._loop = asyncio.get_event_loop()
# Initialize logging
init_logging()
self.logger = Logger("SILOQY-LAUNCHER")
self.logger.info("Starting SILOQY system on Nautilus framework")
# Set up signal handlers for graceful shutdown
for sig in [signal.SIGINT, signal.SIGTERM]:
signal.signal(sig, self._signal_handler)
try:
# Initialize Nautilus TradingNode
self._initialize_nautilus()
# Create and register actors (NOT async)
self._create_actors()
# Start the system
await self._start_system()
# Wait for shutdown signal
await self.shutdown_event.wait()
except Exception as e:
self.logger.error(f"Error running SILOQY system: {e}")
raise
finally:
# Graceful shutdown
await self._shutdown()
def _initialize_nautilus(self):
"""
Initialize Nautilus TradingNode with minimal configuration
NOTE: We don't need Binance data clients since SILOQY handles that directly
"""
# Create minimal configuration - no exchange clients needed
config = TradingNodeConfig(
trader_id=TraderId("SILOQY-TRADER-001"),
# No data_clients - SILOQY manages its own Binance connections
)
# Create TradingNode
self.trading_node = TradingNode(config=config)
# Build the node (not async)
self.trading_node.build()
self.logger.info("Nautilus TradingNode initialized")
def _create_actors(self):
"""
Create and register all SILOQY actors including discovery actor
"""
# Create actor instances
discovery_actor = SILOQYSymbolDiscoveryActor(symbols=self.symbols)
main_actor = SILOQYMainActor()
regime_actor = DOLPHINRegimeActor(max_symbols=10000) # Increased for dynamic discovery
normalizer_actor = SILOQYNormalizerActor()
# Register actors with the node
self.trading_node.add_actor(discovery_actor)
self.trading_node.add_actor(main_actor)
self.trading_node.add_actor(regime_actor)
self.trading_node.add_actor(normalizer_actor)
self.logger.info("SILOQY actors registered with TradingNode")
async def _start_system(self):
"""
Start the TradingNode and all actors
"""
# Start the node (not async)
self.trading_node.run()
symbol_info = f"provided {len(self.symbols)} symbols" if self.symbols else "dynamic symbol discovery"
self.logger.info(f"SILOQY system started successfully with {symbol_info}")
if self.symbols:
self.logger.info(f"Symbols: {', '.join(self.symbols[:10])}{'...' if len(self.symbols) > 10 else ''}")
async def _shutdown(self):
"""
Graceful shutdown of the system
"""
self.logger.info("Shutting down SILOQY system...")
if self.trading_node is not None:
# Stop the node (not async)
self.trading_node.stop()
# Dispose resources
self.trading_node.dispose()
self.logger.info("SILOQY system shutdown complete")
def _signal_handler(self, signum, frame):
"""
Handle shutdown signals - async safe version
"""
self.logger.info(f"Received signal {signum}, initiating shutdown...")
if self._loop:
self._loop.call_soon_threadsafe(self.shutdown_event.set)
else:
self.shutdown_event.set() # Fallback
def main():
"""
Entry point for the launcher
"""
# Default symbols to monitor (can be overridden with command line args)
default_symbols = [
"BTCUSDT", "ETHUSDT", "BNBUSDT", "ADAUSDT", "XRPUSDT",
"SOLUSDT", "DOGEUSDT", "DOTUSDT", "AVAXUSDT", "MATICUSDT"
]
# In a real implementation, you would parse command line arguments
# For now, we'll use None to enable dynamic discovery
symbols = None # Set to default_symbols to use specific symbols
# Create and run the launcher
launcher = SILOQYLauncher(symbols=symbols)
# Run the system
asyncio.run(launcher.run())
if __name__ == "__main__":
main()
Key Changes Made
-
Removed Nautilus-Binance integration:
- Removed all Binance client configuration
- No data client factory registration since SILOQY handles Binance directly
-
Fixed method call issues:
- Changed
await self.trading_node.build()toself.trading_node.build() - Changed
await self.trading_node.run_async()toself.trading_node.run() - Fixed
stop()and related methods
- Changed
-
Simplified system start:
- Removed the start_task and task cancellation logic that was causing issues
- The system now starts directly with
await self._start_system()
-
Maintained actor registration:
- Kept all SILOQY actors for message bus communication
This keeps the original functionality intact while fixing the immediate issues. The launcher now provides only the Nautilus framework without trying to manage exchange connections, letting your SILOQY implementation handle that directly.
Prompt:
26/8/2025, 8:50:47
2025-08-26T06:50:19.714407000Z [ERROR] TRADER-000.SILOQY-LAUNCHER: Error running SILOQY system: 'TradingNode' object has no attribute 'add_actor'
Response:
26/8/2025, 8:51:30
Thought process: Diagnosed Nautilus TradingNode API method incompatibility, proposed reconfiguration.
This error is quite specific and points to an issue with the Nautilus TradingNode API. The error message says:
```
[ERROR] TRADER-000.SILOQY-LAUNCHER: Error running SILOQY system: 'TradingNode' object has no attribute 'add_actor'
```
This suggests that in the current version of Nautilus Trader being used, the TradingNode class does not have an `add_actor` method, which we're trying to call in our launcher implementation.
Let me look at the relevant part of the code that's causing this issue:
```python
def _create_actors(self):
"""
Create and register all SILOQY actors including discovery actor
"""
# Create actor instances
discovery_actor = SILOQYSymbolDiscoveryActor(symbols=self.symbols)
main_actor = SILOQYMainActor()
regime_actor = DOLPHINRegimeActor(max_symbols=10000) # Increased for dynamic discovery
normalizer_actor = SILOQYNormalizerActor()
# Register actors with the node
self.trading_node.add_actor(discovery_actor) # This line is causing the error
self.trading_node.add_actor(main_actor)
self.trading_node.add_actor(regime_actor)
self.trading_node.add_actor(normalizer_actor)
self.logger.info("SILOQY actors registered with TradingNode")
```
The issue is that we're trying to use `self.trading_node.add_actor()`, but this method doesn't exist in the Nautilus TradingNode class being used.
Looking at the Nautilus documentation and the recent changes to the API, it appears the method for adding actors to a TradingNode might have changed. Let me think about how to fix this.
In Nautilus Trader, actors should typically be registered through the TradingNodeConfig when creating the TradingNode, not by calling an "add_actor" method after the TradingNode is created. This seems to be a common pattern in recent versions of Nautilus.
So we need to modify our approach to include actors in the TradingNodeConfig when we initialize the TradingNode, rather than trying to add them afterwards.
Let's modify the approach to add actors through the TradingNodeConfig:
1. Define the actors in the TradingNodeConfig
2. Create the TradingNode with that config
3. Build and run the node
I should make sure we don't lose any functionality from the original code.
The error message indicates that the add_actor method doesn't exist on the TradingNode object in your Nautilus version. In current Nautilus Trader versions, actors must be defined in the TradingNodeConfig when initializing the node, not added afterwards.
Here's a fixed implementation that registers actors through the proper configuration:
#!/usr/bin/env python3
"""
SILOQY Nautilus Launcher
Initializes Nautilus Trading framework and starts the SILOQY actor system:
- SILOQYSymbolDiscoveryActor: Symbol discovery and initial data fetching
- SILOQYMainActor: WebSocket connections and data ingestion
- DOLPHINRegimeActor: Market regime detection
- SILOQYNormalizerActor: Data normalization for Nautilus integration
"""
import asyncio
import signal
import sys
from typing import List, Optional
# Nautilus imports
try:
from nautilus_trader.config import TradingNodeConfig, ImportableActorConfig
from nautilus_trader.live.node import TradingNode
from nautilus_trader.model.identifiers import Venue, TraderId
from nautilus_trader.common.component import Logger, init_logging
NAUTILUS = True
except ImportError:
NAUTILUS = False
print("ERROR: Nautilus Trader not installed. Please install with: pip install nautilus-trader")
sys.exit(1)
# SILOQY imports
from siloqy_multi_exchange_engine_Nautilus_Actor_3_12 import (
SILOQYSymbolDiscoveryActor,
SILOQYMainActor,
DOLPHINRegimeActor,
SILOQYNormalizerActor,
RAW_TOPIC,
STRUCTURED_TOPIC,
REGIME_TOPIC,
SYMBOLS_DISCOVERED_TOPIC,
CANDLES_INITIAL_TOPIC
)
class SILOQYLauncher:
"""
Launcher for SILOQY system on Nautilus framework
"""
def __init__(self, symbols: Optional[List[str]] = None, config_path: Optional[str] = None):
"""
Initialize the launcher
Parameters:
-----------
symbols : List[str], optional
List of trading symbols to monitor. If None, discovers all symbols.
config_path : str, optional
Path to Nautilus configuration file
"""
self.symbols = symbols # Can be None for dynamic discovery
self.config_path = config_path
self.trading_node = None
self.logger = None
self.shutdown_event = asyncio.Event()
self._loop = None # Will be set when we enter the event loop
async def run(self):
"""
Main entry point for running the SILOQY system
"""
# Store event loop reference
self._loop = asyncio.get_event_loop()
# Initialize logging
init_logging()
self.logger = Logger("SILOQY-LAUNCHER")
self.logger.info("Starting SILOQY system on Nautilus framework")
# Set up signal handlers for graceful shutdown
for sig in [signal.SIGINT, signal.SIGTERM]:
signal.signal(sig, self._signal_handler)
try:
# Initialize Nautilus TradingNode
self._initialize_nautilus()
# Start the system
await self._start_system()
# Wait for shutdown signal
await self.shutdown_event.wait()
except Exception as e:
self.logger.error(f"Error running SILOQY system: {e}")
raise
finally:
# Graceful shutdown
await self._shutdown()
def _initialize_nautilus(self):
"""
Initialize Nautilus TradingNode with minimal configuration
NOTE: We don't need Binance data clients since SILOQY handles that directly
"""
# Create actor configs
actor_configs = [
# Symbol Discovery Actor
ImportableActorConfig(
actor_path="siloqy_multi_exchange_engine_Nautilus_Actor_3_12:SILOQYSymbolDiscoveryActor",
config={"symbols": self.symbols}
),
# Main Actor
ImportableActorConfig(
actor_path="siloqy_multi_exchange_engine_Nautilus_Actor_3_12:SILOQYMainActor",
config={}
),
# Regime Actor
ImportableActorConfig(
actor_path="siloqy_multi_exchange_engine_Nautilus_Actor_3_12:DOLPHINRegimeActor",
config={"max_symbols": 10000}
),
# Normalizer Actor
ImportableActorConfig(
actor_path="siloqy_multi_exchange_engine_Nautilus_Actor_3_12:SILOQYNormalizerActor",
config={}
)
]
# Create minimal configuration with actors
config = TradingNodeConfig(
trader_id=TraderId("SILOQY-TRADER-001"),
actors=actor_configs,
# No data_clients - SILOQY manages its own Binance connections
)
# Create TradingNode
self.trading_node = TradingNode(config=config)
# Build the node (not async)
self.trading_node.build()
self.logger.info("Nautilus TradingNode initialized with actors")
async def _start_system(self):
"""
Start the TradingNode and all actors
"""
# Start the node (not async)
self.trading_node.run()
symbol_info = f"provided {len(self.symbols)} symbols" if self.symbols else "dynamic symbol discovery"
self.logger.info(f"SILOQY system started successfully with {symbol_info}")
if self.symbols:
self.logger.info(f"Symbols: {', '.join(self.symbols[:10])}{'...' if len(self.symbols) > 10 else ''}")
async def _shutdown(self):
"""
Graceful shutdown of the system
"""
self.logger.info("Shutting down SILOQY system...")
if self.trading_node is not None:
# Stop the node (not async)
self.trading_node.stop()
# Dispose resources
self.trading_node.dispose()
self.logger.info("SILOQY system shutdown complete")
def _signal_handler(self, signum, frame):
"""
Handle shutdown signals - async safe version
"""
self.logger.info(f"Received signal {signum}, initiating shutdown...")
if self._loop:
self._loop.call_soon_threadsafe(self.shutdown_event.set)
else:
self.shutdown_event.set() # Fallback
def main():
"""
Entry point for the launcher
"""
# Default symbols to monitor (can be overridden with command line args)
default_symbols = [
"BTCUSDT", "ETHUSDT", "BNBUSDT", "ADAUSDT", "XRPUSDT",
"SOLUSDT", "DOGEUSDT", "DOTUSDT", "AVAXUSDT", "MATICUSDT"
]
# In a real implementation, you would parse command line arguments
# For now, we'll use None to enable dynamic discovery
symbols = None # Set to default_symbols to use specific symbols
# Create and run the launcher
launcher = SILOQYLauncher(symbols=symbols)
# Run the system
asyncio.run(launcher.run())
if __name__ == "__main__":
main()
Key Changes
-
Removed
add_actormethod calls:- Instead of creating actors and adding them separately, I now include them in the TradingNodeConfig
-
Added ImportableActorConfig:
- Used the proper Nautilus configuration structure for actors
- Set the correct module path and config parameters
-
Eliminated the separate
_create_actorsmethod:- All actor configuration is now part of the node initialization
- Maintains the same functionality but follows Nautilus's expected pattern
This approach follows the standard Nautilus pattern of configuring everything upfront through the configuration object rather than calling methods after the node is created.
Powered by Claude Exporter