189 lines
5.5 KiB
Python
189 lines
5.5 KiB
Python
"""
|
|
Base interface for exchange WebSocket connectors.
|
|
"""
|
|
|
|
from abc import ABC, abstractmethod
|
|
from typing import Callable, List, Optional
|
|
from ..models.core import ConnectionStatus, OrderBookSnapshot, TradeEvent
|
|
|
|
|
|
class ExchangeConnector(ABC):
|
|
"""Base interface for exchange WebSocket connectors"""
|
|
|
|
def __init__(self, exchange_name: str):
|
|
self.exchange_name = exchange_name
|
|
self._data_callbacks: List[Callable] = []
|
|
self._status_callbacks: List[Callable] = []
|
|
self._connection_status = ConnectionStatus.DISCONNECTED
|
|
|
|
@abstractmethod
|
|
async def connect(self) -> bool:
|
|
"""
|
|
Establish connection to the exchange WebSocket.
|
|
|
|
Returns:
|
|
bool: True if connection successful, False otherwise
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
async def disconnect(self) -> None:
|
|
"""Disconnect from the exchange WebSocket."""
|
|
pass
|
|
|
|
@abstractmethod
|
|
async def subscribe_orderbook(self, symbol: str) -> None:
|
|
"""
|
|
Subscribe to order book updates for a symbol.
|
|
|
|
Args:
|
|
symbol: Trading symbol (e.g., 'BTCUSDT')
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
async def subscribe_trades(self, symbol: str) -> None:
|
|
"""
|
|
Subscribe to trade updates for a symbol.
|
|
|
|
Args:
|
|
symbol: Trading symbol (e.g., 'BTCUSDT')
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
async def unsubscribe_orderbook(self, symbol: str) -> None:
|
|
"""
|
|
Unsubscribe from order book updates for a symbol.
|
|
|
|
Args:
|
|
symbol: Trading symbol (e.g., 'BTCUSDT')
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
async def unsubscribe_trades(self, symbol: str) -> None:
|
|
"""
|
|
Unsubscribe from trade updates for a symbol.
|
|
|
|
Args:
|
|
symbol: Trading symbol (e.g., 'BTCUSDT')
|
|
"""
|
|
pass
|
|
|
|
def get_connection_status(self) -> ConnectionStatus:
|
|
"""
|
|
Get current connection status.
|
|
|
|
Returns:
|
|
ConnectionStatus: Current connection status
|
|
"""
|
|
return self._connection_status
|
|
|
|
def add_data_callback(self, callback: Callable) -> None:
|
|
"""
|
|
Add callback for data updates.
|
|
|
|
Args:
|
|
callback: Function to call when data is received
|
|
Signature: callback(data: Union[OrderBookSnapshot, TradeEvent])
|
|
"""
|
|
if callback not in self._data_callbacks:
|
|
self._data_callbacks.append(callback)
|
|
|
|
def remove_data_callback(self, callback: Callable) -> None:
|
|
"""
|
|
Remove data callback.
|
|
|
|
Args:
|
|
callback: Callback function to remove
|
|
"""
|
|
if callback in self._data_callbacks:
|
|
self._data_callbacks.remove(callback)
|
|
|
|
def add_status_callback(self, callback: Callable) -> None:
|
|
"""
|
|
Add callback for status updates.
|
|
|
|
Args:
|
|
callback: Function to call when status changes
|
|
Signature: callback(exchange: str, status: ConnectionStatus)
|
|
"""
|
|
if callback not in self._status_callbacks:
|
|
self._status_callbacks.append(callback)
|
|
|
|
def remove_status_callback(self, callback: Callable) -> None:
|
|
"""
|
|
Remove status callback.
|
|
|
|
Args:
|
|
callback: Callback function to remove
|
|
"""
|
|
if callback in self._status_callbacks:
|
|
self._status_callbacks.remove(callback)
|
|
|
|
def _notify_data_callbacks(self, data):
|
|
"""Notify all data callbacks of new data."""
|
|
for callback in self._data_callbacks:
|
|
try:
|
|
callback(data)
|
|
except Exception as e:
|
|
# Log error but don't stop other callbacks
|
|
print(f"Error in data callback: {e}")
|
|
|
|
def _notify_status_callbacks(self, status: ConnectionStatus):
|
|
"""Notify all status callbacks of status change."""
|
|
self._connection_status = status
|
|
for callback in self._status_callbacks:
|
|
try:
|
|
callback(self.exchange_name, status)
|
|
except Exception as e:
|
|
# Log error but don't stop other callbacks
|
|
print(f"Error in status callback: {e}")
|
|
|
|
@abstractmethod
|
|
async def get_symbols(self) -> List[str]:
|
|
"""
|
|
Get list of available trading symbols.
|
|
|
|
Returns:
|
|
List[str]: List of available symbols
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def normalize_symbol(self, symbol: str) -> str:
|
|
"""
|
|
Normalize symbol to exchange format.
|
|
|
|
Args:
|
|
symbol: Standard symbol format (e.g., 'BTCUSDT')
|
|
|
|
Returns:
|
|
str: Exchange-specific symbol format
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
async def get_orderbook_snapshot(self, symbol: str, depth: int = 20) -> Optional[OrderBookSnapshot]:
|
|
"""
|
|
Get current order book snapshot.
|
|
|
|
Args:
|
|
symbol: Trading symbol
|
|
depth: Number of price levels to retrieve
|
|
|
|
Returns:
|
|
OrderBookSnapshot: Current order book or None if unavailable
|
|
"""
|
|
pass
|
|
|
|
@property
|
|
def name(self) -> str:
|
|
"""Get exchange name."""
|
|
return self.exchange_name
|
|
|
|
@property
|
|
def is_connected(self) -> bool:
|
|
"""Check if connector is connected."""
|
|
return self._connection_status == ConnectionStatus.CONNECTED |