diff --git a/python/valuecell/agents/common/trading/data/market.py b/python/valuecell/agents/common/trading/data/market.py index 2e056b6d1..ace266183 100644 --- a/python/valuecell/agents/common/trading/data/market.py +++ b/python/valuecell/agents/common/trading/data/market.py @@ -9,6 +9,7 @@ MarketSnapShotType, ) from valuecell.agents.common.trading.utils import get_exchange_cls, normalize_symbol +from valuecell.utils.i18n_utils import detect_user_region from .interfaces import BaseMarketDataSource @@ -24,7 +25,21 @@ class SimpleMarketDataSource(BaseMarketDataSource): """ def __init__(self, exchange_id: Optional[str] = None) -> None: - self._exchange_id = exchange_id or "binance" + if not exchange_id: + # Auto-detect region and select appropriate exchange + region = detect_user_region() + if region == "us": + # Use OKX for United States users (best support for USDT perpetuals) + self._exchange_id = "okx" + logger.info( + "Detected US region, using okx exchange (USDT perpetuals supported)" + ) + else: + # Use regular Binance for other regions + self._exchange_id = "binance" + logger.info("Detected non-US region, using binance exchange") + else: + self._exchange_id = exchange_id def _normalize_symbol(self, symbol: str) -> str: """Normalize symbol format for specific exchanges. diff --git a/python/valuecell/utils/i18n_utils.py b/python/valuecell/utils/i18n_utils.py index 796ace120..6e6ab6b71 100644 --- a/python/valuecell/utils/i18n_utils.py +++ b/python/valuecell/utils/i18n_utils.py @@ -65,6 +65,31 @@ def detect_browser_language(accept_language_header: str) -> str: return DEFAULT_LANGUAGE +def detect_user_region() -> str: + """Detect user region based on IP geolocation. + + Returns: + Region code: 'us' for United States, 'default' for others + """ + try: + import httpx + + with httpx.Client(timeout=3.0) as client: + resp = client.get("https://ipapi.co/json/") + if resp.status_code == 200: + data = resp.json() + country_code = data.get("country_code", "").upper() + + if country_code == "US": + return "us" + + return "default" + return "default" + except Exception: + # If detection fails, return default + return "default" + + def get_timezone_for_language(language: str) -> str: """Get default timezone for a language.