feat(hub): exchange price precision, entry price, and trend DCA display

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-03 21:25:24 +08:00
parent fac28c402b
commit f95118065d
5 changed files with 368 additions and 49 deletions
+87
View File
@@ -52,6 +52,7 @@ def install_strategy_trend(app: Flask, repo_root: str, app_module: Any = None, *
cfg = build_trend_config(app_module, **build_kw)
app.extensions["strategy_trend_cfg"] = cfg
register_trend_routes(app, cfg)
_patch_hub_monitor_enrich(app, cfg)
@app.context_processor
def _trend_ctx():
@@ -268,9 +269,95 @@ def _insert_preview_snapshot(conn, preview_id: str, created: str, exp_ms: int, p
)
def _format_trend_price(cfg: dict, symbol: str, value) -> str:
if value in (None, ""):
return ""
m = _m(cfg)
sym = symbol or ""
norm = getattr(m, "normalize_exchange_symbol", None)
if callable(norm):
try:
sym = norm(sym) or sym
except Exception:
pass
try:
m.ensure_markets_loaded()
return str(m.exchange.price_to_precision(sym, float(value)))
except Exception:
fn = getattr(m, "format_price_for_symbol", None)
if callable(fn):
return fn(symbol, value)
return str(value)
def _trend_add_leg_fields(cfg: dict, d: dict) -> dict:
"""解析已补仓次数与已触达网格价(供策略页与中控 monitor 共用)。"""
import json
out = dict(d)
try:
legs_done = int(out.get("legs_done") or 0)
except (TypeError, ValueError):
legs_done = 0
try:
dca_legs = int(out.get("dca_legs") or 0)
except (TypeError, ValueError):
dca_legs = 0
try:
grid = json.loads(out.get("grid_prices_json") or "[]")
if not isinstance(grid, list):
grid = []
except Exception:
grid = []
add_prices: list[float] = []
for x in grid[:legs_done]:
try:
add_prices.append(float(x))
except (TypeError, ValueError):
pass
sym = out.get("exchange_symbol") or out.get("symbol") or ""
out["add_count"] = legs_done
out["add_count_total"] = dca_legs
out["add_prices"] = add_prices
out["add_prices_display"] = [_format_trend_price(cfg, sym, p) for p in add_prices]
for field in ("stop_loss", "take_profit", "add_upper", "avg_entry_price"):
if out.get(field) not in (None, ""):
out[f"{field}_display"] = _format_trend_price(cfg, sym, out.get(field))
return out
def enrich_trend_plan_for_hub(cfg: dict, raw: dict) -> dict:
"""中控 /api/hub/monitor:补仓次数、加仓价(交易所精度)。"""
return _trend_add_leg_fields(cfg, dict(raw or {}))
def _patch_hub_monitor_enrich(app: Flask, cfg: dict) -> None:
ctx = dict(app.config.get("HUB_CTX") or {})
prev = ctx.get("enrich_monitor")
def enrich_monitor(keys=None, orders=None, trends=None, rolls=None):
payload: dict[str, Any] = {}
if callable(prev):
try:
prev_out = prev(keys=keys, orders=orders, trends=trends, rolls=rolls)
if isinstance(prev_out, dict):
payload.update(prev_out)
except Exception:
pass
if trends:
payload["trends"] = [
enrich_trend_plan_for_hub(cfg, t) for t in trends if isinstance(t, dict)
]
return payload
ctx["enrich_monitor"] = enrich_monitor
app.config["HUB_CTX"] = ctx
def enrich_trend_plan(cfg: dict, row) -> dict:
m = _m(cfg)
d = _row(cfg, row)
d = _trend_add_leg_fields(cfg, d)
try:
d["breakeven_applied"] = int(d.get("breakeven_applied") or 0) != 0
except Exception: