
简介这套基于JAVA的AI开源量化交易平台源码包面向具备编程能力的专业程序员广泛应用于期货、股票、外汇及数字货币等交易场景支持历史回放、策略研发、模拟与实盘交易并兼顾全自动与半自动操作模式可有效替代文华、MC、金字塔等商业软件。包内含579个文件压缩后仅1.83MB以408个Java核心源码文件为主配合62个JavaScript和24个Vue组件构建前端交互界面另有XML/JSON/YML等配置文件、Proto协议定义、Dockerfile及证书密钥文件方便进行本地部署与二次开发。已有380人学习下载。通过学习这份资源可掌握多市场量化交易平台的完整架构设计理解Java与Vue前后端分离的实现思路并可直接基于源码进行策略定制、接口对接与自动化交易系统搭建是金融科技与程序化交易爱好者极具价值的参考项目。1. 从标题出发JAVA系AI量化平台为什么值得做用Python做量化研究的人很多但真正要把策略跑进实盘很多人最后都卡在同一个地方Python回测出来的曲线再漂亮也压不住行情网关、订单队列、断线重连和交易会话这些底层环节的抖动。我自己在期货和股票上做过几轮自动交易最终的落地方案都落在同一个选型上——一个基于JAVA的、AI能力可插拔的开源量化交易平台。它解决的痛点是三层研究端的策略要能无缝接入执行端行情、订单、成交回报这些对时间敏感的部分要扛得住JVM级别的并发整个系统要开源、可改、可审计。这一篇面向的读者是手里已有模型或策略、不想从零搭底层、又在Java和Python之间摇摆不定的从业者。2. 为什么是JAVA而不是Python选型逻辑与开源平台的四个核心模块2.1 Java生态在量化交易里的底层优势量化交易第一道分水岭是语言选型。Python在特征研究、模型训练阶段几乎没有对手但到了自动交易阶段它有几个硬伤GIL让多线程并发下单变得别扭动态类型在行情解析和订单状态机上容易出边界问题部署到生产环境的进程管理、依赖打包也麻烦。JAVA的优势恰好补在这些短板上具体说三点。第一价格和数量可以用强类型精确表达。期货、股票、外汇的报价通常带小数浮点运算在反复撮合和累计盈亏时会引入误差。常见做法是内部用long表示最小报价单位的整数倍展示层再转成DecimalJAVA在这一层的类型约束能直接把这类错误挡在编译期。第二并发模型天然适合多品种、多账户场景。一个自动交易实例往往同时监听几十个合约的行情每个合约独立计算信号、独立下订单。Java的线程池按symbol分片加上Netty负责行情解码写出来的代码比Python的asyncio直白很多。Netty的零拷贝和背压机制在行情爆发时不容易把内存打爆。第三运维体系成熟。开源社区里围绕Spring Boot、Prometheus、Grafana的监控方案几乎是现成的行情延迟、订单成交耗时、拒单率这些指标直接暴露成端点就好不需要自己发明轮子。JAVA的内存问题也比Python更容易定位GC日志、堆转储、火焰图都有标准工具。当然JAVA不是没有代价数学库和AI生态确实比Python薄。所以我在实际项目里很少让Java去承担模型训练而是让它专注做「决策执行」和「交易生命周期管理」。完整的链路通常是Python做离线训练和特征研究导出模型文件JAVA平台在线加载并执行交易决策。这正好是这类开源平台最常见的设计——研究端自由执行端可靠。2.2 开源平台典型模块划分行情、策略、风控、执行一个能用于多交易场景的开源量化平台无论代码怎么写边界都逃不开下面这四个模块。我第一次搭平台时试图把代码全塞进一个工程里后来发现拆开才是正路。模块职责典型实现行情接入接收交易所/券商推送协议解码tick重组为K线Netty网关 消息队列数据服务历史行情存取、K线合成、指标计算、复权处理JDBC/ClickHouse 缓存策略引擎事件驱动框架、信号生成、策略状态管理策略接口 策略容器执行层订单路由、重试、成交回报、撤单、持仓同步交易所API适配器风控层资金校验、仓位限额、频率限制、熔断独立过滤链行情接入和执行层是平台里最容易出问题的两块也是最值得复用开源实现的地方。自研这两块的成本极高你得处理交易所的登录鉴权、心跳、断线重连、行情序列号校验、订单状态机迁移还要应对不同交易所完全不同的协议风格。开源项目把这一层抽象成了统一接口你只需要为特定交易所写一个适配器。策略引擎和执行层之间务必加入风控层。常见的开源平台里风控是以责任链形式挂在订单下发路径上的先查资金够不够、仓位超没超、下单频率超没超、是否在禁止交易时段任何一条不满足就把订单拦下。这一步绝不能省因为AI模型的输出天然带概率性模型眼里的「好机会」和风控眼里的「可承受风险」经常是两回事。2.3 数据层与回测引擎决定一个平台值不值得改评估一个开源量化平台先打开它的数据层和回测引擎看。如果数据层只支持CSV导入、回测引擎只按日线撮合这个平台的适用场景就很窄如果它支持tick回放、分笔撮合、多种手续费模型说明作者真正做过实盘而不是只写了一个研究框架。数据层要解决的核心问题只有一个历史数据的完整性与对齐。股票有复权、停牌、涨跌停期货有换月、夜盘、最后交易日的涨跌停板幅度变化外汇和加密资产是7x24小时交易但不同交易对之间的交易时间仍有细微差异。开源平台通常在数据服务里统一存储原始tickK线由平台自己合成而不是直接存第三方算好的K线——这样才能保证未来调整参数时能重新合成。回测引擎的撮合模式直接决定回测结果的可靠程度。按bar撮合的回测速度快但默认按收盘价成交会严重高估收益按tick撮合更贴近真实盘口但需要高质量的tick历史数据而且回测速度慢好几个数量级。避坑的方法是平台至少要同时支持两种模式快速筛选用bar上线前验证用tick。若项目支持自定义撮合器尽量把「对手价滑点」作为默认设置后面第5章还会详细展开。3. 跑通回测最小可复现的搭建、配置与验证流程3.1 先梳理工程结构再动手构建拿到任何Java开源量化平台第一件事不是看README而是先确认本机环境再构建一次用失败日志判断项目健康度。常见平台都是Maven或Gradle聚合工程模块命名一般能看出分层意图。# 检查本机 JDK 与 Maven 版本常见平台要求 JDK 11 / Maven 3.6 java -version mvn -v # 在项目根目录做聚合构建跳过测试以节省时间 mvn clean install -DskipTests构建输出的关键点在最后的BUILD SUCCESS或BUILD FAILURE。如果失败先看是依赖下载失败还是编译失败。国内网络环境下依赖下载失败很常见换成镜像源即可编译失败通常意味着JDK版本不匹配多数开源平台在JDK 11上最稳。构建成功后用ls查看各模块的target目录确认核心模块已产出jar包。我第一次构建这类项目时犯过一个低级错误直接用mvn install跑了全量测试结果一个和数据相关的测试因为没有测试数据而失败我以为是代码问题排查了整整一天。后来养成习惯先-DskipTests构建跑通再逐步打开测试验证功能。3.2 配置文件里的关键参数滑点、手续费与数据区间开源平台一般把回测参数集中在单独配置文件中常见的格式是YAML。这里给出一份典型的最小配置并解释每个参数的意义backtest: start: 2023-01-01 # 回测起始日期 end: 2023-12-31 # 回测结束日期 initial_capital: 1000000 # 初始资金单位元 symbols: - rb8888 # 螺纹钢主连 - IF8888 # 股指期货主连 fee_rate: 0.0001 # 手续费率双边按成交金额计 slippage: 1 # 滑点单位最小变动价位 data_mode: bar # bar 撮合可换 tick bar_interval: 1m # K线周期1m / 5m / 1dinitial_capital的取值会影响仓位计算结果建议按真实可投入资金设置不要为了曲线好看而虚高。slippage是最容易被低估的参数在流动性好的品种上设1个tick偏乐观设2到3个tick更接近实盘对手价成交。fee_rate要写「双边」还是「单边」各平台约定不同统一确认一下否则回测手续费会差一倍。回测区间建议至少包含一段完整的牛熊或震荡行情。只看单边上涨区间得出的收益曲线没有说服力后面样本外验证还需要另外留数据。3.3 跑第一个回测并看懂输出报告构建和配置都完成后回测通常是通过命令行或管理端Web页面触发的# 假设平台提供了 CLI 入口以回测模式运行 java -jar platform.jar --mode backtest --config backtest.yaml --output result/跑完后输出目录里一般会产生三类东西订单明细、成交明细、按日统计的净值曲线。先看订单明细里的成交价格和信号价格之间的差这能直接反映滑点设置是否合理再看成交明细的成交时间是否全在交易时段内如果有成交时间出现在不该出现的时段说明数据对齐存在问题。一份回测报告还需要回答四个问题总收益率是多少最大回撤出现在哪一段夏普比率是否超过1年化换手率是多少。如果收益率很高但换手率异常比如一天下单几百次多半是策略过度敏感或数据里有未来函数。我自己的习惯是第一个回测不追求盈利先让平台跑通哪怕收益率为负也没关系——平台的数据流水、订单状态机没有问题比一次漂亮的回测结果重要得多。4. 给平台装上AI大脑特征工程、模型训练与信号到订单4.1 特征工程模型只认数字先让行情变成张量把AI模型接到Java量化平台上核心不是训练而是让模型的输入输出和交易闭环对齐。模型的输入是特征张量输出是概率或回归值。特征怎么从原始行情里抽出来直接决定模型的上限。我用得最多的特征分三类。第一类是基础行情特征对数收益、滚动窗口标准差、RSI、MACD柱值这些可以直接在Java里用TA-Lib风格的库算也可以在Python里算好后落库。第二类是盘口微观特征买卖一档价差、委托量不平衡度、主动买盘占比这类特征在tick级别的策略里价值更大但在bar级回测里取不到所以平台必须支持tick级数据回放。第三类是跨品种特征比如螺纹钢和铁矿石的比价、股指期货和现货指数的基差这类特征能捕捉到单品种看不到的联动信息。下面给出一段用Python做特征工程的常见写法注意特征里不要混入未来数据import numpy as np import pandas as pd def make_features(df: pd.DataFrame, window: int 20) - pd.DataFrame: df df.sort_values(datetime) # 对数收益用 shift(1) 保证只用历史数据 df[log_ret] np.log(df[close] / df[close].shift(1)) # 滚动波动率窗口内标准差 df[vol] df[log_ret].rolling(window).std() # 动量窗口内累计收益 df[momentum] df[close] / df[close].shift(window) - 1 # 标签未来 5 根 bar 是否上涨用于分类训练 df[label] (df[close].shift(-5) df[close]).astype(int) return df.dropna()这段代码的逻辑要点全在shift上。shift(1)保证当前特征只用到历史数据shift(-5)把标签映射到未来这两者组合避免了「用未来数据训练」这一最常见的错误。参数window建议按回测周期调整1分钟级别的策略用10到20日线级别的策略用20到60。过小的窗口噪声大过大的窗口反应慢具体数值要对照不同品种的波动特性去试。4.2 Python离线训练、Java在线推理常见的过程分工AI量化平台很少把训练也放进Java里。一个可维护的结构是Python负责研究和训练导出开放格式的模型文件Java平台负责加载模型在实盘或回测中做前向推理。ONNX是目前跨语言最顺的格式Java生态里可以用ONNX Runtime直接加载。Python端训练完的典型导出语句import onnx from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType # 假设 model 是已训练的 sklearn 模型 initial_type [(float_input, FloatTensorType([None, 6]))] onnx_model convert_sklearn(model, initial_typesinitial_type) onnx.save(onnx_model, strategy_v3.onnx)Java端加载并做推理的代码逻辑如下// 加载 ONNX 模型通常在策略初始化时执行一次 OrtEnvironment env OrtEnvironment.getEnvironment(); OrtSession session env.createSession(strategy_v3.onnx, new OrtSession.SessionOptions()); // 将实时特征拼成 float 数组维度必须与训练时一致 float[] input new float[]{logRet, vol, momentum, rsi, bidAskSpread, orderImbalance}; OnnxTensor tensor OnnxTensor.createTensor(env, new float[][]{input}); // 前向推理拿到模型输出 try (OrtSession.Result result session.run(Map.of(float_input, tensor))) { float[] probs result.get(0).getValue() instanceof OnnxTensor ? ((OnnxTensor) result.get(0).getValue()).getFloatBuffer().array() : null; // probs[0] 即模型预测的上涨概率 }这里最需要注意的参数是输入维度。训练时的特征数量是6个Java端就必须传6个顺序也不能乱训练时第1列是收益推理时第1个位置也要是收益否则模型表现会断崖式下降。很多「模型上线后失效」的问题根源不在模型而在特征拼接顺序不一致。ONNX Runtime加载模型后每次推理都会创建张量建议复用OrtSession避免反复加载模型。在多线程环境下ONNX Runtime的session可以多线程共享但每个线程要有独立的OrtEnvironment或合理控制并发否则会遇到底层Native库的段错误。4.3 从概率到订单信号阈值、仓位与止损模型输出的概率本身不是订单。把概率映射成交易动作需要三个参数信号阈值、仓位比例、止损止损逻辑。常见做法是设一个对称阈值比如概率大于0.55开多单小于0.45开空单中间区间不交易。阈值调低会增加交易频率也会增加手续费支出调高会减少交易次数但单次信号的胜率更高。这个参数没有标准答案要用回测去扫。信号确认后按下单接口生成订单。Java平台的订单对象一般长这样// 根据信号概率计算下单方向 OrderSide side probs[0] 0.55 ? OrderSide.BUY : OrderSide.SELL; if (probs[0] 0.45 probs[0] 0.55) { return; // 概率落在中间区间不开仓 } // 固定风险比例计算仓位每笔交易只允许亏损总资金的 1% double riskPerTrade 0.01; double stopDistance currentPrice * 0.01; // 止损距离 1% double quantity (initialCapital * riskPerTrade) / stopDistance; OrderRequest order OrderRequest.builder() .symbol(symbol) .side(side) .orderType(OrderType.LIMIT) .price(currentPrice tickSize * slippage) .quantity(quantity) .build(); orderSender.send(order);quantity的计算逻辑很多人会忽略。它不是拍脑袋定的而是由风险预算和止损距离共同决定亏损上限固定止损距离越大仓位越小。这保证每笔交易的亏损对总资金的影响是可控的不会因为某一次信号错误就元气大伤。price在限价单里取当前价 滑点×最小变动价位是为了提高成交概率实际成交价可能更差这一点要在回测里同样体现。止损单最好和服务端联动。本地机器上的止损逻辑在断电或网络中断时会失效所以常见做法是在下完开仓单后立即在交易所或券商端挂一个止损单。JAVA平台在断线重连后也要主动查询未成交订单和持仓避免本地状态和服务端状态失同步。5. 主动踩坑JAVA自动交易平台的五类翻车现场与排查清单5.1 现象回测浮盈实盘一开就跑不过回测这是自动交易最经典的心理落差回测年化30%实盘一个月亏掉8%。原因大多出在撮合模型的乐观偏差上。回测引擎如果默认按当前bar收盘价或对手价无滑点成交等于假设交易者永远能拿到最好的价格这显然不真实。尤其在小品种或冷门时段你的下单量本身就会推动价格回测根本无法模拟这种冲击成本。解决回测配置里强制加上slippage和冲击成本模型。我一般把滑点设成2个最小变动价位起手续费按真实费率乘1.2倍做安全垫。另外对比成交明细里「信号触发时间和订单成交时间」的间隔间隔越大说明实际成交价偏离预期越多回测越不可信。5.2 现象订单发出去了但成交回报对不上账常见于多合约同时交易时本地持仓记录是平的但账户里明明还有仓位。原因多数是成交回报乱序或者断线期间漏掉了回报包。Java平台若直接用一个全局ConcurrentHashMap维护持仓在回报顺序错乱时减仓和加仓的顺序就会颠倒。解决持仓状态必须用事件源模式把每一条成交回报按订单ID归档持仓数量只由「成交回报事件」推导而不是直接累加字段。断线重连后先拉一次交易所持仓和未成交订单做对账差异项以交易所数据为准修正本地状态这一步不能省。5.3 现象行情一快策略引擎的下单请求被限频打回股票、期货、外汇的API都有频率限制有的按每秒请求数限制有的按每分钟订单数限制。AI模型在行情剧烈波动时会密集触发信号如果策略引擎不控速订单请求会在几秒内撞上限制轻则拒单重则被交易接口临时封禁。解决在风控层加请求令牌桶把下单速率控制在交易所限制的一半以下留出余量。对于同品种的重复信号做一个去抖合并相同方向、相同价格区间的信号在N秒内只允许产生一单。这两个参数令牌桶速率、去抖窗口都要做成可配置的实盘前按接口文档换算清楚。5.4 现象回测曲线完美一换区间就变成直线亏损这是未来函数和过拟合的混合体。未来函数常见的有两种一是计算指标时用了当根bar的收盘价却在当根bar内做决策——这在bar回测里根本不可能实时做到二是训练模型时把整个回测区间的数据都拿去训练再在同一段区间上回测模型等于提前背了答案。解决指标计算统一走shift保障决策只能使用当前bar之前已确认的数据训练集和回测集必须时间上完全分开可以用前70%的时间段训练、后30%回测。过拟合则从参数数量上控制一个策略关键参数超过5个并且各个参数都存在极窄的「黄金区间」基本可以判定过拟合。为了确认参数稳健性把关键参数在每个方向上拨动20%看收益是否还算平滑如果一拨就崩那这个策略不是策略是玄学。5.5 现象同一个模型换一个品种就失效AI模型在期货上训练完换到股票指数上准确率几乎腰斩。这不奇怪不同品种的波动率、交易时间、微观结构差异巨大模型学到的特征分布完全是两套。另外金融市场是非平稳过程过去十年的规律未必适用于未来。解决模型上线前做「时间切片验证」把历史数据分成多段模型在每一段上都跑一遍确认不是只有某一段特别赚钱。跨品种迁移时保留模型结构用目标品种的数据重新训练最后两层而不是直接拿原模型硬跑。如果目标品种数据量太小就降低模型复杂度用线性模型或浅层树模型减少过拟合风险。6. 从能跑到能靠得住样本外验证、参数硬化与人工接管预案有没有效最终要靠在真实场景里验证。我在每个策略上线前都会做一轮「无实盘模拟」用平台的纸面交易模式跑两到四周每天人工检查订单记录、成交回报和持仓变化确认这个策略在真实行情下的行为和回测一致。这一步能筛掉大部分数据对齐、时间戳、委托价偏差这类问题。样本外验证要提前留数据。回测时用2023年全年调参那就把2024年初至今完全封存只在最后验证时打开一次。如果样本外的收益曲线形状、最大回撤和回测差异超过30%说明参数过拟合需要回炉重做。样本外验证通过后再用小额资金实盘跑一个月实盘结果不追求盈利只要求「偏差可控」——成交滑点、交易频率、胜率都和模拟纸面结果对得上。参数硬化是一个很容易被忽略的步骤。所谓硬化是把策略里的关键参数从「最优值」调整到「稳健区间」哪怕牺牲一点回测收益也要换实盘的可靠性。比如回测中最优的止损距离是1.2%而1.0%到1.5%这一段收益差异不大那就取中间的1.2%或偏向保守的1.0%而不是取极值。极值参数通常是噪声拟合出来的实盘里最脆弱。最后一定要有人工接管预案。即便平台再开源、再可靠行情极端波动、交易所系统升级、API协议变更这类黑天鹅事件还是会发生。我会在风控层挂三个开关全局熔断开关、单策略暂停开关、单品种撤单开关。一旦实盘净值回撤超过预设阈值比如5%就自动停掉所有新开仓只留平仓权限人工确认原因后再手动恢复。这个「后悔药」机制我复盘过很多次关键时刻救过大回撤也避免过一次因API协议变化导致的连环错单。做自动交易这几年我的一个习惯是永远保持「半自动」心态AI模型负责发现机会风控和人工负责拦截错误。再可靠的Java平台也只是执行工具它不会替你判断一个模型是否已经失效。每次上线前我都会重新打开平台日志亲手过一遍三类记录——拒单原因、重连耗时、成交滑点——确认它们都在预期范围内才放心。希望这些实战经验能帮你在量化自动交易这条路上少走些弯路。本文还有配套的精品资源点击获取