StockTV 币安交易所数据 Java 对接文档
·
本文档详细介绍如何使用 Java 语言通过 StockTV API 对接币安交易所数据,包含实时行情、K线数据、交易对信息等完整功能。
🚀 快速开始
环境要求
- JDK 8+
- Maven 3.6+
- 网络连接(可访问
api.stocktv.top)
项目依赖
<!-- pom.xml -->
<dependencies>
<!-- HTTP客户端 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<!-- JSON处理 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<!-- WebSocket客户端 -->
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.3</version>
</dependency>
<!-- 日志框架 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.7</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
</dependencies>
🏗️ 核心架构
项目结构
src/main/java/com/stocktv/binance/
├── config/
│ └── BinanceConfig.java
├── model/
│ ├── CryptoPair.java
│ ├── TickerPrice.java
│ ├── KLine.java
│ ├── Trade.java
│ └── ApiResponse.java
├── client/
│ ├── BinanceHttpClient.java
│ └── BinanceWebSocketClient.java
├── service/
│ └── BinanceDataService.java
└── demo/
└── BinanceDemo.java
📦 核心代码实现
1. 配置类
package com.stocktv.binance.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
/**
* 币安数据配置类
*/
public class BinanceConfig {
// API 基础配置
public static final String BASE_URL = "https://api.stocktv.top";
public static final String WS_URL = "wss://ws-api.stocktv.top/connect";
// 币安接口路径
public static final String CRYPTO_PAIR_LIST = "/crypto/pairlist";
public static final String CRYPTO_TICKER_PRICE = "/crypto/tickerPrice";
public static final String CRYPTO_LAST_PRICE = "/crypto/lastPrice";
public static final String CRYPTO_GET_KLINES = "/crypto/getKlines";
public static final String CRYPTO_GET_TRADES = "/crypto/getTrades";
// 币安市场ID
public static final int BINANCE_MARKET_ID = 338;
// 主要交易对
public static final String BTC_USDT = "BTCUSDT";
public static final String ETH_USDT = "ETHUSDT";
public static final String BNB_USDT = "BNBUSDT";
public static final String ADA_USDT = "ADAUSDT";
public static final String DOT_USDT = "DOTUSDT";
public static final String XRP_USDT = "XRPUSDT";
public static final String LTC_USDT = "LTCUSDT";
public static final String LINK_USDT = "LINKUSDT";
public static final String BCH_USDT = "BCHUSDT";
public static final String XLM_USDT = "XLMUSDT";
// API Key
private final String apiKey;
// HTTP 客户端和JSON处理器
private final CloseableHttpClient httpClient;
private final ObjectMapper objectMapper;
public BinanceConfig(String apiKey) {
this.apiKey = apiKey;
this.httpClient = HttpClients.createDefault();
this.objectMapper = new ObjectMapper();
this.objectMapper.findAndRegisterModules();
}
// Getter方法
public String getApiKey() { return apiKey; }
public CloseableHttpClient getHttpClient() { return httpClient; }
public ObjectMapper getObjectMapper() { return objectMapper; }
}
2. 数据模型类
加密货币交易对数据模型
package com.stocktv.binance.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* 加密货币交易对数据模型
*/
@Data
public class CryptoPair {
@JsonProperty("symbol")
private String symbol;
@JsonProperty("legal_currency_price")
private BigDecimal legalCurrencyPrice;
@JsonProperty("market_cap_display")
private String marketCapDisplay;
@JsonProperty("percent_change_utc0_3d")
private BigDecimal percentChangeUtc03d;
@JsonProperty("price")
private String price;
@JsonProperty("price_change_today")
private String priceChangeToday;
@JsonProperty("rank")
private Integer rank;
@JsonProperty("logo")
private String logo;
@JsonProperty("id")
private Long id;
@JsonProperty("price_display")
private String priceDisplay;
@JsonProperty("price_display_cny")
private BigDecimal priceDisplayCny;
@JsonProperty("market_id")
private Integer marketId;
@JsonProperty("market_name")
private String marketName;
@JsonProperty("market_cap_usd")
private String marketCapUsd;
@JsonProperty("exchange_time")
private String exchangeTime;
@JsonProperty("percent_change_1h")
private BigDecimal percentChange1h;
@JsonProperty("percent_change_24h")
private BigDecimal percentChange24h;
@JsonProperty("name")
private String name;
@JsonProperty("volume_24h")
private String volume24h;
@JsonProperty("price_usd")
private String priceUsd;
@JsonProperty("available_supply")
private Long availableSupply;
@JsonProperty("alias")
private String alias;
@JsonProperty("currency")
private String currency;
@JsonProperty("pair")
private String pair;
@JsonProperty("percent_change_7d")
private BigDecimal percentChange7d;
@JsonProperty("category")
private String category;
@JsonProperty("search_field")
private String searchField;
/**
* 获取数值形式的当前价格
*/
public BigDecimal getNumericPrice() {
try {
return new BigDecimal(price);
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
/**
* 获取交易对基础货币
*/
public String getBaseAsset() {
if (pair != null && pair.contains("/")) {
return pair.split("/")[0];
}
return symbol.replace("USDT", "");
}
/**
* 获取交易对报价货币
*/
public String getQuoteAsset() {
if (pair != null && pair.contains("/")) {
return pair.split("/")[1];
}
return "USDT";
}
}
价格行情数据模型
package com.stocktv.binance.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* 价格行情数据模型
*/
@Data
public class TickerPrice {
@JsonProperty("priceChange")
private String priceChange;
@JsonProperty("symbol")
private String symbol;
@JsonProperty("count")
private Long count;
@JsonProperty("openPrice")
private String openPrice;
@JsonProperty("lastId")
private Long lastId;
@JsonProperty("quoteVolume")
private String quoteVolume;
@JsonProperty("firstId")
private Long firstId;
@JsonProperty("volume")
private String volume;
@JsonProperty("weightedAvgPrice")
private String weightedAvgPrice;
@JsonProperty("lowPrice")
private String lowPrice;
@JsonProperty("highPrice")
private String highPrice;
@JsonProperty("closeTime")
private Long closeTime;
@JsonProperty("openTime")
private Long openTime;
@JsonProperty("priceChangePercent")
private String priceChangePercent;
@JsonProperty("lastPrice")
private String lastPrice;
/**
* 获取数值形式的最后价格
*/
public BigDecimal getNumericLastPrice() {
try {
return new BigDecimal(lastPrice);
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
/**
* 获取数值形式的涨跌幅
*/
public BigDecimal getNumericPriceChangePercent() {
try {
return new BigDecimal(priceChangePercent);
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
/**
* 获取数值形式的交易量
*/
public BigDecimal getNumericVolume() {
try {
return new BigDecimal(volume);
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
}
最新价格数据模型
package com.stocktv.binance.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* 最新价格数据模型
*/
@Data
public class LastPrice {
@JsonProperty("symbol")
private String symbol;
@JsonProperty("price")
private String price;
/**
* 获取数值形式的价格
*/
public BigDecimal getNumericPrice() {
try {
return new BigDecimal(price);
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
}
K线数据模型
package com.stocktv.binance.model;
import lombok.Data;
import java.math.BigDecimal;
/**
* K线数据模型
*/
@Data
public class KLine {
private Long openTime;
private BigDecimal openPrice;
private BigDecimal highPrice;
private BigDecimal lowPrice;
private BigDecimal closePrice;
private BigDecimal volume;
private Long closeTime;
private BigDecimal quoteAssetVolume;
private Integer numberOfTrades;
private BigDecimal takerBuyBaseAssetVolume;
private BigDecimal takerBuyQuoteAssetVolume;
private String ignore;
/**
* 构造函数 - 从数组解析
*/
public KLine(Object[] data) {
if (data != null && data.length >= 11) {
this.openTime = ((Number) data[0]).longValue();
this.openPrice = new BigDecimal(data[1].toString());
this.highPrice = new BigDecimal(data[2].toString());
this.lowPrice = new BigDecimal(data[3].toString());
this.closePrice = new BigDecimal(data[4].toString());
this.volume = new BigDecimal(data[5].toString());
this.closeTime = ((Number) data[6]).longValue();
this.quoteAssetVolume = new BigDecimal(data[7].toString());
this.numberOfTrades = ((Number) data[8]).intValue();
this.takerBuyBaseAssetVolume = new BigDecimal(data[9].toString());
this.takerBuyQuoteAssetVolume = new BigDecimal(data[10].toString());
if (data.length > 11) {
this.ignore = data[11].toString();
}
}
}
/**
* 计算振幅百分比
*/
public BigDecimal getAmplitudePercent() {
if (openPrice.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
}
return highPrice.subtract(lowPrice)
.divide(openPrice, 4, BigDecimal.ROUND_HALF_UP)
.multiply(BigDecimal.valueOf(100));
}
/**
* 计算涨跌幅百分比
*/
public BigDecimal getChangePercent() {
if (openPrice.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
}
return closePrice.subtract(openPrice)
.divide(openPrice, 4, BigDecimal.ROUND_HALF_UP)
.multiply(BigDecimal.valueOf(100));
}
}
交易数据模型
package com.stocktv.binance.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* 交易数据模型
*/
@Data
public class Trade {
@JsonProperty("quoteQty")
private String quoteQty;
@JsonProperty("price")
private String price;
@JsonProperty("qty")
private String qty;
@JsonProperty("isBestMatch")
private Boolean isBestMatch;
@JsonProperty("id")
private Long id;
@JsonProperty("time")
private Long time;
@JsonProperty("isBuyerMaker")
private Boolean isBuyerMaker;
/**
* 获取数值形式的价格
*/
public BigDecimal getNumericPrice() {
try {
return new BigDecimal(price);
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
/**
* 获取数值形式的数量
*/
public BigDecimal getNumericQty() {
try {
return new BigDecimal(qty);
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
/**
* 获取交易方向
*/
public String getTradeDirection() {
return Boolean.TRUE.equals(isBuyerMaker) ? "SELL" : "BUY";
}
}
API响应包装类
package com.stocktv.binance.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* API通用响应包装类
*/
@Data
public class ApiResponse<T> {
@JsonProperty("code")
private Integer code;
@JsonProperty("message")
private String message;
@JsonProperty("data")
private T data;
/**
* 判断请求是否成功
*/
public boolean isSuccess() {
return code != null && code == 200;
}
}
/**
* 交易对列表响应包装类
*/
@Data
class PairListResponse {
@JsonProperty("total_count")
private Integer totalCount;
@JsonProperty("total_page")
private Integer totalPage;
@JsonProperty("list")
private List<CryptoPair> list;
@JsonProperty("fields")
private List<String> fields;
}
3. HTTP客户端实现
package com.stocktv.binance.client;
import com.fasterxml.jackson.core.type.TypeReference;
import com.stocktv.binance.config.BinanceConfig;
import com.stocktv.binance.model.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 币安数据HTTP客户端
*/
public class BinanceHttpClient {
private static final Logger logger = LoggerFactory.getLogger(BinanceHttpClient.class);
private final BinanceConfig config;
private final CloseableHttpClient httpClient;
public BinanceHttpClient(BinanceConfig config) {
this.config = config;
this.httpClient = config.getHttpClient();
}
/**
* 获取交易对列表
*/
public List<CryptoPair> getPairList(Integer page, Integer size) throws IOException, URISyntaxException {
URIBuilder uriBuilder = new URIBuilder(config.BASE_URL + config.CRYPTO_PAIR_LIST)
.addParameter("key", config.getApiKey())
.addParameter("marketId", String.valueOf(config.BINANCE_MARKET_ID));
if (page != null) {
uriBuilder.addParameter("page", String.valueOf(page));
}
if (size != null) {
uriBuilder.addParameter("size", String.valueOf(size));
}
URI uri = uriBuilder.build();
ApiResponse<PairListResponse> response = executeGetRequest(uri,
new TypeReference<ApiResponse<PairListResponse>>() {});
if (response.isSuccess()) {
logger.info("成功获取 {} 个交易对", response.getData().getList().size());
return response.getData().getList();
} else {
throw new RuntimeException("获取交易对列表失败: " + response.getMessage());
}
}
/**
* 获取最新行情
*/
public List<TickerPrice> getTickerPrice(List<String> symbols) throws IOException, URISyntaxException {
if (symbols == null || symbols.isEmpty()) {
throw new IllegalArgumentException("交易对列表不能为空");
}
// 限制最大数量
if (symbols.size() > 100) {
symbols = symbols.subList(0, 100);
logger.warn("交易对数量超过限制,只取前100个");
}
String symbolsStr = String.join(",", symbols);
URI uri = new URIBuilder(config.BASE_URL + config.CRYPTO_TICKER_PRICE)
.addParameter("key", config.getApiKey())
.addParameter("symbols", symbolsStr)
.build();
ApiResponse<List<TickerPrice>> response = executeGetRequest(uri,
new TypeReference<ApiResponse<List<TickerPrice>>>() {});
if (response.isSuccess()) {
logger.info("成功获取 {} 个交易对的最新行情", response.getData().size());
return response.getData();
} else {
throw new RuntimeException("获取最新行情失败: " + response.getMessage());
}
}
/**
* 获取最新价格
*/
public List<LastPrice> getLastPrice(List<String> symbols) throws IOException, URISyntaxException {
if (symbols == null || symbols.isEmpty()) {
throw new IllegalArgumentException("交易对列表不能为空");
}
// 限制最大数量
if (symbols.size() > 100) {
symbols = symbols.subList(0, 100);
logger.warn("交易对数量超过限制,只取前100个");
}
String symbolsStr = String.join(",", symbols);
URI uri = new URIBuilder(config.BASE_URL + config.CRYPTO_LAST_PRICE)
.addParameter("key", config.getApiKey())
.addParameter("symbols", symbolsStr)
.build();
ApiResponse<List<LastPrice>> response = executeGetRequest(uri,
new TypeReference<ApiResponse<List<LastPrice>>>() {});
if (response.isSuccess()) {
logger.info("成功获取 {} 个交易对的最新价格", response.getData().size());
return response.getData();
} else {
throw new RuntimeException("获取最新价格失败: " + response.getMessage());
}
}
/**
* 获取K线数据
*/
public List<KLine> getKlines(String symbol, String interval) throws IOException, URISyntaxException {
if (symbol == null || symbol.trim().isEmpty()) {
throw new IllegalArgumentException("交易对不能为空");
}
URI uri = new URIBuilder(config.BASE_URL + config.CRYPTO_GET_KLINES)
.addParameter("key", config.getApiKey())
.addParameter("symbol", symbol)
.addParameter("interval", interval)
.build();
// K线数据返回的是数组的数组
ApiResponse<List<Object[]>> response = executeGetRequest(uri,
new TypeReference<ApiResponse<List<Object[]>>>() {});
if (response.isSuccess()) {
List<KLine> klines = response.getData().stream()
.map(KLine::new)
.collect(Collectors.toList());
logger.info("成功获取交易对 {} 的K线数据,共 {} 条", symbol, klines.size());
return klines;
} else {
throw new RuntimeException("获取K线数据失败: " + response.getMessage());
}
}
/**
* 获取近期成交
*/
public List<Trade> getTrades(String symbol) throws IOException, URISyntaxException {
if (symbol == null || symbol.trim().isEmpty()) {
throw new IllegalArgumentException("交易对不能为空");
}
URI uri = new URIBuilder(config.BASE_URL + config.CRYPTO_GET_TRADES)
.addParameter("key", config.getApiKey())
.addParameter("symbol", symbol)
.build();
ApiResponse<List<Trade>> response = executeGetRequest(uri,
new TypeReference<ApiResponse<List<Trade>>>() {});
if (response.isSuccess()) {
logger.info("成功获取交易对 {} 的成交数据,共 {} 条", symbol, response.getData().size());
return response.getData();
} else {
throw new RuntimeException("获取成交数据失败: " + response.getMessage());
}
}
/**
* 搜索交易对
*/
public List<CryptoPair> searchPairs(String keyword, Integer limit) throws IOException, URISyntaxException {
List<CryptoPair> allPairs = getPairList(1, 1000); // 获取较多数据用于搜索
return allPairs.stream()
.filter(pair ->
pair.getSymbol().toLowerCase().contains(keyword.toLowerCase()) ||
pair.getName().toLowerCase().contains(keyword.toLowerCase()) ||
(pair.getSearchField() != null &&
pair.getSearchField().toLowerCase().contains(keyword.toLowerCase())))
.limit(limit != null ? limit : 10)
.collect(Collectors.toList());
}
/**
* 获取Top N市值的加密货币
*/
public List<CryptoPair> getTopMarketCapPairs(int topN) throws IOException, URISyntaxException {
List<CryptoPair> allPairs = getPairList(1, topN);
// 按排名排序
return allPairs.stream()
.sorted((p1, p2) -> {
if (p1.getRank() == null) return 1;
if (p2.getRank() == null) return -1;
return p1.getRank().compareTo(p2.getRank());
})
.limit(topN)
.collect(Collectors.toList());
}
/**
* 通用GET请求执行方法
*/
private <T> T executeGetRequest(URI uri, TypeReference<T> typeReference) throws IOException {
HttpGet request = new HttpGet(uri);
logger.debug("执行币安API请求: {}", uri);
try (CloseableHttpResponse response = httpClient.execute(request)) {
int statusCode = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString(response.getEntity());
if (statusCode != 200) {
throw new IOException("HTTP请求失败,状态码: " + statusCode);
}
logger.debug("币安API响应: {}", responseBody);
return config.getObjectMapper().readValue(responseBody, typeReference);
}
}
/**
* 关闭HTTP客户端
*/
public void close() throws IOException {
if (httpClient != null) {
httpClient.close();
}
}
}
4. WebSocket客户端实现
package com.stocktv.binance.client;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.stocktv.binance.config.BinanceConfig;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* 币安WebSocket实时数据客户端
*/
public class BinanceWebSocketClient {
private static final Logger logger = LoggerFactory.getLogger(BinanceWebSocketClient.class);
private final BinanceConfig config;
private final ObjectMapper objectMapper;
private WebSocketClient webSocketClient;
private CountDownLatch connectionLatch;
public BinanceWebSocketClient(BinanceConfig config) {
this.config = config;
this.objectMapper = config.getObjectMapper();
}
/**
* 连接WebSocket服务器
*/
public void connect() throws Exception {
String wsUrl = config.WS_URL + "?key=" + config.getApiKey();
URI serverUri = URI.create(wsUrl);
connectionLatch = new CountDownLatch(1);
webSocketClient = new WebSocketClient(serverUri) {
@Override
public void onOpen(ServerHandshake handshake) {
logger.info("币安WebSocket连接已建立");
connectionLatch.countDown();
}
@Override
public void onMessage(String message) {
try {
handleRealTimeMessage(message);
} catch (Exception e) {
logger.error("处理WebSocket消息时出错", e);
}
}
@Override
public void onClose(int code, String reason, boolean remote) {
logger.info("币安WebSocket连接已关闭: code={}, reason={}, remote={}", code, reason, remote);
}
@Override
public void onError(Exception ex) {
logger.error("币安WebSocket连接错误", ex);
}
};
webSocketClient.connect();
// 等待连接建立
if (!connectionLatch.await(10, TimeUnit.SECONDS)) {
throw new RuntimeException("WebSocket连接超时");
}
}
/**
* 处理实时消息
*/
private void handleRealTimeMessage(String message) throws Exception {
JsonNode jsonNode = objectMapper.readTree(message);
// 解析实时行情数据
if (jsonNode.has("symbol") || jsonNode.has("pid")) {
RealTimeData realTimeData = parseRealTimeData(jsonNode);
onRealTimeData(realTimeData);
} else {
logger.debug("收到其他消息: {}", message);
}
}
/**
* 解析实时数据
*/
private RealTimeData parseRealTimeData(JsonNode jsonNode) {
RealTimeData data = new RealTimeData();
if (jsonNode.has("symbol")) {
data.setSymbol(jsonNode.get("symbol").asText());
}
if (jsonNode.has("pid")) {
data.setPid(jsonNode.get("pid").asText());
}
if (jsonNode.has("last_numeric")) {
data.setLastPrice(jsonNode.get("last_numeric").asText());
}
if (jsonNode.has("bid")) {
data.setBid(jsonNode.get("bid").asText());
}
if (jsonNode.has("ask")) {
data.setAsk(jsonNode.get("ask").asText());
}
if (jsonNode.has("high")) {
data.setHigh(jsonNode.get("high").asText());
}
if (jsonNode.has("low")) {
data.setLow(jsonNode.get("low").asText());
}
if (jsonNode.has("pc")) {
data.setPriceChange(jsonNode.get("pc").asText());
}
if (jsonNode.has("pcp")) {
data.setChangePercent(jsonNode.get("pcp").asText());
}
if (jsonNode.has("turnover_numeric")) {
data.setVolume(jsonNode.get("turnover_numeric").asText());
}
if (jsonNode.has("time")) {
data.setTime(jsonNode.get("time").asText());
}
if (jsonNode.has("timestamp")) {
data.setTimestamp(jsonNode.get("timestamp").asText());
}
return data;
}
/**
* 处理实时数据
*/
protected void onRealTimeData(RealTimeData data) {
String symbol = data.getSymbol() != null ? data.getSymbol() : data.getPid();
// 记录基础信息
logger.debug("实时行情: {} - 价格: {}, 涨跌幅: {}%",
symbol, data.getLastPrice(), data.getChangePercent());
// 价格预警逻辑
try {
double changePercent = Double.parseDouble(data.getChangePercent());
if (Math.abs(changePercent) > 5.0) {
logger.warn("🚨 加密货币价格波动预警: {} 波动 {}%", symbol, changePercent);
}
// 大额交易监控
if (data.getVolume() != null) {
double volume = Double.parseDouble(data.getVolume());
if (volume > 1000000) { // 100万美元以上
logger.info("💰 大额交易: {} 成交额 ${}", symbol, volume);
}
}
} catch (NumberFormatException e) {
// 忽略转换错误
}
}
/**
* 发送消息
*/
public void sendMessage(String message) {
if (webSocketClient != null && webSocketClient.isOpen()) {
webSocketClient.send(message);
}
}
/**
* 关闭连接
*/
public void close() {
if (webSocketClient != null) {
webSocketClient.close();
}
}
/**
* 实时数据模型
*/
public static class RealTimeData {
private String pid;
private String symbol;
private String lastPrice;
private String bid;
private String ask;
private String high;
private String low;
private String priceChange;
private String changePercent;
private String volume;
private String time;
private String timestamp;
// Getters and Setters
public String getPid() { return pid; }
public void setPid(String pid) { this.pid = pid; }
public String getSymbol() { return symbol; }
public void setSymbol(String symbol) { this.symbol = symbol; }
public String getLastPrice() { return lastPrice; }
public void setLastPrice(String lastPrice) { this.lastPrice = lastPrice; }
public String getBid() { return bid; }
public void setBid(String bid) { this.bid = bid; }
public String getAsk() { return ask; }
public void setAsk(String ask) { this.ask = ask; }
public String getHigh() { return high; }
public void setHigh(String high) { this.high = high; }
public String getLow() { return low; }
public void setLow(String low) { this.low = low; }
public String getPriceChange() { return priceChange; }
public void setPriceChange(String priceChange) { this.priceChange = priceChange; }
public String getChangePercent() { return changePercent; }
public void setChangePercent(String changePercent) { this.changePercent = changePercent; }
public String getVolume() { return volume; }
public void setVolume(String volume) { this.volume = volume; }
public String getTime() { return time; }
public void setTime(String time) { this.time = time; }
public String getTimestamp() { return timestamp; }
public void setTimestamp(String timestamp) { this.timestamp = timestamp; }
}
}
更多推荐
所有评论(0)