stability and error cleaning. rule to read specs

This commit is contained in:
Dobromir Popov
2025-08-10 13:05:41 +03:00
parent e05163deb7
commit 6861d0f20b
4 changed files with 51 additions and 8 deletions

View File

@@ -98,6 +98,14 @@ class BybitInterface(ExchangeInterface):
testnet=self.test_mode
)
# Sync server time for REST client and prefer larger recv_window
try:
self.rest_client.sync_server_time()
# Increase REST recv window defensively
self.rest_client.recv_window_ms = max(self.rest_client.recv_window_ms, 20000)
except Exception:
pass
# Test pybit connection first
try:
account_info = self.session.get_wallet_balance(accountType="UNIFIED")

View File

@@ -40,6 +40,9 @@ class BybitRestClient:
# Rate limiting
self.last_request_time = 0
self.min_request_interval = 0.1 # 100ms between requests
# Recv window and server time sync
self.recv_window_ms = 20000 # 20 seconds to tolerate clock drift
self.time_delta_ms = 0 # server_time_ms - local_time_ms
# Request session for connection pooling
self.session = requests.Session()
@@ -61,7 +64,7 @@ class BybitRestClient:
HMAC-SHA256 signature
"""
# Bybit signature format: timestamp + api_key + recv_window + params
recv_window = "5000" # 5 seconds
recv_window = str(self.recv_window_ms)
param_str = f"{timestamp}{self.api_key}{recv_window}{params}"
signature = hmac.new(
@@ -86,7 +89,7 @@ class BybitRestClient:
'X-BAPI-API-KEY': self.api_key,
'X-BAPI-SIGN': signature,
'X-BAPI-TIMESTAMP': timestamp,
'X-BAPI-RECV-WINDOW': '5000',
'X-BAPI-RECV-WINDOW': str(self.recv_window_ms),
'Content-Type': 'application/json'
}
@@ -116,7 +119,9 @@ class BybitRestClient:
self._rate_limit()
url = f"{self.base_url}{endpoint}"
timestamp = str(int(time.time() * 1000))
# Apply server time delta
local_ms = int(time.time() * 1000)
timestamp = str(local_ms + self.time_delta_ms)
if params is None:
params = {}
@@ -165,6 +170,20 @@ class BybitRestClient:
error_msg = result.get('retMsg', 'Unknown error')
error_code = result.get('retCode', 'Unknown')
logger.error(f"Bybit Error {error_code}: {error_msg}")
# Handle time drift (10002) by syncing server time and retrying once
if signed and str(error_code) == '10002':
try:
self.sync_server_time()
# increase recv window defensively
self.recv_window_ms = max(self.recv_window_ms, 30000)
# Retry once
return self._make_request(method, endpoint, params, signed)
except Exception:
pass
# Handle rate limit (10016) by brief backoff and retry
if str(error_code) == '10016':
time.sleep(0.25)
return self._make_request(method, endpoint, params, signed)
raise Exception(f"Bybit Error {error_code}: {error_msg}")
return result
@@ -173,6 +192,18 @@ class BybitRestClient:
"""Get server time (public endpoint)."""
return self._make_request('GET', '/v5/market/time')
def sync_server_time(self) -> None:
"""Sync local-server time delta to reduce 10002 invalid timestamp errors."""
try:
res = self.get_server_time()
server_ts = int(res.get('result', {}).get('timeSecond', 0)) * 1000
if server_ts > 0:
local_ms = int(time.time() * 1000)
self.time_delta_ms = server_ts - local_ms
logger.info(f"Bybit server time synced. Delta: {self.time_delta_ms} ms")
except Exception as e:
logger.warning(f"Failed to sync Bybit server time: {e}")
def get_account_info(self) -> Dict[str, Any]:
"""Get account information (private endpoint)."""
return self._make_request('GET', '/v5/account/wallet-balance',