@@ -1256,3 +1256,162 @@ def get_data_source_file_path(self) -> Union[str, None]:
12561256 locally, otherwise None.
12571257 """
12581258 return self .data_file_path
1259+
1260+
1261+ class CCXTTickerDataProvider (DataProvider ):
1262+ """
1263+ Data provider for ticker data using the CCXT library.
1264+
1265+ Fetches real-time ticker data (bid, ask, last price, volume, etc.)
1266+ for a given symbol and market via CCXT's fetch_ticker API.
1267+
1268+ In backtest mode, ticker data is derived from OHLCV data
1269+ (handled by the DataProviderService fallback), so this provider
1270+ only serves live/non-backtest use cases.
1271+ """
1272+ data_type = DataType .TICKER
1273+ data_provider_identifier = "ccxt_ticker_data_provider"
1274+
1275+ def __init__ (
1276+ self ,
1277+ symbol : str = None ,
1278+ market : str = None ,
1279+ data_provider_identifier : str = None ,
1280+ config = None
1281+ ):
1282+ if data_provider_identifier is None :
1283+ data_provider_identifier = self .data_provider_identifier
1284+
1285+ super ().__init__ (
1286+ symbol = symbol ,
1287+ market = market ,
1288+ data_provider_identifier = data_provider_identifier ,
1289+ config = config
1290+ )
1291+
1292+ def has_data (
1293+ self ,
1294+ data_source : DataSource ,
1295+ start_date : datetime = None ,
1296+ end_date : datetime = None ,
1297+ ) -> bool :
1298+ data_type = data_source .data_type
1299+ market = data_source .market
1300+ symbol = data_source .symbol
1301+
1302+ if not DataType .TICKER .equals (data_type ):
1303+ return False
1304+
1305+ if market is None :
1306+ market = "binance"
1307+
1308+ try :
1309+ market = market .lower ()
1310+ exchange_class = getattr (ccxt , market )
1311+ exchange = exchange_class ()
1312+ symbols = list (exchange .load_markets ().keys ())
1313+ return symbol in symbols
1314+ except ccxt .NetworkError :
1315+ return False
1316+ except Exception as e :
1317+ logger .error (e )
1318+ return False
1319+
1320+ def prepare_backtest_data (
1321+ self ,
1322+ backtest_start_date ,
1323+ backtest_end_date ,
1324+ fill_missing_data : bool = False ,
1325+ show_progress : bool = False ,
1326+ ) -> None :
1327+ # Ticker backtest data is derived from OHLCV by the
1328+ # DataProviderService fallback — nothing to prepare here.
1329+ pass
1330+
1331+ def get_backtest_data (
1332+ self ,
1333+ backtest_index_date : datetime ,
1334+ backtest_start_date : datetime = None ,
1335+ backtest_end_date : datetime = None ,
1336+ data_source : DataSource = None ,
1337+ ):
1338+ # Backtest ticker data is handled by DataProviderService
1339+ # falling back to OHLCV data.
1340+ return None
1341+
1342+ def get_data (
1343+ self ,
1344+ date : datetime = None ,
1345+ start_date : datetime = None ,
1346+ end_date : datetime = None ,
1347+ save : bool = False ,
1348+ ) -> dict :
1349+ if self .market is None :
1350+ raise OperationalException (
1351+ "Market is not set. Please set the market "
1352+ "before calling get_data."
1353+ )
1354+
1355+ if self .symbol is None :
1356+ raise OperationalException (
1357+ "Symbol is not set. Please set the symbol "
1358+ "before calling get_data."
1359+ )
1360+
1361+ market_credential = self .get_credential (self .market )
1362+ exchange = CCXTOHLCVDataProvider .initialize_exchange (
1363+ self .market , market_credential
1364+ )
1365+ ticker = exchange .fetch_ticker (self .symbol )
1366+
1367+ return {
1368+ "symbol" : self .symbol ,
1369+ "market" : self .market ,
1370+ "datetime" : ticker .get ("datetime" ),
1371+ "high" : ticker .get ("high" ),
1372+ "low" : ticker .get ("low" ),
1373+ "bid" : ticker .get ("bid" ),
1374+ "ask" : ticker .get ("ask" ),
1375+ "open" : ticker .get ("open" ),
1376+ "close" : ticker .get ("close" ),
1377+ "last" : ticker .get ("last" ),
1378+ "volume" : ticker .get ("baseVolume" ),
1379+ }
1380+
1381+ def copy (self , data_source : DataSource ) -> "CCXTTickerDataProvider" :
1382+ if data_source .market is None or data_source .market == "" :
1383+ raise OperationalException (
1384+ "DataSource has no `market` attribute specified. "
1385+ "Please specify the market attribute in the data source "
1386+ "specification before using the CCXT ticker data provider."
1387+ )
1388+
1389+ if data_source .symbol is None or data_source .symbol == "" :
1390+ raise OperationalException (
1391+ "DataSource has no `symbol` attribute specified. "
1392+ "Please specify the symbol attribute in the data source "
1393+ "specification before using the CCXT ticker data provider."
1394+ )
1395+
1396+ return CCXTTickerDataProvider (
1397+ symbol = data_source .symbol ,
1398+ market = data_source .market ,
1399+ data_provider_identifier = data_source .data_provider_identifier ,
1400+ config = self .config ,
1401+ )
1402+
1403+ def get_number_of_data_points (
1404+ self , start_date : datetime , end_date : datetime
1405+ ) -> int :
1406+ # Ticker data is a single point-in-time snapshot
1407+ return 1
1408+
1409+ def get_missing_data_dates (
1410+ self , start_date : datetime , end_date : datetime
1411+ ) -> list :
1412+ # No stored data to have gaps in
1413+ return []
1414+
1415+ def get_data_source_file_path (self ):
1416+ # Ticker data is not file-based
1417+ return None
0 commit comments