083a4e8d63
One class per provider (TwelveData, Oanda, Tiingo), all subclassing BaseDataProvider which owns cache, validation/cleaning, freshness + boundary guarantees, fetch_range pagination, and streaming stubs — subclasses implement only _fetch_raw. config.json data_providers.active selects the live feed; data_provider.py / oanda_provider.py stay as back-compat shims. Module 16 provider-abstraction tests (253 total green). Claude-Session: https://claude.ai/code/session_01Mc7XKYyPySVXiUpcN82QEK
55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
"""
|
|
ForexBot2 — Data-provider package
|
|
==================================
|
|
One class per provider, all subclassing `BaseDataProvider` (which owns
|
|
caching, validation, boundary guarantees, and range pagination — the
|
|
behavior the signal pipeline depends on).
|
|
|
|
Adding a provider = one module implementing `_fetch_raw` + one registry
|
|
entry + one config.json `data_providers` block. The live feed is selected
|
|
by config.json `data_providers.active`; registration alone changes
|
|
nothing.
|
|
"""
|
|
|
|
from typing import Dict
|
|
|
|
from app_config import AppConfigError, get_app_config
|
|
from config import PlatformConfig
|
|
|
|
from providers.base import BaseDataProvider, DataIntegrityError, _is_forex_weekend
|
|
from providers.twelve_data import TwelveDataProvider
|
|
from providers.oanda import OandaDataError, OandaDataProvider
|
|
from providers.tiingo import TiingoDataError, TiingoDataProvider
|
|
|
|
#: config.json data_providers.active selects from here.
|
|
PROVIDER_REGISTRY: Dict[str, type] = {
|
|
"twelve_data": TwelveDataProvider,
|
|
"oanda": OandaDataProvider,
|
|
"tiingo": TiingoDataProvider,
|
|
}
|
|
|
|
|
|
def make_data_provider(config: PlatformConfig) -> BaseDataProvider:
|
|
"""Build the ACTIVE data provider (config.json: data_providers.active)."""
|
|
name = get_app_config().active_provider
|
|
cls = PROVIDER_REGISTRY.get(name)
|
|
if cls is None:
|
|
raise AppConfigError(
|
|
f'Unknown data provider "{name}"; '
|
|
f"registered: {sorted(PROVIDER_REGISTRY)}")
|
|
return cls(config)
|
|
|
|
|
|
__all__ = [
|
|
"BaseDataProvider",
|
|
"DataIntegrityError",
|
|
"OandaDataError",
|
|
"OandaDataProvider",
|
|
"TiingoDataError",
|
|
"TiingoDataProvider",
|
|
"TwelveDataProvider",
|
|
"PROVIDER_REGISTRY",
|
|
"make_data_provider",
|
|
"_is_forex_weekend",
|
|
]
|