lavori in corso: agginto campo provider a productinfo. Inseguire le istanze e mettere il campo provider come init quano si istanzia
This commit is contained in:
@@ -13,21 +13,28 @@ class ProductInfo(BaseModel):
|
|||||||
price: float = 0.0
|
price: float = 0.0
|
||||||
volume_24h: float = 0.0
|
volume_24h: float = 0.0
|
||||||
currency: str = ""
|
currency: str = ""
|
||||||
|
provider: str = ""
|
||||||
|
|
||||||
|
def init(self, provider:str):
|
||||||
|
self.provider = provider
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def aggregate(products: dict[str, list['ProductInfo']]) -> list['ProductInfo']:
|
def aggregate(products: dict[str, list['ProductInfo']]) -> list['ProductInfo']:
|
||||||
"""
|
"""
|
||||||
Aggregates a list of ProductInfo by symbol.
|
Aggregates a list of ProductInfo by symbol across different providers.
|
||||||
Args:
|
Args:
|
||||||
products (dict[str, list[ProductInfo]]): Map provider -> list of ProductInfo
|
products (dict[str, list[ProductInfo]]): Map provider -> list of ProductInfo
|
||||||
Returns:
|
Returns:
|
||||||
list[ProductInfo]: List of ProductInfo aggregated by symbol
|
list[ProductInfo]: List of ProductInfo aggregated by symbol, combining data from all providers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Costruzione mappa symbol -> lista di ProductInfo
|
# Costruzione mappa symbol -> lista di ProductInfo (da tutti i provider)
|
||||||
symbols_infos: dict[str, list[ProductInfo]] = {}
|
symbols_infos: dict[str, list[ProductInfo]] = {}
|
||||||
for _, product_list in products.items():
|
for provider_name, product_list in products.items():
|
||||||
for product in product_list:
|
for product in product_list:
|
||||||
|
# Assicuriamo che il provider sia impostato
|
||||||
|
if not product.provider:
|
||||||
|
product.provider = provider_name
|
||||||
symbols_infos.setdefault(product.symbol, []).append(product)
|
symbols_infos.setdefault(product.symbol, []).append(product)
|
||||||
|
|
||||||
# Aggregazione per ogni symbol
|
# Aggregazione per ogni symbol
|
||||||
@@ -37,13 +44,24 @@ class ProductInfo(BaseModel):
|
|||||||
|
|
||||||
product.id = f"{symbol}_AGGREGATED"
|
product.id = f"{symbol}_AGGREGATED"
|
||||||
product.symbol = symbol
|
product.symbol = symbol
|
||||||
product.currency = next(p.currency for p in product_list if p.currency)
|
product.currency = next((p.currency for p in product_list if p.currency), "")
|
||||||
|
|
||||||
|
# Raccogliamo i provider che hanno fornito dati
|
||||||
|
providers = [p.provider for p in product_list if p.provider]
|
||||||
|
product.provider = ", ".join(set(providers)) if providers else "AGGREGATED"
|
||||||
|
|
||||||
volume_sum = sum(p.volume_24h for p in product_list)
|
# Calcolo del volume medio
|
||||||
|
volume_sum = sum(p.volume_24h for p in product_list if p.volume_24h > 0)
|
||||||
product.volume_24h = volume_sum / len(product_list) if product_list else 0.0
|
product.volume_24h = volume_sum / len(product_list) if product_list else 0.0
|
||||||
|
|
||||||
prices = sum(p.price * p.volume_24h for p in product_list)
|
# Calcolo del prezzo pesato per volume (VWAP - Volume Weighted Average Price)
|
||||||
product.price = (prices / volume_sum) if volume_sum > 0 else 0.0
|
if volume_sum > 0:
|
||||||
|
prices_weighted = sum(p.price * p.volume_24h for p in product_list if p.volume_24h > 0)
|
||||||
|
product.price = prices_weighted / volume_sum
|
||||||
|
else:
|
||||||
|
# Se non c'è volume, facciamo una media semplice dei prezzi
|
||||||
|
valid_prices = [p.price for p in product_list if p.price > 0]
|
||||||
|
product.price = sum(valid_prices) / len(valid_prices) if valid_prices else 0.0
|
||||||
|
|
||||||
aggregated_products.append(product)
|
aggregated_products.append(product)
|
||||||
return aggregated_products
|
return aggregated_products
|
||||||
|
|||||||
@@ -104,7 +104,9 @@ class MarketAPIsTool(MarketWrapper, Toolkit):
|
|||||||
Raises:
|
Raises:
|
||||||
Exception: If all providers fail to return results.
|
Exception: If all providers fail to return results.
|
||||||
"""
|
"""
|
||||||
all_products = self.handler.try_call_all(lambda w: w.get_products(asset_ids))
|
all_products: dict[str, list[ProductInfo]] = {}
|
||||||
|
for asset in asset_ids:
|
||||||
|
all_products[asset] = self.handler.try_call_all(lambda w: w.get_product(asset))
|
||||||
return ProductInfo.aggregate(all_products)
|
return ProductInfo.aggregate(all_products)
|
||||||
|
|
||||||
def get_historical_prices_aggregated(self, asset_id: str = "BTC", limit: int = 100) -> list[Price]:
|
def get_historical_prices_aggregated(self, asset_id: str = "BTC", limit: int = 100) -> list[Price]:
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ class TestMarketDataAggregator:
|
|||||||
|
|
||||||
info = aggregated[0]
|
info = aggregated[0]
|
||||||
assert info is not None
|
assert info is not None
|
||||||
assert info.id == "BTC-USD_AGGREGATED"
|
assert info.id == "BTC_AGGREGATED"
|
||||||
assert info.symbol == "BTC"
|
assert info.symbol == "BTC"
|
||||||
assert info.currency == "USD"
|
assert info.currency == "USD"
|
||||||
assert info.price == pytest.approx(100000.0, rel=1e-3) # type: ignore
|
assert info.price == pytest.approx(100000.0, rel=1e-3) # type: ignore
|
||||||
|
|||||||
Reference in New Issue
Block a user