参考目标价:状态应答里的估值子字典归一,持仓页只显示中性情景不触发(第二十二批加一例,全套 678)
This commit is contained in:
parent
fbad890b7d
commit
48a562f170
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1565,6 +1565,10 @@ body.dock-r:not(.r-fold) .side-r .strip{display:none;}
|
|||
<span class="mono nowrap"
|
||||
v-if="s.row.user_stop_price!=null || s.row.user_target_price!=null">{{ s.row.user_stop_price!=null ? s.row.user_stop_price : '-' }}/{{ s.row.user_target_price!=null ? s.row.user_target_price : '-' }}</span>
|
||||
<span v-else class="muted">未设</span>
|
||||
<!-- 参考目标价 (2026-09-07 拍板): 选股系统按盈利预测算的中性情景估值, 只显示不触发,
|
||||
不替代上面你手设的目标价 —— 到价提议只认命令表里那个数。 -->
|
||||
<div class="muted" v-if="s.row.ref_target" :title="s.row.ref_target.text || ''"
|
||||
style="font-size:11px">参考 {{ s.row.ref_target.price }}({{ s.row.ref_target.firms }} 家中性估值,只显示不触发)</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 入场论点随持仓走 (2026-09-07 第三件)。左栏回答「当初为什么买」: 账本里这只票首批入场那条
|
||||
|
|
|
|||
|
|
@ -59,16 +59,16 @@
|
|||
test_batch22_units.py 逻辑状态四态接入 (2026-09-07 第三件): 解析层收逻辑状态/硬数字带它而研判
|
||||
白名单不收/判决候选而逻辑存疑强制交人/持仓存疑停增持侧/研究走弱
|
||||
减持默认关且开了必交人/同轮减持优先级/早上取回与映射新鲜度/策略
|
||||
买入腿按来源暂停恢复/持仓视图两栏三情形/假仓库签名/安全边际整句透传 (16 例)
|
||||
买入腿按来源暂停恢复/持仓视图两栏三情形/假仓库签名/安全边际整句透传/参考目标价 (17 例)
|
||||
test_page_enum_guard.py 页面文案守卫 (静态扫描, 不连库不起浏览器): 枚举字段不许
|
||||
直接印到页面上 / 判据码显示前必须剥前缀 / 不许把整个对象
|
||||
打给交易员看 / 翻译兜底不许让英文码单独当句子 (1 例)
|
||||
test_wiring.py 装配自检: 服务层→核心→落表 全链路 (内存桩) +
|
||||
目标价到价必定入队 (档位 full 也不自动卖) +
|
||||
用户设的止损价与目标价单独成列显示 (70 例)
|
||||
共 677 例
|
||||
共 678 例
|
||||
(总数按实跑逐批相加校正过两次: 曾写 649 是笔误, 实为 650; 09-03 先后加了同轮只发一条
|
||||
减持与研究理由两键各一例, 到 652; 09-04 加了仅展示跳过原因与空候选说明各一例, 到 654; 又加了页面文案守卫一例, 到 655; 09-07 审查修复加了跨轮减持等五例, 到 660; 第二件低把握驳回交人一例, 到 661; 第三件逻辑状态接入第二十二批十五例, 到 676; 第四件安全边际整句透传一例, 现为 677)
|
||||
减持与研究理由两键各一例, 到 652; 09-04 加了仅展示跳过原因与空候选说明各一例, 到 654; 又加了页面文案守卫一例, 到 655; 09-07 审查修复加了跨轮减持等五例, 到 660; 第二件低把握驳回交人一例, 到 661; 第三件逻辑状态接入第二十二批十五例, 到 676; 第四件安全边际整句透传一例, 到 677; 参考目标价一例, 现为 678)
|
||||
任一子集失败即整体失败 (退出码 1)。
|
||||
|
||||
哨兵位置清单 (2026-09-03 抄录; 改了对应的东西就得来这些地方改断言, 断言不动就是漏了):
|
||||
|
|
|
|||
|
|
@ -438,6 +438,29 @@ def _():
|
|||
assert nv["state"] == "逻辑成立" and nv["settle_note"] == "维持" and "研报论断" in nv["text"], nv
|
||||
|
||||
|
||||
@case("参考目标价·状态应答里的估值子字典归一, 持仓行只在算得出时给 ref_target, 算不出或缺就不给")
|
||||
def _():
|
||||
val = {"neut": 56.05, "pess": 42.64, "opt": 84.96, "price": 50.17, "quarter": "2026Q4", "firms": 8,
|
||||
"as_of": "2026-08-28", "na": None, "implied_pe": 21.4, "odds": 0.78}
|
||||
payload = {"date": "2026-09-04", "states": [
|
||||
{"input": CODE, "code": "SH600000", "source": "daily", **hold(), "valuation": val, "valuation_text": "安全边际(2026 年度预测,8 家):…"},
|
||||
{"input": "600001.SH", "code": "SH600001", "source": "daily", **hold(), "valuation": {"na": "覆盖机构只有 1 家,不足 2 家", "firms": 1}},
|
||||
{"input": "600002.SH", "code": "SH600002", "source": "computed", **hold()}]}
|
||||
m = pf.parse_logic_states(payload)
|
||||
assert m[CODE]["valuation"]["neut"] == 56.05 and m[CODE]["valuation"]["firms"] == 8, m[CODE]
|
||||
assert "implied_pe" not in m[CODE]["valuation"] and m[CODE]["valuation_text"].startswith("安全边际"), m[CODE]
|
||||
assert m["600001.SH"]["valuation"]["na"] and m["600002.SH"]["valuation"] is None
|
||||
rows = [pos(), pos("600001.SH"), pos("600002.SH")]
|
||||
from app.repo import pms_repo
|
||||
with _Patch() as p:
|
||||
p(pms_repo, "list_lots", lambda *a, **k: [])
|
||||
lss.decorate_positions(rows, m)
|
||||
assert rows[0]["ref_target"] == {"price": 56.05, "pess": 42.64, "opt": 84.96, "quarter": "2026Q4", "firms": 8,
|
||||
"as_of": "2026-08-28", "text": "安全边际(2026 年度预测,8 家):…"}, rows[0]["ref_target"]
|
||||
assert rows[1]["ref_target"] is None and rows[2]["ref_target"] is None
|
||||
assert lss.ref_target_view(None) is None and lss.ref_target_view({}) is None
|
||||
|
||||
|
||||
@case("假仓库·ledger_by_ref 与真 repo 同名同签名 (第十批 [M1] 也会扫, 这里先钉一次)")
|
||||
def _():
|
||||
import ast
|
||||
|
|
|
|||
Loading…
Reference in New Issue