@@ -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