以下是几个 Java 开发的开源项目,支持对接 OKX(欧易)和币安(Binance)交易所 API,涵盖量化交易、行情分析、自动套利等功能,适合 Java 开发者使用:
1. XChange(推荐)
- GitHub: https://github.com/knowm/XChange
- 特点:
- 支持 50+ 交易所(包括 Binance、OKX、Coinbase、Kraken 等)。
- 提供 REST + WebSocket 接口,适合高频交易。
- 支持 现货、合约、期权 交易。
- 代码示例(获取 BTC/USDT 行情):java
import org.knowm.xchange.Exchange; import org.knowm.xchange.ExchangeFactory; import org.knowm.xchange.binance.BinanceExchange; import org.knowm.xchange.currency.CurrencyPair; import org.knowm.xchange.dto.marketdata.Ticker; import org.knowm.xchange.service.marketdata.MarketDataService; public class BinanceTickerExample { public static void main(String[] args) throws Exception { Exchange exchange = ExchangeFactory.INSTANCE.createExchange(BinanceExchange.class); MarketDataService marketDataService = exchange.getMarketDataService(); Ticker ticker = marketDataService.getTicker(CurrencyPair.BTC_USDT); System.out.println("BTC/USDT 最新价格: " + ticker.getLast()); } }
import org.knowm.xchange.Exchange; import org.knowm.xchange.ExchangeFactory; import org.knowm.xchange.binance.BinanceExchange; import org.knowm.xchange.currency.CurrencyPair; import org.knowm.xchange.dto.marketdata.Ticker; import org.knowm.xchange.service.marketdata.MarketDataService; public class BinanceTickerExample { public static void main(String[] args) throws Exception { Exchange exchange = ExchangeFactory.INSTANCE.createExchange(BinanceExchange.class); MarketDataService marketDataService = exchange.getMarketDataService(); Ticker ticker = marketDataService.getTicker(CurrencyPair.BTC_USDT); System.out.println("BTC/USDT 最新价格: " + ticker.getLast()); } }
- 适用场景:
- 量化交易、自动交易机器人、行情监控。
2. Binance Connector(官方 Java SDK)
- GitHub: https://github.com/binance/binance-connector-java
- 特点:
- Binance 官方维护,稳定性高。
- 支持 REST + WebSocket 行情、交易、账户管理。
- 适合 高频交易、量化策略开发。
- 代码示例(查询账户余额):java
import com.binance.connector.client.impl.SpotClientImpl; import java.util.LinkedHashMap; public class BinanceAccountExample { public static void main(String[] args) { String apiKey = "YOUR_API_KEY"; String secretKey = "YOUR_SECRET_KEY"; SpotClientImpl client = new SpotClientImpl(apiKey, secretKey); LinkedHashMap<String, Object> params = new LinkedHashMap<>(); String result = client.createTrade().account(params); System.out.println("账户信息: " + result); } }
import com.binance.connector.client.impl.SpotClientImpl; import java.util.LinkedHashMap; public class BinanceAccountExample { public static void main(String[] args) { String apiKey = "YOUR_API_KEY"; String secretKey = "YOUR_SECRET_KEY"; SpotClientImpl client = new SpotClientImpl(apiKey, secretKey); LinkedHashMap<String, Object> params = new LinkedHashMap<>(); String result = client.createTrade().account(params); System.out.println("账户信息: " + result); } }
- 适用场景:
- Binance 交易所的自动化交易、高频策略。
3. OKX Java SDK(官方)
- GitHub: https://github.com/okx/api-examples/tree/master/java
- 特点:
- OKX 官方提供的 Java SDK,支持 REST + WebSocket。
- 涵盖 现货、合约、期权、杠杆交易。
- 代码示例(获取 BTC/USDT 行情):java
import okhttp3.*; import java.io.IOException; public class OkxTickerExample { public static void main(String[] args) throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://www.okx.com/api/v5/market/ticker?instId=BTC-USDT") .build(); Response response = client.newCall(request).execute(); System.out.println("BTC/USDT 行情: " + response.body().string()); } }
import okhttp3.*; import java.io.IOException; public class OkxTickerExample { public static void main(String[] args) throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://www.okx.com/api/v5/market/ticker?instId=BTC-USDT") .build(); Response response = client.newCall(request).execute(); System.out.println("BTC/USDT 行情: " + response.body().string()); } }
- 适用场景:
- OKX 交易所的量化交易、自动交易机器人。
4. TA4J(技术分析库)
- GitHub: https://github.com/ta4j/ta4j
- 特点:
- 纯 Java 技术分析库,支持 EMA、RSI、MACD、布林带 等指标。
- 可与 XChange 结合,实现量化策略回测。
- 代码示例(计算 RSI 指标):java
import org.ta4j.core.*; import org.ta4j.core.indicators.RSIIndicator; import org.ta4j.core.indicators.helpers.ClosePriceIndicator; public class RSIExample { public static void main(String[] args) { BarSeries series = new BaseBarSeriesBuilder().withName("BTC_USDT").build(); // 添加K线数据(如从交易所API获取) ClosePriceIndicator closePrice = new ClosePriceIndicator(series); RSIIndicator rsi = new RSIIndicator(closePrice, 14); System.out.println("当前 RSI(14): " + rsi.getValue(series.getEndIndex())); } }
import org.ta4j.core.*; import org.ta4j.core.indicators.RSIIndicator; import org.ta4j.core.indicators.helpers.ClosePriceIndicator; public class RSIExample { public static void main(String[] args) { BarSeries series = new BaseBarSeriesBuilder().withName("BTC_USDT").build(); // 添加K线数据(如从交易所API获取) ClosePriceIndicator closePrice = new ClosePriceIndicator(series); RSIIndicator rsi = new RSIIndicator(closePrice, 14); System.out.println("当前 RSI(14): " + rsi.getValue(series.getEndIndex())); } }
- 适用场景:
- 量化策略开发、回测、技术分析。
5. Cryptomator(加密存储,非交易)
- GitHub: https://github.com/cryptomator/cryptomator
- 特点:
- 开源文件加密工具,可用于 安全存储 API 密钥。
- 适用于需要保护交易数据的开发者。
- 适用场景:
- 保护交易所 API Key、交易日志加密。
总结:Java 开源项目推荐
项目 | 适用场景 | 交易所支持 | 特点 |
---|---|---|---|
XChange | 多交易所API对接 | Binance, OKX, 50+ | 灵活,适合量化交易 |
Binance Connector | Binance 官方SDK | Binance | 高频交易支持 |
OKX Java SDK | OKX 官方SDK | OKX | 合约、期权支持 |
TA4J | 技术分析、回测 | 无(需结合XChange) | EMA/RSI/MACD |
Cryptomator | API密钥加密存储 | 无 | 安全存储 |
推荐组合
- XChange + TA4J → 量化策略开发(回测+实盘)。
- Binance Connector + OKX SDK → 高频套利交易。
- Cryptomator → 保护API密钥安全。
这些项目均开源,适合 Java 开发者构建自己的交易系统! 🚀
以下是基于 XChange + TA4J 的量化策略开发全流程指南,涵盖环境搭建、策略编写、回测与实盘部署,并提供完整代码示例:
1. 环境准备
(1) 安装依赖
bash
# 安装 XChange (交易所API) 和 TA4J (技术分析库)
pip install ccxt # XChange的Python替代方案(Java版XChange需Maven)
# 安装 XChange (交易所API) 和 TA4J (技术分析库)
pip install ccxt # XChange的Python替代方案(Java版XChange需Maven)
对于 Java 项目(使用Maven):
xml
<!-- pom.xml -->
<dependencies>
<!-- XChange -->
<dependency>
<groupId>org.knowm.xchange</groupId>
<artifactId>xchange-binance</artifactId>
<version>5.0.15</version>
</dependency>
<!-- TA4J -->
<dependency>
<groupId>org.ta4j</groupId>
<artifactId>ta4j-core</artifactId>
<version>0.15</version>
</dependency>
</dependencies>
<!-- pom.xml -->
<dependencies>
<!-- XChange -->
<dependency>
<groupId>org.knowm.xchange</groupId>
<artifactId>xchange-binance</artifactId>
<version>5.0.15</version>
</dependency>
<!-- TA4J -->
<dependency>
<groupId>org.ta4j</groupId>
<artifactId>ta4j-core</artifactId>
<version>0.15</version>
</dependency>
</dependencies>
2. 数据获取(XChange)
(1) 从交易所获取K线数据
java
import org.knowm.xchange.Exchange;
import org.knowm.xchange.ExchangeFactory;
import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.dto.marketdata.Kline;
import org.knowm.xchange.service.marketdata.MarketDataService;
import java.util.List;
public class DataFetcher {
public static void main(String[] args) throws Exception {
// 初始化Binance交易所
Exchange exchange = ExchangeFactory.INSTANCE.createExchange(BinanceExchange.class);
MarketDataService marketDataService = exchange.getMarketDataService();
// 获取BTC/USDT的1小时K线(最近100根)
List<Kline> klines = marketDataService.getKlines("BTC/USDT", "1h", 100);
System.out.println("最新K线收盘价: " + klines.get(klines.size() - 1).getClose());
}
}
import org.knowm.xchange.Exchange;
import org.knowm.xchange.ExchangeFactory;
import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.dto.marketdata.Kline;
import org.knowm.xchange.service.marketdata.MarketDataService;
import java.util.List;
public class DataFetcher {
public static void main(String[] args) throws Exception {
// 初始化Binance交易所
Exchange exchange = ExchangeFactory.INSTANCE.createExchange(BinanceExchange.class);
MarketDataService marketDataService = exchange.getMarketDataService();
// 获取BTC/USDT的1小时K线(最近100根)
List<Kline> klines = marketDataService.getKlines("BTC/USDT", "1h", 100);
System.out.println("最新K线收盘价: " + klines.get(klines.size() - 1).getClose());
}
}
(2) 转换为TA4J的BarSeries
java
import org.ta4j.core.*;
import org.ta4j.core.num.DoubleNum;
import java.time.ZonedDateTime;
public class DataConverter {
public static BarSeries convertToTa4j(List<Kline> klines) {
BarSeries series = new BaseBarSeriesBuilder().withName("BTC_USDT").build();
for (Kline kline : klines) {
Bar bar = new BaseBar(
kline.getTime(), // 时间
kline.getOpen(), kline.getHigh(), // 开盘价、最高价
kline.getLow(), kline.getClose(), // 最低价、收盘价
kline.getVolume(), // 成交量
DoubleNum::valueOf // 数值类型
);
series.addBar(bar);
}
return series;
}
}
import org.ta4j.core.*;
import org.ta4j.core.num.DoubleNum;
import java.time.ZonedDateTime;
public class DataConverter {
public static BarSeries convertToTa4j(List<Kline> klines) {
BarSeries series = new BaseBarSeriesBuilder().withName("BTC_USDT").build();
for (Kline kline : klines) {
Bar bar = new BaseBar(
kline.getTime(), // 时间
kline.getOpen(), kline.getHigh(), // 开盘价、最高价
kline.getLow(), kline.getClose(), // 最低价、收盘价
kline.getVolume(), // 成交量
DoubleNum::valueOf // 数值类型
);
series.addBar(bar);
}
return series;
}
}
3. 策略编写(TA4J)
(1) 双均线交叉策略
java
import org.ta4j.core.*;
import org.ta4j.core.indicators.SMAIndicator;
import org.ta4j.core.trading.rules.CrossedUpIndicatorRule;
import org.ta4j.core.trading.rules.CrossedDownIndicatorRule;
public class MovingAverageStrategy {
public static Strategy buildStrategy(BarSeries series) {
// 指标定义
ClosePriceIndicator closePrice = new ClosePriceIndicator(series);
SMAIndicator shortSma = new SMAIndicator(closePrice, 5); // 5日均线
SMAIndicator longSma = new SMAIndicator(closePrice, 20); // 20日均线
// 交易规则
Rule entryRule = new CrossedUpIndicatorRule(shortSma, longSma); // 短线上穿长线:买入
Rule exitRule = new CrossedDownIndicatorRule(shortSma, longSma); // 短线下穿长线:卖出
return new BaseStrategy(entryRule, exitRule);
}
}
import org.ta4j.core.*;
import org.ta4j.core.indicators.SMAIndicator;
import org.ta4j.core.trading.rules.CrossedUpIndicatorRule;
import org.ta4j.core.trading.rules.CrossedDownIndicatorRule;
public class MovingAverageStrategy {
public static Strategy buildStrategy(BarSeries series) {
// 指标定义
ClosePriceIndicator closePrice = new ClosePriceIndicator(series);
SMAIndicator shortSma = new SMAIndicator(closePrice, 5); // 5日均线
SMAIndicator longSma = new SMAIndicator(closePrice, 20); // 20日均线
// 交易规则
Rule entryRule = new CrossedUpIndicatorRule(shortSma, longSma); // 短线上穿长线:买入
Rule exitRule = new CrossedDownIndicatorRule(shortSma, longSma); // 短线下穿长线:卖出
return new BaseStrategy(entryRule, exitRule);
}
}
(2) RSI超买超卖策略
java
import org.ta4j.core.indicators.RSIIndicator;
import org.ta4j.core.trading.rules.UnderThresholdRule;
import org.ta4j.core.trading.rules.OverThresholdRule;
public class RsiStrategy {
public static Strategy buildStrategy(BarSeries series) {
ClosePriceIndicator closePrice = new ClosePriceIndicator(series);
RSIIndicator rsi = new RSIIndicator(closePrice, 14); // RSI(14)
// RSI < 30 买入,RSI > 70 卖出
Rule entryRule = new UnderThresholdRule(rsi, 30);
Rule exitRule = new OverThresholdRule(rsi, 70);
return new BaseStrategy(entryRule, exitRule);
}
}
import org.ta4j.core.indicators.RSIIndicator;
import org.ta4j.core.trading.rules.UnderThresholdRule;
import org.ta4j.core.trading.rules.OverThresholdRule;
public class RsiStrategy {
public static Strategy buildStrategy(BarSeries series) {
ClosePriceIndicator closePrice = new ClosePriceIndicator(series);
RSIIndicator rsi = new RSIIndicator(closePrice, 14); // RSI(14)
// RSI < 30 买入,RSI > 70 卖出
Rule entryRule = new UnderThresholdRule(rsi, 30);
Rule exitRule = new OverThresholdRule(rsi, 70);
return new BaseStrategy(entryRule, exitRule);
}
}
4. 回测引擎
java
import org.ta4j.core.*;
import org.ta4j.core.analysis.criteria.TotalProfitCriterion;
public class BacktestEngine {
public static void run(BarSeries series, Strategy strategy) {
// 初始化交易历史
TradingRecord tradingRecord = new BaseTradingRecord();
// 运行回测
for (int i = series.getBeginIndex(); i <= series.getEndIndex(); i++) {
if (strategy.shouldEnter(i)) {
tradingRecord.enter(i, series.getBar(i).getClosePrice(), DoubleNum.valueOf(10)); // 买入10单位
} else if (strategy.shouldExit(i)) {
tradingRecord.exit(i, series.getBar(i).getClosePrice(), DoubleNum.valueOf(10));
}
}
// 打印结果
System.out.println("总交易次数: " + tradingRecord.getTradeCount());
System.out.println("总盈亏: " + new TotalProfitCriterion().calculate(series, tradingRecord));
}
}
import org.ta4j.core.*;
import org.ta4j.core.analysis.criteria.TotalProfitCriterion;
public class BacktestEngine {
public static void run(BarSeries series, Strategy strategy) {
// 初始化交易历史
TradingRecord tradingRecord = new BaseTradingRecord();
// 运行回测
for (int i = series.getBeginIndex(); i <= series.getEndIndex(); i++) {
if (strategy.shouldEnter(i)) {
tradingRecord.enter(i, series.getBar(i).getClosePrice(), DoubleNum.valueOf(10)); // 买入10单位
} else if (strategy.shouldExit(i)) {
tradingRecord.exit(i, series.getBar(i).getClosePrice(), DoubleNum.valueOf(10));
}
}
// 打印结果
System.out.println("总交易次数: " + tradingRecord.getTradeCount());
System.out.println("总盈亏: " + new TotalProfitCriterion().calculate(series, tradingRecord));
}
}
5. 实盘交易(XChange)
java
import org.knowm.xchange.dto.trade.MarketOrder;
import org.knowm.xchange.service.trade.TradeService;
public class LiveTrader {
public static void executeTrade(Exchange exchange, boolean isBuy, String symbol, double amount) {
TradeService tradeService = exchange.getTradeService();
MarketOrder order = new MarketOrder(
isBuy ? Order.OrderType.BID : Order.OrderType.ASK,
BigDecimal.valueOf(amount),
new CurrencyPair(symbol)
);
try {
String orderId = tradeService.placeMarketOrder(order);
System.out.println("订单已提交,ID: " + orderId);
} catch (Exception e) {
System.err.println("交易失败: " + e.getMessage());
}
}
}
import org.knowm.xchange.dto.trade.MarketOrder;
import org.knowm.xchange.service.trade.TradeService;
public class LiveTrader {
public static void executeTrade(Exchange exchange, boolean isBuy, String symbol, double amount) {
TradeService tradeService = exchange.getTradeService();
MarketOrder order = new MarketOrder(
isBuy ? Order.OrderType.BID : Order.OrderType.ASK,
BigDecimal.valueOf(amount),
new CurrencyPair(symbol)
);
try {
String orderId = tradeService.placeMarketOrder(order);
System.out.println("订单已提交,ID: " + orderId);
} catch (Exception e) {
System.err.println("交易失败: " + e.getMessage());
}
}
}
6. 全流程整合
java
public class Main {
public static void main(String[] args) throws Exception {
// 1. 获取数据
List<Kline> klines = DataFetcher.fetchKlines("BTC/USDT", "1h", 100);
BarSeries series = DataConverter.convertToTa4j(klines);
// 2. 构建策略
Strategy strategy = MovingAverageStrategy.buildStrategy(series);
// 3. 回测
BacktestEngine.run(series, strategy);
// 4. 实盘(需配置API密钥)
Exchange exchange = ExchangeFactory.INSTANCE.createExchange(BinanceExchange.class);
exchange.getExchangeSpecification().setApiKey("YOUR_API_KEY");
exchange.getExchangeSpecification().setSecretKey("YOUR_SECRET");
// 根据策略信号交易
int lastIndex = series.getEndIndex();
if (strategy.shouldEnter(lastIndex)) {
LiveTrader.executeTrade(exchange, true, "BTC/USDT", 0.01);
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
// 1. 获取数据
List<Kline> klines = DataFetcher.fetchKlines("BTC/USDT", "1h", 100);
BarSeries series = DataConverter.convertToTa4j(klines);
// 2. 构建策略
Strategy strategy = MovingAverageStrategy.buildStrategy(series);
// 3. 回测
BacktestEngine.run(series, strategy);
// 4. 实盘(需配置API密钥)
Exchange exchange = ExchangeFactory.INSTANCE.createExchange(BinanceExchange.class);
exchange.getExchangeSpecification().setApiKey("YOUR_API_KEY");
exchange.getExchangeSpecification().setSecretKey("YOUR_SECRET");
// 根据策略信号交易
int lastIndex = series.getEndIndex();
if (strategy.shouldEnter(lastIndex)) {
LiveTrader.executeTrade(exchange, true, "BTC/USDT", 0.01);
}
}
}
7. 进阶优化
(1) 参数优化
java
// 使用Walk-Forward优化均线周期
for (int shortPeriod = 5; shortPeriod <= 10; shortPeriod++) {
for (int longPeriod = 20; longPeriod <= 50; longPeriod += 10) {
Strategy tempStrategy = new MovingAverageStrategy(shortPeriod, longPeriod);
BacktestEngine.run(series, tempStrategy);
}
}
// 使用Walk-Forward优化均线周期
for (int shortPeriod = 5; shortPeriod <= 10; shortPeriod++) {
for (int longPeriod = 20; longPeriod <= 50; longPeriod += 10) {
Strategy tempStrategy = new MovingAverageStrategy(shortPeriod, longPeriod);
BacktestEngine.run(series, tempStrategy);
}
}
(2) 多线程回测
java
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> BacktestEngine.run(series, strategy));
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> BacktestEngine.run(series, strategy));
(3) 可视化结果
- 使用 Matplotlib-Java 或 JFreeChart 绘制资金曲线:java
// 示例:JFreeChart绘制净值曲线 XYSeries equitySeries = new XYSeries("净值"); for (Trade trade : tradingRecord.getTrades()) { equitySeries.add(trade.getExit().getIndex(), trade.getProfit().doubleValue()); }
// 示例:JFreeChart绘制净值曲线 XYSeries equitySeries = new XYSeries("净值"); for (Trade trade : tradingRecord.getTrades()) { equitySeries.add(trade.getExit().getIndex(), trade.getProfit().doubleValue()); }
8. 关键注意事项
- 数据质量:确保K线数据无缺失(填充空白时段)。
- 手续费计算:在回测中扣除交易费用(Binance现货约0.1%)。
- 滑点控制:实盘使用限价单而非市价单。
- 风险控制:单笔交易不超过总资金的2%。
通过以上步骤,您已完成从数据获取到实盘交易的完整量化流程。XChange + TA4J 的组合尤其适合 中低频趋势跟踪策略(如均线、RSI)。如需高频交易,可改用 CCXT + 异步IO(Python)或 Alpaca API(美股)。