从L2行情到逐笔交易:本地数据引擎如何重构主力资金分析体系
做短线和量化策略的人都明白,资金流向是判断市场情绪最直接的信号。但想把资金分析做到位,数据质量和获取效率是绕不开的坎。我之前用在线API做主力资金监控,要么延迟太高错过关键信号,要么字段不全算不准净流,后来转向本地落盘方案,才算真正把资金分析的流程跑通了。今天想聊聊用ig50本地数据引擎做L2行情和逐笔交易分析的实战经验。
在线API做资金分析的痛点比想象中多。Wind的L2数据确实全,但年费不是个人能承受的;Tushare有DDX、DDY这些指标,可积分门槛和频次限制摆在那,盘中实时监控根本跑不起来。更要命的是数据延迟,等你拿到主力净流入数据的时候,股价已经涨了一截,所谓的信号早就变成了噪音。还有逐笔交易这种高频数据,在线接口单次只能拉一只股票几分钟的数据,想做全市场大单扫描,光请求排队就得耗半小时。我之前写过一个脚本,用在线API跑全市场主力净流入排名,从发起请求到拿到结果,最快也要15分钟,盘中策略根本等不起。
后来换成ig50本地数据引擎,才发现思路完全不同。L2行情指标和逐笔交易数据都是后台自动拉取落盘,程序直接读本地文件,不用管网络请求、不用限流、不用处理超时重试。L2行情指标在time/real/trace/l2sign/{股票代码}路径下,包含主力净流入、主力净比、散户净比、DDX/DDY/DDZ这些核心指标,每10秒更新一次,3秒左右落盘;逐笔交易在time/real/trace/onebyone/{股票代码}路径下,记录每一笔成交的时间、价格、成交量和交易方向,每2分钟更新一次。
先看L2行情指标的读取,下面这段代码是我盘中监控主力资金动向的核心逻辑:
import json
import pandas as pd
from pathlib import Path
from datetime import datetime
DATA_DIR = Path('/ig50-data')
def load_l2_indicator(code):
"""读取单只股票的L2行情指标"""
path = DATA_DIR / 'time' / 'real' / 'trace' / 'l2sign' / code
if not path.exists():
return None
with open(path, 'r', encoding='utf-8') as f:
data = json.load(f)
return data
# 读取股票列表
with open(DATA_DIR / 'base' / 'gplist', 'r', encoding='utf-8') as f:
stock_list = json.load(f)
df_stocks = pd.DataFrame(stock_list)
# 过滤掉ST和新股
df_pool = df_stocks[(df_stocks['isSt'] == 0) & (df_stocks['isNew'] == 0)]
# 批量读取全市场L2指标(纯本地文件读取,无任何网络开销)
l2_records = []
for code in df_pool['dm']:
l2 = load_l2_indicator(code)
if l2:
l2_records.append({
'代码': l2.get('dm'),
'名称': l2.get('mc'),
'主力净流入': l2.get('zlJlr'),
'主力净比': l2.get('zlJlb'),
'散户净比': l2.get('shJlb'),
'DDX': l2.get('ddx'),
'DDY': l2.get('ddy'),
'DDZ': l2.get('ddz'),
'5分钟主力净额': l2.get('f5MinZlJe'),
'近三日主力净额': l2.get('f3DayZlJe'),
'更新时间': l2.get('updateTime'),
})
df_l2 = pd.DataFrame(l2_records)
# 主力净流入转数值
df_l2['主力净流入'] = pd.to_numeric(df_l2['主力净流入'], errors='coerce')
df_l2['主力净比'] = pd.to_numeric(df_l2['主力净比'], errors='coerce')
df_l2['DDX'] = pd.to_numeric(df_l2['DDX'], errors='coerce')
# 按主力净流入排序,找出资金扎堆的股票
top_inflow = df_l2.sort_values('主力净流入', ascending=False).head(20)
print('=== 主力净流入TOP20 ===')
print(top_inflow[['代码', '名称', '主力净流入', '主力净比', 'DDX']])
# 筛选主力净比>10%且DDX>0.1的强势股(主力持续买入信号)
strong_stocks = df_l2[(df_l2['主力净比'] > 10) & (df_l2['DDX'] > 0.1)]
print(f'\n主力净比>10%且DDX>0.1的股票数量:{len(strong_stocks)}')
这段代码最关键的地方在于,全市场5000多只股票的L2指标扫一遍,因为是本地文件IO,5秒以内就能跑完。换成在线API,这个量级的请求至少要等5分钟,还得处理限流和超时。
L2指标给的是汇总数据,想看得更细就得用逐笔交易。下面这段代码是用逐笔数据计算大单占比和资金流向的:
def load_tick_data(code):
"""读取单只股票的逐笔交易数据"""
path = DATA_DIR / 'time' / 'real' / 'trace' / 'onebyone' / code
if not path.exists():
return None
with open(path, 'r', encoding='utf-8') as f:
data = json.load(f)
return data
# 以贵州茅台为例(600519)
code = '600519'
tick_data = load_tick_data(code)
if tick_data:
df_tick = pd.DataFrame(tick_data)
# 字段:成交时间、成交量(股)、成交价、交易方向(0中性盘,1买入,2卖出)
df_tick['成交时间'] = pd.to_datetime(df_tick['成交时间'], format='%H:%M:%S')
df_tick['成交量'] = pd.to_numeric(df_tick['成交量'], errors='coerce')
df_tick['成交价'] = pd.to_numeric(df_tick['成交价'], errors='coerce')
# 计算大单(单笔>100手)和小单
big_order_threshold = 100 * 100 # 100手 = 10000股
df_tick['大单标记'] = df_tick['成交量'] > big_order_threshold
# 计算买入和卖出金额
buy_mask = df_tick['交易方向'] == 1
sell_mask = df_tick['交易方向'] == 2
total_buy = (df_tick.loc[buy_mask, '成交量'] * df_tick.loc[buy_mask, '成交价']).sum()
total_sell = (df_tick.loc[sell_mask, '成交量'] * df_tick.loc[sell_mask, '成交价']).sum()
net_flow = total_buy - total_sell
# 大单买入和卖出金额
big_buy = (df_tick.loc[buy_mask & df_tick['大单标记'], '成交量'] *
df_tick.loc[buy_mask & df_tick['大单标记'], '成交价']).sum()
big_sell = (df_tick.loc[sell_mask & df_tick['大单标记'], '成交量'] *
df_tick.loc[sell_mask & df_tick['大单标记'], '成交价']).sum()
total_volume = df_tick['成交量'].sum()
big_volume = df_tick.loc[df_tick['大单标记'], '成交量'].sum()
print(f'=== {code} 逐笔数据分析 ===')
print(f'总成交笔数:{len(df_tick)}')
print(f'总成交量:{total_volume/10000:.2f}万股')
print(f'大单成交量:{big_volume/10000:.2f}万股(占比 {big_volume/total_volume*100:.2f}%)')
print(f'买入金额:{total_buy/10000:.2f}万元')
print(f'卖出金额:{total_sell/10000:.2f}万元')
print(f'资金净流入:{net_flow/10000:.2f}万元')
print(f'大单买入金额:{big_buy/10000:.2f}万元')
print(f'大单卖出金额:{big_sell/10000:.2f}万元')
# 按分钟聚合,看资金流向变化趋势
df_tick = df_tick.set_index('成交时间')
df_tick['金额'] = df_tick['成交量'] * df_tick['成交价']
# 分钟级资金净流入
minute_flow = df_tick.resample('1T').apply({
'金额': lambda x: x[df_tick.loc[x.index, '交易方向'] == 1].sum() -
x[df_tick.loc[x.index, '交易方向'] == 2].sum()
})
print('\n=== 分钟级资金流向(最近10分钟)===')
print(minute_flow['金额'].tail(10) / 10000)
逐笔数据的价值在于能看清资金的微观结构。通过计算大单占比和分钟级资金流向,可以判断是机构在主动买入还是散户在跟风。我之前用在线API做同样的分析,因为数据不全和延迟问题,经常误判;现在本地数据完整,分析结果靠谱多了。
把L2指标和逐笔交易结合起来,就能构建一个完整的主力资金监控体系。下面这段代码是我实际在用的盘中监控脚本:
def monitor_main_force(top_n=10):
"""盘中主力资金实时监控"""
with open(DATA_DIR / 'base' / 'gplist', 'r', encoding='utf-8') as f:
stock_list = json.load(f)
df_stocks = pd.DataFrame(stock_list)
df_pool = df_stocks[(df_stocks['isSt'] == 0) & (df_stocks['isNew'] == 0)]
results = []
for code in df_pool['dm']:
l2 = load_l2_indicator(code)
if not l2:
continue
# 读取实时行情获取当前价格
rt_path = DATA_DIR / 'time' / 'real' / code
if rt_path.exists():
with open(rt_path, 'r', encoding='utf-8') as f:
rt = json.load(f)
price = rt.get('p')
change_pct = rt.get('pc')
else:
price = None
change_pct = None
results.append({
'代码': l2.get('dm'),
'名称': l2.get('mc'),
'现价': price,
'涨跌幅': change_pct,
'主力净流入': l2.get('zlJlr'),
'主力净比': l2.get('zlJlb'),
'DDX': l2.get('ddx'),
'DDZ': l2.get('ddz'),
})
df_result = pd.DataFrame(results)
for col in ['主力净流入', '主力净比', 'DDX', 'DDZ', '现价', '涨跌幅']:
df_result[col] = pd.to_numeric(df_result[col], errors='coerce')
# 筛选条件:主力净比>5% 且 DDX>0 且 涨幅<5%(避免追高)
candidates = df_result[(df_result['主力净比'] > 5) &
(df_result['DDX'] > 0) &
(df_result['涨跌幅'] < 5) &
(df_result['涨跌幅'] > -2)]
# 按主力净流入排序
candidates = candidates.sort_values('主力净流入', ascending=False).head(top_n)
print(f'\n=== {datetime.now().strftime("%H:%M:%S")} 主力资金监控 ===')
print(f'符合条件股票数:{len(candidates)}')
print(candidates[['代码', '名称', '现价', '涨跌幅', '主力净流入', '主力净比', 'DDX']])
return candidates
# 运行监控
monitor_main_force(top_n=15)
用本地数据做资金分析,最大的体感差异是"实时性"和"完整性"。以前用在线API,数据延迟几十毫秒到几百毫秒不等,盘中监控经常滞后;现在本地读取,数据更新后3秒就能读到,几乎是实时的。而且数据在自己机器上,想怎么分析就怎么分析,不用受接口限制。比如我最近在研究DDX和DDZ的组合信号,要是用在线API,根本没办法做历史回测验证;现在本地有完整的历史L2数据,想回测多久就回测多久。
资料参考ig50.com/index_realtime.html?maodian=rt-trace-l2Sign-title,如有侵犯网站权利,请联系我撤回。

43

被折叠的 条评论
为什么被折叠?



