Skip to content

Commit b908287

Browse files
get_symbol_precision and fetch_ohlcv handle for malformed data - BYBIT
1 parent 2d6570a commit b908287

File tree

2 files changed

+35
-207
lines changed

2 files changed

+35
-207
lines changed

directionalscalper/core/exchanges/bybit.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ def get_futures_balance_bybit(self):
567567
# logging.info("Traceback: %s", traceback.format_exc())
568568
# return None, None
569569

570-
def get_symbol_precision_bybit(self, symbol, max_retries=3, retry_delay=5):
570+
def get_symbol_precision_bybit(self, symbol, max_retries=1000, retry_delay=5):
571571
for attempt in range(max_retries):
572572
try:
573573
# Use fetch_markets to retrieve data for all markets
@@ -597,7 +597,6 @@ def get_symbol_precision_bybit(self, symbol, max_retries=3, retry_delay=5):
597597
logging.info(f"All retry attempts failed for get_symbol_precision_bybit({symbol}).")
598598
return None, None
599599

600-
601600
def get_positions_bybit(self, symbol, max_retries=100, retry_delay=5) -> dict:
602601
values = {
603602
"long": {

directionalscalper/core/exchanges/exchange.py

Lines changed: 34 additions & 205 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,59 +1379,58 @@ def fetch_ohlcv(self, symbol, timeframe='1d', limit=None, max_retries=100, base_
13791379
try:
13801380
with self.rate_limiter:
13811381
# Fetch the OHLCV data from the exchange
1382-
ohlcv = self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit) # Pass the limit parameter
1383-
1382+
ohlcv = self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
1383+
13841384
# Create a DataFrame from the OHLCV data
13851385
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
1386-
1386+
13871387
# Convert the timestamp to datetime
13881388
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
1389-
1389+
13901390
# Set the timestamp as the index
13911391
df.set_index('timestamp', inplace=True)
1392-
1392+
13931393
return df
13941394

13951395
except ccxt.RateLimitExceeded as e:
1396+
# Exponential backoff for rate limits
13961397
retries += 1
13971398
delay = min(base_delay * (2 ** retries) + random.uniform(0, 0.1 * (2 ** retries)), max_delay)
13981399
logging.info(f"Rate limit exceeded: {e}. Retrying in {delay:.2f} seconds...")
13991400
time.sleep(delay)
14001401

14011402
except ccxt.BadSymbol as e:
1402-
# Handle the BadSymbol error gracefully and exit the loop
14031403
logging.info(f"Bad symbol: {symbol}. Error: {e}")
1404-
break # Exit the retry loop as the symbol is invalid
1404+
break # Symbol is invalid; no point retrying
14051405

14061406
except ccxt.BaseError as e:
1407-
# Log the error message
1407+
# Return an empty DataFrame on other ccxt exchange errors
14081408
logging.info(f"Failed to fetch OHLCV data: {self.exchange.id} {e}")
14091409
logging.error(traceback.format_exc())
1410-
return pd.DataFrame() # Return empty DataFrame for other base errors
1410+
return pd.DataFrame()
14111411

14121412
except Exception as e:
1413-
# Log the error message and traceback
1413+
# Catch unexpected errors, including malformed JSON
14141414
logging.info(f"Unexpected error occurred while fetching OHLCV data: {e}")
14151415
logging.error(traceback.format_exc())
1416-
1417-
# Handle specific error scenarios
1418-
if isinstance(e, TypeError) and 'string indices must be integers' in str(e):
1419-
logging.info(f"TypeError occurred: {e}")
1420-
logging.info(f"Response content: {self.exchange.last_http_response}")
1421-
1422-
try:
1423-
response = json.loads(self.exchange.last_http_response)
1424-
logging.info(f"Parsed response into a dictionary: {response}")
1425-
except json.JSONDecodeError as json_error:
1426-
logging.info(f"Failed to parse response: {json_error}")
1427-
1428-
return pd.DataFrame() # Return empty DataFrame on unexpected errors
14291416

1417+
error_str = str(e)
1418+
# Check for malformed JSON indicators
1419+
if ("string indices must be integers" in error_str) or ("Extra data" in error_str):
1420+
# Retry logic for malformed response
1421+
retries += 1
1422+
delay = min(base_delay * (2 ** retries) + random.uniform(0, 0.1 * (2 ** retries)), max_delay)
1423+
logging.info(f"Malformed JSON or appended data. Retrying in {delay:.2f} seconds...")
1424+
time.sleep(delay)
1425+
continue
1426+
else:
1427+
# If it's another unexpected error, just return an empty DataFrame
1428+
return pd.DataFrame()
1429+
1430+
# If we exhaust max_retries, return an empty DataFrame
14301431
logging.error(f"Failed to fetch OHLCV data after {max_retries} retries.")
14311432
return pd.DataFrame()
14321433

1433-
1434-
14351434
# def fetch_ohlcv(self, symbol, timeframe='1d', limit=None, max_retries=100, base_delay=10, max_delay=60):
14361435
# """
14371436
# Fetch OHLCV data for the given symbol and timeframe.
@@ -1442,7 +1441,7 @@ def fetch_ohlcv(self, symbol, timeframe='1d', limit=None, max_retries=100, base_
14421441
# :param max_retries: Maximum number of retries for API calls.
14431442
# :param base_delay: Base delay for exponential backoff.
14441443
# :param max_delay: Maximum delay for exponential backoff.
1445-
# :return: DataFrame with OHLCV data.
1444+
# :return: DataFrame with OHLCV data or an empty DataFrame on error.
14461445
# """
14471446
# retries = 0
14481447

@@ -1469,166 +1468,38 @@ def fetch_ohlcv(self, symbol, timeframe='1d', limit=None, max_retries=100, base_
14691468
# logging.info(f"Rate limit exceeded: {e}. Retrying in {delay:.2f} seconds...")
14701469
# time.sleep(delay)
14711470

1471+
# except ccxt.BadSymbol as e:
1472+
# # Handle the BadSymbol error gracefully and exit the loop
1473+
# logging.info(f"Bad symbol: {symbol}. Error: {e}")
1474+
# break # Exit the retry loop as the symbol is invalid
1475+
14721476
# except ccxt.BaseError as e:
14731477
# # Log the error message
14741478
# logging.info(f"Failed to fetch OHLCV data: {self.exchange.id} {e}")
1475-
# # Log the traceback for further debugging
14761479
# logging.error(traceback.format_exc())
1477-
# return pd.DataFrame()
1480+
# return pd.DataFrame() # Return empty DataFrame for other base errors
14781481

14791482
# except Exception as e:
14801483
# # Log the error message and traceback
14811484
# logging.info(f"Unexpected error occurred while fetching OHLCV data: {e}")
1482-
# logging.info(traceback.format_exc())
1485+
# logging.error(traceback.format_exc())
14831486

1484-
# # Attempt to handle the specific 'string indices must be integers' error
1487+
# # Handle specific error scenarios
14851488
# if isinstance(e, TypeError) and 'string indices must be integers' in str(e):
14861489
# logging.info(f"TypeError occurred: {e}")
1487-
1488-
# # Print the response for debugging
14891490
# logging.info(f"Response content: {self.exchange.last_http_response}")
14901491

14911492
# try:
1492-
# # Attempt to parse the response
14931493
# response = json.loads(self.exchange.last_http_response)
14941494
# logging.info(f"Parsed response into a dictionary: {response}")
14951495
# except json.JSONDecodeError as json_error:
14961496
# logging.info(f"Failed to parse response: {json_error}")
14971497

1498-
# return pd.DataFrame()
1498+
# return pd.DataFrame() # Return empty DataFrame on unexpected errors
14991499

15001500
# logging.error(f"Failed to fetch OHLCV data after {max_retries} retries.")
15011501
# return pd.DataFrame()
15021502

1503-
# def fetch_ohlcv(self, symbol, timeframe='1d', limit=None, max_retries=100, base_delay=10, max_delay=60):
1504-
# """
1505-
# Fetch OHLCV data for the given symbol and timeframe.
1506-
1507-
# :param symbol: Trading symbol.
1508-
# :param timeframe: Timeframe string.
1509-
# :param limit: Limit the number of returned data points.
1510-
# :param max_retries: Maximum number of retries for API calls.
1511-
# :param base_delay: Base delay for exponential backoff.
1512-
# :param max_delay: Maximum delay for exponential backoff.
1513-
# :return: DataFrame with OHLCV data.
1514-
# """
1515-
# retries = 0
1516-
1517-
# while retries < max_retries:
1518-
# try:
1519-
# with self.rate_limiter:
1520-
# # Fetch the OHLCV data from the exchange
1521-
# ohlcv = self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit) # Pass the limit parameter
1522-
1523-
# # Create a DataFrame from the OHLCV data
1524-
# df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
1525-
1526-
# # Convert the timestamp to datetime
1527-
# df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
1528-
1529-
# # Set the timestamp as the index
1530-
# df.set_index('timestamp', inplace=True)
1531-
1532-
# return df
1533-
1534-
# except ccxt.RateLimitExceeded as e:
1535-
# retries += 1
1536-
# delay = min(base_delay * (2 ** retries) + random.uniform(0, 0.1 * (2 ** retries)), max_delay)
1537-
# logging.info(f"Rate limit exceeded: {e}. Retrying in {delay:.2f} seconds...")
1538-
# time.sleep(delay)
1539-
1540-
# except ccxt.BaseError as e:
1541-
# # Log the error message
1542-
# logging.info(f"Failed to fetch OHLCV data: {self.exchange.id} {e}")
1543-
# # Log the traceback for further debugging
1544-
# logging.error(traceback.format_exc())
1545-
# return pd.DataFrame()
1546-
1547-
# except Exception as e:
1548-
# # Log the error message and traceback
1549-
# logging.info(f"Unexpected error occurred while fetching OHLCV data: {e}")
1550-
# logging.info(traceback.format_exc())
1551-
1552-
# # Attempt to handle the specific 'string indices must be integers' error
1553-
# if isinstance(e, TypeError) and 'string indices must be integers' in str(e):
1554-
# logging.info(f"TypeError occurred: {e}")
1555-
1556-
# # Print the response for debugging
1557-
# logging.info(f"Response content: {self.exchange.last_http_response}")
1558-
1559-
# try:
1560-
# # Attempt to parse the response
1561-
# response = json.loads(self.exchange.last_http_response)
1562-
# logging.info(f"Parsed response into a dictionary: {response}")
1563-
# except json.JSONDecodeError as json_error:
1564-
# logging.info(f"Failed to parse response: {json_error}")
1565-
1566-
# return pd.DataFrame()
1567-
1568-
# raise Exception(f"Failed to fetch OHLCV data after {max_retries} retries.")
1569-
1570-
# def fetch_ohlcv(self, symbol, timeframe='1d', limit=None, max_retries=100, base_delay=10, max_delay=60):
1571-
# """
1572-
# Fetch OHLCV data for the given symbol and timeframe.
1573-
1574-
# :param symbol: Trading symbol.
1575-
# :param timeframe: Timeframe string.
1576-
# :param limit: Limit the number of returned data points.
1577-
# :param max_retries: Maximum number of retries for API calls.
1578-
# :param base_delay: Base delay for exponential backoff.
1579-
# :param max_delay: Maximum delay for exponential backoff.
1580-
# :return: DataFrame with OHLCV data.
1581-
# """
1582-
# retries = 0
1583-
1584-
# while retries < max_retries:
1585-
# try:
1586-
# with self.rate_limiter:
1587-
# # Fetch the OHLCV data from the exchange
1588-
# ohlcv = self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit) # Pass the limit parameter
1589-
1590-
# # Create a DataFrame from the OHLCV data
1591-
# df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
1592-
1593-
# # Convert the timestamp to datetime
1594-
# df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
1595-
1596-
# # Set the timestamp as the index
1597-
# df.set_index('timestamp', inplace=True)
1598-
1599-
# return df
1600-
1601-
# except ccxt.RateLimitExceeded as e:
1602-
# retries += 1
1603-
# delay = min(base_delay * (2 ** retries) + random.uniform(0, 0.1 * (2 ** retries)), max_delay)
1604-
# logging.info(f"Rate limit exceeded: {e}. Retrying in {delay:.2f} seconds...")
1605-
# time.sleep(delay)
1606-
1607-
# except ccxt.BaseError as e:
1608-
# # Log the error message
1609-
# logging.info(f"Failed to fetch OHLCV data: {self.exchange.id} {e}")
1610-
# # Log the traceback for further debugging
1611-
# logging.error(traceback.format_exc())
1612-
# return pd.DataFrame()
1613-
1614-
# except Exception as e:
1615-
# # Check if the error is related to response parsing
1616-
# if 'response' in locals() and isinstance(response, str):
1617-
# logging.info(f"Response is a string: {response}")
1618-
# try:
1619-
# # Attempt to parse the response
1620-
# response = json.loads(response)
1621-
# logging.info("Parsed response into a dictionary")
1622-
# except json.JSONDecodeError as json_error:
1623-
# logging.info(f"Failed to parse response: {json_error}")
1624-
1625-
# # Log any other unexpected errors
1626-
# logging.info(f"Unexpected error occurred while fetching OHLCV data: {e}")
1627-
# logging.info(traceback.format_exc())
1628-
# return pd.DataFrame()
1629-
1630-
# raise Exception(f"Failed to fetch OHLCV data after {max_retries} retries.")
1631-
16321503
# def fetch_ohlcv(self, symbol, timeframe='1d', limit=None):
16331504
# """
16341505
# Fetch OHLCV data for the given symbol and timeframe.
@@ -1680,48 +1551,6 @@ def fetch_ohlcv(self, symbol, timeframe='1d', limit=None, max_retries=100, base_
16801551

16811552
# return pd.DataFrame()
16821553

1683-
1684-
# def fetch_ohlcv(self, symbol, timeframe='1d', limit=None):
1685-
# """
1686-
# Fetch OHLCV data for the given symbol and timeframe.
1687-
1688-
# :param symbol: Trading symbol.
1689-
# :param timeframe: Timeframe string.
1690-
# :param limit: Limit the number of returned data points.
1691-
# :return: DataFrame with OHLCV data.
1692-
# """
1693-
# try:
1694-
# # Fetch the OHLCV data from the exchange
1695-
# ohlcv = self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit) # Pass the limit parameter
1696-
1697-
# # Create a DataFrame from the OHLCV data
1698-
# df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
1699-
1700-
# # Convert the timestamp to datetime
1701-
# df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
1702-
1703-
# # Set the timestamp as the index
1704-
# df.set_index('timestamp', inplace=True)
1705-
1706-
# return df
1707-
1708-
# except ccxt.BaseError as e:
1709-
# # Log the error message
1710-
# logging.error(f"Failed to fetch OHLCV data: {self.exchange.id} {e}")
1711-
1712-
# # Log the traceback for further debugging
1713-
# logging.error(traceback.format_exc())
1714-
1715-
# # Return an empty DataFrame in case of an error
1716-
# return pd.DataFrame()
1717-
1718-
# except Exception as e:
1719-
# # Log any other unexpected errors
1720-
# logging.error(f"Unexpected error occurred while fetching OHLCV data: {e}")
1721-
# logging.error(traceback.format_exc())
1722-
1723-
# return pd.DataFrame()
1724-
17251554
def get_orderbook(self, symbol, max_retries=3, retry_delay=5) -> dict:
17261555
values = {"bids": [], "asks": []}
17271556

0 commit comments

Comments
 (0)