""" 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", ]