feat(hub): exchange price precision, entry price, and trend DCA display
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user