fix: 信号-分析对齐(reconcile以已存分析为唯一事实源) + prompt持仓上下文(已持有/未持有分开给建议,禁止两头写)
This commit is contained in:
@@ -95,6 +95,14 @@ def collect_data(code):
|
||||
data["changelog_json"] = r[12] or ""
|
||||
data["reassessed_at"] = r[13] or ""
|
||||
data["position_advice"] = r[14] or ""
|
||||
# 持仓状态(2026-07-22 老爸要求:LLM 必须知道是否持有/成本/股数)
|
||||
hr = conn.execute("SELECT shares, cost, price FROM holdings WHERE code=? AND is_active=1 AND shares>0", (code,)).fetchone()
|
||||
if hr and hr[0]:
|
||||
data["held"] = True
|
||||
data["held_shares"] = hr[0]
|
||||
data["held_cost"] = hr[1] or 0
|
||||
else:
|
||||
data["held"] = False
|
||||
conn.close()
|
||||
|
||||
# 从腾讯API拉最新价和基本面
|
||||
@@ -205,6 +213,20 @@ def build_prompt(data):
|
||||
# 完整分析原文(不截断)
|
||||
_full_analysis = data.get('full_analysis', '') or ''
|
||||
_fa_display = _full_analysis if _full_analysis else '(首次分析,无历史)'
|
||||
|
||||
# ── 持仓上下文(2026-07-22 老爸要求:LLM 必须知道持有状态,建议不得两头都写)──
|
||||
if data.get('held'):
|
||||
_sh = data.get('held_shares', 0)
|
||||
_cost = data.get('held_cost', 0)
|
||||
_px = data.get('price', 0) or 0
|
||||
_pnl = ((_px - _cost) / _cost * 100) if _cost else 0
|
||||
_position_context = (f"⚠️ 我当前【已持有】{data['code']}:{_sh}股,成本{_cost:.2f}元,"
|
||||
f"现价{_px}元(盈亏{_pnl:+.1f}%)。你的建议必须基于「已持有」状态给出"
|
||||
f"(加减仓/止损止盈/持有观察),禁止给「未持有者」的建仓建议。")
|
||||
else:
|
||||
_position_context = (f"⚠️ 我当前【未持有】{data['code']}。你的建议必须基于「未持有」状态给出"
|
||||
f"(是否建仓/什么价位建仓/仓位多大),禁止假设我有浮盈、"
|
||||
f"禁止出现「已持仓者」视角的建议。")
|
||||
|
||||
_orig_strategy_section = f"""当前策略参数: {_params_str}
|
||||
|
||||
@@ -235,6 +257,7 @@ PE={data.get('pe','?')}(最新财报) 市值={data.get('mcap','?')}亿
|
||||
当前信号:{data.get('timing_signal','?')} 分类:{data.get('stock_category','?')}
|
||||
|
||||
我的总资产={total}元,可用现金={cash}元。
|
||||
{_position_context}
|
||||
|
||||
请严格按以下格式输出(注意节标题不可省略):
|
||||
|
||||
@@ -373,8 +396,11 @@ def save_result(code, full_text, parsed):
|
||||
conn.execute(sql, params)
|
||||
conn.commit()
|
||||
|
||||
# ── 推荐操作 tag 同步(与 XMPP 动作级信号同源)──
|
||||
sync_recommend_tag(conn, code, parsed.get("signal", ""))
|
||||
# ── 信号以分析为唯一事实源(防信号/分析脱节)──
|
||||
from mofin_db import reconcile_signal_from_analysis
|
||||
final_sig = reconcile_signal_from_analysis(conn, code)
|
||||
# ── 推荐操作 tag 同步(跟随对齐后的信号)──
|
||||
sync_recommend_tag(conn, code, final_sig)
|
||||
|
||||
# 买入信号推送已统一收拢到 sync_recommend_tag 的转场推送(防双重告警)。
|
||||
# 本路径只负责写库+tag,推送由 mofin_db.push_recommend_alert 在 tag 转场时触发。
|
||||
|
||||
@@ -550,34 +550,14 @@ def main():
|
||||
else:
|
||||
print(f" ⚠️ 12维分析未完成,跳过保存")
|
||||
print(f" [DB] holding_strategies 已更新: {code}")
|
||||
# 从LLM输出提取信号
|
||||
if _full_analysis_text and '【综合结论】' in _full_analysis_text:
|
||||
try:
|
||||
_sig_line = [l for l in _full_analysis_text.split('\n') if '综合结论' in l]
|
||||
if _sig_line:
|
||||
_sig = '买入' if '买入' in _sig_line[0] else '关注' if '关注' in _sig_line[0] else '观望' if '观望' in _sig_line[0] else '卖出' if '卖出' in _sig_line[0] else ''
|
||||
if _sig:
|
||||
_ts_conn = __import__('sqlite3').connect('/home/hmo/MoFin/data/mofin.db')
|
||||
_ts_conn.execute(
|
||||
"UPDATE holding_strategies SET timing_signal=? WHERE code=? AND status='active'", (_sig, code))
|
||||
_ts_conn.commit()
|
||||
# 推荐操作 tag 同步(与 XMPP 动作级信号同源)
|
||||
from mofin_db import sync_recommend_tag
|
||||
sync_recommend_tag(_ts_conn, code, _sig)
|
||||
_ts_conn.close()
|
||||
print(f" ✅ LLM信号={_sig} 已写入")
|
||||
# 买入信号→推XMPP
|
||||
if _sig == "买入":
|
||||
try:
|
||||
_nr2 = __import__('sqlite3').connect('/home/hmo/MoFin/data/mofin.db').execute(
|
||||
"SELECT name, price, entry_low, entry_high, stop_loss, take_profit, position_advice FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
|
||||
if _nr2:
|
||||
_xm = f"📈 {_nr2[0] or code}({code}) 价{_nr2[1]}→12维买入信号!区间{_nr2[2]}~{_nr2[3]} 损{_nr2[4]} 盈{_nr2[5]} 仓位{_nr2[6] or '-'}"
|
||||
from alert_helper import notify as _notify2, ACTION as _ACT2
|
||||
_notify2("买入信号", _xm, _ACT2)
|
||||
print(f" 📨 XMPP推送买入信号")
|
||||
except: pass
|
||||
except: pass
|
||||
# 信号以已存分析为唯一事实源(防信号/分析脱节)
|
||||
# 推荐推送统一走 reconcile→tag→摘要队列(batch 结束统一发,不再单只推送)
|
||||
from mofin_db import reconcile_signal_from_analysis
|
||||
_rc_conn = __import__('sqlite3').connect('/home/hmo/MoFin/data/mofin.db')
|
||||
_sig = reconcile_signal_from_analysis(_rc_conn, code)
|
||||
_rc_conn.close()
|
||||
if _sig:
|
||||
print(f" ✅ LLM信号={_sig} 已对齐")
|
||||
# 冷却期已更新(reassessed_at写入)
|
||||
except Exception as _dbe:
|
||||
print(f" [DB FAIL] holding_strategies 写入失败: {_dbe}", file=sys.stderr)
|
||||
|
||||
Reference in New Issue
Block a user