@@ -36,6 +36,50 @@ IBKRClient = None
|
||||
MT5Client = None
|
||||
|
||||
|
||||
def _normalize_symbol_for_order(symbol: str, market_type: str = "swap") -> str:
|
||||
"""
|
||||
规范化符号格式,确保符号符合交易所要求。
|
||||
|
||||
处理各种输入格式:
|
||||
- BTC/USDT -> BTC/USDT
|
||||
- BTCUSDT -> BTC/USDT
|
||||
- BTC/USDT:USDT -> BTC/USDT
|
||||
- PI, TRX -> PI/USDT, TRX/USDT (默认添加 /USDT)
|
||||
|
||||
Args:
|
||||
symbol: 原始符号
|
||||
market_type: 市场类型 (spot/swap)
|
||||
|
||||
Returns:
|
||||
规范化后的符号
|
||||
"""
|
||||
if not symbol:
|
||||
return symbol
|
||||
|
||||
sym = symbol.strip()
|
||||
|
||||
# 移除 swap/futures 后缀
|
||||
if ':' in sym:
|
||||
sym = sym.split(':', 1)[0]
|
||||
|
||||
sym = sym.upper()
|
||||
|
||||
# 如果已经有分隔符,直接返回(假设格式正确)
|
||||
if '/' in sym:
|
||||
return sym
|
||||
|
||||
# 尝试从常见报价货币中识别
|
||||
common_quotes = ['USDT', 'USD', 'BTC', 'ETH', 'BUSD', 'USDC']
|
||||
for quote in common_quotes:
|
||||
if sym.endswith(quote) and len(sym) > len(quote):
|
||||
base = sym[:-len(quote)]
|
||||
if base:
|
||||
return f"{base}/{quote}"
|
||||
|
||||
# 如果无法识别,默认使用 USDT
|
||||
return f"{sym}/USDT"
|
||||
|
||||
|
||||
def _signal_to_sides(signal_type: str) -> Tuple[str, str, bool]:
|
||||
"""
|
||||
Returns (side, pos_side, reduce_only)
|
||||
@@ -80,6 +124,9 @@ def place_order_from_signal(
|
||||
# Spot does not support short signals in this system.
|
||||
if mt == "spot" and ("short" in (signal_type or "").lower()):
|
||||
raise LiveTradingError("spot market does not support short signals")
|
||||
|
||||
# 规范化符号格式(统一处理裸符号如 PI, TRX 等)
|
||||
symbol = _normalize_symbol_for_order(symbol, market_type=mt)
|
||||
|
||||
if isinstance(client, BinanceFuturesClient):
|
||||
return client.place_market_order(
|
||||
|
||||
@@ -14,12 +14,28 @@ from typing import Dict, Tuple
|
||||
|
||||
|
||||
def _split_base_quote(symbol: str) -> Tuple[str, str]:
|
||||
"""
|
||||
分割符号为基础货币和报价货币。
|
||||
|
||||
处理各种格式:
|
||||
- BTC/USDT -> (BTC, USDT)
|
||||
- BTCUSDT -> (BTCUSDT, "") - 需要进一步处理
|
||||
- PI, TRX -> (PI, "") - 需要进一步处理
|
||||
"""
|
||||
s = (symbol or "").strip()
|
||||
if ":" in s:
|
||||
s = s.split(":", 1)[0]
|
||||
if "/" not in s:
|
||||
# Already exchange-specific (best-effort)
|
||||
return s, ""
|
||||
# 尝试识别报价货币(常见格式:BASEQUOTE)
|
||||
s_upper = s.upper()
|
||||
common_quotes = ['USDT', 'USD', 'BTC', 'ETH', 'BUSD', 'USDC', 'BNB']
|
||||
for quote in common_quotes:
|
||||
if s_upper.endswith(quote) and len(s_upper) > len(quote):
|
||||
base = s_upper[:-len(quote)]
|
||||
if base:
|
||||
return base, quote
|
||||
# 无法识别,返回原符号和空报价
|
||||
return s_upper, ""
|
||||
base, quote = s.split("/", 1)
|
||||
return base.strip().upper(), quote.strip().upper()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user