Source code for ccxt_pandas.wrappers.ccxt_pandas_multi_exchange

from collections.abc import Callable
from dataclasses import dataclass
from typing import Literal

import ccxt
import pandas as pd

from ccxt_pandas.utils.pandas_utils import append_non_empty, concat_results
from ccxt_pandas.wrappers.ccxt_pandas_exchange import CCXTPandasExchange


[docs] @dataclass class CCXTPandasMultiExchange: """ Manages multiple cryptocurrency exchanges and aggregates method call results into unified DataFrames. Attributes: exchange_names (tuple): Exchange identifiers to initialize. exchanges (dict[str, CCXTPandasExchange]): Exchange ID → client mapping. errors (str): Error handling mode: "raise", "warn", or "ignore". """ exchange_names: tuple = () exchanges: dict[str, CCXTPandasExchange] | None = None errors: Literal["ignore", "raise", "warn"] = "raise" def __post_init__(self): if self.exchanges is None: self.exchanges = {} for exchange_id in self.exchange_names: exchange_class = getattr(ccxt, exchange_id) exchange = exchange_class() self.exchanges[exchange_id] = CCXTPandasExchange( exchange=exchange, exchange_name=exchange_id, errors=self.errors ) def __getattr__(self, method_name) -> Callable[..., pd.DataFrame]: def wrapper_function(*args, **kwargs) -> pd.DataFrame: results = [] for name, exchange in self.exchanges.items(): method = getattr(exchange, method_name) data = method(*args, **kwargs) results = append_non_empty(results=results, data=data) return concat_results(results=results) return wrapper_function