金融数据特征:非结构化数据与结构化数据的融合之道
做金融RAG系统,第一关就是跟数据打交道。
说实话,金融数据是我见过最「分裂」的数据类型。一边是规规矩矩的表格,一边是乱七八糟的文本。我刚开始做这个方向时,总觉得把数据喂给大模型就行了。结果呢?模型吐出来的东西,连我自己都看不下去。
后来我明白了——不懂金融数据的脾气,就别想做好RAG。
一、非结构化数据:研报、公告、新闻
这类数据占了金融数据的80%以上。说白了,就是那些没法直接塞进Excel里的东西。
1. 研报
券商研报,我个人的最爱。一份研报里,有文字、有图表、有表格、有公式。你想想看,PDF格式的研报,里面可能还嵌套着图片格式的表格。
我在项目中遇到过最头疼的事——研报里的表格被渲染成图片。OCR识别出来,数字串行、单位丢失、表头错位。后来我改用多模态模型直接解析,效果好了不少。
2. 公告
上市公司的公告,格式倒是统一。但坑在哪里?公告里的「附注」和「更正声明」。
我曾经踩过一个坑:某公司发布了一季度财报预告,第二天又发了个更正公告。我的RAG系统只索引了第一份,结果模型回答时引用了错误数据。嗯,这里要注意——公告必须做版本管理,旧版本要标记为「已作废」。
3. 新闻
财经新闻,噪音最大。一条消息,不同媒体能写出十个版本。而且新闻里经常夹杂着「据知情人士透露」「或」「可能」这类模糊词。
我的做法是:对新闻做情感打分和置信度标注。比如「据传」开头的新闻,置信度直接打0.3。这样大模型在生成回答时,能自动降低这类信息的权重。
二、结构化数据:行情、财报
这类数据规规矩矩,但量太大。你想想看,A股5000多只股票,每秒都在产生行情数据。一天下来,光高频数据就能有几个TB。
1. 行情数据
行情数据的特点是:高频率、低延迟、强时序。我习惯用ClickHouse来存储,查询速度比MySQL快10倍以上。
但RAG系统直接查行情?不行。大模型看不懂「开盘价15.23,收盘价15.67」这种原始数据。我的做法是:先做特征工程,把原始行情转化成「5日均线突破」「MACD金叉」这类语义化特征。
# 伪代码:行情数据语义化
def semantic_market_data(stock_code, date):
raw_data = query_clickhouse(stock_code, date)
features = {
'trend': '上升趋势' if raw_data['ma5'] > raw_data['ma20'] else '下降趋势',
'volume': '放量' if raw_data['volume'] > raw_data['volume_ma5'] * 1.5 else '缩量',
'volatility': '高波动' if raw_data['振幅'] > 5 else '低波动'
}
return features
2. 财报数据
财报数据,最讲究「一致性」。同一家公司,不同季度的财报科目名称可能不一样。比如「营业收入」和「主营业务收入」,其实是同一个东西。
我踩过的坑:某次RAG系统把「归母净利润」和「净利润」当成两个字段,结果模型算出来的PE倍数完全不对。后来我建了一个财报科目映射表,把同义词统一映射到标准字段。
三、数据时效性与合规要求
金融数据,时间就是金钱。但时间也是风险。
1. 时效性分层
我习惯把数据按时效性分成三层:
| 层级 | 数据类型 | 更新频率 | 存储策略 |
|---|---|---|---|
| T0 | 实时行情、突发新闻 | 秒级 | Redis + Kafka |
| T1 | 研报、公告、日行情 | 日级 | Elasticsearch + ClickHouse |
| T2 | 财报、历史数据、宏观数据 | 季度/年度 | 对象存储 + 离线数仓 |
为什么这么分?说白了,不同时效性的数据,对RAG的检索策略完全不同。T0数据要用流式检索,T2数据可以用批量索引。
2. 合规要求
金融合规,不是闹着玩的。我见过有团队因为用了未授权的数据源,被罚到破产。
合规要点就三条:
- 数据来源合规:必须使用持牌机构的数据。万得、同花顺、东方财富这些,该买授权就买。
- 数据使用合规:不能把付费数据喂给公开的大模型API。我建议用私有化部署的模型来处理敏感数据。
- 数据输出合规:RAG系统不能生成「投资建议」。我习惯在系统里加一层合规过滤,把「买入」「卖出」这类词替换成「关注」「警惕」。
四、知识体系总览
说了这么多,我画了一张图,帮你把金融数据的特征串起来。
这张图我画了好几次才满意。你想想看,金融数据就像一座冰山——结构化数据是露出水面的那一角,非结构化数据才是水下庞大的主体。而时效性和合规,就是冰山的温度计和围栏。
公众号:蓝海资料掘金营,微信deep3321