diff --git a/trading_system/binance_client.py b/trading_system/binance_client.py index 990850b..f4d7910 100644 --- a/trading_system/binance_client.py +++ b/trading_system/binance_client.py @@ -396,23 +396,31 @@ class BinanceClient: timeout=timeout ) - # 支持中文名交易对:若 symbol 含非 ASCII,用 baseAsset+quoteAsset 作为 API 下单用 symbol,并建立映射 + # 支持中文名交易对:若 symbol 含非 ASCII,尝试用 baseAsset+quoteAsset 作为 API 下单用 symbol + # 如果 baseAsset+quoteAsset 也是非 ASCII,则直接使用原始 symbol self._display_to_api_symbol.clear() usdt_pairs = [] for s in exchange_info['symbols']: if not (s['symbol'].endswith('USDT') and s['status'] == 'TRADING' and s.get('contractType') == 'PERPETUAL'): continue sym = s['symbol'] + + # 1. 如果是 ASCII,直接使用 if sym.isascii(): usdt_pairs.append(sym) continue + + # 2. 如果非 ASCII,尝试构建英文 symbol (base+quote) api_sym = (s.get('baseAsset') or '') + (s.get('quoteAsset') or '') if api_sym and api_sym.isascii(): usdt_pairs.append(api_sym) self._display_to_api_symbol[sym] = api_sym logger.debug(f"交易对显示名 -> API symbol: '{sym}' -> '{api_sym}'") else: - logger.warning(f"跳过无法解析为英文 symbol 的交易对: {sym!r} (baseAsset={s.get('baseAsset')!r}, quoteAsset={s.get('quoteAsset')!r})") + # 3. 如果 base+quote 也是非 ASCII(如 '币安人生USDT'),则直接使用原始 symbol + # 用户反馈希望交易这些特殊币种 + usdt_pairs.append(sym) + logger.info(f"添加非ASCII交易对: {sym!r} (baseAsset={s.get('baseAsset')!r})") if self._display_to_api_symbol: logger.info(f"已映射 {len(self._display_to_api_symbol)} 个中文/非ASCII交易对到英文 symbol,均可正常下单") logger.info(f"获取到 {len(usdt_pairs)} 个USDT永续合约交易对") @@ -618,9 +626,8 @@ class BinanceClient: if not sym.endswith('USDT'): continue # 支持中文名:用映射后的 API symbol 作为 key,便于扫描与下单一致 - api_sym = self._display_to_api_symbol.get(sym, sym) if not sym.isascii() else sym - if not api_sym.isascii(): - continue + api_sym = self._display_to_api_symbol.get(sym, sym) + # 移除 ASCII 检查,允许非 ASCII 交易对 result[api_sym] = { 'symbol': api_sym, 'price': float(ticker.get('lastPrice', 0)), @@ -1183,9 +1190,8 @@ class BinanceClient: """ # 支持中文名:将显示名解析为 API 使用的英文 symbol symbol = self._resolve_api_symbol(symbol) - # 校验 symbol 合法性(API 仅接受 ASCII) - if not symbol or not symbol.isascii(): - logger.error(f"❌ 下单请求包含非法 Symbol: '{symbol}' (包含非ASCII字符)") + if not symbol: + logger.error(f"❌ 下单请求 symbol 为空") import traceback logger.error(f" 调用堆栈:\n{traceback.format_exc()}") return None @@ -1491,8 +1497,8 @@ class BinanceClient: 是否成功 """ symbol = self._resolve_api_symbol(symbol) - if not symbol or not symbol.isascii(): - logger.error(f"❌ 取消订单请求包含非法 Symbol: '{symbol}'") + if not symbol: + logger.error(f"❌ 取消订单请求 symbol 为空") import traceback logger.error(f" 调用堆栈:\n{traceback.format_exc()}") return False @@ -1855,8 +1861,8 @@ class BinanceClient: """ leverage = int(leverage) # 币安 API 要求整数;动态杠杆可能传入 float symbol = self._resolve_api_symbol(symbol) - if not symbol or not symbol.isascii(): - logger.error(f"❌ 设置杠杆请求包含非法 Symbol: '{symbol}'") + if not symbol: + logger.error(f"❌ 设置杠杆请求 symbol 为空") import traceback logger.error(f" 调用堆栈:\n{traceback.format_exc()}") return False diff --git a/trading_system/market_scanner.py b/trading_system/market_scanner.py index e760d9c..12c6214 100644 --- a/trading_system/market_scanner.py +++ b/trading_system/market_scanner.py @@ -52,9 +52,9 @@ class MarketScanner: logger.info("开始扫描市场...") - # 获取所有USDT交易对(仅使用纯 ASCII symbol,避免本地化名称导致下单报错) + # 获取所有USDT交易对 raw_symbols = await self.client.get_all_usdt_pairs() - all_symbols = [s for s in (raw_symbols or []) if s and s.isascii()] + all_symbols = [s for s in (raw_symbols or []) if s] if raw_symbols and len(all_symbols) < len(raw_symbols): logger.info(f"已过滤 {len(raw_symbols) - len(all_symbols)} 个非ASCII交易对,保留 {len(all_symbols)} 个") if not all_symbols: @@ -134,12 +134,11 @@ class MarketScanner: tasks = [get_symbol_change_with_limit(symbol) for symbol in pre_filtered_symbols] results = await asyncio.gather(*tasks, return_exceptions=True) - # 过滤有效结果(排除非 ASCII symbol,防止下单时报错) + # 过滤有效结果 valid_results = [ r for r in results if isinstance(r, dict) and r.get('changePercent') is not None - and (r.get('symbol') or '').isascii() ] # ⚠️ 优化2:成交量验证 - 24H Volume低于1000万美金,直接剔除