5e507d0b66
Load enabled instances from settings, fetch market info via /api/hub/market, and apply exchange-specific amount and price precision in trend and roll calculators. Co-authored-by: Cursor <cursoragent@cursor.com>
82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
"""实例 USDT 永续合约信息(与实盘 ccxt 精度一致)。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Callable, Optional, Tuple
|
|
|
|
from hub_calculator_market_lib import (
|
|
amount_decimals_from_exchange,
|
|
normalize_base_symbol,
|
|
price_decimals_from_exchange,
|
|
resolve_usdt_perp_symbol,
|
|
)
|
|
from hub_ohlcv_lib import normalize_price_tick, price_tick_from_market
|
|
|
|
|
|
def fetch_usdt_swap_market_info(
|
|
*,
|
|
base_or_symbol: str,
|
|
normalize_symbol_input: Callable[[str], str],
|
|
normalize_exchange_symbol: Callable[[str], str],
|
|
ensure_markets_loaded: Callable[[], None],
|
|
exchange: Any,
|
|
exchange_id: str = "",
|
|
) -> dict[str, Any]:
|
|
"""供各实例 /api/hub/market 调用。"""
|
|
raw = str(base_or_symbol or "").strip()
|
|
if not raw:
|
|
return {"ok": False, "msg": "请输入币种,如 ETH"}
|
|
|
|
try:
|
|
ensure_markets_loaded()
|
|
except Exception as exc:
|
|
return {"ok": False, "msg": f"加载市场失败: {exc}"}
|
|
|
|
base_u = normalize_base_symbol(raw)
|
|
hub_sym = normalize_symbol_input(raw if base_u else raw)
|
|
try:
|
|
ex_sym = normalize_exchange_symbol(hub_sym)
|
|
except Exception:
|
|
ex_sym = hub_sym
|
|
|
|
sym, err = resolve_usdt_perp_symbol(exchange, base_u or hub_sym)
|
|
if err and ex_sym:
|
|
markets = getattr(exchange, "markets", None) or {}
|
|
if ex_sym in markets:
|
|
sym = ex_sym
|
|
err = None
|
|
if err or not sym:
|
|
return {"ok": False, "msg": err or f"未找到 {base_u or raw}/USDT 永续合约"}
|
|
|
|
market = exchange.market(sym)
|
|
try:
|
|
contract_size = float(market.get("contractSize") or 1.0)
|
|
except (TypeError, ValueError):
|
|
contract_size = 1.0
|
|
if contract_size <= 0:
|
|
contract_size = 1.0
|
|
|
|
price_tick = normalize_price_tick(price_tick_from_market(exchange, sym))
|
|
amt_dec = amount_decimals_from_exchange(exchange, sym)
|
|
px_dec = price_decimals_from_exchange(exchange, sym, price_tick)
|
|
min_amount = None
|
|
try:
|
|
min_amount = float((market.get("limits") or {}).get("amount", {}).get("min"))
|
|
except (TypeError, ValueError):
|
|
min_amount = None
|
|
|
|
base_out = (market.get("base") or base_u or "").upper() or base_u
|
|
return {
|
|
"ok": True,
|
|
"exchange": (exchange_id or "").strip().lower(),
|
|
"base": base_out,
|
|
"exchange_symbol": sym,
|
|
"display_symbol": f"{base_out}/USDT" if base_out else sym,
|
|
"contract_size": contract_size,
|
|
"price_tick": price_tick,
|
|
"price_decimals": px_dec,
|
|
"amount_decimals": amt_dec,
|
|
"min_amount": min_amount,
|
|
}
|
|
|