* fix dependencies uv.lock * refactor test markers for clarity * refactor: clean up imports and remove unused files * refactor: remove unused agent files and clean up market API instructions * refactor: enhance wrapper initialization with keyword arguments and clean up tests * refactor: remove PublicBinanceAgent * refactor: aggregator - simplified MarketDataAggregator and related models to functions * refactor: update README and .env.example to reflect the latest changes to the project * refactor: simplify product info and price creation in YFinanceWrapper * refactor: remove get_all_products method from market API wrappers and update documentation * fix: environment variable assertions * refactor: remove status attribute from ProductInfo and update related methods to use timestamp_ms * feat: implement aggregate_history_prices function to calculate hourly price averages * refactor: update docker-compose and app.py for improved environment variable handling and compatibility * feat: add detailed market instructions and improve error handling in price aggregation methods * feat: add aggregated news retrieval methods for top headlines and latest news * refactor: improve error messages in WrapperHandler for better clarity * fix: correct quote currency extraction in create_product_info and remove debug prints from tests
87 lines
3.3 KiB
Python
87 lines
3.3 KiB
Python
import os
|
|
from enum import Enum
|
|
from datetime import datetime, timedelta
|
|
from coinbase.rest import RESTClient
|
|
from coinbase.rest.types.product_types import Candle, GetProductResponse, Product
|
|
from .base import ProductInfo, BaseWrapper, Price
|
|
|
|
|
|
def get_product(product_data: GetProductResponse | Product) -> ProductInfo:
|
|
product = ProductInfo()
|
|
product.id = product_data.product_id or ""
|
|
product.symbol = product_data.base_currency_id or ""
|
|
product.price = float(product_data.price) if product_data.price else 0.0
|
|
product.volume_24h = float(product_data.volume_24h) if product_data.volume_24h else 0.0
|
|
return product
|
|
|
|
def get_price(candle_data: Candle) -> Price:
|
|
price = Price()
|
|
price.high = float(candle_data.high) if candle_data.high else 0.0
|
|
price.low = float(candle_data.low) if candle_data.low else 0.0
|
|
price.open = float(candle_data.open) if candle_data.open else 0.0
|
|
price.close = float(candle_data.close) if candle_data.close else 0.0
|
|
price.volume = float(candle_data.volume) if candle_data.volume else 0.0
|
|
price.timestamp_ms = int(candle_data.start) * 1000 if candle_data.start else 0
|
|
return price
|
|
|
|
|
|
class Granularity(Enum):
|
|
UNKNOWN_GRANULARITY = 0
|
|
ONE_MINUTE = 60
|
|
FIVE_MINUTE = 300
|
|
FIFTEEN_MINUTE = 900
|
|
THIRTY_MINUTE = 1800
|
|
ONE_HOUR = 3600
|
|
TWO_HOUR = 7200
|
|
FOUR_HOUR = 14400
|
|
SIX_HOUR = 21600
|
|
ONE_DAY = 86400
|
|
|
|
class CoinBaseWrapper(BaseWrapper):
|
|
"""
|
|
Wrapper per le API di Coinbase Advanced Trade.\n
|
|
Implementa l'interfaccia BaseWrapper per fornire accesso unificato
|
|
ai dati di mercato di Coinbase tramite le API REST.\n
|
|
https://docs.cdp.coinbase.com/api-reference/advanced-trade-api/rest-api/introduction
|
|
"""
|
|
|
|
def __init__(self, currency: str = "USD"):
|
|
api_key = os.getenv("COINBASE_API_KEY")
|
|
assert api_key, "COINBASE_API_KEY environment variable not set"
|
|
|
|
api_private_key = os.getenv("COINBASE_API_SECRET")
|
|
assert api_private_key, "COINBASE_API_SECRET environment variable not set"
|
|
|
|
self.currency = currency
|
|
self.client: RESTClient = RESTClient(
|
|
api_key=api_key,
|
|
api_secret=api_private_key
|
|
)
|
|
|
|
def __format(self, asset_id: str) -> str:
|
|
return asset_id if '-' in asset_id else f"{asset_id}-{self.currency}"
|
|
|
|
def get_product(self, asset_id: str) -> ProductInfo:
|
|
asset_id = self.__format(asset_id)
|
|
asset = self.client.get_product(asset_id)
|
|
return get_product(asset)
|
|
|
|
def get_products(self, asset_ids: list[str]) -> list[ProductInfo]:
|
|
all_asset_ids = [self.__format(asset_id) for asset_id in asset_ids]
|
|
assets = self.client.get_products(product_ids=all_asset_ids)
|
|
return [get_product(asset) for asset in assets.products]
|
|
|
|
def get_historical_prices(self, asset_id: str = "BTC", limit: int = 100) -> list[Price]:
|
|
asset_id = self.__format(asset_id)
|
|
end_time = datetime.now()
|
|
start_time = end_time - timedelta(days=14)
|
|
|
|
data = self.client.get_candles(
|
|
product_id=asset_id,
|
|
granularity=Granularity.ONE_HOUR.name,
|
|
start=str(int(start_time.timestamp())),
|
|
end=str(int(end_time.timestamp())),
|
|
limit=limit
|
|
)
|
|
return [get_price(candle) for candle in data.candles]
|