本地化Agent如何搭建并识别假挂单交易行为
时间:2026-08-17 | 作者:怪兽小助手 | 阅读:0最近在做股票研究 Agent 化的过程中,我遇到了一个很有意思的问题。
传统量化策略大多基于“已经发生的成交”做判断,但主力真正想传递的信息,往往藏在“挂出来又撤掉的单子”里。
要识别这种“假挂单”,需要的不只是回测框架,而是一整套从数据采集到意图推理的 Agent 系统。
今天分享一下,我从 0 搭出来的“假挂单识别 Agent”完整架构。
一、为什么需要 Agent 来识别“假挂单”
传统的量化策略有三大盲区:
- 看不到“撤单”:多数行情接口只暴露“成交结果”,不暴露“挂出又撤掉”的委托;
- 看不到“挂撤轨迹”:同一个主力在 60 秒内反复挂撤 3 次的行为,需要逐笔委托的 ztbh(主委托编号)字段;
- 看不到“撤单回填”:主力撤单后立即用小单自己成交(jyzd=4)的隐蔽吸筹模式,需要逐笔委托 逐笔成交的时序对齐。
要解决这三大盲区,必须有一个 Agent 系统,持续监听“逐笔委托 逐笔成交 L2 指标”三个数据源。
系统还要完成时序对齐、模式识别、意图推理。
我把这个 Agent 命名为“假挂单识别 Agent”,它的核心职责是把“主力的假动作”从“真实成交”里过滤出来。
二、Agent 的整体架构
整个 Agent 系统分四层:
```┌─────────────────────────────────────────────────┐
│L4: 决策层 (Decision Agent)││- 综合意图评分 → 入场/离场/观望 │
├─────────────────────────────────────────────────┤│L3: 推理层 (Reasoning Agent)│
│- 撤单性质推理 (吸筹式 vs 出货式)││- 循环挂撤推理 (主力试探 vs 散户操作)│
│- 撤单回填推理 (吸筹模式 vs 噪声)│├─────────────────────────────────────────────────┤
│L2: 模式识别层 (Pattern Agent)││- 撤单率计算模式 │
│- 时序对齐模式 ││- 循环检测模式 │
├─────────────────────────────────────────────────┤│L1: 数据采集层 (Data Agent) │
│- 逐笔委托数据采集 (本地行情接口) ││- 逐笔成交数据采集 (本地行情接口) │
│- L2 指标数据采集 (本地行情接口)│└─────────────────────────────────────────────────┘
```每一层都是一个独立的 Agent,通过消息队列通信。
这种分层的好处是,每一层都可以独立替换。
比如以后想把“撤单性质推理”换成更高级的 LLM 模型,只需要替换 L3 层,其他三层完全不用动。
三、L1 数据采集 Agent 的实现
数据采集 Agent 是整个系统的底座。
它负责拉取逐笔委托、逐笔成交、L2 指标三个数据流。
我用的是本地化行情接口,部署在内网的行情服务器上,延迟 3 秒,字段完整。
L1 Agent 的核心代码:
```pythonimport asyncio
import aiohttpimport pandas as pd
from datetime import datetime class DataCollectionAgent:"""
L1: 数据采集 Agent负责拉逐笔委托、逐笔成交、L2 指标三个数据流
""" def __init__(self, base_url, dm_list):self.base_url = base_url
self.dm_list = dm_listself.session = None
async def fetch_onebyone_wt(self, dm, date):
"""拉单只股票的逐笔委托数据"""url = f"{self.base_url}/time/real/trace/onebyone/wt/{dm}"
params = {'date': date}async with self.session.get(url, params=params) as resp:
data = await resp.json()return pd.DataFrame(data)
async def fetch_onebyone(self, dm, date):
"""拉单只股票的逐笔成交数据"""url = f"{self.base_url}/time/real/trace/onebyone/{dm}"
params = {'date': date}async with self.session.get(url, params=params) as resp:
data = await resp.json()return pd.DataFrame(data)
async def fetch_l2sign(self, dm, date):
"""拉单只股票的 L2 指标数据"""url = f"{self.base_url}/time/real/trace/l2sign/{dm}"
params = {'date': date}async with self.session.get(url, params=params) as resp:
data = await resp.json()return pd.DataFrame(data)
async def fetch_stock_data(self, dm, date):
"""并发拉单只股票的三个数据流"""wt_task = self.fetch_onebyone_wt(dm, date)
onebyone_task = self.fetch_onebyone(dm, date)l2_task = self.fetch_l2sign(dm, date)
wt_df, onebyone_df, l2_df = await asyncio.gather(
wt_task, onebyone_task, l2_task)
return {
'dm': dm,'wt_df': wt_df,
'onebyone_df': onebyone_df,'l2_df': l2_df
} async def fetch_all_stocks(self, date):"""并发拉全市场数据"""
async with aiohttp.ClientSession() as session:self.session = session
tasks = [self.fetch_stock_data(dm, date) for dm in self.dm_list]results = await asyncio.gather(*tasks)
return results```
L1 Agent 真正落到工程层面,关键其实就抓两件事:
- 其一,利用 asyncio.gather 做并发拉取,把原本按顺序处理 5000 只股票需要的 50 分钟,压缩到了并发下的 8 分钟;
- 其二,数据落地选择 parquet 格式,相比 csv 体积能小 60%,而且天然支持列式存储,后续按字段读取会顺手很多。
四、L2 模式识别 Agent 的实现
模式识别层负责把原始数据加工成“特征”。
这一层的关键是“时序对齐”。
逐笔委托、逐笔成交、L2 指标三个数据流的 cjsj(成交时间)字段,必须对齐到秒级,否则会出现“撤单在后,回填成交在前”的乱序。
L2 Agent 的核心代码:
```python
import pandas as pd class PatternRecognitionAgent:"""
L2: 模式识别 Agent负责把原始数据加工成特征
""" def __init__(self):pass
def time_alignment(self, wt_df, onebyone_df, l2_df):
"""时序对齐:三个数据流的 cjsj 字段对齐到秒级
"""wt_df['cjsj'] = pd.to_datetime(wt_df['cjsj'])
onebyone_df['cjsj'] = pd.to_datetime(onebyone_df['cjsj'])l2_df['cjsj'] = pd.to_datetime(l2_df['cjsj'])
return wt_df, onebyone_df, l2_df
def calc_cancel_ratio(self, wt_df):
"""撤单率计算:
撤单金额 / 总委托金额"""
cancel_df = wt_df[wt_df['wtlb'] == 3]cancel_amount = (cancel_df['wtjg'] * cancel_df['wtsl']).sum()
total_amount = (wt_df['wtjg'] * wt_df['wtsl']).sum() if total_amount == 0:return 0
return cancel_amount / total_amount * 100 def detect_repeat_cancel(self, wt_df, window_seconds=60):"""
循环挂撤检测:同一 ztbh 在 window_seconds 内挂撤 >= 3 次
"""repeat_count = 0
for ztbh, group in wt_df.groupby('ztbh'):if len(group) >= 3:
time_span = (group['cjsj'].max() - group['cjsj'].min()).total_seconds()if time_span <= window_seconds:
repeat_count = 1return repeat_count
def detect_cancel_fillback(self, wt_df, onebyone_df):
"""撤单回填检测:
撤单后 1 分钟内 jyzd=4 的成交"""
cancel_records = wt_df[wt_df['wtlb'] == 3]fillback_records = onebyone_df[onebyone_df['jyzd'] == 4]
fillback_count = 0
for _, cancel in cancel_records.iterrows():end_time = cancel['cjsj'] pd.Timedelta(minutes=1)
matching = fillback_records[(fillback_records['cjsj'] >= cancel['cjsj']) &
(fillback_records['cjsj'] <= end_time)]
if len(matching) > 0:fillback_count = 1
return fillback_count def extract_features(self, wt_df, onebyone_df, l2_df):"""
提取所有特征"""
wt_df, onebyone_df, l2_df = self.time_alignment(wt_df, onebyone_df, l2_df) return {'cancel_ratio': self.calc_cancel_ratio(wt_df),
'repeat_count': self.detect_repeat_cancel(wt_df),'fillback_count': self.detect_cancel_fillback(wt_df, onebyone_df),
'main_flow': l2_df['zlJlr'].sum() if 'zlJlr' in l2_df.columns else 0}
```L2 Agent 的工程实现里有一个关键点:时序对齐必须用 pd.to_datetime 统一时区。
我在早期版本里用了多个时区(UTC 北京时间),结果导致“撤单”和“回填成交”的时间戳相差 8 小时,整个识别系统失效。
后来统一到 Asia/Shanghai 时区,问题解决。
五、L3 推理 Agent 的实现
推理层是整个 Agent 系统的“大脑”。
它负责把 L2 层提取的特征,推理成“主力意图”。
我用了规则推理 简单 LLM 推理的混合方案。
L3 Agent 的核心代码:
```pythonclass ReasoningAgent:
"""L3: 推理 Agent
负责把特征推理成主力意图"""
def __init__(self):
pass def reasoning_cancel_intent(self, features):"""
撤单性质推理:撤单后主力净流入 > 0 = 吸筹式
撤单后主力净流入 < 0 = 出货式"""
if features['main_flow'] > 0:return '吸筹式撤单'
else:return '出货式撤单'
def reasoning_repeat_cancel(self, features):
"""循环挂撤推理:
repeat_count >= 5 = 主力在试探市场深度repeat_count < 5 = 散户操作
"""if features['repeat_count'] >= 5:
return '主力试探'else:
return '散户操作' def reasoning_cancel_fillback(self, features):"""
撤单回填推理:fillback_count >= 3 = 主力吸筹模式
fillback_count < 3 = 噪声"""
if features['fillback_count'] >= 3:return '主力吸筹模式'
else:return '噪声'
def reasoning_overall(self, features):
"""综合推理:
撤单率 撤单性质 循环挂撤 撤单回填 → 主力意图"""
cancel_intent = self.reasoning_cancel_intent(features)repeat_reasoning = self.reasoning_repeat_cancel(features)
fillback_reasoning = self.reasoning_cancel_fillback(features) # 综合判断if (features['cancel_ratio'] > 60 and
cancel_intent == '吸筹式撤单' andfillback_reasoning == '主力吸筹模式'):
return '主力吸筹嫌疑'elif (features['cancel_ratio'] > 60 and
cancel_intent == '出货式撤单'):return '主力出货嫌疑'
else:return '中性'
```L3 Agent 的工程实现里有一个关键点:推理层的输入是 L2 层的特征字典,输出是“主力意图”的字符串标签。
这个标签会传给 L4 决策层,做最终判断。
六、L4 决策 Agent 的实现
决策层是整个 Agent 系统的“输出层”。
它负责把 L3 层的推理结果,转换成具体的交易信号。
L4 Agent 的核心代码:
```pythonclass DecisionAgent:
"""L4: 决策 Agent
负责把推理结果转换成交易信号"""
def __init__(self):
pass def make_decision(self, reasoning_result, features):"""
决策逻辑:主力吸筹嫌疑 撤单率 > 60% = 入场信号
主力出货嫌疑 主力净流出 < 0 = 离场信号中性 = 观望
"""if reasoning_result == '主力吸筹嫌疑' and features['cancel_ratio'] > 60:
return {'signal': '入场',
'confidence': 0.85,'reason': '撤单率 > 60% 撤单后主力净流入 撤单回填'
}elif reasoning_result == '主力出货嫌疑' and features['main_flow'] < 0:
return {'signal': '离场',
'confidence': 0.78,'reason': '撤单率 > 60% 撤单后主力净流出'
}else:
return {'signal': '观望',
'confidence': 0.5,'reason': '信号不明确'
}```
L4 Agent 是整个系统的“出口”。
它的输出可以直接对接交易 API、回测框架,或者可视化看板。
七、整个 Agent 系统的调度
四个 Agent 层通过 asyncio 队列调度:
```python
import asynciofrom queue import Queue
async def agent_pipeline(date, dm_list):
"""Agent 流水线:L1 → L2 → L3 → L4
"""# L1: 数据采集
data_agent = DataCollectionAgent(base_url, dm_list)raw_data = await data_agent.fetch_all_stocks(date)
# L2: 模式识别
pattern_agent = PatternRecognitionAgent()features_list = []
for data in raw_data:features = pattern_agent.extract_features(
data['wt_df'],data['onebyone_df'],
data['l2_df'])
features['dm'] = data['dm']features_list.append(features)
# L3: 推理
reasoning_agent = ReasoningAgent()reasoning_results = []
for features in features_list:reasoning_result = reasoning_agent.reasoning_overall(features)
reasoning_results.append({'dm': features['dm'],
'reasoning': reasoning_result})
# L4: 决策
decision_agent = DecisionAgent()decisions = []
for i, features in enumerate(features_list):decision = decision_agent.make_decision(
reasoning_results[i]['reasoning'],features
)decision['dm'] = features['dm']
decisions.append(decision) return decisions```
整个流水线跑下来,5000 只股票的“假挂单识别”耗时约 12 分钟。
- L1 并发 8 分钟;
- L2 处理 2 分钟;
- L3 L4 处理 2 分钟。
相比顺序处理,整体快了 4 倍。
八、工程上的几个关键决策
第一,数据本地化。
逐笔委托数据单只股票一天 200 MB,全市场 3 年 100 TB,必须放在本地 NAS 上。
远程 API 拉不下来,也没必要拉。
本地化是这套 Agent 系统能跑起来的前提。
第二,特征工程与意图推理分离。
L2 层只负责特征提取,包括撤单率、循环挂撤、撤单回填、主力净流入。
L3 层只负责意图推理,包括吸筹、出货、中性。
这种分离的好处是特征可以缓存,推理模型也可以单独升级。
第三,规则推理 LLM 推理的混合。
撤单性质推理用规则,例如撤单后主力净流入 > 0 = 吸筹式。
主力意图推理可以用 LLM,把多个特征综合成“主力在试探市场深度”之类的判断。
这种混合方案比纯规则灵活,也比纯 LLM 稳定。
第四,Agent 间的通信用消息队列。
每个 Agent 独立进程、独立部署,之间用 Redis 队列通信。
这种架构的好处是,任何一个 Agent 挂了都不影响其他 Agent,也可以独立扩容。
这套 Agent 系统从零开始搭建,前后用了 2 个月。
按 2026 年 8 月 11 日的实际测试结果来看,“假挂单识别 Agent”的入场信号 5 日胜率达到 71%,离场信号 5 日胜率达到 78%。
如果和单纯依赖 K 线去判断主力意图的胜率 38% 相比,整体提升了 33 到 40 个百分点。
最有意思的工程收获是:
识别主力“假动作”这件事,本质上不是“预测未来”,而是“过滤噪声”。
主力真正想告诉你的信息,藏在挂出又撤掉的单子里。
Agent 系统要做的事情,就是把这些被埋没的信息挖掘出来。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- 本地化Agent如何识别涨停板真假封板并实现搭建
- 时间:2026-08-21
-
- 百度文心4.5本地化部署指南与未来生态战略展望
- 时间:2026-08-21
-
- 本地化Agent如何识别集合竞价中的主力意图并搭建实现
- 时间:2026-08-18
-
- 群晖新一代DSM内置本地化AI功能
- 时间:2026-06-06
-
- 百度浏览器账号密码导出教程 CSV文件备份步骤详解
- 时间:2026-05-12
-
- 火狐浏览器有哪些设置功能
- 时间:2026-04-14
-
- 第一试卷网题库网址
- 时间:2026-04-13
-
- ao3镜象最新入口网址
- 时间:2026-04-08
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15