从L2行情到逐笔交易:本地数据引擎如何重构主力资金分析体系

从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,如有侵犯网站权利,请联系我撤回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值