@@ -108,6 +108,7 @@ def format_small_account_cash_substitution_notes(
108108
109109_DETAIL_FIELD_SPLIT_RE = re .compile (r",\s*(?=[A-Za-z_][\w-]*\s*=)" )
110110_STRUCTURED_PAREN_RE = re .compile (r"^(?P<key>[A-Za-z_][\w-]*)\((?P<details>.*)\)$" )
111+ _DASHBOARD_POSITION_LINE_RE = re .compile (r"^[A-Z][A-Z0-9./-]{0,12}\s*:" )
111112
112113
113114I18N = {
@@ -469,29 +470,74 @@ def _is_dashboard_signal_line(line: str) -> bool:
469470 )
470471
471472
472- def _format_dashboard_lines (
473+ def _is_dashboard_account_title (line : str , * , translator : Callable [..., str ]) -> bool :
474+ text = str (line or "" ).strip ()
475+ account_titles = {
476+ translator ("account_overview_title" ),
477+ "📌 Strategy Account" ,
478+ "📌 Strategy portfolio" ,
479+ "📌 策略账户概览" ,
480+ }
481+ return text in account_titles
482+
483+
484+ def _is_dashboard_holdings_title (line : str , * , translator : Callable [..., str ]) -> bool :
485+ text = str (line or "" ).strip ()
486+ holdings_titles = {
487+ translator ("holdings_title" ),
488+ "💼 Strategy Holdings" ,
489+ "💼 Strategy holdings" ,
490+ "💼 策略持仓" ,
491+ }
492+ return text in holdings_titles
493+
494+
495+ def _is_dashboard_account_metric_line (line : str , * , translator : Callable [..., str ]) -> bool :
496+ text = str (line or "" ).strip ()
497+ lowered = text .lower ()
498+ if not text :
499+ return False
500+ if text .startswith ((translator ("dashboard_label" ), "📊 Dashboard" , "📊 资产看板" )):
501+ return True
502+ if text .startswith (("Income:" , "收益:" , "收入:" )):
503+ return True
504+ if _DASHBOARD_POSITION_LINE_RE .match (text ) and (
505+ "$" in text or "股" in text or "share" in lowered
506+ ):
507+ return True
508+ metric_labels = {
509+ translator ("total_assets" ),
510+ translator ("buying_power" ),
511+ translator ("reserved_cash" ),
512+ translator ("investable_cash" ),
513+ translator ("equity" ),
514+ "Total assets (strategy symbols + cash)" ,
515+ "Buying power" ,
516+ "Reserved cash" ,
517+ "Investable cash" ,
518+ "Equity" ,
519+ "总资产(策略标的+现金)" ,
520+ "购买力" ,
521+ "预留现金" ,
522+ "可投资现金" ,
523+ "净值" ,
524+ }
525+ return any (label and label .lower () in lowered for label in metric_labels )
526+
527+
528+ def _format_generated_dashboard_lines (
473529 portfolio : Mapping [str , Any ],
474530 execution : Mapping [str , Any ],
475531 * ,
476532 translator : Callable [..., str ],
477533) -> list [str ]:
478- dashboard_text = str (execution .get ("dashboard_text" ) or "" ).strip ()
479- if dashboard_text :
480- has_signal_display = bool (str (execution .get ("signal_display" ) or "" ).strip ())
481- lines = []
482- for line in dashboard_text .splitlines ():
483- if not line .strip ():
484- continue
485- if has_signal_display and _is_dashboard_signal_line (line ):
486- continue
487- lines .append (_base_localize_notification_text (line .rstrip (), translator = translator ))
488- return lines
489-
490534 lines = [translator ("account_overview_title" )]
491535 total_equity = _safe_float (portfolio .get ("total_equity" ))
492536 if total_equity is not None :
493537 lines .append (f" - { translator ('total_assets' )} : { _format_money (total_equity )} " )
494- buying_power = _safe_float (portfolio .get ("liquid_cash" ))
538+ buying_power = _safe_float (portfolio .get ("buying_power" ))
539+ if buying_power is None :
540+ buying_power = _safe_float (portfolio .get ("liquid_cash" ))
495541 if buying_power is not None :
496542 lines .append (f" - { translator ('buying_power' )} : { _format_money (buying_power )} " )
497543 reserved_cash = _safe_float (execution .get ("reserved_cash" ))
@@ -533,6 +579,41 @@ def _format_dashboard_lines(
533579 return lines
534580
535581
582+ def _format_dashboard_lines (
583+ portfolio : Mapping [str , Any ],
584+ execution : Mapping [str , Any ],
585+ * ,
586+ translator : Callable [..., str ],
587+ ) -> list [str ]:
588+ generated_lines = _format_generated_dashboard_lines (portfolio , execution , translator = translator )
589+ dashboard_text = str (execution .get ("dashboard_text" ) or "" ).strip ()
590+ if not dashboard_text :
591+ return generated_lines
592+
593+ has_signal_display = bool (str (execution .get ("signal_display" ) or "" ).strip ())
594+ extra_lines = []
595+ skipping_dashboard_holdings = False
596+ for raw_line in dashboard_text .splitlines ():
597+ if not raw_line .strip ():
598+ continue
599+ localized = _base_localize_notification_text (raw_line .rstrip (), translator = translator )
600+ if has_signal_display and _is_dashboard_signal_line (localized ):
601+ continue
602+ if _is_dashboard_holdings_title (localized , translator = translator ):
603+ skipping_dashboard_holdings = True
604+ continue
605+ if skipping_dashboard_holdings :
606+ if raw_line .startswith ((" " , "\t " , "-" )):
607+ continue
608+ skipping_dashboard_holdings = False
609+ if _is_dashboard_account_title (localized , translator = translator ):
610+ continue
611+ if _is_dashboard_account_metric_line (localized , translator = translator ):
612+ continue
613+ extra_lines .append (localized )
614+ return [* generated_lines , * extra_lines ]
615+
616+
536617def _localize_timing_contract (contract : Any , * , translator : Callable [..., str ]) -> str :
537618 value = str (contract or "" ).strip ()
538619 if value == "same_trading_day" :
0 commit comments