Label dashboard positions from monitor sources with priority.
Match hedge/roll/trend/order/key monitors for source badges, show option target monitors in green, and refresh the dashboard with the board 5s cycle. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -973,9 +973,119 @@ def format_account_remark(ac: dict) -> str:
|
||||
return ";".join(parts)
|
||||
|
||||
|
||||
def _monitor_item_matches_position(item: dict, symbol: str, side: str) -> bool:
|
||||
o_sym = item.get("exchange_symbol") or item.get("symbol") or ""
|
||||
if not _symbols_match(symbol, o_sym):
|
||||
return False
|
||||
return (str(item.get("direction") or "").lower() == str(side or "").lower())
|
||||
|
||||
|
||||
def _order_monitor_source_label(order: dict) -> tuple[int, str]:
|
||||
"""返回 (优先级, 来源标签). 对冲=1 … 关键位=5."""
|
||||
mt = str(
|
||||
order.get("monitor_type_display")
|
||||
or order.get("monitor_type_label")
|
||||
or order.get("monitor_type")
|
||||
or ""
|
||||
).strip()
|
||||
if "顺势" in mt:
|
||||
return 2, "顺势加仓"
|
||||
if "趋势" in mt:
|
||||
return 3, "趋势回调"
|
||||
if "关键位" in mt:
|
||||
return 5, "关键位"
|
||||
return 4, "下单监控"
|
||||
|
||||
|
||||
def _hedge_matches_position(plan: dict, symbol: str, side: str) -> bool:
|
||||
"""进行中对冲计划是否覆盖该永续仓(方向 + 永续腿/标的)."""
|
||||
direction = str(plan.get("direction") or "").lower()
|
||||
if direction and direction != str(side or "").lower():
|
||||
return False
|
||||
for leg in plan.get("legs") or []:
|
||||
if not isinstance(leg, dict):
|
||||
continue
|
||||
if str(leg.get("leg_role") or "") != "perp":
|
||||
continue
|
||||
if str(leg.get("status") or "open") not in ("", "open"):
|
||||
continue
|
||||
if _symbols_match(symbol, str(leg.get("symbol") or "")):
|
||||
return True
|
||||
und = str(plan.get("underlying") or "").strip()
|
||||
if und and _symbols_match(symbol, und):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _hedge_source_label(plan: dict) -> str:
|
||||
pt = str(plan.get("plan_type") or "").strip()
|
||||
if pt == "perp_options" or str(plan.get("plan_type_label") or "") == "永期对冲":
|
||||
return "永期对冲"
|
||||
if pt == "options_options" or str(plan.get("plan_type_label") or "") == "期期对冲":
|
||||
return "期期对冲"
|
||||
return "对冲"
|
||||
|
||||
|
||||
def resolve_position_monitor_source(pos: dict, hub_mon: Optional[dict]) -> str:
|
||||
"""仓位来源:对冲 > 顺势加仓 > 趋势回调 > 下单监控 > 关键位;对不上为 —."""
|
||||
if not isinstance(hub_mon, dict) or hub_mon.get("ok") is False:
|
||||
return "—"
|
||||
sym = str(pos.get("symbol") or "")
|
||||
side = str(pos.get("side") or "")
|
||||
if not sym:
|
||||
return "—"
|
||||
candidates: list[tuple[int, str]] = []
|
||||
for h in hub_mon.get("hedges") or []:
|
||||
if isinstance(h, dict) and _hedge_matches_position(h, sym, side):
|
||||
candidates.append((1, _hedge_source_label(h)))
|
||||
for r in hub_mon.get("rolls") or []:
|
||||
if isinstance(r, dict) and _monitor_item_matches_position(r, sym, side):
|
||||
candidates.append((2, "顺势加仓"))
|
||||
for t in hub_mon.get("trends") or []:
|
||||
if isinstance(t, dict) and _monitor_item_matches_position(t, sym, side):
|
||||
candidates.append((3, "趋势回调"))
|
||||
for o in hub_mon.get("orders") or []:
|
||||
if isinstance(o, dict) and _monitor_item_matches_position(o, sym, side):
|
||||
candidates.append(_order_monitor_source_label(o))
|
||||
for k in hub_mon.get("keys") or []:
|
||||
if isinstance(k, dict) and _monitor_item_matches_position(k, sym, side):
|
||||
candidates.append((5, "关键位"))
|
||||
if not candidates:
|
||||
return "—"
|
||||
candidates.sort(key=lambda x: x[0])
|
||||
return candidates[0][1]
|
||||
|
||||
|
||||
def _options_source_label(p: dict) -> str:
|
||||
"""看板期权来源:仅对冲标期期/永期;纯期权或对不上监控显示 —."""
|
||||
source = str(p.get("source") or "").strip()
|
||||
label = str(p.get("source_label") or "").strip()
|
||||
if source == "perp_options" or label == "永期对冲":
|
||||
return "永期对冲"
|
||||
if source == "options_options" or label == "期期对冲":
|
||||
return "期期对冲"
|
||||
hedge = p.get("hedge_plan_target") if isinstance(p.get("hedge_plan_target"), dict) else None
|
||||
if hedge:
|
||||
return _hedge_source_label(hedge)
|
||||
return "—"
|
||||
|
||||
|
||||
def _options_target_monitor_text(p: dict) -> str:
|
||||
raw = p.get("target_monitor_text")
|
||||
if raw not in (None, ""):
|
||||
return str(raw)
|
||||
try:
|
||||
from lib.instance.instance_dashboard_lib import _format_options_target
|
||||
|
||||
return _format_options_target(p)
|
||||
except Exception:
|
||||
return "—"
|
||||
|
||||
|
||||
def format_dashboard_account_detail(ac: dict) -> dict[str, Any]:
|
||||
"""数据看板分户卡片:监控仅数量,持仓逐行(含浮盈亏与来源)."""
|
||||
"""数据看板分户卡片:监控数量 + 持仓表(来源=监控匹配)."""
|
||||
mon = ac.get("monitor_lines") or {}
|
||||
hub_mon = ac.get("hub_monitor") if isinstance(ac.get("hub_monitor"), dict) else None
|
||||
position_lines: list[dict[str, Any]] = []
|
||||
for p in _filter_open_positions(ac.get("positions") or []):
|
||||
sym = p.get("symbol") or "?"
|
||||
@@ -984,10 +1094,11 @@ def format_dashboard_account_detail(ac: dict) -> dict[str, Any]:
|
||||
if contracts is None:
|
||||
contracts = p.get("size")
|
||||
upnl = _position_float_pnl(p)
|
||||
source = resolve_position_monitor_source(p, hub_mon)
|
||||
position_lines.append(
|
||||
{
|
||||
"kind": "position",
|
||||
"source": "永续",
|
||||
"source": source,
|
||||
"symbol": sym,
|
||||
"side": side,
|
||||
"contracts": contracts,
|
||||
@@ -998,28 +1109,21 @@ def format_dashboard_account_detail(ac: dict) -> dict[str, Any]:
|
||||
opt_snap = ac.get("options_snapshot") if isinstance(ac.get("options_snapshot"), dict) else {}
|
||||
options_positions: list[dict[str, Any]] = []
|
||||
if opt_snap.get("ok") is not False and opt_snap.get("enabled") is not False:
|
||||
from lib.options.options_pricing_lib import format_options_breakeven_line
|
||||
|
||||
for p in opt_snap.get("positions") or []:
|
||||
if not isinstance(p, dict):
|
||||
continue
|
||||
options_positions.append(p)
|
||||
inst = p.get("inst_id") or "?"
|
||||
opt_type = (p.get("opt_type") or "").upper()
|
||||
row = dict(p)
|
||||
row["source_label"] = _options_source_label(p)
|
||||
row["target_monitor_text"] = _options_target_monitor_text(p)
|
||||
options_positions.append(row)
|
||||
inst = row.get("inst_id") or "?"
|
||||
opt_type = (row.get("opt_type") or "").upper()
|
||||
label = "Call" if opt_type == "C" else "Put" if opt_type == "P" else opt_type or "OPT"
|
||||
upl = p.get("upl")
|
||||
be_line = format_options_breakeven_line(
|
||||
expiry_be_px=p.get("expiry_be_px"),
|
||||
close_be_px=p.get("close_be_px"),
|
||||
idx_px=p.get("idx_px"),
|
||||
)
|
||||
text = f"期权 {inst} {label}"
|
||||
if be_line:
|
||||
text = f"{text} {be_line}"
|
||||
upl = row.get("upl")
|
||||
line: dict[str, Any] = {
|
||||
"kind": "options",
|
||||
"source": "期权",
|
||||
"text": text,
|
||||
"source": row.get("source_label") or "—",
|
||||
"text": f"期权 {inst} {label}",
|
||||
}
|
||||
if upl is not None:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user