clean up config & singleton client

This commit is contained in:
mhmmdjafarg 2025-12-29 20:37:54 +07:00
parent 72061a8ae2
commit cb9c63972a
8 changed files with 85 additions and 45 deletions

View File

@ -8,3 +8,4 @@ TAAPI_API_KEY=taapi_api_key_placeholder
BYBIT_BASE_URL=https://api-demo.bybit.com
BYBIT_API_KEY=bybit_api_key_placeholder
BYBIT_API_SECRET=bybit_api_secret_placeholder
COIN_GECKO_API_BASE_URL=https://api.coingecko.com/api/v3

View File

@ -1,20 +1,33 @@
from binance_common.configuration import ConfigurationRestAPI
from binance_common.constants import SPOT_REST_API_PROD_URL
from binance_sdk_spot.spot import Spot
import os
from datetime import datetime
import csv
import io
from tradingagents.dataflows.config import get_config
def get_api_key() -> str:
"""Retrieve the API key for Binance from environment variables."""
api_key = os.getenv("BINANCE_API_KEY")
if not api_key:
raise ValueError("BINANCE_API_KEY environment variable is not set.")
return api_key
_client = None
configuration = ConfigurationRestAPI(api_key=get_api_key(), base_path=SPOT_REST_API_PROD_URL)
client = Spot(config_rest_api=configuration)
def get_binance_client():
"""Get or create Binance client with lazy initialization."""
global _client
if _client is None:
try:
config = get_config()
api_key = config["external"].get("BINANCE_API_KEY", "")
if not api_key:
raise ValueError("BINANCE_API_KEY not found in configuration")
configuration = ConfigurationRestAPI(
api_key=api_key,
base_path=SPOT_REST_API_PROD_URL
)
_client = Spot(config_rest_api=configuration)
except Exception as e:
print(f"ERROR: Failed to initialize Binance client: {e}")
raise
return _client
def get_market_data(symbol: str, start_date: str, end_date: str):
"""Fetch market data for a given symbol from Binance. Get OHLCV data. interval is 1 day.
@ -36,6 +49,7 @@ def get_market_data(symbol: str, start_date: str, end_date: str):
print(f"DEBUG: Fetching data for {formatted_symbol} from {start_date} to {end_date}")
try:
client = get_binance_client()
response = client.rest_api.klines(
symbol=formatted_symbol,
start_time=start_epoch,
@ -80,6 +94,8 @@ def get_market_data(symbol: str, start_date: str, end_date: str):
csv_string = output.getvalue()
output.close()
title = f"# Market Data for {symbol} from {start_date} to {end_date}\n\n"
csv_string = title + csv_string
return csv_string
except Exception as e:

View File

@ -1,5 +1,6 @@
import requests
from .alpha_vantage_common import API_BASE_URL
from tradingagents.dataflows.config import get_config
def get_market_cap() -> str:
"""
@ -8,8 +9,11 @@ def get_market_cap() -> str:
Returns:
str: Market capitalization percentage data for cryptocurrencies
"""
endpoint = f"https://api.coingecko.com/api/v3/global"
config = get_config()
api_base_url = config["external"].get("COIN_GECKO_API_BASE_URL", "https://api.coingecko.com/api/v3")
endpoint = f"{api_base_url}/global"
response = requests.get(endpoint)
print(f"DEBUG: CoinGecko API response status code: {response.status_code}")
response.raise_for_status()
data = response.json()
market_cap_pct = data.get("data", {}).get("market_cap_percentage", {})
@ -18,4 +22,4 @@ def get_market_cap() -> str:
for coin, percentage in market_cap_pct.items():
# Format each line as "Coin: XX.XX%"
result += f"- {coin.upper()}: {percentage:.2f}%\n"
return result
return result

View File

@ -94,9 +94,6 @@ VENDOR_METHODS = {
# technical_indicators
"get_indicators": {
"taapi": get_crypto_stats_indicators_window,
# "alpha_vantage": get_alpha_vantage_indicator,
# "yfinance": get_stock_stats_indicators_window,
# "local": get_stock_stats_indicators_window
},
"get_indicators_bulk": {
"taapi": get_crypto_stats_indicators,

View File

@ -1,10 +1,27 @@
from openai import OpenAI
from .config import get_config
_client = None
def get_openai_client():
"""Get or create OpenAI client with lazy initialization."""
global _client
if _client is None:
try:
config = get_config()
base_url = config.get("backend_url")
if not base_url:
raise ValueError("backend_url not found in configuration")
_client = OpenAI(base_url=base_url)
except Exception as e:
print(f"ERROR: Failed to initialize OpenAI client: {e}")
raise
return _client
def get_stock_news_openai(query, start_date, end_date):
config = get_config()
client = OpenAI(base_url=config["backend_url"])
client = get_openai_client()
response = client.responses.create(
model=config["quick_think_llm"],
@ -39,7 +56,7 @@ def get_stock_news_openai(query, start_date, end_date):
def get_crypto_news_openai(query, start_date, end_date):
config = get_config()
client = OpenAI(base_url=config["backend_url"])
client = get_openai_client()
response = client.responses.create(
model=config["quick_think_llm"],
@ -74,7 +91,7 @@ def get_crypto_news_openai(query, start_date, end_date):
def get_global_news_openai(curr_date, look_back_days=7, limit=5):
config = get_config()
client = OpenAI(base_url=config["backend_url"])
client = get_openai_client()
response = client.responses.create(
model=config["quick_think_llm"],
@ -110,7 +127,7 @@ def get_global_news_openai(curr_date, look_back_days=7, limit=5):
def get_fundamentals_openai(ticker, curr_date):
config = get_config()
client = OpenAI(base_url=config["backend_url"])
client = get_openai_client()
response = client.responses.create(
model=config["quick_think_llm"],
@ -146,7 +163,7 @@ def get_fundamentals_openai(ticker, curr_date):
def get_whitepaper_openai(symbol):
config = get_config()
client = OpenAI(base_url=config["backend_url"])
client = get_openai_client()
response = client.responses.create(
model=config["quick_think_llm"],
@ -177,4 +194,4 @@ def get_whitepaper_openai(symbol):
store=True,
)
return response.output[1].content[0].text
return response.output[1].content[0].text

View File

@ -1,16 +1,7 @@
import requests
from typing import Annotated, List, Dict
import os
from typing import Annotated, List
from tradingagents.dataflows.config import get_config
def get_api_key() -> str:
"""Retrieve the API key for TAAPI from environment variables."""
api_key = os.getenv("TAAPI_API_KEY")
if not api_key:
raise ValueError("TAAPI_API_KEY environment variable is not set.")
return api_key
# This is for single indicator, unused for now but kept for reference
def get_crypto_stats_indicators_window(
symbol: Annotated[str, "ticker symbol of the coin/asset"],
@ -58,8 +49,10 @@ def get_crypto_stats_indicators_window(
return f"Error: Indicator '{indicator}' is not supported. Please choose from: {list(supported_indicators.keys())}"
config = get_config()
base_url = config["tool_providers"].get("TAAPI_BASE_URL", "https://api.taapi.io")
api_key = get_api_key()
base_url = config["external"].get("TAAPI_BASE_URL", "https://api.taapi.io")
api_key = config["external"].get("TAAPI_API_KEY", "")
if not api_key:
return "Error: TAAPI_API_KEY is not set in the configuration."
# Set backtrack as requested
backtrack = look_back_days
@ -187,8 +180,10 @@ def get_crypto_stats_indicators(
return f"Error: Indicators {invalid_indicators} are not supported. Please choose from: {list(supported_indicators.keys())}"
config = get_config()
base_url = config["tool_providers"].get("TAAPI_BASE_URL", "https://api.taapi.io")
api_key = get_api_key()
base_url = config["external"].get("TAAPI_BASE_URL", "https://api.taapi.io")
api_key = config["external"].get("TAAPI_API_KEY", "")
if not api_key:
return "Error: TAAPI_API_KEY is not set in the configuration."
# Construct the bulk API URL
url = f"{base_url}/bulk"

View File

@ -1,13 +1,19 @@
import asyncio
from telethon import TelegramClient
from datetime import datetime, timedelta, timezone
import os
from tradingagents.dataflows.config import get_config
def get_api_credentials():
api_id = int(os.getenv("TELEGRAM_API_ID", ""))
api_hash = os.getenv("TELEGRAM_API_HASH", "")
session_name = os.getenv("TELEGRAM_SESSION_NAME", "")
return api_id, api_hash, session_name
"""Retrieve Telegram API credentials from environment variables."""
config = get_config()
api_id = config["external"]["TELEGRAM_API_ID"]
api_hash = config["external"]["TELEGRAM_API_HASH"]
session_name = config["external"]["TELEGRAM_SESSION_NAME"]
if not api_id or not api_hash or not session_name:
raise ValueError("Missing required Telegram credentials: TELEGRAM_API_ID, TELEGRAM_API_HASH, or TELEGRAM_SESSION_NAME")
return int(api_id), api_hash, session_name
async def _get_channel_history_async(start_date_str, end_date_str):
"""
@ -55,4 +61,4 @@ def get_crypto_news_telegram(curr_date, look_back_days=7, limit=100):
start_date_str = start_date.strftime('%Y-%m-%d')
end_date_str = end_date.strftime('%Y-%m-%d')
return asyncio.run(_get_channel_history_async(start_date_str, end_date_str))
return asyncio.run(_get_channel_history_async(start_date_str, end_date_str))

View File

@ -21,23 +21,27 @@ DEFAULT_CONFIG = {
# Category-level configuration (default for all tools in category)
"data_vendors": {
"core_crypto_apis": "binance", # Options: binance
"core_stock_apis": "yfinance", # Options: yfinance, alpha_vantage, local
"technical_indicators": "taapi", # Options: taapi
"fundamental_data": "alpha_vantage", # Options: openai, alpha_vantage, local
"news_data": "openai", # Options: openai, alpha_vantage, google, local
"fundamental_data": "openai", # Options: openai
"news_data": "openai", # Options: local, openai, telegram
},
# Tool-level configuration (takes precedence over category-level)
"tool_vendors": {
# Example: "get_stock_data": "alpha_vantage", # Override category default
"get_global_news": "telegram" # Override category default
},
# Tool provider settings
"tool_providers": {
"TAAPI_BASE_URL": os.getenv("TAAPI_BASE_URL", "https://api.taapi.io"),
},
"external": {
"BINANCE_API_KEY": os.getenv("BINANCE_API_KEY", ""),
"TAAPI_BASE_URL": os.getenv("TAAPI_BASE_URL", "https://api.taapi.io"),
"TAAPI_API_KEY": os.getenv("TAAPI_API_KEY", ""),
"BYBIT_BASE_URL": os.getenv("BYBIT_BASE_URL", "https://api-demo.bybit.com"),
"BYBIT_API_KEY": os.getenv("BYBIT_API_KEY", ""),
"BYBIT_API_SECRET": os.getenv("BYBIT_API_SECRET", ""),
"COIN_GECKO_API_BASE_URL": os.getenv("COIN_GECKO_API_BASE_URL", "https://api.coingecko.com/api/v3"),
"TELEGRAM_API_ID": os.getenv("TELEGRAM_API_ID", ""),
"TELEGRAM_API_HASH": os.getenv("TELEGRAM_API_HASH", ""),
"TELEGRAM_SESSION_NAME": os.getenv("TELEGRAM_SESSION_NAME", ""),
}
}