diff --git a/install_trading.py b/install_trading.py index 6562eec..a7ed4fe 100644 --- a/install_trading.py +++ b/install_trading.py @@ -67,7 +67,7 @@ from strategy.strategy_roll_lib import preview_roll from strategy.strategy_snapshot_lib import list_snapshots, save_snapshot from strategy.strategy_trend_lib import compute_trend_plan_futures, trend_dca_level_reached from strategy.strategy_snapshot_lib import STRATEGY_ROLL, STRATEGY_TREND -from symbols import ths_to_codes, resolve_main_contract, PRODUCTS, PRODUCT_CATEGORIES +from symbols import ths_to_codes, resolve_main_contract, PRODUCTS, PRODUCT_CATEGORIES, position_symbol_meta from trading_context import ( TRADING_MODE_LIVE, TRADING_MODE_SIM, @@ -112,6 +112,16 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se return "固定金额" return "固定手数" + def _symbol_display_fields(sym: str) -> dict: + meta = position_symbol_meta(sym) + name = meta.get("name") or sym + return { + "symbol": name, + "symbol_name": name, + "symbol_exchange": meta.get("exchange") or "", + "symbol_is_main": bool(meta.get("is_main")), + } + def _schedule_recommend_refresh() -> None: from db_conn import DB_PATH @@ -338,12 +348,12 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se lots = int(mon.get("lots") or 0) base = { "symbol_code": sym, - "symbol": mon.get("symbol_name") or sym, "direction": direction, "direction_label": "做多" if direction == "long" else "做空", "lots": lots, "source": "monitor", "monitor_id": mon.get("id"), + **_symbol_display_fields(sym), } sl = mon.get("stop_loss") tp = mon.get("take_profit") @@ -368,7 +378,6 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se sym = mon.get("symbol") or "" pending.append({ "symbol_code": sym, - "symbol": mon.get("symbol_name") or sym, "direction": mon.get("direction") or "long", "direction_label": "做多" if (mon.get("direction") or "long") == "long" else "做空", "lots": int(mon.get("lots") or 0), @@ -379,6 +388,7 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se "monitor_id": mon.get("id"), "can_cancel_order": is_trading_session(), "cancel_allowed": is_trading_session(), + **_symbol_display_fields(sym), }) ctp_st = ctp_status(mode) if ctp_st.get("connected"): @@ -391,7 +401,6 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se label = "平仓委托" pending.append({ "symbol_code": sym, - "symbol": sym, "direction": o.get("direction") or "long", "direction_label": "做多" if o.get("direction") == "long" else "做空", "lots": int(o.get("lots") or 0), @@ -402,6 +411,7 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se "order_id": o.get("order_id"), "can_cancel_order": is_trading_session(), "cancel_allowed": is_trading_session(), + **_symbol_display_fields(sym), }) return pending @@ -767,8 +777,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se "source_label": source_label, "sync_pending": ctp is None and mon is not None, "monitor_id": mon["id"] if mon else None, - "symbol": codes.get("name", sym) if codes else (mon.get("symbol_name") if mon else sym), "symbol_code": sym, + **_symbol_display_fields(sym), "direction": direction, "direction_label": "做多" if direction == "long" else "做空", "lots": lots, @@ -838,8 +848,8 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se "source_label": "委托挂单中", "sync_pending": True, "monitor_id": mon.get("id"), - "symbol": codes.get("name", sym) if codes else (mon.get("symbol_name") or sym), "symbol_code": sym, + **_symbol_display_fields(sym), "direction": direction, "direction_label": "做多" if direction == "long" else "做空", "lots": lots, diff --git a/static/css/trade.css b/static/css/trade.css index e1c1d07..40300a6 100644 --- a/static/css/trade.css +++ b/static/css/trade.css @@ -65,7 +65,9 @@ .gap-badge{font-size:.72rem} .rec-market-link{color:inherit;text-decoration:none;display:inline-flex;flex-wrap:wrap;align-items:baseline;gap:.2rem .35rem} .rec-market-link:hover strong,.rec-market-link:hover .text-accent{color:var(--accent);text-decoration:underline} -.rec-change-up{color:var(--profit)} +.pos-symbol-sub{font-size:.72rem;line-height:1.35} +.pos-main-badge{font-size:.68rem;vertical-align:middle} +.pos-change-up{color:var(--profit)} .rec-change-down{color:var(--loss)} #recommend .trade-table-wrap{max-height:min(70vh,520px)} #positions .card-body.card-scroll{flex:1;max-height:none;overflow-y:auto} diff --git a/static/js/trade.js b/static/js/trade.js index 103d1ab..71ea5e2 100644 --- a/static/js/trade.js +++ b/static/js/trade.js @@ -806,6 +806,25 @@ return '未开启'; } + function posSymbolTitleHtml(row, extraBadges) { + extraBadges = extraBadges || ''; + var name = row.symbol_name || row.symbol || ''; + var code = row.symbol_code || ''; + var mainBadge = row.symbol_is_main ? ' 主力' : ''; + var title = name + mainBadge; + if (code && String(name).toLowerCase() !== String(code).toLowerCase()) { + title += ' ' + code + ''; + } else if (!name && code) { + title = '' + code + ''; + } + return title + extraBadges; + } + + function posSymbolSubHtml(row) { + if (row.symbol_exchange) return row.symbol_exchange; + return row.symbol_code || ''; + } + function buildPendingOrderCard(row) { var dirBadge = row.direction_label || (row.direction === 'long' ? '做多' : '做空'); var openT = (row.open_time || '').replace('T', ' ').slice(0, 16); @@ -827,10 +846,10 @@ ' · 约 ' + remainMin + ' 分钟内未成交自动撤单'; return ( '