feat: position hard-constraint + cash-linked sizing + rotation context

- 建议仓位必须具体数字%,模糊表述(中等仓位/减仓或观望/轻仓)视为输出作废
- 必须结合可用现金计算可买股数,理想仓位超现金时写出实际可执行仓位+换仓建议
- 未持有股票注入最弱3只持仓上下文,LLM可给'减持XX换入'的具体换仓建议
This commit is contained in:
hmo
2026-07-24 14:04:02 +08:00
parent a6ad0f6f9e
commit 1523f9ad16
+28 -2
View File
@@ -285,6 +285,29 @@ def build_prompt(data):
_position_context = (f"⚠️ 我当前【未持有】{data['code']}。你的建议必须基于「未持有」状态给出" _position_context = (f"⚠️ 我当前【未持有】{data['code']}。你的建议必须基于「未持有」状态给出"
f"(是否建仓/什么价位建仓/仓位多大),禁止假设我有浮盈、" f"(是否建仓/什么价位建仓/仓位多大),禁止假设我有浮盈、"
f"禁止出现「已持仓者」视角的建议。") f"禁止出现「已持仓者」视角的建议。")
# ── 换仓上下文(2026-07-24 老爸:现金不足时给出具体换股建议)──
_rotation_context = ""
if not data.get('held'):
try:
_rc = sqlite3.connect(DB)
_weak = _rc.execute("""
SELECT hs.code, hs.name, hs.timing_signal, h.position_pct, h.cost
FROM holding_strategies hs
JOIN holdings h ON hs.code = h.code AND h.is_active = 1
WHERE hs.status='active' AND h.shares > 0
AND hs.timing_signal IN ('弱势持有','观望','持有')
ORDER BY CASE hs.timing_signal WHEN '弱势持有' THEN 0 WHEN '观望' THEN 1 ELSE 2 END,
h.position_pct DESC LIMIT 3""").fetchall()
_rc.close()
if _weak:
_wl = "".join(f"{w[1]}({w[0]}){w[2]}仓位{w[3]:.1f}%" for w in _weak)
_rotation_context = (f"\n我的最弱持仓(可减换仓候选):{_wl}"
f"若你认为{data['code']}比它们更值得持有,在【操作建议】末尾明确写"
f"「换仓建议:减持XX换入本股」。")
except Exception:
pass
_position_context += _rotation_context
_orig_strategy_section = f"""当前策略参数: {_params_str} _orig_strategy_section = f"""当前策略参数: {_params_str}
@@ -372,8 +395,11 @@ PE={data.get('pe','?')}(最新财报) 市值={data.get('mcap','?')}亿
大盘偏弱×0.8,大盘偏强×1.15 大盘偏弱×0.8,大盘偏强×1.15
蓝筹/白马×1.2,成长×0.85,题材/短线×0.6 蓝筹/白马×1.2,成长×0.85,题材/短线×0.6
最终仓位范围:5%~20% 最终仓位范围:5%~20%
同时考虑:现金{cash}元足够买多少手。 ⚠️ 仓位硬约束(必须遵守):
输出格式:"X%(理由:一句话说明为什么这个仓位" - 必须输出具体数字%(如"8%(理由)"),禁止"中等仓位/减仓或观望/轻仓/适量"等模糊表述——模糊仓位视为输出作废
- 必须结合可用现金{cash}元计算可买股数,仓位%对应的金额不得超过可用现金
- 若理想仓位超出现金,明确写出:实际可执行仓位X%(受现金限制),并给出换仓建议(减持哪只弱持仓换入本股)
输出格式:"X%(理由:含现金可行性的一句话说明)"
⚠️ 输出纪律(必须遵守): ⚠️ 输出纪律(必须遵守):
1. 直接以【维持或修改】开头,禁止任何寒暄、开场白、分隔线 1. 直接以【维持或修改】开头,禁止任何寒暄、开场白、分隔线