news 2026/8/24 4:30:12

Java量化系列(五十)|股票资金信息爬取全落地!搞懂资金运用+SQL+代码,精准捕捉主力动向

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java量化系列(五十)|股票资金信息爬取全落地!搞懂资金运用+SQL+代码,精准捕捉主力动向

重要提示:本篇是「股票资金数据」实战落地篇,衔接前49篇量化策略优化内容,全程围绕「资金运用逻辑+数据爬取+存储落地」展开——从资金流向底层逻辑,到SQL表设计、Do实体类(给定直接用),再到某券商资金数据爬取、解析、存储全代码,所有代码均为可运行版本,复制粘贴即可嵌入你的量化项目,新手也能快速打通资金数据闭环!

量化交易的核心逻辑:资金决定涨跌,异动只是表象。前49篇我们搞定了异动数据,但很多量化新手依然会踩坑——只看异动信号,不看资金流向,导致误判假突破、追高被套。

其实,股票的涨跌本质是资金的“进”与“出”:主力资金净流入,股价大概率拉升;主力资金持续净流出,再强的异动也只是昙花一现。想要做高胜率量化策略,必须先搞懂「股票资金是怎么运用的」,再落地「资金数据的爬取与存储」,让资金流向成为策略的“定海神针”。

今天第50篇,我将从实战角度出发,先通俗讲解股票资金的运用逻辑(新手也能听懂),再把给定的SQL、StockBkMoneyHistoryDo实体类、爬取解析代码,一步步拆解落地,全程无冗余、无废话,所有代码可直接复用,帮你彻底搞定股票资金数据!

注:全文无敏感词,基于Java主流量化框架开发,适配某券商最新资金接口,兼容前49篇的量化框架,建议收藏+转发,避免后续找不到!

一、先搞懂核心:股票资金到底是怎么运用的?🤔

很多新手看资金数据,只看“主力净流入/流出”,却不知道资金是如何在市场中流转、影响股价的。其实股票资金的运用,本质是「不同资金主体的博弈」,核心分为4类资金,每类资金的运用逻辑的都直接决定股价走势——这也是我们爬取资金数据的核心意义。

结合实战场景,用通俗的语言拆解,不用复杂术语,新手也能秒懂:

1. 主力资金(核心主导者)

核心定义:机构、游资等大资金主体,资金量庞大(通常千万级以上),是决定股价中期走势的核心力量,也是我们量化策略重点跟踪的对象。

运用逻辑:主力资金不会盲目买卖,通常分为3个阶段:

① 建仓阶段:悄悄买入,资金净流入温和增加,股价波动不大(避免引起市场注意);

② 拉升阶段:资金大量净流入,股价快速上涨(借助利好消息,吸引散户跟风);

③ 出货阶段:资金净流出,股价缓慢下跌(悄悄卖出,套牢跟风散户)。

我们爬取的「today_main_inflow」(主力净注入净额),就是跟踪主力资金动向的核心指标——持续净流入,大概率是建仓或拉升阶段;持续净流出,需警惕出货风险。

2. 超大单资金(主力的“先锋部队”)

核心定义:单笔成交金额超大的资金(通常500万以上),主要是主力资金的“快速操作通道”,用于快速建仓、拉升或出货。

运用逻辑:超大单资金净流入突然激增,往往是主力开始发力的信号(比如突发利好,主力快速抢筹);超大单净流出激增,可能是主力紧急出货,需立即规避风险。

对应爬取数据中的「today_super_inflow」(超大净注入净额),可辅助判断主力的操作节奏——超大单+主力资金双净流入,信号更可靠。

3. 大单/中单/小单资金(市场跟随者)

① 大单资金:单笔成交金额较大(100-500万),多为中小机构或大户资金,跟随主力操作,是股价拉升的“辅助力量”;

② 中单资金:单笔成交金额中等(10-100万),多为散户中的大户,操作相对理性,对股价影响有限;

③ 小单资金:单笔成交金额较小(10万以下),主要是普通散户资金,资金分散、操作频繁,是市场的“跟风者”,往往成为主力收割的对象。

对应爬取数据中的「today_more_inflow」(大单)、「today_middle_inflow」(中单)、「today_small_inflow」(小单),通过这三类资金的流向,可判断市场情绪:如果小单净流入激增,说明散户跟风严重,主力可能随时出货。

4. 资金运用的核心逻辑(实战重点)

记住一句话:主力资金主导趋势,超大单决定节奏,中小单反映情绪

举个实战例子:某股票主力资金净流入1亿,超大单净流入8000万,大单净流入2000万,中单、小单净流出——说明主力在快速建仓,中小散户在卖出,此时是量化策略的介入时机;反之,主力净流出1亿,超大单净流出8000万,小单净流入激增——说明主力出货,散户接盘,需立即止损。

这也是我们为什么要爬取、存储这些资金数据:只有掌握资金的流向和运用逻辑,才能让量化策略摆脱“只看异动、不看本质”的误区,提升胜率。

二、核心前提:3个关键组件|资金数据落地的基础🎯

想要实现股票资金数据的爬取与存储,必须先搞定「存储→实体→枚举」三大组件(给定的Do类直接复用),这是数据闭环的基础——SQL表负责存储资金历史数据,Do类映射数据库表,枚举类统一管理资金类型,三者联动才能确保数据抓取、解析、存储无缝衔接。

以下组件均为实战可运行版本,给定的代码直接复制使用,无需修改,重点讲解使用方法和核心细节。

1. SQL表设计:stock_bk_money_history(板块资金注入历史表)

核心作用:存储板块、概念、地域、股票四个维度的资金注入历史数据,包含主力、超大单、大单等所有核心资金字段,适配后续策略回测、资金流向分析,索引优化到位,查询效率拉满(给定SQL直接执行)。

CREATE TABLE `stock_bk_money_history` ( `id` int NOT NULL AUTO_INCREMENT COMMENT 'id编号', `bk_code` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '版块编号', `bk_name` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '版块名称', `curr_date` timestamp NULL DEFAULT NULL COMMENT '当前日期', `type` int DEFAULT '1' COMMENT '类型 1是版块 2是 概念 3是地域 4是股票', `bk_now_price` decimal(10,4) DEFAULT NULL COMMENT '最新价', `bk_now_proportion` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '版块涨跌比例', `market` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '市场', `today_main_inflow` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日主力净注入净额', `today_main_inflow_proportion` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日主力净注入净额 占比', `today_super_inflow` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日 超大净注入净额', `today_super_inflow_proportion` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日 超大净注入净额 占比', `today_more_inflow` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日 大单净注入净额', `today_more_inflow_proportion` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日 大单净注入净额 占比', `today_middle_inflow` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日 中单净注入净额', `today_middle_inflow_proportion` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日 中单净注入净额 占比', `today_small_inflow` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日 小单净注入净额', `today_small_inflow_proportion` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日 小单净注入净额 占比', `today_main_inflow_code` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日主力净注入股票编码', `today_main_inflow_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '今日主力净注入股票名称', `sort_num` int DEFAULT NULL COMMENT '排序顺序', PRIMARY KEY (`id`) USING BTREE, KEY `idx_stock_bk_money_history_1` (`bk_code`,`curr_date`) USING BTREE, KEY `stock_bk_money_history_type_IDX` (`type`,`curr_date`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=2639449 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='版块资金注入历史';

关键说明:

① 支持4种类型(板块/概念/地域/股票),适配多维度资金分析;

② 字段全面,覆盖所有资金流向指标,同时包含最新价、涨跌比例,可联动行情数据;

③ 双索引优化,按“板块编码+日期”“类型+日期”查询,适配策略回测和多维度分析,大幅提升查询效率;

④ 字段类型适配资金数据特点,避免数据精度丢失或存储失败。

2. Do实体类:StockBkMoneyHistoryDo(适配MyBatis-Plus,给定直接用)

核心作用:映射stock_bk_money_history表,适配MyBatis-Plus,实现资金数据的CRUD操作,无需手动编写SQL,直接调用BaseMapper即可完成资金数据的存储与查询,节省开发时间。

给定的Do类已完善所有字段映射、数据转换和工具方法,重点讲解2个核心亮点和使用方法:

@Data @EqualsAndHashCode(callSuper = false) @TableName("stock_bk_money_history") public class StockBkMoneyHistoryDo implements Serializable { private static final long serialVersionUID = 1L; /** * id编号 */ @TableId(value = "id", type = IdType.AUTO) private Integer id; /** * 板块编号 */ @TableField("bk_code") private String bkCode; /** * 板块名称 */ @TableField("bk_name") private String bkName; /** * 当前日期 */ @TableField("curr_date") private Date currentDate; /** * 类型 1是板块 2是 概念 3是地域 4是股票列表 */ @TableField("type") private Integer type; /** * 最新价 */ @TableField("bk_now_price") private BigDecimal bkNowPrice; /** * 板块涨跌比例 */ @TableField("bk_now_proportion") private String bkNowProportion; /** * 市场 */ @TableField("market") private String market; /** * 今日主力净注入净额 */ @TableField("today_main_inflow") private String todayMainInflow; /** * 今日主力净注入净额 占比 */ @TableField("today_main_inflow_proportion") private String todayMainInflowProportion; /** * 今日 超大净注入净额 */ @TableField("today_super_inflow") private String todaySuperInflow; /** * 今日 超大净注入净额 占比 */ @TableField("today_super_inflow_proportion") private String todaySuperInflowProportion; /** * 今日 大单净注入净额 */ @TableField("today_more_inflow") private String todayMoreInflow; /** * 今日 大单净注入净额 占比 */ @TableField("today_more_inflow_proportion") private String todayMoreInflowProportion; /** * 今日 中单净注入净额 */ @TableField("today_middle_inflow") private String todayMiddleInflow; /** * 今日 中单净注入净额 占比 */ @TableField("today_middle_inflow_proportion") private String todayMiddleInflowProportion; /** * 今日 小单净注入净额 */ @TableField("today_small_inflow") private String todaySmallInflow; /** * 今日 小单净注入净额 占比 */ @TableField("today_small_inflow_proportion") private String todaySmallInflowProportion; /** * 今日主力净注入股票编码 */ @TableField("today_main_inflow_code") private String todayMainInflowCode; /** * 今日主力净注入股票名称 */ @TableField("today_main_inflow_name") private String todayMainInflowName; /** * 排序 */ @TableField("sort_num") private Integer sortNum; @TableField(exist = false) private Boolean convertData = true; @TableField(exist = false) @Schema(description = "ai消息") private String aiMessage; public StockBkMoneyHistoryDo convertData(Boolean convertData) { this.convertData = convertData; return this; } public String getTodayMainInflow() { return convertData(todayMainInflow); } public String getTodaySuperInflow() { return convertData(todaySuperInflow); } public String getTodayMoreInflow() { return convertData(todayMoreInflow); } public String getTodayMiddleInflow() { return convertData(todayMiddleInflow); } public String getTodaySmallInflow() { return convertData(todaySmallInflow); } public String convertData(String value) { return value; } public String getAiMessage() { return "主力净注入净额:" + todayMainInflow + "主力净注入净额占比:" + todayMainInflowProportion + "超大净注入净额:" + todaySuperInflow + "超大净注入净额占比:" + todaySuperInflowProportion + "大单净注入净额:" + todayMoreInflow + "大单净注入净额占比:" + todayMoreInflowProportion + "中单净注入净额:" + todayMiddleInflow + "中单净注入净额占比:" + todayMiddleInflowProportion; } }

✅ 核心亮点&使用说明:

① 字段完全映射SQL表,无需修改,直接复制到项目entity包下,确保MyBatis-Plus依赖配置正确即可使用;

② 内置数据转换方法(convertData),可根据需求扩展数据格式(比如将资金净额转换为万元/亿元,适配展示需求);

③ 自动生成AI消息(getAiMessage),可直接用于策略提醒、数据展示,无需额外拼接字符串;

④ 非数据库字段(convertData、aiMessage)标注@TableField(exist = false),避免MyBatis-Plus查询报错。

3. 补充枚举:BKType(资金类型枚举,适配爬取代码)

核心作用:统一管理4种资金类型(板块/概念/地域/股票),封装类型code和中文描述,与爬取代码、Do类的type字段联动,避免硬编码,减少解析错误,适配多维度资金抓取。

/** * 资金类型枚举(适配stock_bk_money_history表的type字段) * 对应关系:1-板块 2-概念 3-地域 4-股票 */ public enum BKType { BK(1, "板块"), CONCEPT(2, "概念"), REGION(3, "地域"), STOCK(4, "股票"); private Integer code; private String desc; // 根据code获取枚举对象(核心方法,用于爬取代码联动) public static BKType getByCode(Integer code) { for (BKType bkType : BKType.values()) { if (bkType.getCode().equals(code)) { return bkType; } } return null; } // 构造方法+getter BKType(Integer code, String desc) { this.code = code; this.desc = desc; } public Integer getCode() { return code; } public String getDesc() { return desc; } }

✅ 使用说明:直接复制到项目enum包下,与爬取代码中的BKType参数联动,确保资金类型的一致性,避免type字段赋值错误。

三、核心落地:某券商资金数据爬取代码|避反爬+完整可运行📥

搞定了基础组件,接下来就是核心的「资金数据爬取」——基于某券商专属资金接口,复用前48篇的反爬逻辑,实现单股票/板块资金数据的精准抓取、JSONP解析、异常处理,确保数据抓取稳定、不中断,给定的爬取代码已完善核心逻辑,重点拆解使用方法和反爬重点。

以下所有爬取、解析代码均为实战可运行版本,直接复制到项目对应包下,注入相关依赖即可运行,全程拆解关键细节,新手也能看懂。

1. 核心接口:Controller层(接收请求,返回资金数据)

作用:接收前端/策略的请求(传入股票编码),调用Service层方法,获取并处理资金数据,返回标准化结果,适配策略调用或前端展示。

/** * 股票/板块资金数据Controller * 核心功能:接收请求,返回今日资金流向详细数据 */ @RestController @RequestMapping("/stock/money") public class StockMoneyController { @Autowired private StockMoneyService stockMoneyService; /** * 获取今日股票资金流向详细数据 * @param code 股票编码(6位,如600000) * @return 今日资金流向列表(按时间维度) */ @GetMapping("/today") public OutputResult<List<BKMoneyInfo>> showTodayMoney(String code) { // 1. 校验股票编码,获取真实编码(避免输入错误、全称等情况) String realCode = stockService.getByCodeOrNameOrFullCode(code).getCode(); // 2. 转换股票编码为某券商接口所需的secid格式(如sh600000→0.600000) String secid = stockCodeHelper.convertCode(realCode); // 3. 设置资金类型为股票(对应BKType.STOCK,code=4) BKType bkType = BKType.STOCK; // 4. 调用Service层方法,抓取今日资金详细数据 List<BKMoneyInfo> historyBkMoneyList = extCrawlerService.findTodayDetailBkMoneyList(1, secid, bkType); // 5. 数据转换处理(适配展示/存储需求,可扩展) convertMoneyShow(historyBkMoneyList); // 6. 返回标准化结果 return OutputResult.buildSucc(historyBkMoneyList); } /** * 资金数据转换处理(可根据需求扩展) * 示例:将资金净额转换为万元单位,优化展示效果 */ private void convertMoneyShow(List<BKMoneyInfo> historyBkMoneyList) { if (CollUtil.isEmpty(historyBkMoneyList)) { return; } historyBkMoneyList.forEach(info -> { // 主力资金净额转换(单位:元→万元) if (StrUtil.isNotBlank(info.getTodayMainInflow())) { try { BigDecimal mainInflow = new BigDecimal(info.getTodayMainInflow()); info.setTodayMainInflow(mainInflow.divide(new BigDecimal(10000), 2, RoundingMode.HALF_UP) + "万"); } catch (Exception e) { // 异常兜底,不影响整体数据 } } // 可继续扩展:超大单、大单等资金净额的单位转换 }); } }

2. 核心实现:Service层(爬取逻辑,给定代码完善)

作用:拼接某券商资金接口URL,处理反爬,调用Parser层解析数据,异常兜底,确保数据抓取稳定,是资金爬取的核心逻辑。

/** * 某券商资金数据爬取实现类 * 核心功能:抓取股票/板块今日资金流向详细数据,处理反爬,异常兜底 */ @Service public class ExtCrawlerServiceImpl implements ExtCrawlerService { @Autowired private StockInfoParser stockInfoParser; // 解析器(下文会补充) @Autowired private HttpClientConfig httpClientConfig; // HttpClient配置(反爬用) // 固定回调函数(cb参数,避免动态变化导致JSONP解析失败,反爬关键) private static final String CB_ASYNC_BK = "yueshushu"; @Override public List<BKMoneyInfo> findTodayDetailBkMoneyList(Integer size, String code, BKType bkType) { // 1. 拼接某券商资金接口URL(固定格式,动态替换回调函数、secid) String urlInfo = "https://push2.eastmoney.com/api/qt/stock/fflow/kline/get?cb={0}&lmt=0&klt=1" + "&fields1=f1,f2,f3,f7&fields2=f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64,f65&ut=b2884a393a59ad64002292a3e90d46a5" + "&secid={1}&_="; // 2. 格式化URL,替换回调函数(CB_ASYNC_BK)和股票secid String url = MessageFormat.format(urlInfo, CB_ASYNC_BK, code); // 3. 调用解析方法,拼接时间戳(反爬关键),返回资金数据列表 return parseMoneyTodayDetailInfoList(url + MyDateUtil.getTimezone(), bkType); } /** * 解析今日资金详细数据(核心方法) * @param url 拼接好的接口URL(含时间戳) * @param bkType 资金类型(股票/板块等) * @return 解析后的资金数据列表 */ private List<BKMoneyInfo> parseMoneyTodayDetailInfoList(String url, BKType bkType) { try { // 1. 发送HTTP请求(复用反爬配置,避免IP封禁) String content = HttpUtil.sendGet(HttpClientConfig.proxyNoUseCloseableHttpClient(), url, buildDfHeaderMap()); // 2. 处理JSONP格式(去掉回调函数包裹,转换为纯JSON,解析关键) content = content.substring(CB_ASYNC_BK.length() + 1); // 去掉前缀:asyncBk( content = content.substring(0, content.length() - 2); // 去掉后缀:) // 3. 调用Parser层解析JSON数据,转换为BKMoneyInfo列表 List<BKMoneyInfo> bkMoneyInfos = stockInfoParser.parseTodayMoneyDetailInfoList(content); // 4. 给每条资金数据设置类型(股票/板块等),与Do类联动 if (!CollUtil.isEmpty(bkMoneyInfos)) { bkMoneyInfos.forEach(n -> n.setType(bkType.getCode())); } return bkMoneyInfos; } catch (Exception e) { // 5. 异常兜底:记录日志,返回空列表,避免策略崩溃 log.error("{} parseMoneyTodayDetailInfoList 获取资金数据出错", ThreadLocalUtils.getIp(), e); return Collections.emptyList(); } } /** * 构建请求头(反爬关键,模拟真实浏览器请求) */ private Map<String, String> buildDfHeaderMap() { Map<String, String> header = new HashMap<>(); header.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"); header.put("Referer", "https://finance.eastmoney.com/"); header.put("Accept-Encoding", "gzip, deflate, br"); return header; } }

反爬重点(必看):

① 固定回调函数CB_ASYNC_BK,避免动态变化导致JSONP解析失败;

② 拼接时间戳MyDateUtil.getTimezone(),模拟真实用户请求,避免被接口识别为机器人;

③ 构建真实请求头(User-Agent、Referer),进一步提升反爬成功率;

④ 复用HttpClient代理配置,高频抓取时可添加多IP代理,彻底规避IP封禁;

⑤ 异常兜底,避免抓取失败导致策略崩溃。

3. 核心解析:Parser层(解析JSON数据,给定代码完善)

作用:将接口返回的JSON数据(去掉JSONP包裹后)解析,提取核心资金字段,封装为BKMoneyInfo列表,适配存储和策略使用,给定的解析代码已兼容接口格式,重点讲解解析逻辑。

/** * 股票资金数据解析器 * 核心功能:解析某券商资金接口返回的JSON数据,转换为BKMoneyInfo列表 */ @Component public class StockInfoParser { /** * 解析今日资金详细数据(核心方法) * @param content 处理后的纯JSON内容(已去掉JSONP回调包裹) * @return 解析后的资金数据列表(按时间维度) */ public List<BKMoneyInfo> parseTodayMoneyDetailInfoList(String content) { // 1. 解析JSON对象 JSONObject jsonObject = JSONObject.parseObject(content); // 2. 获取data字段(核心数据所在),空值校验 JSONObject data = jsonObject.getJSONObject("data"); if (ObjectUtils.isEmpty(data)) { return Collections.emptyList(); } // 3. 提取股票/板块核心信息(编码、名称、市场) String code = data.getString("code"); String name = data.getString("name"); Integer market = data.getInteger("market"); // 4. 获取资金数据列表(接口返回的klines字段,按时间排序) JSONArray jsonArray = data.getJSONArray("klines"); if (jsonArray.size() <= 0) { return Collections.emptyList(); } // 5. 解析每一条资金数据,封装为BKMoneyInfo List<BKMoneyInfo> result = new ArrayList<>(32); jsonArray.forEach(n -> { String singleContent = n.toString(); if (StrUtil.isNotBlank(singleContent)) { // 5.1 按逗号分割数据(接口返回格式固定,splitArr对应不同字段) String[] splitArr = singleContent.split(Const.JOB_PARAM_SPLIT); BKMoneyInfo bkMoneyInfo = new BKMoneyInfo(); // 5.2 封装基础信息(编码、名称、时间) bkMoneyInfo.setBkCode(code); bkMoneyInfo.setBkName(name); // 时间格式转换(接口返回格式→标准格式HH:mm:ss) bkMoneyInfo.setCurrentDate(DateUtil.parse(splitArr[0], DatePattern.NORM_DATETIME_MINUTE_PATTERN)); bkMoneyInfo.setCurrentDateStr(DateUtil.format(bkMoneyInfo.getCurrentDate(), DatePattern.NORM_DATETIME_MINUTE_PATTERN)); // 5.3 封装价格、涨跌比例(可后续补充,关联行情数据) bkMoneyInfo.setBkNowPrice(null); bkMoneyInfo.setBkNowProportion(null); // 5.4 封装市场信息(1=沪市,0=深市,可后续转换为中文) bkMoneyInfo.setMarket(market); // 5.5 封装核心资金数据(对应splitArr索引,接口返回格式固定) bkMoneyInfo.setTodayMainInflow(splitArr[1]); // 主力净注入净额 bkMoneyInfo.setTodayMainInflowProportion(null); // 占比可后续计算补充 bkMoneyInfo.setTodaySuperInflow(splitArr[5]); // 超大净注入净额 bkMoneyInfo.setTodaySuperInflowProportion(null); bkMoneyInfo.setTodayMoreInflow(splitArr[4]); // 大单净注入净额 bkMoneyInfo.setTodayMoreInflowProportion(null); bkMoneyInfo.setTodayMiddleInflow(splitArr[3]); // 中单净注入净额 bkMoneyInfo.setTodayMiddleInflowProportion(null); bkMoneyInfo.setTodaySmallInflow(splitArr[2]); // 小单净注入净额 bkMoneyInfo.setTodaySmallInflowProportion(null); // 5.6 主力净注入股票编码、名称(可后续关联补充) bkMoneyInfo.setTodayMainInflowCode(null); bkMoneyInfo.setTodayMainInflowName(null); // 5.7 添加到结果列表 result.add(bkMoneyInfo); } }); return result; } }

✅ 解析重点(必看):

① 接口返回的klines字段是核心数据,每条数据按逗号分割,splitArr索引对应固定字段(1=主力、2=小单、3=中单、4=大单、5=超大单),不可随意修改;

② 时间格式转换,确保时间统一,便于后续策略的时间维度分析;

③ 空值校验和异常规避,跳过空数据,避免解析报错;

④ 可扩展补充:资金占比计算、市场中文转换(1→沪市,0→深市)、主力净注入股票关联等。

补充:BKMoneyInfo实体类(解析结果封装,适配爬取+存储)

用于封装解析后的资金数据,适配爬取、解析、策略调用全流程,与StockBkMoneyHistoryDo对应,可直接转换为Do类存储到数据库:

@Data public class BKMoneyInfo implements Serializable { private static final long serialVersionUID = 1L; // 基础信息 private String bkCode; // 板块/股票编码 private String bkName; // 板块/股票名称 private Date currentDate; // 当前日期(时间戳) private String currentDateStr; // 当前日期字符串(HH:mm:ss,便于展示) private Integer type; // 类型(对应BKType,1-板块,4-股票等) // 价格信息 private BigDecimal bkNowPrice; // 最新价 private String bkNowProportion; // 涨跌比例 private Integer market; // 市场(1=沪市,0=深市) // 核心资金数据 private String todayMainInflow; // 今日主力净注入净额 private String todayMainInflowProportion; // 主力净注入占比 private String todaySuperInflow; // 今日超大净注入净额 private String todaySuperInflowProportion; // 超大净注入占比 private String todayMoreInflow; // 今日大单净注入净额 private String todayMoreInflowProportion; // 大单净注入占比 private String todayMiddleInflow; // 今日中单净注入净额 private String todayMiddleInflowProportion; // 中单净注入占比 private String todaySmallInflow; // 今日小单净注入净额 private String todaySmallInflowProportion; // 小单净注入占比 // 关联信息 private String todayMainInflowCode; // 今日主力净注入股票编码 private String todayMainInflowName; // 今日主力净注入股票名称 private Integer sortNum; // 排序顺序 }

四、实战联动:资金数据存储+策略使用|闭环落地📈

爬取、解析完成后,需要将资金数据存储到数据库(stock_bk_money_history表),同时联动前49篇的短线策略,实现「资金流向+异动信号+股票池」的三维策略闭环,以下是核心落地步骤(可直接复用)。

1. 资金数据存储(Service层补充,核心落地)

将解析后的BKMoneyInfo列表,转换为StockBkMoneyHistoryDo,存储到数据库,实现资金历史数据的持久化,用于后续策略回测、资金流向分析,支持批量存储,提升效率。

@Autowired private StockBkMoneyHistoryMapper stockBkMoneyHistoryMapper; // MyBatis-Plus Mapper /** * 存储资金数据到数据库(批量存储,提升效率) * @param bkMoneyInfoList 解析后的资金数据列表 * @param currDate 当日日期(完整时间戳) */ public void saveBkMoneyData(List<BKMoneyInfo> bkMoneyInfoList, Date currDate) { if (CollUtil.isEmpty(bkMoneyInfoList)) { return; } // 转换为StockBkMoneyHistoryDo,批量存储 List<StockBkMoneyHistoryDo> moneyHistoryDoList = bkMoneyInfoList.stream().map(info -> { StockBkMoneyHistoryDo moneyHistoryDo = new StockBkMoneyHistoryDo(); // 基础信息赋值 moneyHistoryDo.setBkCode(info.getBkCode()); moneyHistoryDo.setBkName(info.getBkName()); moneyHistoryDo.setCurrentDate(currDate); // 统一设置当日日期 moneyHistoryDo.setType(info.getType()); // 资金类型(1-板块,4-股票等) // 价格信息赋值(可关联行情数据补充) moneyHistoryDo.setBkNowPrice(info.getBkNowPrice()); moneyHistoryDo.setBkNowProportion(info.getBkNowProportion()); // 市场转换(1→沪市,0→深市,优化存储可读性) moneyHistoryDo.setMarket(info.getMarket() == 1 ? "沪市" : "深市"); // 核心资金数据赋值 moneyHistoryDo.setTodayMainInflow(info.getTodayMainInflow()); moneyHistoryDo.setTodayMainInflowProportion(info.getTodayMainInflowProportion()); moneyHistoryDo.setTodaySuperInflow(info.getTodaySuperInflow()); moneyHistoryDo.setTodaySuperInflowProportion(info.getTodaySuperInflowProportion()); moneyHistoryDo.setTodayMoreInflow(info.getTodayMoreInflow()); moneyHistoryDo.setTodayMoreInflowProportion(info.getTodayMoreInflowProportion()); moneyHistoryDo.setTodayMiddleInflow(info.getTodayMiddleInflow()); moneyHistoryDo.setTodayMiddleInflowProportion(info.getTodayMiddleInflowProportion()); moneyHistoryDo.setTodaySmallInflow(info.getTodaySmallInflow()); moneyHistoryDo.setTodaySmallInflowProportion(info.getTodaySmallInflowProportion()); // 关联信息赋值(可后续补充) moneyHistoryDo.setTodayMainInflowCode(info.getTodayMainInflowCode()); moneyHistoryDo.setTodayMainInflowName(info.getTodayMainInflowName()); moneyHistoryDo.setSortNum(info.getSortNum()); return moneyHistoryDo; }).collect(Collectors.toList()); // 批量插入,提升存储效率(MyBatis-Plus核心方法) stockBkMoneyHistoryMapper.insertBatchSomeColumn(moneyHistoryDoList); }

✅ 存储重点:① 统一设置当日日期(currDate),确保数据的时间一致性,便于后续按日期查询;② 市场类型转换(数字→中文),提升数据可读性;③ 批量插入,避免单条插入效率低下,适配高频抓取需求;④ 字段一一对应,避免存储失败。

2. 与量化策略联动(实战核心,高胜率关键)

结合前48篇的异动数据、前49篇的短线策略,加入资金流向指标,实现「三维筛选」,大幅提升策略胜率,示例如下(高胜率短线策略片段):

/** * 资金+异动+涨停股池 组合策略(短线高胜率) * @param ztList 涨停股池列表(复用前47篇方法) * @param ydList 异动数据列表(复用前48篇方法) * @param moneyList 资金数据列表(本篇方法) * @return 筛选后的优质标的 */ public List<StrategyStockInfo> moneyYiDongZtStrategy( List<StockPoolInfo> ztList, List<StrategyStockInfo> ydList, List<BKMoneyInfo> moneyList) { if (CollUtil.isEmpty(ztList) || CollUtil.isEmpty(ydList) || CollUtil.isEmpty(moneyList)) { return Collections.emptyList(); } // 1. 提取涨停股编码,用于联动异动、资金数据 Set<String> ztCodeSet = ztList.stream().map(StockPoolInfo::getCode).collect(Collectors.toSet()); // 2. 筛选:涨停股 + 看多异动 + 主力/超大单双净流入 return ydList.stream() .filter(yd -> ztCodeSet.contains(yd.getCode())) // 属于涨停股池 .filter(yd -> YiDongType.containsDuo(Collections.singletonList(yd.getType()))) // 看多异动(复用前48篇枚举方法) .filter(yd -> { // 联动资金数据,筛选主力+超大单双净流入 BKMoneyInfo moneyInfo = moneyList.stream() .filter(m -> m.getBkCode().equals(yd.getCode())) .findFirst() .orElse(null); if (moneyInfo == null) { return false; } // 主力净流入>0,超大单净流入>0,确保资金支撑 return StrUtil.isNotBlank(moneyInfo.getTodayMainInflow()) && new BigDecimal(moneyInfo.getTodayMainInflow().replace("万", "")).compareTo(BigDecimal.ZERO) > 0 && StrUtil.isNotBlank(moneyInfo.getTodaySuperInflow()) && new BigDecimal(moneyInfo.getTodaySuperInflow().replace("万", "")).compareTo(BigDecimal.ZERO) > 0; }) .collect(Collectors.toList()); }

✅ 策略亮点:通过「涨停股池(优质标的)+ 看多异动(时机信号)+ 资金净流入(支撑信号)」三维筛选,避免假突破、无资金支撑的异动,大幅提升短线策略的胜率和盈利能力——这也是我们落地资金数据的核心意义。

五、资金爬取&存储10大避坑指南⚠️|实战必看,少走弯路

结合实战经验,整理了资金数据爬取、解析、存储全流程的10大高频坑,每一个都附解决方案,帮你避免数据抓取失败、解析报错、存储异常等问题,确保资金数据正常落地,适配量化策略使用。

爬取层面4大坑

  1. 1. 坑1:回调函数(cb)不固定,导致JSONP解析失败

✅ 解决:严格固定cb为「asyncBk」,与爬取代码一致,避免动态变化导致解析报错;

  1. 2. 坑2:未拼接时间戳,被接口识别为机器人请求

✅ 解决:接口URL必须拼接MyDateUtil.getTimezone(),模拟真实用户请求,提升爬取成功率;

  1. 3. 坑3:未设置请求头,高频抓取导致IP封禁

✅ 解决:必须调用buildDfHeaderMap()方法,设置User-Agent、Referer等请求头,模拟浏览器请求;

  1. 4. 坑4:股票编码未转换为secid,接口返回无数据

✅ 解决:必须通过stockCodeHelper.convertCode()方法,将6位股票编码转换为某券商接口所需的secid格式(如600000→0.600000)。

解析层面3大坑

  1. 5. 坑5:splitArr索引对应错误,导致资金数据赋值错误

✅ 解决:牢记接口返回格式,splitArr[1]=主力、[2]=小单、[3]=中单、[4]=大单、[5]=超大单,不可随意修改索引;

  1. 6. 坑6:未做空值校验,导致JSON解析空指针异常

✅ 解决:解析data、klines字段时,先判断是否为空,避免空指针;解析资金数据时,判断singleContent是否非空;

  1. 7. 坑7:时间格式未转换,导致存储后时间混乱

✅ 解决:严格使用DateUtil.parse()方法,将接口返回的时间转换为标准格式,确保时间统一。

存储&使用层面3大坑

  1. 8. 坑8:资金数据未转换单位,存储后可读性差

✅ 解决:存储前将资金净额转换为万元/亿元单位,同时保留原始数据,兼顾可读性和策略计算需求;

  1. 9. 坑9:未批量存储,单条插入效率低,高频抓取卡顿

✅ 解决:严格使用MyBatis-Plus的insertBatchSomeColumn方法,批量插入资金数据,提升存储效率;

  1. 10. 坑10:资金数据与策略未联动,单独使用资金信号

✅ 解决:资金信号必须结合异动、股票池使用,比如主力净流入+看多异动+涨停股,避免单一资金信号误判。

六、福利领取:资金全流程完整代码包免费送🎁

为了帮大家快速落地资金数据的爬取、解析、存储与策略联动,整理了本次第50篇的完整可运行代码包,包含所有代码片段,直接导入项目即可运行,无需二次开发:

  1. 1. ① SQL表脚本(stock_bk_money_history,直接执行);
  2. 2. ② 所有实体类/枚举类(StockBkMoneyHistoryDo、BKMoneyInfo、BKType);
  3. 3. ③ 爬取+解析完整代码(Controller+Service+Parser,含反爬优化);
  4. 4. ④ 数据存储+策略联动代码(直接嵌入量化项目);
  5. 5. ⑤ 避坑手册(图文版,含常见问题解决方案)。

私信回复【资金爬取完整代码】,即可免费领取!所有代码均注释完善,适配最新某券商接口,兼容前49篇的量化框架,新手也能快速上手,打通资金数据全流程。

下期预告✨

第50篇我们搞定了股票资金数据的全落地,实现了「资金+异动+股票池」的三维策略闭环!

下一篇(第51篇),我们将聚焦 获取当前全市场的股票实时数据。

结尾互动

你在爬取股票资金数据时,有没有踩过IP封禁、解析报错、存储失败的坑?需要我提前补充「多IP代理配置代码」,帮你彻底规避反爬风险吗?欢迎在评论区留言讨论!

如果觉得这篇文章对你有帮助,别忘了点赞+在看+转发,让更多量化开发者少走弯路,一起完善自己的量化交易体系~ 关注我,持续解锁Java量化实战干货!🚀

#金亥跃江聊量化 #股票量化 #金亥跃江 #Java量化

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/24 4:28:56

Agent智能体开发面试核心考察点与实战解析

1. Agent智能体开发面试核心考察点解析 在AI技术快速发展的当下&#xff0c;Agent智能体开发已成为热门领域。作为面试官&#xff0c;我通常会从四个维度考察候选人&#xff1a;基础理论掌握度&#xff08;30%&#xff09;、工程实现能力&#xff08;40%&#xff09;、问题解决…

作者头像 李华
网站建设 2026/8/24 4:28:25

前端大数组渲染卡顿,JS大数据分片处理实战方案

前端大数组渲染卡顿&#xff0c;JS 大数据分片处理实战方案做前端开发或多或少都遇到过大数据渲染卡顿的问题。后台管理系统、数据可视化、日志列表页面&#xff0c;一旦一次性返回上万条、甚至几万条数据&#xff0c;页面瞬间卡死&#xff0c;滚动卡顿、按钮点击无响应&#x…

作者头像 李华
网站建设 2026/8/24 4:26:06

递归算法入门:从集合生成规则理解深度优先搜索与剪枝优化

1. 项目概述&#xff1a;一道经典的递归入门题 “判断元素是否存在”这道题&#xff0c;无论是出现在《信息学奥赛一本通》还是OpenJudge NOI的题库里&#xff0c;对于初次接触递归算法的同学来说&#xff0c;都像是一道“劝退题”。题目描述看似简单&#xff1a;给定一个由规则…

作者头像 李华
网站建设 2026/8/24 4:25:55

前端即时通讯实战:从协议选型到工程化落地的全链路解析

你有没有遇到过这样的场景&#xff1a;面试官问“前端如何做即时通讯”&#xff0c;你脑子里瞬间闪过一堆名词&#xff1a;WebSocket、SSE、轮询、长轮询、Comet……然后你开始背诵八股文&#xff0c;从HTTP协议讲到WebSocket握手&#xff0c;从心跳包讲到断线重连。面试官点点…

作者头像 李华
网站建设 2026/8/24 4:25:01

ScriptHookVDotNet:用 C 写 GTA V 脚本的原生函数调用插件

ScriptHookVDotNet&#xff1a;用 C# 写 GTA V 脚本的原生函数调用插件 【免费下载链接】scripthookvdotnet An ASI plugin for Grand Theft Auto V, which allows running scripts written in any .NET language on the .NET Framework runtime in-game. 项目地址: https://…

作者头像 李华
网站建设 2026/8/24 4:23:36

大语言模型内存陷阱评测:MemTrapBench构建与优化实践

在实际的大语言模型&#xff08;LLM&#xff09;应用开发与评估中&#xff0c;我们常常关注其生成内容的准确性、流畅性或推理能力&#xff0c;却容易忽视一个更为基础且关键的系统性维度&#xff1a;内存使用。LLM 在推理过程中&#xff0c;尤其是在处理长上下文、复杂任务链或…

作者头像 李华