Files
upo-app-agents/src/app/markets/cryptocompare.py
Giacomo Bertolazzi 517842c834 Refactor and update structure (#20)
* Aggiorna gli agenti e il modello del team per utilizzare OLLAMA_QWEN_1B

* Riorganizza e rinomina funzioni di estrazione in moduli di mercato e notizie; migliora la gestione delle importazioni

* Spostato main nel corretto file __main__ e aggiornato il README.md

* Aggiunta cartella per i modelli, agenti e team

* Aggiornata la posizione delle istruzioni

* Rimossi TODO e Aggiunto documentazione per metodi aggregated

* Aggiornate le istruzioni del coordinatore del team

* utils type checks

* Rinominato BaseWrapper in MarketWrapper e fix type check markets

* fix type checks di notizie e social.

* Aggiunti type hints finali

* Riorganizzati gli import

* Refactoring architetturale e spostamento classi base

- Eliminazione del file __init__.py obsoleto che importava ChatManager e Pipeline
- Spostamento della classe Pipeline in agents/pipeline.py
- Spostamento della classe ChatManager in utils/chat_manager.py
- Aggiornamento di __main__.py per importare da app.utils e app.agents, e modifica della logica per utilizzare Pipeline invece di chat per la selezione di provider e stile
- Creazione della cartella base con classi base comuni: markets.py (ProductInfo, Price, MarketWrapper), news.py (Article, NewsWrapper), social.py (SocialPost, SocialComment, SocialWrapper)
- Aggiornamento di tutti gli import nel progetto (markets/, news/, social/, utils/, tests/) per utilizzare la nuova struttura base/

* Aggiornato Readme

* Corretto il valore predefinito della valuta in BinanceWrapper da "USDT" a "USD"

* fix type in tests

* fix type per models

* Rinominato 'quote_currency' in 'currency' e aggiornato il trattamento del timestamp in Price

* fix errors found by Copilot

* WrapperHandler: semplificata la logica di chiamata delle funzioni sui wrapper

* fix docs

* fix demos, semplificata logica lista ollama
2025-10-08 16:21:09 +02:00

82 lines
3.1 KiB
Python

import os
from typing import Any
import requests
from app.base.markets import ProductInfo, MarketWrapper, Price
def extract_product(asset_data: dict[str, Any]) -> ProductInfo:
product = ProductInfo()
product.id = asset_data.get('FROMSYMBOL', '') + '-' + asset_data.get('TOSYMBOL', '')
product.symbol = asset_data.get('FROMSYMBOL', '')
product.price = float(asset_data.get('PRICE', 0))
product.volume_24h = float(asset_data.get('VOLUME24HOUR', 0))
assert product.price > 0, "Invalid price data received from CryptoCompare"
return product
def extract_price(price_data: dict[str, Any]) -> Price:
timestamp = price_data.get('time', 0)
price = Price()
price.high = float(price_data.get('high', 0))
price.low = float(price_data.get('low', 0))
price.open = float(price_data.get('open', 0))
price.close = float(price_data.get('close', 0))
price.volume = float(price_data.get('volumeto', 0))
price.set_timestamp(timestamp_s=timestamp)
return price
BASE_URL = "https://min-api.cryptocompare.com"
class CryptoCompareWrapper(MarketWrapper):
"""
Wrapper per le API pubbliche di CryptoCompare.
La documentazione delle API è disponibile qui: https://developers.coindesk.com/documentation/legacy/Price/SingleSymbolPriceEndpoint
!!ATTENZIONE!! sembra essere una API legacy e potrebbe essere deprecata in futuro.
"""
def __init__(self, currency:str='USD'):
api_key = os.getenv("CRYPTOCOMPARE_API_KEY")
assert api_key, "CRYPTOCOMPARE_API_KEY environment variable not set"
self.api_key = api_key
self.currency = currency
def __request(self, endpoint: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
if params is None:
params = {}
params['api_key'] = self.api_key
response = requests.get(f"{BASE_URL}{endpoint}", params=params)
return response.json()
def get_product(self, asset_id: str) -> ProductInfo:
response = self.__request("/data/pricemultifull", params = {
"fsyms": asset_id,
"tsyms": self.currency
})
data = response.get('RAW', {}).get(asset_id, {}).get(self.currency, {})
return extract_product(data)
def get_products(self, asset_ids: list[str]) -> list[ProductInfo]:
response = self.__request("/data/pricemultifull", params = {
"fsyms": ",".join(asset_ids),
"tsyms": self.currency
})
assets: list[ProductInfo] = []
data = response.get('RAW', {})
for asset_id in asset_ids:
asset_data = data.get(asset_id, {}).get(self.currency, {})
assets.append(extract_product(asset_data))
return assets
def get_historical_prices(self, asset_id: str, limit: int = 100) -> list[Price]:
response = self.__request("/data/v2/histohour", params = {
"fsym": asset_id,
"tsym": self.currency,
"limit": limit-1 # because the API returns limit+1 items (limit + current)
})
data = response.get('Data', {}).get('Data', [])
prices = [extract_price(price_data) for price_data in data]
return prices