Source code for src.bcra_connector.estadisticas_cambiarias.estadisticas_cambiarias

"""
Data models for the BCRA Currency Exchange Statistics API.
Provides classes for currency quotations, historical data, and response handling.
"""

from dataclasses import dataclass
from datetime import date
from typing import TYPE_CHECKING, Any, Dict, List, Optional

if TYPE_CHECKING:
    import pandas as pd


[docs] @dataclass class Divisa: """ Represents a currency. :param codigo: The currency code (ISO) :param denominacion: The currency name """ codigo: str denominacion: str def __post_init__(self) -> None: """Validate instance after initialization.""" if not self.codigo.strip(): raise ValueError("Currency code cannot be empty") if not self.denominacion.strip(): raise ValueError("Currency name cannot be empty")
[docs] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "Divisa": """Create a Divisa instance from a dictionary.""" return cls(codigo=data["codigo"], denominacion=data["denominacion"])
[docs] @dataclass class CotizacionDetalle: """ Represents details of a currency quotation. :param codigo_moneda: The currency code :param descripcion: The currency description :param tipo_pase: The exchange rate :param tipo_cotizacion: The quotation type """ codigo_moneda: str descripcion: str tipo_pase: float tipo_cotizacion: float
[docs] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "CotizacionDetalle": """Create a CotizacionDetalle instance from a dictionary.""" return cls( codigo_moneda=data["codigoMoneda"], descripcion=data["descripcion"], tipo_pase=float(data["tipoPase"]), tipo_cotizacion=float(data["tipoCotizacion"]), )
[docs] @dataclass class CotizacionFecha: """ Represents currency quotations for a specific date. :param fecha: The date of the quotations :param detalle: List of quotation details """ fecha: Optional[date] detalle: List[CotizacionDetalle]
[docs] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "CotizacionFecha": """Create a CotizacionFecha instance from a dictionary.""" return cls( fecha=date.fromisoformat(data["fecha"]) if data["fecha"] else None, detalle=[CotizacionDetalle.from_dict(d) for d in data["detalle"]], )
[docs] def to_dict(self) -> Dict[str, Any]: """Convert the CotizacionFecha instance to a dictionary.""" return { "fecha": self.fecha.isoformat() if self.fecha else None, "detalle": [ { "codigoMoneda": d.codigo_moneda, "descripcion": d.descripcion, "tipoPase": d.tipo_pase, "tipoCotizacion": d.tipo_cotizacion, } for d in self.detalle ], }
[docs] def to_dataframe(self) -> "pd.DataFrame": """ Convert the CotizacionFecha instance to a pandas DataFrame. Returns a DataFrame with exchange rate information for each currency. Columns: fecha, codigoMoneda, descripcion, tipoPase, tipoCotizacion. Requires pandas: ``pip install bcra-connector[pandas]`` :return: DataFrame with exchange rate data. :raises ImportError: If pandas is not installed. """ try: import pandas as pd except ImportError: raise ImportError( "pandas is required for to_dataframe(). " "Install with: pip install bcra-connector[pandas]" ) rows = [ { "fecha": self.fecha, "codigoMoneda": d.codigo_moneda, "descripcion": d.descripcion, "tipoPase": d.tipo_pase, "tipoCotizacion": d.tipo_cotizacion, } for d in self.detalle ] return pd.DataFrame(rows)
[docs] @dataclass class Resultset: """ Represents metadata about the result set. :param count: The number of results :param offset: The offset of the results :param limit: The limit of the results """ count: int offset: int limit: int
[docs] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "Resultset": """Create a Resultset instance from a dictionary.""" return cls(count=data["count"], offset=data["offset"], limit=data["limit"])
[docs] @dataclass class Metadata: """ Represents metadata about the response. :param resultset: The resultset metadata """ resultset: Resultset
[docs] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "Metadata": """Create a Metadata instance from a dictionary.""" return cls(resultset=Resultset.from_dict(data["resultset"]))
[docs] @dataclass class DivisaResponse: """ Represents the response for the Divisas endpoint. :param status: The HTTP status code :param results: List of Divisa objects """ status: int results: List[Divisa]
[docs] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "DivisaResponse": """Create a DivisaResponse instance from a dictionary.""" return cls( status=data["status"], results=[Divisa.from_dict(d) for d in data["results"]], )
[docs] @dataclass class CotizacionResponse: """ Represents the response for the Cotizaciones endpoint. :param status: The HTTP status code :param results: CotizacionFecha object """ status: int results: CotizacionFecha
[docs] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "CotizacionResponse": """Create a CotizacionResponse instance from a dictionary.""" return cls( status=data["status"], results=CotizacionFecha.from_dict(data["results"]) )
[docs] @dataclass class CotizacionesResponse: """ Represents the response for the Cotizaciones/{codMoneda} endpoint. :param status: The HTTP status code :param metadata: Metadata about the response :param results: List of CotizacionFecha objects """ status: int metadata: Metadata results: List[CotizacionFecha]
[docs] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "CotizacionesResponse": """Create a CotizacionesResponse instance from a dictionary.""" return cls( status=data["status"], metadata=Metadata.from_dict(data["metadata"]), results=[CotizacionFecha.from_dict(d) for d in data["results"]], )
[docs] @dataclass class ErrorResponse: """ Represents an error response from the API. :param status: The HTTP status code :param error_messages: List of error messages """ status: int error_messages: List[str]
[docs] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "ErrorResponse": """Create an ErrorResponse instance from a dictionary.""" return cls(status=data["status"], error_messages=data["errorMessages"])