diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py
index 7fb3f6e..962c6e0 100644
--- a/crypto_monitor_binance/app.py
+++ b/crypto_monitor_binance/app.py
@@ -9530,6 +9530,7 @@ register_trade_records_api(
to_effective_trade_dict=to_effective_trade_dict,
filter_trade_records_excluding_miss=filter_trade_records_excluding_miss,
app_tz=APP_TZ,
+ format_price_fn=format_price_for_symbol,
)
def _dashboard_enrich_orders(items):
diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py
index 07b89af..a070a3b 100644
--- a/crypto_monitor_gate/app.py
+++ b/crypto_monitor_gate/app.py
@@ -9368,6 +9368,7 @@ register_trade_records_api(
to_effective_trade_dict=to_effective_trade_dict,
filter_trade_records_excluding_miss=filter_trade_records_excluding_miss,
app_tz=APP_TZ,
+ format_price_fn=format_price_for_symbol,
)
def _dashboard_enrich_orders(items):
diff --git a/crypto_monitor_okx/app.py b/crypto_monitor_okx/app.py
index 36ba081..8555625 100644
--- a/crypto_monitor_okx/app.py
+++ b/crypto_monitor_okx/app.py
@@ -2107,6 +2107,7 @@ def to_effective_trade_dict(row):
def format_price_for_symbol(symbol, value):
+ """价格展示:与交易所 price_to_precision 一致(与入库 round_price_to_exchange 对齐)."""
if value in (None, ""):
return "-"
try:
@@ -2115,8 +2116,15 @@ def format_price_for_symbol(symbol, value):
return str(value)
if v == 0:
return "0"
+ try:
+ ex_sym = normalize_okx_symbol(str(symbol or "").strip()) if symbol else ""
+ if ex_sym:
+ ensure_markets_loaded()
+ return str(exchange.price_to_precision(ex_sym, v))
+ except Exception:
+ pass
av = abs(v)
- # 根据币价量级动态精度:低价币保留更多小数,高价币减少噪音位数
+ # 无法加载市场或无该合约时:按价格量级回退(尽量不阻断页面)
if av >= 10000:
d = 2
elif av >= 100:
@@ -9035,6 +9043,7 @@ register_trade_records_api(
to_effective_trade_dict=to_effective_trade_dict,
filter_trade_records_excluding_miss=filter_trade_records_excluding_miss,
app_tz=APP_TZ,
+ format_price_fn=format_price_for_symbol,
)
diff --git a/lib/common/static/records_review_page.js b/lib/common/static/records_review_page.js
index 3010ecd..43b853c 100644
--- a/lib/common/static/records_review_page.js
+++ b/lib/common/static/records_review_page.js
@@ -42,6 +42,25 @@
return n.toFixed(digits == null ? 2 : digits);
}
+ /** 优先用后端交易所精度字符串;否则回退量级格式(与 formatPriceForInput 一致). */
+ function fmtPx(display, raw) {
+ if (display != null && display !== "") return esc(display);
+ if (raw == null || raw === "") return "—";
+ var n = Number(raw);
+ if (!Number.isFinite(n)) return esc(raw);
+ var av = Math.abs(n);
+ var d;
+ if (av >= 10000) d = 2;
+ else if (av >= 100) d = 3;
+ else if (av >= 1) d = 4;
+ else if (av >= 0.01) d = 6;
+ else if (av >= 0.0001) d = 8;
+ else d = 10;
+ var text = n.toFixed(d);
+ if (text.indexOf(".") >= 0) text = text.replace(/\.?0+$/, "");
+ return text;
+ }
+
function fmtTime(s) {
if (!s) return "—";
return esc(String(s).slice(0, 16));
@@ -199,13 +218,13 @@
dirTxt +
"" +
"
" +
- fmtNum(t.trigger_price, 4) +
+ fmtPx(t.trigger_price_display, t.trigger_price) +
" | " +
"" +
- fmtNum(stopShow, 4) +
+ fmtPx(t.stop_loss_display, stopShow) +
" | " +
"" +
- fmtNum(tpShow, 4) +
+ fmtPx(t.take_profit_display, tpShow) +
" | " +
"" +
margin +
diff --git a/lib/instance/records_api_register.py b/lib/instance/records_api_register.py
index fb7d541..dd96ffd 100644
--- a/lib/instance/records_api_register.py
+++ b/lib/instance/records_api_register.py
@@ -18,6 +18,7 @@ def register_trade_records_api(
to_effective_trade_dict: Callable[[Any], dict[str, Any]],
filter_trade_records_excluding_miss: Callable[[list], list],
app_tz: Any,
+ format_price_fn: Callable[[Any, Any], str] | None = None,
) -> None:
from lib.instance.records_list_lib import list_trade_records_page
@@ -48,6 +49,7 @@ def register_trade_records_api(
filter_fn=filter_trade_records_excluding_miss,
limit=limit,
offset=offset,
+ format_price_fn=format_price_fn,
)
return jsonify(payload)
finally:
diff --git a/lib/instance/records_list_lib.py b/lib/instance/records_list_lib.py
index dbda60d..8b8062b 100644
--- a/lib/instance/records_list_lib.py
+++ b/lib/instance/records_list_lib.py
@@ -2,7 +2,32 @@
from __future__ import annotations
-from typing import Any, Callable
+from typing import Any, Callable, Optional
+
+
+def enrich_trade_price_displays(
+ item: dict[str, Any],
+ format_price_fn: Optional[Callable[[Any, Any], str]] = None,
+) -> dict[str, Any]:
+ """为成交/止损/止盈补交易所精度展示字段(供交易记录表直接渲染)."""
+ if not format_price_fn or not isinstance(item, dict):
+ return item
+ sym = item.get("symbol")
+ stop_show = item.get("display_open_stop_loss")
+ if stop_show in (None, ""):
+ stop_show = item.get("initial_stop_loss")
+ if stop_show in (None, ""):
+ stop_show = item.get("stop_loss")
+ tp_show = item.get("effective_take_profit")
+ if tp_show in (None, ""):
+ tp_show = item.get("take_profit")
+ try:
+ item["trigger_price_display"] = format_price_fn(sym, item.get("trigger_price"))
+ item["stop_loss_display"] = format_price_fn(sym, stop_show)
+ item["take_profit_display"] = format_price_fn(sym, tp_show)
+ except Exception:
+ pass
+ return item
def list_trade_records_page(
@@ -16,6 +41,7 @@ def list_trade_records_page(
limit: int = 5,
offset: int = 0,
fetch_cap: int = 1000,
+ format_price_fn: Optional[Callable[[Any, Any], str]] = None,
) -> dict[str, Any]:
"""按列表窗拉取、enrich、过滤「错过」后分页."""
limit = max(1, min(100, int(limit or 5)))
@@ -33,6 +59,8 @@ def list_trade_records_page(
page = pages
offset = (page - 1) * limit
items = records[offset : offset + limit]
+ if format_price_fn is not None:
+ items = [enrich_trade_price_displays(dict(it), format_price_fn) for it in items]
return {
"ok": True,
"items": items,
diff --git a/tests/test_records_list_lib.py b/tests/test_records_list_lib.py
index bde81b0..b9a1fcf 100644
--- a/tests/test_records_list_lib.py
+++ b/tests/test_records_list_lib.py
@@ -78,6 +78,25 @@ class RecordsListLibTest(unittest.TestCase):
self.assertEqual(out["page"], 2)
self.assertEqual(len(out["items"]), 5)
+ def test_price_display_enrich(self):
+ from lib.instance.records_list_lib import enrich_trade_price_displays
+
+ item = {
+ "symbol": "BTC/USDT",
+ "trigger_price": 63902.0,
+ "display_open_stop_loss": 64500.0,
+ "effective_take_profit": 62800.0,
+ }
+
+ def _fmt(sym, v):
+ self.assertEqual(sym, "BTC/USDT")
+ return f"{float(v):.1f}"
+
+ out = enrich_trade_price_displays(item, _fmt)
+ self.assertEqual(out["trigger_price_display"], "63902.0")
+ self.assertEqual(out["stop_loss_display"], "64500.0")
+ self.assertEqual(out["take_profit_display"], "62800.0")
+
if __name__ == "__main__":
unittest.main()
|