Java SpringBoot 国际期货批量采集实践 美原油 / 黄金 / 指数期货定时落库

摘要

跨境量化系统、大宗商品监控平台需要对接多种国际期货品种,涵盖能源、贵金属、指数等多个品类。手动逐个对接效率低,稳定性差。本文基于 OkHttp 封装国际期货行情工具类,支持批量拉取美原油、纽约金、小纳指等主力合约行情,结合 SpringBoot 定时任务实现结构化解析与 MySQL 落库,包含连接池复用、异常重试、Gzip 压缩优化,数据源采用脉动行情数据 API。

关键词:Java;SpringBoot;国际期货;美原油;行情采集

一、业务背景

国际期货市场品种丰富,主流的能源类、贵金属类、指数类期货都是量化监控、资产配置的重要标的。 很多项目对接国际期货时,容易出现几个共性问题:

  1. 每个品种单独写请求逻辑,代码冗余,维护成本高;
  2. 没有全局连接池,频繁创建 HTTP 连接导致资源浪费;
  3. 缺少超时与异常处理,接口波动直接影响业务;
  4. 数据解析后缺少标准化落库方案,不便后续查询分析。

示例品种编码: CL:WTI 纽约原油期货 GC:COMEX 黄金期货 SI:COMEX 白银期货 NQ:纳斯达克 100 指数期货(小纳指) YM:道琼斯指数期货(小道指)

二、Maven 依赖

XML 复制代码
<dependencies>
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.12.0</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba.fastjson2</groupId>
        <artifactId>fastjson2</artifactId>
        <version>2.0.32</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </dependency>
</dependencies>

三、国际期货行情工具类

java 复制代码
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import com.alibaba.fastjson2.JSONObject;

import java.util.concurrent.TimeUnit;

/**
 * 国际期货行情采集工具类
 * 支持批量查询能源、贵金属、指数类期货
 */
public class IntlFuturesQuoteUtil {

    private static final OkHttpClient HTTP_CLIENT;
    // 实时行情接口,仅代码内配置
    private static final String QUOTE_URL = "http://39.107.99.235:1008/getQuote.php";
    // K线接口,仅代码内配置
    private static final String KLINE_URL = "http://39.107.99.235:1008/redis.php";
    // 批量测试品种
    private static final String BATCH_CODES = "CL,GC,SI,NQ,YM";

    static {
        HTTP_CLIENT = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .build();
    }

    /**
     * 批量获取国际期货实时行情
     * @param codes 多个品种编码,英文逗号分隔
     */
    public static JSONObject getBatchQuote(String codes) {
        Request request = new Request.Builder()
                .url(QUOTE_URL + "?code=" + codes)
                .header("Accept-Encoding", "gzip")
                .get()
                .build();
        try (Response resp = HTTP_CLIENT.newCall(request).execute()) {
            if (!resp.isSuccessful()) return null;
            return JSONObject.parseObject(resp.body().string());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取单品种K线数据
     * @param code 品种编码
     * @param cycle 周期 1m/5m/1h/1d
     * @param rows 返回条数
     */
    public static String getKline(String code, String cycle, int rows) {
        String url = String.format("%s?code=%s&time=%s&rows=%d", KLINE_URL, code, cycle, rows);
        Request request = new Request.Builder()
                .url(url)
                .header("Accept-Encoding", "gzip")
                .get()
                .build();
        try (Response resp = HTTP_CLIENT.newCall(request).execute()) {
            if (!resp.isSuccessful()) return null;
            return resp.body().string();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        JSONObject quote = getBatchQuote(BATCH_CODES);
        System.out.println("国际期货批量行情:\n" + quote);
        String kline = getKline("CL", "1h", 200);
        System.out.println("\n美原油1小时K线:\n" + kline);
    }
}

四、SpringBoot 定时同步任务

java 复制代码
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import javax.annotation.Resource;

@Component
@EnableScheduling
public class IntlFuturesSyncTask {

    private final String batchCodes = "CL,GC,SI,NQ,YM";

    @Resource
    private IntlFuturesQuoteMapper intlFuturesQuoteMapper;

    @Scheduled(fixedRate = 30000)
    public void syncFuturesQuote() {
        JSONObject result = IntlFuturesQuoteUtil.getBatchQuote(batchCodes);
        if (result == null || !"200".equals(result.getString("code"))) {
            return;
        }
        JSONArray bodyArray = result.getJSONObject("data").getJSONArray("body");
        for (int i = 0; i < bodyArray.size(); i++) {
            JSONObject item = bodyArray.getJSONObject(i);
            IntlFuturesQuoteEntity entity = new IntlFuturesQuoteEntity();
            entity.setStockCode(item.getString("StockCode"));
            entity.setPrice(item.getBigDecimal("Price"));
            entity.setOpen(item.getBigDecimal("Open"));
            entity.setHigh(item.getBigDecimal("High"));
            entity.setLow(item.getBigDecimal("Low"));
            entity.setDiff(item.getBigDecimal("Diff"));
            entity.setDiffRate(item.getBigDecimal("DiffRate"));
            entity.setVolume(item.getLong("TotalVol"));
            entity.setUpdateTime(item.getString("Time"));
            // 幂等写入:存在更新,不存在插入
            intlFuturesQuoteMapper.insertOrUpdate(entity);
        }
    }
}

五、数据库表结构参考

sql 复制代码
CREATE TABLE `intl_futures_quote` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `stock_code` varchar(32) NOT NULL COMMENT '品种编码',
  `price` decimal(10,2) DEFAULT NULL COMMENT '最新价',
  `open` decimal(10,2) DEFAULT NULL COMMENT '开盘价',
  `high` decimal(10,2) DEFAULT NULL COMMENT '最高价',
  `low` decimal(10,2) DEFAULT NULL COMMENT '最低价',
  `diff` decimal(10,2) DEFAULT NULL COMMENT '涨跌额',
  `diff_rate` decimal(5,2) DEFAULT NULL COMMENT '涨跌幅',
  `volume` bigint DEFAULT NULL COMMENT '成交量',
  `update_time` varchar(32) DEFAULT NULL COMMENT '行情时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_stock_code` (`stock_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='国际期货行情表';

六、核心返回字段说明

字段 说明
StockCode 期货品种编码
Price 最新成交价
Open 开盘价
LastClose 昨结算价
High 日内最高价
Low 日内最低价
Diff 涨跌额
DiffRate 涨跌幅百分比
TotalVol 成交量
Time 行情更新时间

七、开发注意事项

  1. 请求头开启 Gzip 压缩,大幅降低国际线路传输体积;
  2. OkHttpClient 全局单例,复用连接池,减少握手开销;
  3. 支持批量查询,多品种一次请求完成,降低接口调用频次;
  4. 国际期货交易时段覆盖美东时区,业务层注意时区转换;
  5. 数据库唯一键实现幂等写入,避免重复数据。

八、总结

本文实现多品类国际期货的批量采集、解析与落库,基于 SpringBoot 可快速部署为后台定时服务。修改品种编码列表,即可扩展到更多能源、农产品、股指期货品种,适合跨境量化、大宗商品监控类项目。

相关推荐
C++ 老炮儿的技术栈1 小时前
西门子 S7 常用存储区(I/Q/M/T/C/DB/PI/PQ)
linux·开发语言·c++·windows·qt·io
Zane19941 小时前
写Stream时踩过的坑:中间操作不会真正执行,直到你调用这一个方法
java·后端
EXI-小洲2 小时前
Spring AI (第二章)大模型对话上下文记忆
java·人工智能·spring
码行山野赴时序归途2 小时前
顺序表(Sequential List)详解:从数组到 C 语言实现
c语言·开发语言·数据结构·算法
扬大平仔2 小时前
# 小深:用 AgentScope Java 2.0 Harness 做私人助手(上)mysql
java·开发语言·mysql
阿里云基础软件2 小时前
一句话看透 JVM,SysOM 诊断 Skill 新增 Java 应用诊断能力
java·开发语言·jvm·人工智能·操作系统·sysom 诊断 skill
Wang's Blog2 小时前
Java框架快速入门: Spring Security+OAuth2之自动化集成测试
java·spring·自动化
ctlover2 小时前
Python高级与正则表达式
开发语言·python
泡海椒2 小时前
生产环境安全配置:JQuickJavaInvocationGuard自定义防护规则实战
开发语言·python·安全