diff --git a/app/services/logic_state_service.py b/app/services/logic_state_service.py index 1afcf70..7a36ea1 100644 --- a/app/services/logic_state_service.py +++ b/app/services/logic_state_service.py @@ -176,6 +176,16 @@ def now_view(st) -> dict: "text": (reasons[0] if reasons else (st.get("why") or ""))[:160]} +def ref_target_view(st): + """参考目标价: 第四件的中性情景估值 (中位每股收益乘中位市盈率), 2026-09-07 拍板在持仓页显示, + 只显示不触发, 不替代用户手设的目标价 (到价提议只认命令表里那个)。算不出就不给。""" + v = st.get("valuation") if isinstance(st, dict) and isinstance(st.get("valuation"), dict) else None + if not v or v.get("na") or v.get("neut") is None: + return None + return {"price": v["neut"], "pess": v.get("pess"), "opt": v.get("opt"), "quarter": v.get("quarter"), + "firms": v.get("firms"), "as_of": v.get("as_of"), "text": st.get("valuation_text")} + + def entry_view(ts_code: str) -> dict: """「当初为什么买」: 首批未平批次 → 它的指令 → 该指令或它来自的提议在账本上的放行记录 → 硬数字里的 判决依据、论断、判决与入场时的逻辑状态。三种情形都要说得出话: 有指令链、外部成交并入、账本无行。""" @@ -229,6 +239,10 @@ def decorate_positions(rows: list, states: dict | None = None) -> list: r["logic_now"] = now_view(states.get(code)) except Exception as e: # noqa: BLE001 r["logic_now"] = {"state": None, "text": f"读数处理失败: {type(e).__name__}"} + try: + r["ref_target"] = ref_target_view(states.get(code)) + except Exception: # noqa: BLE001 + r["ref_target"] = None if int(r.get("total_qty") or 0) <= 0: r["entry"] = None continue diff --git a/app/services/plan_feed.py b/app/services/plan_feed.py index 551070e..0256cbc 100644 --- a/app/services/plan_feed.py +++ b/app/services/plan_feed.py @@ -613,6 +613,14 @@ def parse_logic_states(payload) -> dict: continue st["source"] = _text_or_none(it.get("source")) st["date"] = day + # 安全边际三情景 (第四件): 持仓页拿中性情景作参考目标价 (2026-09-07 拍板, 只显示不触发)。 + v = it.get("valuation") if isinstance(it.get("valuation"), dict) else None + st["valuation"] = ({"neut": _float_or_none(v.get("neut")), "pess": _float_or_none(v.get("pess")), + "opt": _float_or_none(v.get("opt")), "price": _float_or_none(v.get("price")), + "quarter": _text_or_none(v.get("quarter")), "firms": _int_or_none(v.get("firms")), + "as_of": _text_or_none(v.get("as_of")), "na": _text_or_none(v.get("na"))} + if v else None) + st["valuation_text"] = _text_or_none(it.get("valuation_text")) out[code] = st return out diff --git a/app/web/static/index.html b/app/web/static/index.html index 8264ba3..695ff78 100644 --- a/app/web/static/index.html +++ b/app/web/static/index.html @@ -1565,6 +1565,10 @@ body.dock-r:not(.r-fold) .side-r .strip{display:none;} {{ s.row.user_stop_price!=null ? s.row.user_stop_price : '-' }}/{{ s.row.user_target_price!=null ? s.row.user_target_price : '-' }} 未设 + +