Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion investing_algorithm_framework/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
SnapshotInterval, AWS_S3_STATE_BUCKET_NAME, BacktestEvaluationFocus, \
save_backtests_to_directory, BacktestMetrics, DATA_DIRECTORY
from .infrastructure import AzureBlobStorageStateHandler, \
CSVOHLCVDataProvider, CCXTOHLCVDataProvider, PandasOHLCVDataProvider, \
CSVOHLCVDataProvider, CCXTOHLCVDataProvider, CCXTTickerDataProvider, \
PandasOHLCVDataProvider, \
AWSS3StorageStateHandler
from .create_app import create_app
from .download_data import download, download_v2, DownloadResult, \
Expand Down Expand Up @@ -110,6 +111,7 @@
'DataType',
'CSVOHLCVDataProvider',
"CCXTOHLCVDataProvider",
"CCXTTickerDataProvider",
"DataProvider",
"get_annual_volatility",
"get_sortino_ratio",
Expand Down
3 changes: 2 additions & 1 deletion investing_algorithm_framework/infrastructure/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
BacktestService
from .data_providers import CSVOHLCVDataProvider, get_default_data_providers, \
get_default_ohlcv_data_providers, CCXTOHLCVDataProvider, \
PandasOHLCVDataProvider
CCXTTickerDataProvider, PandasOHLCVDataProvider
from .order_executors import CCXTOrderExecutor, BacktestOrderExecutor
from .portfolio_providers import CCXTPortfolioProvider

Expand Down Expand Up @@ -46,6 +46,7 @@
"get_default_ohlcv_data_providers",
"AWSS3StorageStateHandler",
"CCXTOHLCVDataProvider",
"CCXTTickerDataProvider",
"BacktestOrderExecutor",
"PandasOHLCVDataProvider",
"BacktestService",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .ccxt import CCXTOHLCVDataProvider
from .ccxt import CCXTOHLCVDataProvider, CCXTTickerDataProvider
from .csv import CSVOHLCVDataProvider
from .pandas import PandasOHLCVDataProvider

Expand All @@ -12,6 +12,7 @@ def get_default_data_providers():
"""
return [
CCXTOHLCVDataProvider(),
CCXTTickerDataProvider(),
]


Expand All @@ -30,6 +31,7 @@ def get_default_ohlcv_data_providers():
__all__ = [
'CSVOHLCVDataProvider',
'CCXTOHLCVDataProvider',
'CCXTTickerDataProvider',
'get_default_data_providers',
'get_default_ohlcv_data_providers',
'PandasOHLCVDataProvider',
Expand Down
159 changes: 159 additions & 0 deletions investing_algorithm_framework/infrastructure/data_providers/ccxt.py
Original file line number Diff line number Diff line change
Expand Up @@ -1256,3 +1256,162 @@ def get_data_source_file_path(self) -> Union[str, None]:
locally, otherwise None.
"""
return self.data_file_path


class CCXTTickerDataProvider(DataProvider):
"""
Data provider for ticker data using the CCXT library.

Fetches real-time ticker data (bid, ask, last price, volume, etc.)
for a given symbol and market via CCXT's fetch_ticker API.

In backtest mode, ticker data is derived from OHLCV data
(handled by the DataProviderService fallback), so this provider
only serves live/non-backtest use cases.
"""
data_type = DataType.TICKER
data_provider_identifier = "ccxt_ticker_data_provider"

def __init__(
self,
symbol: str = None,
market: str = None,
data_provider_identifier: str = None,
config=None
):
if data_provider_identifier is None:
data_provider_identifier = self.data_provider_identifier

super().__init__(
symbol=symbol,
market=market,
data_provider_identifier=data_provider_identifier,
config=config
)

def has_data(
self,
data_source: DataSource,
start_date: datetime = None,
end_date: datetime = None,
) -> bool:
data_type = data_source.data_type
market = data_source.market
symbol = data_source.symbol

if not DataType.TICKER.equals(data_type):
return False

if market is None:
market = "binance"

try:
market = market.lower()
exchange_class = getattr(ccxt, market)
exchange = exchange_class()
symbols = list(exchange.load_markets().keys())
return symbol in symbols
except ccxt.NetworkError:
return False
except Exception as e:
logger.error(e)
return False

def prepare_backtest_data(
self,
backtest_start_date,
backtest_end_date,
fill_missing_data: bool = False,
show_progress: bool = False,
) -> None:
# Ticker backtest data is derived from OHLCV by the
# DataProviderService fallback — nothing to prepare here.
pass

def get_backtest_data(
self,
backtest_index_date: datetime,
backtest_start_date: datetime = None,
backtest_end_date: datetime = None,
data_source: DataSource = None,
):
# Backtest ticker data is handled by DataProviderService
# falling back to OHLCV data.
return None

def get_data(
self,
date: datetime = None,
start_date: datetime = None,
end_date: datetime = None,
save: bool = False,
) -> dict:
if self.market is None:
raise OperationalException(
"Market is not set. Please set the market "
"before calling get_data."
)

if self.symbol is None:
raise OperationalException(
"Symbol is not set. Please set the symbol "
"before calling get_data."
)

market_credential = self.get_credential(self.market)
exchange = CCXTOHLCVDataProvider.initialize_exchange(
self.market, market_credential
)
ticker = exchange.fetch_ticker(self.symbol)

return {
"symbol": self.symbol,
"market": self.market,
"datetime": ticker.get("datetime"),
"high": ticker.get("high"),
"low": ticker.get("low"),
"bid": ticker.get("bid"),
"ask": ticker.get("ask"),
"open": ticker.get("open"),
"close": ticker.get("close"),
"last": ticker.get("last"),
"volume": ticker.get("baseVolume"),
}

def copy(self, data_source: DataSource) -> "CCXTTickerDataProvider":
if data_source.market is None or data_source.market == "":
raise OperationalException(
"DataSource has no `market` attribute specified. "
"Please specify the market attribute in the data source "
"specification before using the CCXT ticker data provider."
)

if data_source.symbol is None or data_source.symbol == "":
raise OperationalException(
"DataSource has no `symbol` attribute specified. "
"Please specify the symbol attribute in the data source "
"specification before using the CCXT ticker data provider."
)

return CCXTTickerDataProvider(
symbol=data_source.symbol,
market=data_source.market,
data_provider_identifier=data_source.data_provider_identifier,
config=self.config,
)

def get_number_of_data_points(
self, start_date: datetime, end_date: datetime
) -> int:
# Ticker data is a single point-in-time snapshot
return 1

def get_missing_data_dates(
self, start_date: datetime, end_date: datetime
) -> list:
# No stored data to have gaps in
return []

def get_data_source_file_path(self):
# Ticker data is not file-based
return None
Loading
Loading