行情区:K线全屏、可选技术指标与交易所价格精度对齐

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-02 14:24:36 +08:00
parent 01d26e9833
commit 84ac9134db
6 changed files with 592 additions and 33 deletions
+52 -15
View File
@@ -56,17 +56,17 @@ def chart_fetch_start_ms(timeframe: str, need: int, now_ms: int | None = None) -
def price_tick_from_market(exchange, exchange_symbol: str) -> Optional[float]:
"""最小价格变动单位(与交易所 tick / price_to_precision 一致)。"""
try:
markets = getattr(exchange, "markets", None) or {}
m = markets.get(exchange_symbol) or {}
prec = m.get("precision") or {}
p = prec.get("price")
if p is not None:
p = float(p)
if p > 0:
return p
info = m.get("info") or {}
for key in ("tickSize", "price_increment", "order_price_round"):
if not getattr(exchange, "markets", None):
exchange.load_markets()
market = exchange.market(exchange_symbol)
except Exception:
return None
info = market.get("info") or {}
if isinstance(info, dict):
for key in ("tickSize", "tickSz", "price_increment", "order_price_round", "quote_increment"):
if info.get(key) not in (None, ""):
try:
v = float(info[key])
@@ -74,11 +74,52 @@ def price_tick_from_market(exchange, exchange_symbol: str) -> Optional[float]:
return v
except (TypeError, ValueError):
pass
limits = market.get("limits") or {}
price_limits = limits.get("price") or {}
if price_limits.get("min") not in (None, ""):
try:
v = float(price_limits["min"])
if v > 0:
return v
except (TypeError, ValueError):
pass
try:
sample = exchange.price_to_precision(exchange_symbol, 12345.678901234)
s = str(sample).strip()
if "." in s:
frac = s.split(".", 1)[1]
if frac:
return 10 ** (-len(frac))
return 1.0
except Exception:
pass
prec = (market.get("precision") or {}).get("price")
if prec is not None:
try:
p = float(prec)
if p >= 1 and abs(p - round(p)) < 1e-9 and p <= 12:
return 10 ** (-int(p))
if 0 < p < 1:
return p
except (TypeError, ValueError):
pass
return None
def _decimals_from_tick(tick: float) -> int:
if tick >= 1:
return 0
s = f"{tick:.12f}".rstrip("0")
if "." in s:
frac = s.split(".", 1)[1]
if frac:
return min(12, len(frac))
return max(0, min(12, int(round(-math.log10(tick)))))
def format_price_by_tick(value: Any, tick: Optional[float]) -> str:
if value in (None, ""):
return "-"
@@ -89,11 +130,7 @@ def format_price_by_tick(value: Any, tick: Optional[float]) -> str:
if v == 0:
return "0"
if tick and tick > 0:
decimals = max(0, min(12, int(round(-math.log10(tick))) if tick < 1 else 0))
if tick >= 1:
decimals = 0
text = f"{v:.{decimals}f}"
return text.rstrip("0").rstrip(".") if "." in text else text
return f"{v:.{_decimals_from_tick(float(tick))}f}"
av = abs(v)
if av >= 10000:
d = 2