Featured image of post A股行情助手——利用数据增强AI解决问题的能力

A股行情助手——利用数据增强AI解决问题的能力

效果展示

上一篇文章末尾提到:功能拆分后的多Agent,遗留了这样几个问题——

  1. 最突出的一点就是:有准确数据,质量就好许多,没有数据还是会拉。

  2. 关于信息置信度的问题:在Agent 自主探索模式下,其实最担心的一个问题就是LLM自己编造数据和事实。

    这里在提示词中约束了在报告中 “每个关键信息后必须标注 [原文]” ,但效果还是不太理想。

  3. 最终输出报告没有一个框架,每次格式都不一样。

  4. 这里代码只能算 demo ,操作起来就很不方便——换个问题,就需要改代码。

  5. 这里用户输入的需求比较模糊(比如,什么叫 “大事件”),导致模型在执行和输出的时候,结论也不稳定。

今天通过一个A股行情助手的案例,展示数据在AI 应用中的重要作用(也就是 1 当中的问题)。

顺便通过 LangGraph + Streamlit 解决之前遗留的问题 4 ,提升用户操作体验,并展示在LangGraph中如何高效应对“上下文污染”的问题。

这个Agent 应用的web 交互界面如下——

用户只需在对话框中提出问题,后台AI 就会完成用户需求分析、信息检索、直至最后报告产出。

例如:这里提问 “集成电路制造板块中,哪些公司有出口业务,我需要其中最值得投资的一只”

稍等片刻,页面会展示相关股票最近一年 价格行情走势图——

演示案例1

并分析个股的财报数据——

最终给出推荐——

哈哈,是不是有点跃跃欲试了呢?

Agent分工

我们先看下这个Agent 的内部处理"总线"。

agent_graph

单看框架,仍然是之前提到的简单多Agent结构——

一个Agent 负责慢思考,一个Agent负责调用工具完成任务执行。之前详细讨论过这部分内容。

简化起见,plan_node 这里只让AI 思考一轮 。

重点是:使用 LangGraph 来编排不同node 节点,维护、管理他们之间的上下文。

简单的代码演示

定义4个节点——

节点名 任务 共享State
plan_node 生成任务计划 Plan Y
llm_call 生成符合工具调用格式的 Action参数 Y
tool_node 工具执行,输出 Observation Y
should_continue 根据 llm_call 输出内容决定去向 Y

Agent 主体代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
from langgraph.graph import MessagesState, StateGraph, START, END
from langchain_core.messages import SystemMessage, HumanMessage, ToolMessage
from langchain_core.prompts import ChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplate,MessagesPlaceholder
from typing_extensions import Literal
from IPython.display import Image, display
from .llm import DeepSeekR1,DeepSeekV3
from .tools.financial_report import get_financial_report
from .tools.stock_price import analyze_stocks
from .prompt import plan_prompt
import pandas as pd

# Nodes
tools = [get_financial_report, analyze_stocks]
tools_by_name = {tool.name: tool for tool in tools}

# 量化循环次数上限,默认3,最大15
DEFAULT_MAX_LOOP = 3
MAX_LOOP_LIMIT = 15

def _get_max_loop(state):
    """从 state 或全局常量获取循环上限"""
    return min(state.get("max_loop_count", DEFAULT_MAX_LOOP), MAX_LOOP_LIMIT)

class State(MessagesState):
    plan: str
    loop_count: int = 0  # 已执行工具调用的次数
    
def plan_node(state):
    deepseek_r1 = DeepSeekR1()
    prompt = plan_prompt
    # 调用 LLM 生成计划
    response = deepseek_r1.invoke([SystemMessage(content=prompt), state["messages"][0]])
    print(f"--- Generated Plan ---\n{response.content}\n----------------------")
    return {"plan": response.content}

def llm_call(state):
    """LLM decides whether to call a tool or not"""
    deepseek_v3 = DeepSeekV3()
    llm_with_tools = deepseek_v3.bind_tools(tools)
    
    plan = state.get("plan", "执行分析")
    messages = [
        SystemMessage(
            content=f"""
你是一个思路清晰,有条理的金融分析师,必须严格按照以下金融分析计划执行:

当前金融分析计划:
{plan}

如果你认为计划已经执行到最后一步了,请在内容的末尾加上\nFinal Answer字样

示例:
分析报告xxxxxxxx
Final Answer
            """
        )
    ] + state["messages"]
    
    # 调用 LLM
    response = llm_with_tools.invoke(messages)
    # 只返回增量消息,不返回整个 state
    return {"messages": [response]}

def tool_node(state):
    """Performs the tool call and increments trade counter"""
    messages = state["messages"]
    last_message = messages[-1]
    
    new_messages = []
    for tool_call in last_message.tool_calls:
        tool_name = tool_call["name"]
        tool_args = tool_call["args"]
        tool_id = tool_call["id"]
        
        tool_func = tools_by_name[tool_name]
        
        try:
            observation = tool_func.invoke(tool_args)
            # 序列化结果
            if isinstance(observation, (pd.DataFrame, pd.Series, list, dict)):
                observation = str(observation)
            new_messages.append(ToolMessage(content=str(observation), tool_call_id=tool_id))
        except Exception as e:
            new_messages.append(ToolMessage(content=f"工具执行出错: {str(e)}", tool_call_id=tool_id))
            
    new_state = {"messages": new_messages}
    # 更新循环计数
    new_state["loop_count"] = state.get("loop_count", 0) + len(new_messages)
    return new_state

def should_continue(state):
    """根据 LLM 是否进行工具调用或是否输出 Final Answer 来决定去向"""
    messages = state["messages"]
    last_message = messages[-1]
    
    # 1. 如果有工具调用,必须进入 environment
    if hasattr(last_message, 'tool_calls') and last_message.tool_calls:
        current_count = state.get("loop_count", 0)
        if current_count >= _get_max_loop(state):
            # 达到上限,强制结束,追加提示
            return "MaxTradeReached"
        return "Action"
    
    # 2. 如果内容包含 Final Answer,结束流程
    if last_message.content and "Final Answer" in last_message.content:
        return "END"
    
    # 3. 如果既没调工具也没说结束,继续让 LLM 处理
    return "Continue"

# Build workflow
agent_builder = StateGraph(State)

# Add nodes
agent_builder.add_node("plan_node", plan_node)
agent_builder.add_node("llm_call", llm_call)
agent_builder.add_node("environment", tool_node)

# Add edges to connect nodes
agent_builder.add_edge(START, "plan_node")
agent_builder.add_edge("plan_node", "llm_call")
agent_builder.add_conditional_edges(
    "llm_call",
    should_continue,
    {
        "Action": "environment",
        "MaxTradeReached": END,
        "END": END,
        "Continue": "llm_call"
    },
)
agent_builder.add_edge("environment", "llm_call")

# Compile the agent
agent = agent_builder.compile()

# Invoke 部分已在 app.py 中通过 streamlit 调用,此处不再自动执行测试逻辑

重点在两个地方——

  1. 不同节点间需要共享信息(例如 LLM 答复内容中的 content 信息和 tool_call 信息)。

    LangGraph本身提供了这样一个类: MessagesState,用来存放不同Agent 场景下LLM 返回的消息。

    不过在本案例中,只保留LLM 原始的内容还不够,需要小改造下:

    一个是plan_node 中生成的总体计划内容 plan

    还有一个是循环次数计数 loop_count,便于控制循环。

1
2
3
4
# 相关代码
class State(MessagesState):
    plan: str
    loop_count: int = 0  # 已执行工具调用的次数
  1. 然后把不同节点像拼乐高一样,拼接起来 ——
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Build workflow
agent_builder = StateGraph(State)

# Add nodes
agent_builder.add_node("plan_node", plan_node)
agent_builder.add_node("llm_call", llm_call)
agent_builder.add_node("environment", tool_node)

# Add edges to connect nodes
agent_builder.add_edge(START, "plan_node")
agent_builder.add_edge("plan_node", "llm_call")
agent_builder.add_conditional_edges(
    "llm_call",
    should_continue,
    {
        "Action": "environment",
        "MaxTradeReached": END,
        "END": END,
        "Continue": "llm_call"
    },
)
agent_builder.add_edge("environment", "llm_call")

💡 如何用它解决“上下文污染”问题?

主要通过以下方法应对:

  1. 共享 State 扩展:将高开销的 plan 规划和大盘计数器存入自定义的 State 中进行进程全局共享,只让 LLM 在 SystemMessage 中看到结构化好的当前步骤逻辑,彻底避免在 Chat Message 历史中塞满规划废话。
  2. 业务特征数据提前加工:工具在向 Agent 返回 Observation 前,会直接通过 pandas/numpy 处理好高维的 区间涨跌幅(%)最大回撤(%)年化波动率(%) 等字典数据,裁剪掉近一年几百个 原始K线行情数据,以极小的数据空间返回给 LLM。

Web 交互页面代码

主体Agent 编排好了后,使用 streamlit 工具生成 web 操作页面(可以让openclaw 帮你生成,效果还可以)。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# app.py 文件
import streamlit as st
import os
import sys
import pandas as pd
import json
from langchain_core.messages import HumanMessage

# 项目根目录
APP_DIR = os.path.dirname(os.path.abspath(__file__))

# 存储路径
CONFIG_FILE = os.path.join(APP_DIR, "config.json")

def load_config():
    if os.path.exists(CONFIG_FILE):
        try:
            with open(CONFIG_FILE, "r") as f:
                return json.load(f)
        except:
            return {}
    return {}

def save_config(config):
    with open(CONFIG_FILE, "w") as f:
        json.dump(config, f)

# 初始加载
saved_config = load_config()
if not os.environ.get("deepseek_key"):
    os.environ["deepseek_key"] = saved_config.get("api_key", "EMPTY")

from agent.agent import agent

st.set_page_config(page_title="A股行情智能助手", layout="wide")

st.title("🤖 A股行情智能助手")
st.caption("基于 LangGraph + DeepSeek 的A股行情分析工具 | 当前环境:OpenClaw")

# 在顶部显示一些关键统计(如果数据可用)
data_path = os.path.join(APP_DIR, 'data', 'all_data.csv')
if os.path.exists(data_path):
    try:
        df_preview = pd.read_csv(data_path)
        total_stocks = df_preview['股票代码'].nunique()
        latest_date = pd.to_datetime(df_preview['日期']).max().strftime('%Y-%m-%d')
        c1, c2, c3 = st.columns(3)
        c1.metric("本地股票总数", f"{total_stocks} 只")
        c2.metric("最新数据日期", latest_date)
        c3.metric("系统状态", "就绪")
    except:
        pass

# 初始化
if "messages" not in st.session_state:
    st.session_state.messages = []
if "run_prompt" not in st.session_state:
    st.session_state.run_prompt = None

with st.sidebar:
    st.header("配置")
    current_key = st.text_input("DeepSeek API Key", type="password", value=os.environ.get("deepseek_key", ""))
    
    col1, col2 = st.columns(2)
    if col1.button("💾 保存 Key"):
        if current_key:
            save_config({"api_key": current_key})
            os.environ["deepseek_key"] = current_key
            st.success("已保存到本地")
        else:
            st.warning("请输入 Key")
            
    if col2.button("🗑️ 清除缓存"):
        if os.path.exists(CONFIG_FILE):
            os.remove(CONFIG_FILE)
            os.environ["deepseek_key"] = "EMPTY"
            st.rerun()
    
    if current_key and current_key != "EMPTY":
        os.environ["deepseek_key"] = current_key

    st.markdown("---")
    
    saved_config = load_config()
    max_loop = saved_config.get("max_loop_count", 3)
    selected_max = st.slider("🔄 最大循环次数", 1, 15, max_loop, help="Agent 最大工具调用次数,默认3,最大15")
    if st.button("💾 保存设置"):
        save_config({"api_key": saved_config.get("api_key", ""), "max_loop_count": selected_max})
        st.success(f"已保存:最大循环次数 = {selected_max}")

    st.markdown("---")
    st.markdown("### 常用功能")
    if st.button("📈 查看涨跌概览"):
        st.session_state.run_prompt = "分析当前A股市场的整体涨跌情况(查看最近一天的涨跌幅)"
    
    if st.button("🏢 白酒双雄对比"):
        st.session_state.run_prompt = "对比分析 600519 和 000858 最近一年的走势和回撤情况"
    
    if st.button("⚡ 半导体龙头分析"):
        st.session_state.run_prompt = "分析 688981 和 603501 的表现,并获取其最新的财务概况"
    
st.info("💡 示例:'分析 600519 和 000858 最近一年的走势' 或 '寻找最近业绩表现好的半导体公司'")

# 定义分析核心逻辑
def run_analysis(prompt_text):
    st.session_state.messages.append({"role": "user", "content": prompt_text})
    
    with st.chat_message("assistant"):
        with st.status("正在思考中...", expanded=True) as status:
            try:
                # 调用 Agent
                messages = [HumanMessage(content=prompt_text)]
                env_key = os.environ.get("deepseek_key")
                if not env_key or env_key == "EMPTY":
                    st.error("请先在侧边栏输入 DeepSeek API Key 并保存")
                    st.stop()
                
                max_loop = saved_config.get("max_loop_count", 3)
                ret = agent.invoke({"plan": "", "messages": messages, "max_loop_count": max_loop})
                final_answer = ret["messages"][-1].content
                
                # 检查结果文件
                output_dir = os.path.join(APP_DIR, "output")
                output_chart = os.path.join(output_dir, "stocks_price_chart.png")
                output_csv = os.path.join(output_dir, "stocks_analysis.csv")
                
                if os.path.exists(output_chart):
                    st.image(output_chart, caption="分析结果图表")
                
                if os.path.exists(output_csv):
                    analysis_df = pd.read_csv(output_csv)
                    st.subheader("📊 量化指标分析")
                    st.dataframe(analysis_df, use_container_width=True)
                    
                    try:
                        os.remove(output_chart)
                        os.remove(output_csv)
                    except: pass
                
                st.markdown(final_answer)
                st.session_state.messages.append({"role": "assistant", "content": final_answer})
                status.update(label="分析完成!", state="complete", expanded=False)
            except Exception as e:
                st.error(f"发生错误: {str(e)}")
                status.update(label="出错啦", state="error")

# 渲染历史记录
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])

# 处理侧边栏按钮触发
if st.session_state.run_prompt:
    p = st.session_state.run_prompt
    st.session_state.run_prompt = None # 清除标记防止循环
    with st.chat_message("user"):
        st.markdown(p)
    run_analysis(p)

# 处理底部输入框触发
if user_input := st.chat_input("输入你的分析需求..."):
    with st.chat_message("user"):
        st.markdown(user_input)
    run_analysis(user_input)

启动应用

最后,启动它——

1
python3 -m streamlit run ./path/Finance_agent/app.py --server.port 8501 --server.address 0.0.0.0 &

展开说说数据

应用的可靠性来源,只有一个——真实的个股行情数据!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
日期,股票代码,开盘,收盘,最高,最低,成交量,成交额,振幅,涨跌幅,涨跌额,换手率
==================================================================
2026-04-30,688981,113.31,118.73,119.88,113.3,1018383,11911527206.0,5.85,5.57,6.26,5.09
2026-05-06,688981,122.0,123.1,128.12,121.74,1292941,16176667799.0,5.37,3.68,4.37,6.47
2026-05-07,688981,125.11,125.34,127.48,122.22,842774,10482928520.0,4.27,1.82,2.24,4.21
2026-05-08,688981,122.9,120.31,123.19,120.05,708618,8595731864.0,2.51,-4.01,-5.03,3.54
2026-05-11,688981,122.99,122.52,124.57,121.9,814860,10017304327.0,2.22,1.84,2.21,4.08
2026-05-12,688981,124.44,121.98,125.44,120.0,817732,10018643228.0,4.44,-0.44,-0.54,4.09
2026-05-13,688981,119.0,121.86,122.5,116.04,954951,11374279337.0,5.3,-0.1,-0.12,4.78
2026-05-14,688981,121.92,117.9,124.04,117.0,790650,9451219953.0,5.78,-3.25,-3.96,3.95
2026-05-15,688981,121.0,119.02,125.0,118.48,1328101,16152497227.0,5.53,0.95,1.12,6.64
2026-05-18,688981,117.4,117.62,120.34,115.6,748969,8855418364.0,3.98,-1.18,-1.4,3.75
2026-05-19,688981,116.16,115.04,116.69,112.68,423465,4841922272.0,3.41,-2.19,-2.58,2.12

但是,仅凭以上数据还不够。

加工个股数据

上面单只股票的行情数据中并没有 区间涨跌幅(%) 最大回撤(%) 年化波动率(%) 这样的数据,而这些都是股票买入时需要考虑的波段风险。那怎么办呢?

需要在工具中提前计算得到——

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 计算日收益率
stock_data['日收益率'] = stock_data['收盘'].pct_change()

# 计算年化波动率 (假设一年252个交易日)
volatility = stock_data['日收益率'].std() * np.sqrt(252) * 100

# 计算关键指标
start_price = stock_data.iloc[0]['收盘']
end_price = stock_data.iloc[-1]['收盘']
total_return = (end_price - start_price) / start_price * 100

# 计算最大回撤
stock_data['max_price'] = stock_data['收盘'].cummax()
stock_data['drawdown'] = (stock_data['max_price'] - stock_data['收盘']) / stock_data['max_price'] * 100
max_drawdown = stock_data['drawdown'].max()

# 添加到结果列表
all_results.append({
    '股票代码': stock_code,
    '起始价格': start_price,
    '结束价格': end_price,
    '区间涨跌幅(%)': total_return,
    '最大回撤(%)': max_drawdown,
    '年化波动率(%)': volatility
})

这样工具执行后,交给LLM 看到的就是 对应股票最近一年的 股票代码 启始价格 结束价格 区间涨跌幅(%) 最大回撤(%) 年化波动率(%) 的字典。

对模型来说,是非常喜欢这种高质量的结构化数据的。

年报数据

此外,为了衡量公司业务发展健康情况,年报数据也是必不可少的——

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
序号,股票代码,股票简称,每股收益,营业总收入-营业总收入,营业总收入-同比增长,营业总收入-季度环比增长,净利润-净利润,净利润-同比增长,净利润-季度环比增长,每股净资产,净资产收益率,每股经营现金流量,销售毛利率,所处行业,最新公告日期
===========================================================================
1,874802,百通新材,0.92,568533417.18,15.2664657113,,70277380.14,5.6561238395,,4.714433245425,,0.243883317106,42.5663104027,,2026-05-26
2,874495,永大股份,0.78,726886558.97,-11.2829906928,809.5712,109380450.58,2.4936171442,4773.7024,5.553841913586,15.19,0.722337518558,25.1149323821,,2026-05-26
3,430458,陆海科技,0.23,83247380.45,-1.7498264956,,12351090.09,12.48,,2.662792619145,8.29,0.270151610955,37.3351179124,,2026-05-26
4,300478,杭州高新,-0.2159,391752002.18,2.0808366297,-28.4642,-27354269.44,-12.41,-10.9108,0.320361491162,-50.41,-0.119990702991,2.7171438055,塑料,2026-05-26
5,920206,彩客科技,2.3,506680824.03,11.4907840585,-15.142,146351473.26,26.552765801,-4.0798,9.221214472817,28.57,2.294345427388,40.0854797434,,2026-05-25
6,875135,巴德股份,2.18,190100741.04,-21.6876508802,,23979073.77,-25.3322493329,,15.512161199091,15.23,0.255547254545,28.3929899614,,2026-05-25
7,875111,尚能股份,0.4,203049955.34,-2.6174349813,,32836441.21,-13.976759715,,4.326996997423,9.83,0.471536309571,32.195271686,,2026-05-25
8,874287,森合高科,3.19,839751554.84,34.8292193479,-8.6453,272284612.15,81.7789291791,-11.9819,9.535480258221,40.15,2.854514755598,46.3541451202,,2026-05-25

以上数据都是公开的,可以从一些财经网站免费下载到。

对照组

为了对比,使用之前做好的阶段五的Agent( 具有多轮规划、反思、执行的多Agent) 处理相同的问题——

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
最终回复 (来自于 Reflection):
Final Answer:
中国集成电路制造板块在历经周期波动与地缘政治重塑后,其出海业务正呈现出截然不同的图景。
通过对晶圆代工龙头(中芯国际、华虹公司/华虹半导体)以及垂直整合制造IDM主要玩家(闻泰科技/安世半导体、扬杰科技、华润微、士兰微)的境外营收占比、毛利特征、技术门槛、财务抗压度及抵御地缘政治脱钩力进行系统性挖掘与量化比对。

我们得出的最终结论是:**中国集成电路制造板块中,不仅有出口业务,且最值得投资的黄金个股是——扬杰科技(300373.SZ)**。

下面将围绕筛选标准、核心企业境外业务对比、财务深度对标、地缘风险防御性以及“最值得投资个股”扬杰科技的投资逻辑进行全方位深度解构。

---

### 一、 集成电路制造板块核心企业出口业务大盘点 (最新数据口径)

在集成电路制造板块中,出口(境外)业务开展最为成熟、出口占比最高的几家龙头公司呈现出以下战略分化:

#### 1. 晶圆代工厂 (Foundry)
*   **中芯国际 (688981.SH / 00981.HK)**    *   **境外营收概况**:截至2026年第一季度最新数据,中芯国际的区域营收中,**中国本土贡献了 89% 的天量营收,而北美(美国)业务回落至 9%,欧亚业务缩水至 2%** [原文](https://finance.yahoo.com/quote/SMIC13.BK/earnings/SMIC13.BK-Q1-2026-earnings_call-554758.html/)。
    *   **业务逻辑**:中芯国际由于追求先进制程(如14nm及以下),饱受美国实体清单设备禁运与芯片法案脱钩制约。境外大设计大厂主动或被动缩减了在中芯国际的制造配额,使得中芯国际在事实上已转化为一家**高度服务于“集成电路国产替代”的内需型代工巨头**。
*   **华虹半导体 / 华虹公司 (688347.SH / 01347.HK)**    *   **境外营收概况**:作为特色工艺代工龙头,华虹的防脱钩属性要优秀得多。在其最新2025年第四季度财务表现中,总营业收入为 5.043 亿美元,其中**北美营收高达 7280 万美元,同比暴增 51.3%,占全季度总营业收入的 14.4%** [原文](https://www1.hkexnews.hk/listedco/listconews/sehk/2026/0212/2026021200389.pdf)。加上欧洲与欧亚其它国家,**其境外销售总和占比可达 20% 上下**。
    *   **业务逻辑**:华虹聚焦在智能卡、嵌入式闪存、MCU、BCD(高压模拟)及车规半导体特色工艺上。非先进制程属性使其不受美国高端设备禁运干扰,海外新能源汽车、家电、消费电子大客户对华虹极具黏性。

#### 2. 垂直整合制造商 (IDM)
*   **闻泰科技 (600745.SH)**    *   **境外营收概况**:其核心半导体资产——原荷兰**安世半导体 (Nexperia)**,是一家拥有极高国际声誉的汽车与工业分立器件巨头。**安世半导体自身的境外营收占比高达 65% ~ 70%**。
    *   **业务逻辑**:安世在欧洲(德、英)拥有前道晶圆厂。虽然出海能力极强,但闻泰科技整体受其**ODM(智能终端方案设计与组装)低毛利重折旧板的剧烈拖累**,母体财务稳健度承压。此外,安世也面临着英国政府限制收购等一定程度的地缘政治干扰。
*   **扬杰科技 (300373.SZ)**    *   **境外营收概况**:中国功率半导体分立器件 IDM 出海的绝对王者。其连续多年来自**境外的营业收入保持在 30% 左右的极高水准**。
    *   **业务逻辑**:扬杰通过在美、欧、日、韩建立深度本土化的团队和渠道网络,以自有品牌形式大规模向欧美白电、工控及汽车 Tier 1 客户出口功率分立器件(二极管、桥堆、MOSFET、IGBT)。

---
。。。

---
。。。
---

### 四、 投资建议与总结

*   **长期投资价值**:**扬杰科技 (300373.SZ)** 结合了优质的 IDM 制造壁垒与强大的高利润出海销售能力。在A股半导体制造相关板块中,它是极其罕见的、不需要依靠巨额政策补贴而能自己在国际大市场上斩获真金白银、保持丰沛健康现金流的高 ROE 卓越标的。
*   **短期估值分析**:当前正值全球半导体行业从周期底部走出、汽车电子与工控市场复苏、以及人工智能服务器(对高功率供电分立器件需求激增)带来新增量的拐点。扬杰科技以目前行业中低历史估值分位数,兼具了业绩的“防震垫”和向上的“出海高成长属性”。

如果您要在集成电路制造(晶圆厂/IDM)中寻找一只**最值得投资的新标杆**,**扬杰科技 (300373.SZ)** 应当是您的首选投资方案。

多Agent 充分发挥了它的长处——在 规划、反思过程中给出了更全面的框架。

通过对晶圆代工龙头(中芯国际、华虹公司/华虹半导体)以及垂直整合制造IDM主要玩家(闻泰科技/安世半导体、扬杰科技、华润微、士兰微)的境外营收占比、毛利特征、技术门槛、财务抗压度及抵御地缘政治脱钩力进行系统性挖掘与量化比对

但是,它报告内在逻辑是不通畅的——

一方面是数据给的不够,另一方面它的判断也比较容易受外部网页提供的结论带跑。

这两个Agent 应用各有优缺点,需要进一步整合。

结尾

这次没有太多的AI 话题含量。如果看完全篇会发现 :

AI基于真实的数据去帮助我们弥补空隙(画图、做表格、生成归纳性的总结),它不是那个生成真实数据的个体。

真实的数据从哪里来呢?从真实世界来!

金融类的 产品本身就是高度数据化、也比较容易 帮助我们做出决策。

所以在这个案例中,数据处理方面没花太多的功夫。但是在数据搜集阶段还是要费些功夫的(想想需要把5000多只股票历年的数据集中拉取下来)。

如果换一个场景,数据就未必这么拉取一下就可行了。可能还需要大量的数据标注、整理、格式化等工作。

所以,对于那些目前还没有很好的量化标准和指标的行业(例如 : 看病、装修设计),AI 依然面临高筑的信息墙壁。 无法接触到真实物理世界高质量的数据,也是这些领域短期内极难被 AI 取代与超越的根本原因。

感谢看到这里,我们下期见。

PS:

也许上星期真应该买个100股 赌一下的 ——

688981_5-19 688981_5-27
Licensed under CC BY-NC-SA 4.0