FinAgent组合经理阶段怎么做:设计、实现逻辑与报告输出

摘要:组合经理(portfolio_manager)是FinAgent单股分析流水线的倒数第二个业务阶段,位于风控评审之后、组合报告之前。它在Risk Judge终稿与规则风险基线之上,由LLM给出五档投资组合评级(Buy/Overweight/Hold/Underweight/Sell)及执行摘要、投资论点等叙事,并与技术面、情绪、风险等结构化字段合并为final_conclusion(最终结论)。本文说明该节点的设计约定、实现逻辑、兜底策略,以及结果如何进入report_json、Markdown 与前端展示。

关键词:FinAgent;LangGraph;组合经理


一、组合经理在流水线中做什么

主图顺序(server/finagent/graph/runner.py):

analyst→research_debate→trader→risk_review→portfolio_manager→build_report
阶段 职责 主要产出
risk_review(上游) 风控辩论+Risk Judge审议交易员方案 final_trade_decisionrisk_sectionrisk_debate_state
portfolio_manager(本文重点) 在风控结论之上,站在整个组合的角度做五档评级+执行摘要 portfolio_outputfinal_conclusion
build_report(下游) 把所有内容打包成网页和PDF report_json、Markdown

对照投研分工:交易员提方案,风控审议并给出裁决终稿,组合经理再从资产配置、仓位与执行节奏等角度给出评级与摘要


二、设计思路:输入、输出与上下游衔接

2.1 设计原则

  1. 汇总上游,不重复拉数:不再访问行情接口,主要阅读交易员方案、风控裁决与辩论、三份分析师报告。
  2. 结构化骨架 + LLM 叙事:先用规则字段生成标题、风险摘要等固定结构,AI再往里填评级和长文,避免报告格式混乱。
  3. 评级必须可解析:Prompt要求AI明确写Buy/Hold/Sell等词,代码用_extract_rating从正文中抽取,供评分卡与Markdown使用。
  4. LLM 失败可降级:模型不可用或报错时,自动降级为HOLD+简短说明,保证整条分析线不会卡,进入最终报告。

2.2 输入字段

portfolio_manager_node从共享状态state读取:

字段 来源 用途
ticker/analysis_date 用户创建分析任务时传入 写入Prompt,标明标的(股票代码)与日期
trader_investment_plan trader 交易员方案
final_trade_decision/risk_debate_state.judge_decision risk_review Risk Judge裁决的正文
risk_debate_state.history risk_review 风控辩论全文(截断后传入)
risk_section risk_review risk_levelrisk_score(风险分数、等级)等
三份 *_report analyst 证据材料,默认最多12000字符,太长会截断

组合经理的输入=交易员方案+风控裁决与辩论+规则风险分+三份分析师报告+部分结构化技术面/情绪字段。

2.3 输出字段

字段 类型 说明
portfolio_output 对象 本阶段总包裹;含llm(表明是否走通了LLM)、portfolio_narrative(大模型生成的完整文本内容)
portfolio_output.final_conclusion 对象 写入report_json.final_conclusion的主结构,组合经理输出的核心业务数据结构,是整份研报最终综合结论的数据源
final_conclusion.rating 字符串 五档标准:BUY/OVERWEIGHT/HOLD/UNDERWEIGHT/SELL(解析失败默认 HOLD
final_conclusion.llm_narrative 字符串 大模型完整投资论述(包含执行摘要、投资逻辑、组合配置建议,全文最长约8000字符),前端组合经理部分的展示
final_conclusion.headline 对象 规则自动生成,如:HIGH 风险 | 情绪=…
memory_log 字符串列表 日志记录,用来排查问题[portfolio_manager] LLM narrativerule final_conclusion

2.4 与下游的关系

  • build_report:若portfolio_output.final_conclusion存在,覆盖/写入report_json["final_conclusion"](最终报告部分);Markdown综合结论一节会展示headlinerating等。
  • trading_signal(交易信号,如买入):仍在build_report中由 final_trade_decision(风控阶段的最终裁决) 解析,由组合经理评级直接映射。
  • Agent 评分卡agent_scorecards.portfolio_manager结合叙事文本、ratingrisk_score给出展示分,标注prototype_shell(该模块属于原型壳功能,仅用于前端页面可视化展示,不能用于实盘交易、合规投研归档)。

三、实现逻辑

核心代码位于server/finagent/agents/managers/portfolio_manager.py

否或异常

读取 state

get_chat_model deep 可用?

组装 Prompt 调用 LLM

generate_final_conclusion 骨架

_extract_rating + 写入 llm_narrative

返回 portfolio_output

规则骨架 + Hold 兜底文案

3.1 LLM 主路径

使用深思考档(与Risk Judge同级),Prompt书写以下要点:

  • 角色:组合经理,在Risk Judge裁决之后给出最终组合评级;
  • 评级需要五选一:Buy/Overweight/Hold/Underweight/Sell;
  • 输出结构(固定模块):Rating(评级)、Executive Summary(执行摘要,包含仓位、入场、风控、周期)、Investment Thesis(基于证据的投资论点);
  • 输入材料:标的与日期、交易员方案、Judge 裁决(截断 6000)、风险基线、风控辩论(6000)、三份分析师报告(8000)。

调用成功后:

  1. 调用generate_final_conclusion(tech, sentiment, risk)得到规则骨架,搭好报告的标准化结构;
  2. 将LLM返回正文写入fc["llm_narrative"],作为前端组合经理部分的展示正文,并用_extract_rating解析fc["rating"](评级),存入对应的存入final_conclusion.rating字段;
  3. 返回portfolio_output: { final_conclusion: fc, llm: True, portfolio_narrative: text },将封装阶段结果返回写入流水线状态。

3.2 评级提取(_extract_rating

在LLM正文中按优先级搜索英文评级词(整词匹配):

UNDERWEIGHTOVERWEIGHTBUYSELLHOLD

均未命中则默认 HOLD。这样可以避免子串误匹配(例如先匹配OVERWEIGHT再匹配WEIGHT)。

3.3 规则兜底

get_chat_model(获取模型)返回None,或invoke抛错的时候:

  • 仍生成generate_final_conclusion的报告标准结构骨架;
  • rating固定为 HOLD(持有);
  • llm_narrative预填写简短英文模板(说明 LLM 不可用、建议暂缓加仓);
  • portfolio_output.llm为**False**,标识本次结论不是LLM生成,是规则兜底产出;memory_log[portfolio_manager] rule final_conclusion,日志说明该阶段触发了降级策略,方便排查模型、接口类故障。

流水线可继续执行build_report,不会出现组合经理阶段整段的缺失。


四、接入主图与阶段开关

主图节点_portfolio_noderunner.py)负责:

1.读取环境配置做阶段校验:从环境变量FINAGENT_ENABLED_STAGES读取当前开启的流水线阶段列表,如果列表里没有配置portfolio_manager,直接跳过本阶段,portfolio_output赋值为空对象,不会执行组合经理的 LLM、规则兜底等所有逻辑。
2.标记当前任务进度:调用mark_stage,把前端展示的任务执行进度更新为组合经理,用户可以在页面看到当前运行到哪一步。
3.执行业务核心函数:把全局流转的状态state转为字典传入,调用我们前面讲的portfolio_manager_node,执行LLM研判/规则兜底的逻辑,拿到处理结果portfolio_output
4.结果回写全局状态:将portfolio_output写回AnalysisGraphState全局状态对象,下游build_report报告生成节点才能读取到组合经理产出的最终结论数据。

.env 完整流水线示例:

FINAGENT_ENABLED_STAGES=analyst,research_debate,trader,risk_review,portfolio_manager,build_report

五、报告输出与前端展示

5.1 写入report_json

build_report阶段逻辑(_build_report_node):

  1. 调用generate_report_json(...)生成含技术面、新闻、风险等的基础 JSON(其中已含一份默认 final_conclusion);
  2. 若主图state 中存在portfolio_output.final_conclusion,则用组合经理产出覆盖上面的 report_json["final_conclusion"]
  3. 同时挂载final_trade_decisiontrading_signaltrader_*risk_debate_state等字段;
  4. 调用build_agent_scorecards(report_json)生成各Agent评分卡。
字段 主要来源阶段 典型含义
trader_investment_plan 交易员 交易方案原文
final_trade_decision 风控 Risk Judge 风控审议后的买/持/卖终稿
final_conclusion(含 rating 组合经理 五档组合评级+执行摘要/论点
trading_signal final_trade_decision解析(build_report) 页面买入/目标价等标签

5.2 Markdown导出

generate_report_markdown 在文末综合结论与辅助建议一节输出:

  • final_conclusion.headlinerecommendation_style
  • 组合经理评级final_conclusion.rating
  • 另附Risk Judge终稿章节与 结构化的交易信号(来自 trading_signal
    在这里插入图片描述

5.3 前端展示

(1)组合经理PortfolioManagerTab

页面区域 数据来源
折叠的组合经理正文 final_conclusion.llm_narrativeportfolio_narrative
标题旁评级BUY/HOLD/… final_conclusion.rating
评分等小标签 agent_scorecards.portfolio_manager

(2)投资结论InvestmentConclusion

汇总展示final_conclusion.headline、风险要点、trading_signal标签,以及交易员/风控/组合经理三张下游评分卡——组合经理在此以评分与评级参与总览,而非重复全文。
在这里插入图片描述

5.4 Agent 评分卡

agent_scorecards.py对组合经理:

  • 文本来源优先final_trade_decision,否则llm_narrative
  • rating映射基础分(如BUY偏高、SELL偏低),再与风险分等加权;
  • 标注 prototype_shell:未部署完整组合约束、归因与实盘合规规则,仅展示用

六、总结

FinAgent的组合经理阶段,在风控Judge终稿与规则风险基线之上,用一次深思考 LLM 调用产出五档评级组合层叙事,并与规则生成的headline、风险摘要等合并为 final_conclusion。它在流水线中的角色是研究—交易—风控之后的最后一环业务 Agent,再把结果交给build_report统一出报告与评分卡。

往期:
【山东大学项目实训FinAgent】风控评审阶段怎么做:设计、实现逻辑与报告输出
【山东大学项目实训FinAgent】 交易员阶段:设计、实现逻辑与报告输出

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐