From f91a2f86e75aebcaad7ee84b8961f66791f9d72e Mon Sep 17 00:00:00 2001 From: zlt Date: Mon, 3 Aug 2026 14:19:33 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=89=E8=82=A1=E8=AE=A1=E5=88=92=E5=85=A5?= =?UTF-8?q?=E6=B1=A0=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.py | 6 +++--- docs/选股计划入池_对接说明.md | 2 +- pool.py | 21 +++++++++++++++++++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/config.py b/config.py index eec2419..4269a15 100644 --- a/config.py +++ b/config.py @@ -61,9 +61,9 @@ def price_mysql() -> Conn: def pms_mysql() -> Conn: - """读持仓(trading_position)与决策系统结论(strategy_daily_results),入池用。 - 这两张表都在 153 代理后面——与热度是同一台,默认直接复用 HEAT_MYSQL_*, - 只有代理路由不通时才需要单独配 PMS_MYSQL_*。""" + """读持仓(首选 PMS 账本 pms_position,下游 trading_position 兜底)与决策系统 + 结论(strategy_daily_results),入池用。这几张表都在 153 代理后面——与热度是 + 同一台,默认直接复用 HEAT_MYSQL_*,只有代理路由不通时才需要单独配 PMS_MYSQL_*。""" return Conn(_opt("PMS_MYSQL_HOST", _req("HEAT_MYSQL_HOST")), int(_opt("PMS_MYSQL_PORT", os.environ.get("HEAT_MYSQL_PORT", "3306"))), _opt("PMS_MYSQL_USER", _req("HEAT_MYSQL_USER")), diff --git a/docs/选股计划入池_对接说明.md b/docs/选股计划入池_对接说明.md index 04dde45..2bb461f 100644 --- a/docs/选股计划入池_对接说明.md +++ b/docs/选股计划入池_对接说明.md @@ -22,7 +22,7 @@ Mongo 侧记账(回收站),分析侧的清理是自动的。 | 规则 | 内容 | |---|---| -| 入池 | 当日计划(强传导主榜前 `POOL_TOP`,与 PMS 候选同口径)∪ 当前持仓(`trading_position` 数量>0) | +| 入池 | 当日计划(强传导主榜前 `POOL_TOP`,与 PMS 候选同口径)∪ 当前持仓(首选 PMS 账本 `pms_position`——新架构下下游 `trading_position` 已无写入方,账本才是有人维护的持仓事实;账本读不到才退回下游表兜底) | | 留池 | 旧成员既不在计划也无持仓、但形态未恶化的,留下继续接受每晚分析——榜单是按条数截断过的,掉榜不等于变坏 | | 出池 | 无持仓、不在计划、且形态已恶化 → 移入回收站 `stock_recycle_bin`。恶化判据用决策系统自己的结论:`strategy_daily_results` 最新定性为 SELL / AVOID / DROPPED | | 上限 | 池子超过 `POOL_MAX`(默认 60)时,从「留池观察」里清最久没上过榜的;这类清退不进回收站(它们没有恶化记录),出池后由决策系统的 DROPPED 机制收尾 | diff --git a/pool.py b/pool.py index 66a6e5b..7f6483b 100644 --- a/pool.py +++ b/pool.py @@ -141,8 +141,25 @@ def build_recycle_docs(d: dict, group_id: str, group_name: str, org_id: str, # 取数(每一路的失败语义见模块头「安全边界」) # ============================================================================ def _read_holdings() -> set: - """当前持仓(trading_position,数量>0)。列名在下游换过多次,按候选名单挑; - 读不到就抛——持仓是出池判断的底线输入,读不到宁可整轮不动池子。""" + """当前持仓。首选 PMS 账本 pms_position(新架构下它才是有人维护的持仓事实源: + 下游 trading_position 表已没有写入方,2026-07-30 实测账户有仓时该表也是空的); + 账本表读不到再退回 trading_position 兜底。两条路都读不到就抛——持仓是出池判断 + 的底线输入,读不到宁可整轮不动池子。""" + try: + rows = db.read_mysql( + "pms", "SELECT ts_code, total_qty, status FROM pms_position") + out = set() + for r in rows.itertuples(): + try: + qty = float(r.total_qty) + except (TypeError, ValueError): + qty = 0.0 + if qty > 0 and str(r.status or "").upper() != "CLOSED": + out.add(common.to_prefix(str(r.ts_code).strip().upper())) + return out + except Exception as e: # noqa: BLE001 —— 账本表读不到才走下游表兜底 + print(f" (PMS 账本 pms_position 读取失败,退回 trading_position 兜底: {e!r})") + rows = db.read_mysql("pms", "SELECT * FROM trading_position") if rows.empty: return set()