9 enhancement con financialdatasettool e yfinance #11

Merged
Berack96 merged 26 commits from 9-enhancement-con-financialdatasettool-e-yfinance into main 2025-10-01 16:19:21 +02:00
8 changed files with 48 additions and 37 deletions
Showing only changes of commit e284006a6d - Show all commits

View File

@@ -20,9 +20,8 @@ COINBASE_API_SECRET=
# https://www.cryptocompare.com/cryptopian/api-keys # https://www.cryptocompare.com/cryptopian/api-keys
CRYPTOCOMPARE_API_KEY= CRYPTOCOMPARE_API_KEY=
# Binance API per Market Agent # https://www.binance.com/en/my/settings/api-management
# Ottenibili da: https://www.binance.com/en/my/settings/api-management # Non necessario per operazioni in sola lettura
# Supporta sia API autenticate che pubbliche (PublicBinance)
BINANCE_API_KEY= BINANCE_API_KEY=
BINANCE_API_SECRET= BINANCE_API_SECRET=

View File

@@ -30,8 +30,7 @@ from dotenv import load_dotenv
from app.markets import ( from app.markets import (
CoinBaseWrapper, CoinBaseWrapper,
CryptoCompareWrapper, CryptoCompareWrapper,
BinanceWrapper, BinanceWrapper,
PublicBinanceAgent,
YFinanceWrapper, YFinanceWrapper,
BaseWrapper BaseWrapper
) )
@@ -241,13 +240,6 @@ def initialize_providers() -> Dict[str, BaseWrapper]:
providers = {} providers = {}
env_vars = check_environment_variables() env_vars = check_environment_variables()
# PublicBinanceAgent (sempre disponibile)
try:
providers["PublicBinance"] = PublicBinanceAgent()
print("✅ PublicBinanceAgent inizializzato con successo")
except Exception as e:
print(f"❌ Errore nell'inizializzazione di PublicBinanceAgent: {e}")
# CryptoCompareWrapper # CryptoCompareWrapper
if env_vars["CRYPTOCOMPARE_API_KEY"]: if env_vars["CRYPTOCOMPARE_API_KEY"]:
try: try:
@@ -269,14 +261,11 @@ def initialize_providers() -> Dict[str, BaseWrapper]:
print("⚠️ CoinBaseWrapper saltato: credenziali Coinbase non complete") print("⚠️ CoinBaseWrapper saltato: credenziali Coinbase non complete")
# BinanceWrapper # BinanceWrapper
if env_vars["BINANCE_API_KEY"] and env_vars["BINANCE_API_SECRET"]: try:
try: providers["Binance"] = BinanceWrapper()
providers["Binance"] = BinanceWrapper() print("✅ BinanceWrapper inizializzato con successo")
print("✅ BinanceWrapper inizializzato con successo") except Exception as e:
except Exception as e: print(f"❌ Errore nell'inizializzazione di BinanceWrapper: {e}")
print(f"❌ Errore nell'inizializzazione di BinanceWrapper: {e}")
else:
print("⚠️ BinanceWrapper saltato: credenziali Binance non complete")
# YFinanceWrapper (sempre disponibile - dati azionari e crypto gratuiti) # YFinanceWrapper (sempre disponibile - dati azionari e crypto gratuiti)
try: try:
@@ -284,7 +273,6 @@ def initialize_providers() -> Dict[str, BaseWrapper]:
print("✅ YFinanceWrapper inizializzato con successo") print("✅ YFinanceWrapper inizializzato con successo")
except Exception as e: except Exception as e:
print(f"❌ Errore nell'inizializzazione di YFinanceWrapper: {e}") print(f"❌ Errore nell'inizializzazione di YFinanceWrapper: {e}")
return providers return providers
def print_summary(results: List[Dict[str, Any]]): def print_summary(results: List[Dict[str, Any]]):

View File

@@ -3,16 +3,47 @@ from pydantic import BaseModel
class BaseWrapper: class BaseWrapper:
""" """
Interfaccia per i wrapper delle API di mercato. Base class for market API wrappers.
Implementa i metodi di base che ogni wrapper deve avere. All market API wrappers should inherit from this class and implement the methods.
""" """
def get_product(self, asset_id: str) -> 'ProductInfo': def get_product(self, asset_id: str) -> 'ProductInfo':
"""
Get product information for a specific asset ID.
Args:
asset_id (str): The asset ID to retrieve information for.
Returns:
ProductInfo: An object containing product information.
"""
raise NotImplementedError raise NotImplementedError
def get_products(self, asset_ids: list[str]) -> list['ProductInfo']: def get_products(self, asset_ids: list[str]) -> list['ProductInfo']:
"""
Get product information for multiple asset IDs.
Args:
asset_ids (list[str]): The list of asset IDs to retrieve information for.
Returns:
list[ProductInfo]: A list of objects containing product information.
"""
raise NotImplementedError raise NotImplementedError
def get_all_products(self) -> list['ProductInfo']: def get_all_products(self) -> list['ProductInfo']:
"""
Get product information for all available assets.
Returns:
list[ProductInfo]: A list of objects containing product information.
"""
raise NotImplementedError raise NotImplementedError
def get_historical_prices(self, asset_id: str = "BTC", limit: int = 100) -> list['Price']: def get_historical_prices(self, asset_id: str = "BTC", limit: int = 100) -> list['Price']:
"""
Get historical price data for a specific asset ID.
Args:
asset_id (str): The asset ID to retrieve price data for.
limit (int): The maximum number of price data points to return.
Returns:
list[Price]: A list of Price objects.
"""
raise NotImplementedError raise NotImplementedError
class ProductInfo(BaseModel): class ProductInfo(BaseModel):

View File

@@ -23,10 +23,7 @@ class BinanceWrapper(BaseWrapper):
def __init__(self, currency: str = "USDT"): def __init__(self, currency: str = "USDT"):
api_key = os.getenv("BINANCE_API_KEY") api_key = os.getenv("BINANCE_API_KEY")
assert api_key is None, "API key is required"
api_secret = os.getenv("BINANCE_API_SECRET") api_secret = os.getenv("BINANCE_API_SECRET")
assert api_secret is None, "API secret is required"
self.currency = currency self.currency = currency
self.client = Client(api_key=api_key, api_secret=api_secret) self.client = Client(api_key=api_key, api_secret=api_secret)

View File

@@ -23,6 +23,8 @@ def pytest_configure(config:pytest.Config):
("social", "marks tests that use social media"), ("social", "marks tests that use social media"),
("limited", "marks tests that have limited execution due to API constraints"), ("limited", "marks tests that have limited execution due to API constraints"),
("wrapper", "marks tests for wrapper handler"), ("wrapper", "marks tests for wrapper handler"),
("tools", "marks tests for tools"),
("aggregator", "marks tests for market data aggregator"),
] ]
for marker in markers: for marker in markers:
line = f"{marker[0]}: {marker[1]}" line = f"{marker[0]}: {marker[1]}"

View File

@@ -4,6 +4,8 @@ from app.agents.market_agent import MarketToolkit
from app.markets import MarketAPIsTool from app.markets import MarketAPIsTool
@pytest.mark.limited # usa molte api calls e non voglio esaurire le chiavi api @pytest.mark.limited # usa molte api calls e non voglio esaurire le chiavi api
@pytest.mark.tools
@pytest.mark.api
class TestMarketAPIsTool: class TestMarketAPIsTool:
def test_wrapper_initialization(self): def test_wrapper_initialization(self):
market_wrapper = MarketAPIsTool("USD") market_wrapper = MarketAPIsTool("USD")

View File

@@ -1,10 +1,12 @@
import pytest import pytest
from app.utils.market_data_aggregator import MarketDataAggregator from app.utils.market_data_aggregator import MarketDataAggregator
from app.utils.aggregated_models import AggregatedProductInfo from app.utils.aggregated_models import AggregatedProductInfo
from app.markets.base import ProductInfo, Price from app.markets.base import ProductInfo, Price
@pytest.mark.aggregator @pytest.mark.aggregator
@pytest.mark.limited
@pytest.mark.market
@pytest.mark.api
class TestMarketDataAggregator: class TestMarketDataAggregator:
def test_initialization(self): def test_initialization(self):
@@ -84,7 +86,3 @@ class TestMarketDataAggregator:
assert len(aggregated._metadata.sources_used) > 0 assert len(aggregated._metadata.sources_used) > 0
assert aggregated._metadata.aggregation_timestamp != "" assert aggregated._metadata.aggregation_timestamp != ""
# La confidence può essere 0.0 se ci sono fonti "unknown" # La confidence può essere 0.0 se ci sono fonti "unknown"
if __name__ == "__main__":
pytest.main([__file__])

6
uv.lock generated
View File

@@ -867,12 +867,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" }, { url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" },
] ]
[[package]]
name = "multitasking"
version = "0.0.12"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/17/0d/74f0293dfd7dcc3837746d0138cbedd60b31701ecc75caec7d3f281feba0/multitasking-0.0.12.tar.gz", hash = "sha256:2fba2fa8ed8c4b85e227c5dd7dc41c7d658de3b6f247927316175a57349b84d1", size = 19984, upload-time = "2025-07-20T21:27:51.636Z" }
[[package]] [[package]]
name = "newsapi-python" name = "newsapi-python"
version = "0.2.7" version = "0.2.7"