From 038c7e5b9c8338103496d40ffb0122b3f61a5185 Mon Sep 17 00:00:00 2001
From: zyy <zyy@email.com>
Date: Fri, 29 May 2026 12:19:47 +0800
Subject: [PATCH] 1
---
trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/RemoteDataServiceImpl.java | 106 +++++-------
trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java | 48 +++--
trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/KlineServiceImpl.java | 198 +++++++++++++++++++++++-
trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/DataDBServiceImpl.java | 113 ++++++++++---
4 files changed, 348 insertions(+), 117 deletions(-)
diff --git a/trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java b/trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java
index e9e9936..082e20c 100644
--- a/trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java
+++ b/trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java
@@ -129,24 +129,24 @@
private List<Map<String, Object>> build(List<Kline> data, String line, String symbol) {
Collections.sort(data);
+ // 相同时间戳保留最新一条(进行中K线会覆盖缓存中的旧数据)
+ Map<Long, Kline> latestByTs = new LinkedHashMap<>();
+ for (Kline kline : data) {
+ latestByTs.put(kline.getTs(), kline);
+ }
+ data = new ArrayList<>(latestByTs.values());
+ Collections.sort(data);
int len = data.size();
for (int i = 1; i < len; i++) {
data.get(i).setOpen(data.get(i - 1).getClose());
}
-
- Set<Long> tsSet = new HashSet<Long>();
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Item bySymbol = itemService.findBySymbol(symbol);
for (int i = 0; i < data.size(); i++) {
Kline kline = data.get(i);
Long ts = kline.getTs();
- if (tsSet.contains(ts)) {
- continue;
- } else {
- tsSet.add(ts);
- }
String fake = bySymbol.getFake();
// if("1".equalsIgnoreCase(fake)){
// klineService.smoothlyKline(kline, 0.99);
@@ -181,20 +181,32 @@
map.put("low", low.setScale(decimal, RoundingMode.HALF_UP));
map.put("volume", kline.getVolume());
- //if (line.equalsIgnoreCase(Kline.PERIOD_15MIN) || line.equalsIgnoreCase(Kline.PERIOD_30MIN) || line.equalsIgnoreCase(Kline.PERIOD_60MIN)) {
- if (i == data.size() - 1) {
- //获取当前价格
- Realtime realtime = DataCache.getLatestRealTime(symbol);
- if (realtime != null) {
- map.put("close", realtime.getClose().setScale(decimal, RoundingMode.HALF_UP));
+ if (i == data.size() - 1) {
+ Realtime realtime = DataCache.getLatestRealTime(symbol);
+ if (realtime != null && realtime.getClose() != null) {
+ close = realtime.getClose();
+ map.put("close", close.setScale(decimal, RoundingMode.HALF_UP));
+ if (close.compareTo(high) > 0) {
+ high = close;
}
- BeforeClose beforeClose = dataDBService.getBeforeClose(kline.getSymbol(), line, ts, realtime);
- if (beforeClose != null) {
- map.put("high", beforeClose.getMaxClose().setScale(decimal, RoundingMode.HALF_UP));
- map.put("low", beforeClose.getMinClose().setScale(decimal, RoundingMode.HALF_UP));
+ if (close.compareTo(low) < 0) {
+ low = close;
}
}
- //}
+ BeforeClose beforeClose = dataDBService.getBeforeClose(kline.getSymbol(), line, ts, realtime);
+ if (beforeClose != null) {
+ if (beforeClose.getMaxClose() != null
+ && beforeClose.getMaxClose().compareTo(BigDecimal.ZERO) > 0) {
+ high = beforeClose.getMaxClose();
+ }
+ if (beforeClose.getMinClose() != null
+ && beforeClose.getMinClose().compareTo(BigDecimal.ZERO) > 0) {
+ low = beforeClose.getMinClose();
+ }
+ }
+ map.put("high", high.setScale(decimal, RoundingMode.HALF_UP));
+ map.put("low", low.setScale(decimal, RoundingMode.HALF_UP));
+ }
list.add(map);
}
return list;
diff --git a/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/DataDBServiceImpl.java b/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/DataDBServiceImpl.java
index 45112bb..bfe29df 100644
--- a/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/DataDBServiceImpl.java
+++ b/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/DataDBServiceImpl.java
@@ -146,43 +146,96 @@
BeforeClose beforeClose = (BeforeClose) redisTemplate.opsForValue().get(RedisKeys.REAL_TIME_BEFORE_CLOSE + symbol + line);
//超出时间重新计算
if (beforeClose == null || ts > beforeClose.getTs()) {
- // 直接获取当前时间的毫秒级时间戳(系统默认时区,但值是全球统一的)
- long currentTimeStamp = System.currentTimeMillis();
-
- // 如果需要严格基于东京时区的当前时间戳(结果和上面一致,因为时间戳是UTC绝对时间)
- //long currentTokyoTimeStamp = Instant.now().atZone(ZoneId.of("America/New_York")).toInstant().toEpochMilli();
- RequestDataHelper.set("symbol", symbol);
- QueryWrapper<Realtime> queryWrapper = new QueryWrapper<Realtime>()
- .eq("symbol", symbol) // 直接写数据库字段名(需和表字段一致)
- .ge("ts", ts)
- .le("ts", currentTimeStamp)
- .select("MAX(CAST(close AS DECIMAL(10,4))) as maxClose",
- "MIN(CAST(close AS DECIMAL(10,4))) as minClose");
- // 4. 执行聚合查询,用selectMap接收结果(键值对:maxClose/minClose -> 对应值)
- Map<String, Object> resultMap = realtimeService.getMap(queryWrapper);
- RequestDataHelper.clear();
- beforeClose = new BeforeClose();
- if (resultMap == null || resultMap.isEmpty()) {
- return beforeClose;
+ beforeClose = calcBeforeClose(symbol, line, ts);
+ if (beforeClose.getMaxClose().compareTo(BigDecimal.ZERO) > 0) {
+ redisTemplate.opsForValue().set(RedisKeys.REAL_TIME_BEFORE_CLOSE + symbol + line, beforeClose);
}
- beforeClose.setMaxClose(convertToBigDecimal(resultMap.get("maxClose")));
- beforeClose.setMinClose(convertToBigDecimal(resultMap.get("minClose")));
- beforeClose.setTs(ts);
+ }
+
+ if (realtime != null && realtime.getClose() != null) {
+ if (beforeClose.getMaxClose() == null || beforeClose.getMaxClose().compareTo(BigDecimal.ZERO) <= 0) {
+ beforeClose.setMaxClose(realtime.getClose());
+ } else if (realtime.getClose().compareTo(beforeClose.getMaxClose()) > 0) {
+ beforeClose.setMaxClose(realtime.getClose());
+ }
+ if (beforeClose.getMinClose() == null || beforeClose.getMinClose().compareTo(BigDecimal.ZERO) <= 0) {
+ beforeClose.setMinClose(realtime.getClose());
+ } else if (realtime.getClose().compareTo(beforeClose.getMinClose()) < 0) {
+ beforeClose.setMinClose(realtime.getClose());
+ }
redisTemplate.opsForValue().set(RedisKeys.REAL_TIME_BEFORE_CLOSE + symbol + line, beforeClose);
}
+ return beforeClose;
+ }
-
- if (realtime != null) {
- if (realtime.getClose().compareTo(beforeClose.getMaxClose()) > 0) {
- beforeClose.setMaxClose(realtime.getClose());
- redisTemplate.opsForValue().set(RedisKeys.REAL_TIME_BEFORE_CLOSE + symbol + line, beforeClose);
+ private BeforeClose calcBeforeClose(String symbol, String line, Long ts) {
+ BeforeClose beforeClose = new BeforeClose();
+ beforeClose.setTs(ts);
+ int interval = sysparaService.find("data_interval").getInteger() / 1000;
+ if (interval <= 0) {
+ interval = 1;
+ }
+ HighLow highLow = null;
+ switch (line) {
+ case Kline.PERIOD_1MIN:
+ highLow = HighLowHandle.get(symbol, 60 / interval, interval);
+ break;
+ case Kline.PERIOD_5MIN:
+ highLow = HighLowHandle.get(symbol, (60 * 5) / interval, interval);
+ break;
+ case Kline.PERIOD_15MIN:
+ highLow = HighLowHandle.get(symbol, (60 * 15) / interval, interval);
+ break;
+ case Kline.PERIOD_30MIN:
+ highLow = HighLowHandle.get(symbol, (60 * 30) / interval, interval);
+ break;
+ case Kline.PERIOD_60MIN:
+ highLow = HighLowHandle.get(symbol, (60 * 60) / interval, interval);
+ break;
+ case Kline.PERIOD_4HOUR:
+ highLow = HighLowHandle.get(symbol, (60 * 60 * 4) / interval, interval);
+ break;
+ case Kline.PERIOD_1DAY:
+ highLow = HighLowHandle.get(symbol, (60 * 60 * 24) / interval, interval);
+ break;
+ case Kline.PERIOD_1WEEK:
+ highLow = HighLowHandle.getByDay(symbol, 7);
+ break;
+ case Kline.PERIOD_1MON:
+ highLow = HighLowHandle.getByDay(symbol, 30);
+ break;
+ default:
+ break;
+ }
+ if (highLow != null && highLow.getHigh() != null) {
+ beforeClose.setMaxClose(highLow.getHigh());
+ }
+ if (highLow != null && highLow.getLow() != null) {
+ beforeClose.setMinClose(highLow.getLow());
+ }
+ if (beforeClose.getMaxClose().compareTo(BigDecimal.ZERO) > 0) {
+ return beforeClose;
+ }
+ long currentTimeStamp = System.currentTimeMillis();
+ RequestDataHelper.set("symbol", symbol);
+ QueryWrapper<Realtime> queryWrapper = new QueryWrapper<Realtime>()
+ .eq("symbol", symbol)
+ .ge("ts", ts)
+ .le("ts", currentTimeStamp)
+ .select("MAX(CAST(close AS DECIMAL(10,4))) as maxClose",
+ "MIN(CAST(close AS DECIMAL(10,4))) as minClose");
+ Map<String, Object> resultMap = realtimeService.getMap(queryWrapper);
+ RequestDataHelper.clear();
+ if (resultMap != null && !resultMap.isEmpty()) {
+ BigDecimal maxClose = convertToBigDecimal(resultMap.get("maxClose"));
+ BigDecimal minClose = convertToBigDecimal(resultMap.get("minClose"));
+ if (maxClose.compareTo(BigDecimal.ZERO) > 0) {
+ beforeClose.setMaxClose(maxClose);
}
- if (realtime.getClose().compareTo(beforeClose.getMinClose()) < 0) {
- beforeClose.setMinClose(realtime.getClose());
- redisTemplate.opsForValue().set(RedisKeys.REAL_TIME_BEFORE_CLOSE + symbol + line, beforeClose);
+ if (minClose.compareTo(BigDecimal.ZERO) > 0) {
+ beforeClose.setMinClose(minClose);
}
}
- System.out.println("realtime.getClose():" + realtime.getClose() + "==" + beforeClose);
return beforeClose;
}
diff --git a/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/KlineServiceImpl.java b/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/KlineServiceImpl.java
index 52a25de..83f5b4b 100644
--- a/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/KlineServiceImpl.java
+++ b/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/KlineServiceImpl.java
@@ -29,6 +29,9 @@
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;
@@ -180,6 +183,165 @@
public Kline buildKline(String symbol, String line, String smallLevelLine, int nums) {
+ if (Kline.PERIOD_5DAY.equals(line)) {
+ return buildKlineLegacy(symbol, line, smallLevelLine, nums);
+ }
+ return buildInProgressKline(symbol, line, smallLevelLine);
+ }
+
+ /**
+ * 按当前周期起点拼接进行中的K线(ts 对齐到周期开盘时间,如 5 分钟线的 9:35)
+ */
+ private Kline buildInProgressKline(String symbol, String line, String smallLevelLine) {
+ try {
+ KlineTimeObject timeObject = DataCache.getKline(symbol, line);
+ if (timeObject == null) {
+ return null;
+ }
+ List<Kline> klineList = timeObject.getKline();
+ Item item = itemService.findBySymbol(symbol);
+ Kline latestSameLineKline = null;
+ if (klineList != null && !klineList.isEmpty()) {
+ latestSameLineKline = klineList.get(klineList.size() - 1);
+ } else if (item.getFake().equalsIgnoreCase("0")) {
+ return null;
+ }
+
+ Realtime latestRealtime = DataCache.getLatestRealTime(symbol);
+ if (latestRealtime == null) {
+ latestRealtime = DataCache.getRealtime(symbol);
+ }
+ if (latestRealtime == null || latestRealtime.getClose() == null) {
+ return null;
+ }
+
+ long currentPeriodTs = alignPeriodStartTs(line, latestRealtime.getTs());
+ if (latestSameLineKline != null && latestSameLineKline.getTs() != null
+ && latestSameLineKline.getTs() > currentPeriodTs) {
+ return null;
+ }
+
+ KlineTimeObject smallObject = DataCache.getKline(symbol, smallLevelLine);
+ List<Kline> periodBars = new ArrayList<>();
+ if (smallObject != null && smallObject.getKline() != null) {
+ periodBars = smallObject.getKline().stream()
+ .filter(k -> k.getTs() != null && k.getTs() >= currentPeriodTs)
+ .collect(Collectors.toList());
+ }
+
+ Kline kline = new Kline();
+ kline.setSymbol(symbol);
+ kline.setPeriod(line);
+ kline.setTs(currentPeriodTs);
+
+ if (latestSameLineKline != null && latestSameLineKline.getTs() != null
+ && latestSameLineKline.getTs() < currentPeriodTs) {
+ kline.setOpen(latestSameLineKline.getClose());
+ } else if (!periodBars.isEmpty() && periodBars.get(0).getOpen() != null) {
+ kline.setOpen(periodBars.get(0).getOpen());
+ } else if (latestRealtime.getOpen() != null) {
+ kline.setOpen(latestRealtime.getOpen());
+ } else {
+ kline.setOpen(latestRealtime.getClose());
+ }
+
+ if (!periodBars.isEmpty()) {
+ Double high = null;
+ Double low = null;
+ for (Kline bar : periodBars) {
+ if (bar.getHigh() != null) {
+ if (high == null || high <= bar.getHigh().doubleValue()) {
+ high = bar.getHigh().doubleValue();
+ }
+ }
+ if (bar.getLow() != null) {
+ if (low == null || low >= bar.getLow().doubleValue()) {
+ low = bar.getLow().doubleValue();
+ }
+ }
+ }
+ kline.setHigh(high == null ? latestRealtime.getClose() : new BigDecimal(high));
+ kline.setLow(low == null ? latestRealtime.getClose() : new BigDecimal(low));
+ kline.setClose(periodBars.get(periodBars.size() - 1).getClose());
+ kline.setVolume(periodBars.stream()
+ .map(Kline::getVolume)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add));
+ kline.setAmount(periodBars.stream()
+ .map(Kline::getAmount)
+ .filter(Objects::nonNull)
+ .reduce(BigDecimal.ZERO, BigDecimal::add));
+ } else {
+ kline.setHigh(latestRealtime.getClose());
+ kline.setLow(latestRealtime.getClose());
+ kline.setClose(latestRealtime.getClose());
+ kline.setVolume(latestRealtime.getVolume());
+ kline.setAmount(latestRealtime.getAmount());
+ }
+
+ kline.setClose(latestRealtime.getClose());
+ if (latestRealtime.getClose().compareTo(kline.getHigh()) > 0) {
+ kline.setHigh(latestRealtime.getClose());
+ }
+ if (latestRealtime.getClose().compareTo(kline.getLow()) < 0) {
+ kline.setLow(latestRealtime.getClose());
+ }
+
+ repairKline(kline);
+ if (kline.getOpen().compareTo(BigDecimal.ZERO) == 0 || kline.getClose().compareTo(BigDecimal.ZERO) == 0) {
+ return null;
+ }
+ return kline;
+ } catch (Exception e) {
+ logger.error("buildInProgressKline error: {}, {}", symbol, line, e);
+ }
+ return null;
+ }
+
+ /**
+ * 将时间戳对齐到K线周期起点(UTC,与火币 id 字段一致)
+ * 1week:周一 00:00 UTC;1mon:每月 1 日 00:00 UTC
+ */
+ private long alignPeriodStartTs(String line, long tsMillis) {
+ ZonedDateTime zdt = Instant.ofEpochMilli(tsMillis).atZone(ZoneOffset.UTC);
+ switch (line) {
+ case Kline.PERIOD_1MIN:
+ return zdt.withSecond(0).withNano(0).toInstant().toEpochMilli();
+ case Kline.PERIOD_5MIN: {
+ int minute = zdt.getMinute();
+ return zdt.withMinute(minute - minute % 5).withSecond(0).withNano(0).toInstant().toEpochMilli();
+ }
+ case Kline.PERIOD_15MIN: {
+ int minute = zdt.getMinute();
+ return zdt.withMinute(minute - minute % 15).withSecond(0).withNano(0).toInstant().toEpochMilli();
+ }
+ case Kline.PERIOD_30MIN: {
+ int minute = zdt.getMinute();
+ return zdt.withMinute(minute - minute % 30).withSecond(0).withNano(0).toInstant().toEpochMilli();
+ }
+ case Kline.PERIOD_60MIN:
+ return zdt.withMinute(0).withSecond(0).withNano(0).toInstant().toEpochMilli();
+ case Kline.PERIOD_1DAY:
+ return zdt.withHour(0).withMinute(0).withSecond(0).withNano(0).toInstant().toEpochMilli();
+ case Kline.PERIOD_1WEEK: {
+ zdt = zdt.withHour(0).withMinute(0).withSecond(0).withNano(0);
+ int dayOfWeek = zdt.getDayOfWeek().getValue();
+ return zdt.minusDays(dayOfWeek - 1L).toInstant().toEpochMilli();
+ }
+ case Kline.PERIOD_1MON:
+ return zdt.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0).toInstant().toEpochMilli();
+ case Kline.PERIOD_2HOUR:
+ return zdt.withMinute(0).withSecond(0).withNano(0).toInstant().toEpochMilli();
+ case Kline.PERIOD_4HOUR: {
+ int hour = zdt.getHour();
+ return zdt.withHour(hour - hour % 4).withMinute(0).withSecond(0).withNano(0).toInstant().toEpochMilli();
+ }
+ default:
+ return zdt.withSecond(0).withNano(0).toInstant().toEpochMilli();
+ }
+ }
+
+ private Kline buildKlineLegacy(String symbol, String line, String smallLevelLine, int nums) {
try {
// 取5分钟K线全部数据集合
KlineTimeObject timeObject = DataCache.getKline(symbol, line);
@@ -211,14 +373,27 @@
if (realtimeKline == null) {
return null;
}
- if (latestSameLineKline != null && latestSameLineKline.getTs() >= realtimeKline.getTs()) {
+ if (latestSameLineKline != null && latestSameLineKline.getTs() > realtimeKline.getTs()) {
return null;
}
if (latestSameLineKline != null) {
long latestSameLineKlineTs = latestSameLineKline.getTs();
- klineOneTop5 = klineOneTop5.stream().filter(r -> r.getTs() > latestSameLineKlineTs).collect(Collectors.toList());
+ if (latestSameLineKlineTs == realtimeKline.getTs()) {
+ klineOneTop5 = klineOne.stream()
+ .filter(r -> r.getTs() >= latestSameLineKlineTs)
+ .collect(Collectors.toList());
+ if (klineOneTop5.size() > nums) {
+ klineOneTop5 = new ArrayList<>(klineOneTop5.subList(klineOneTop5.size() - nums, klineOneTop5.size()));
+ }
+ } else {
+ klineOneTop5 = klineOneTop5.stream()
+ .filter(r -> r.getTs() > latestSameLineKlineTs)
+ .collect(Collectors.toList());
+ }
}
-
+ if (klineOneTop5.isEmpty()) {
+ return null;
+ }
Double high = null;
Double low = null;
@@ -673,11 +848,16 @@
latestKilne = klineList.get(klineList.size() - 1);
}
Realtime realtime = realTimeList.get(realTimeList.size() - 1);
- if (latestKilne != null && latestKilne.getTs() >= realtime.getTs()) {
+ long currentMinuteTs = alignPeriodStartTs(Kline.PERIOD_1MIN, realtime.getTs());
+ if (latestKilne != null && latestKilne.getTs() != null && latestKilne.getTs() > currentMinuteTs) {
return null;
}
- long lastKlineTs = latestKilne.getTs();
- realTimeList = realTimeList.stream().filter(r -> r.getTs() > lastKlineTs).collect(Collectors.toList());
+ realTimeList = realTimeList.stream()
+ .filter(r -> r.getTs() != null && r.getTs() >= currentMinuteTs)
+ .collect(Collectors.toList());
+ if (realTimeList.isEmpty()) {
+ realTimeList = Collections.singletonList(realtime);
+ }
Double high = null;
Double low = null;
for (Realtime realTime : realTimeList) {
@@ -692,11 +872,11 @@
// 保存K线到数据库
Kline kline = new Kline();
kline.setSymbol(symbol);
- kline.setTs(realtime.getTs());
- if (latestKilne != null) {
+ kline.setTs(currentMinuteTs);
+ if (latestKilne != null && latestKilne.getTs() != null && latestKilne.getTs() < currentMinuteTs) {
kline.setOpen(latestKilne.getClose());
} else {
- kline.setOpen(realTimeList.get(0).getOpen());
+ kline.setOpen(realTimeList.get(0).getOpen() != null ? realTimeList.get(0).getOpen() : realtime.getClose());
}
kline.setHigh(new BigDecimal(high));
kline.setLow(new BigDecimal(low));
diff --git a/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/RemoteDataServiceImpl.java b/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/RemoteDataServiceImpl.java
index 785ae72..c97d876 100644
--- a/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/RemoteDataServiceImpl.java
+++ b/trading-order-huobi/src/main/java/com.yami.trading.huobi/data/internal/RemoteDataServiceImpl.java
@@ -73,10 +73,6 @@
@Override
public List<Kline> kline(String symbol, String line) {
- Item bySymbol = itemService.findBySymbol(symbol);
- if(Item.cryptos.equals(bySymbol.getType())){
- return klineCryptos(symbol, line);
- }
KlineTimeObject timeObject = DataCache.getKline(symbol, line);
List<Kline> list = new ArrayList<Kline>();
if (timeObject != null) {
@@ -85,7 +81,7 @@
List<Kline> list_clone = new ArrayList<Kline>();
try {
for (int i = 0; i < list.size(); i++) {
- if(list.get(i) == null){
+ if (list.get(i) == null) {
continue;
}
Kline kline = (Kline) list.get(i).clone();
@@ -96,71 +92,61 @@
}
Realtime realtime = DataCache.getLatestRealTime(symbol);
- if (realtime != null) {
- Kline kline = null;
- if (KlineConstant.PERIOD_1MIN.equals(line)) {
- kline = klineService.bulidKline1Minute(realtime, KlineConstant.PERIOD_1MIN);
- } else if (KlineConstant.PERIOD_5MIN.equals(line)) {
- kline = klineService.bulidKline5Minute(realtime, KlineConstant.PERIOD_5MIN);
- } else if (KlineConstant.PERIOD_15MIN.equals(line)) {
- kline = klineService.bulidKline15Minute(realtime, KlineConstant.PERIOD_15MIN);
- } else if (KlineConstant.PERIOD_30MIN.equals(line)) {
- kline = klineService.bulidKline30Minute(realtime, KlineConstant.PERIOD_30MIN);
- } else if (KlineConstant.PERIOD_60MIN.equals(line)) {
- kline = klineService.bulidKline60Minute(realtime, KlineConstant.PERIOD_60MIN);
- } else if (KlineConstant.PERIOD_4HOUR.equals(line)) {
- kline = klineService.bulidKline4Hour(realtime, KlineConstant.PERIOD_4HOUR);
- } else if (KlineConstant.PERIOD_1DAY.equals(line)) {
- kline = klineService.bulidKline1Day(realtime, KlineConstant.PERIOD_1DAY);
- } else if (KlineConstant.PERIOD_5DAY.equals(line)) {
- kline = klineService.bulidKline5Day(realtime, KlineConstant.PERIOD_5DAY);
- } else if (KlineConstant.PERIOD_1WEEK.equals(line)) {
- kline = klineService.bulidKline1Week(realtime, KlineConstant.PERIOD_1WEEK);
- } else if (KlineConstant.PERIOD_1MON.equals(line)) {
- kline = klineService.bulidKline1Mon(realtime, KlineConstant.PERIOD_1MON);
- } else if (KlineConstant.PERIOD_QUARTER.equals(line)) {
- kline = klineService.bulidKline1Mon(realtime, KlineConstant.PERIOD_QUARTER);
- } else if (KlineConstant.PERIOD_YEAR.equals(line)) {
- kline = klineService.bulidKline1Mon(realtime, KlineConstant.PERIOD_YEAR);
- }
- if (null != kline) {
- list_clone.add(kline);
- }
+ if (realtime == null) {
+ realtime = DataCache.getRealtime(symbol);
}
- // 按时间升序
+ if (realtime != null) {
+ appendOrReplaceKline(list_clone, buildCurrentKline(realtime, line));
+ }
Collections.sort(list_clone);
return list_clone;
+ }
+ private Kline buildCurrentKline(Realtime realtime, String line) {
+ if (KlineConstant.PERIOD_1MIN.equals(line)) {
+ return klineService.bulidKline1Minute(realtime, KlineConstant.PERIOD_1MIN);
+ } else if (KlineConstant.PERIOD_5MIN.equals(line)) {
+ return klineService.bulidKline5Minute(realtime, KlineConstant.PERIOD_5MIN);
+ } else if (KlineConstant.PERIOD_15MIN.equals(line)) {
+ return klineService.bulidKline15Minute(realtime, KlineConstant.PERIOD_15MIN);
+ } else if (KlineConstant.PERIOD_30MIN.equals(line)) {
+ return klineService.bulidKline30Minute(realtime, KlineConstant.PERIOD_30MIN);
+ } else if (KlineConstant.PERIOD_60MIN.equals(line)) {
+ return klineService.bulidKline60Minute(realtime, KlineConstant.PERIOD_60MIN);
+ } else if (KlineConstant.PERIOD_4HOUR.equals(line)) {
+ return klineService.bulidKline4Hour(realtime, KlineConstant.PERIOD_4HOUR);
+ } else if (KlineConstant.PERIOD_1DAY.equals(line)) {
+ return klineService.bulidKline1Day(realtime, KlineConstant.PERIOD_1DAY);
+ } else if (KlineConstant.PERIOD_5DAY.equals(line)) {
+ return klineService.bulidKline5Day(realtime, KlineConstant.PERIOD_5DAY);
+ } else if (KlineConstant.PERIOD_1WEEK.equals(line)) {
+ return klineService.bulidKline1Week(realtime, KlineConstant.PERIOD_1WEEK);
+ } else if (KlineConstant.PERIOD_1MON.equals(line)) {
+ return klineService.bulidKline1Mon(realtime, KlineConstant.PERIOD_1MON);
+ } else if (KlineConstant.PERIOD_QUARTER.equals(line)) {
+ return klineService.bulidKlineQuarter(realtime, KlineConstant.PERIOD_QUARTER);
+ } else if (KlineConstant.PERIOD_YEAR.equals(line)) {
+ return klineService.bulidKlineYear(realtime, KlineConstant.PERIOD_YEAR);
+ }
+ return null;
}
public List<Kline> klineCryptos(String symbol, String line) {
- KlineTimeObject timeObject = DataCache.getKline(symbol, line);
- List<Kline> list = new ArrayList<Kline>();
- if (timeObject != null) {
- list = timeObject.getKline();
+ return kline(symbol, line);
+ }
+
+ private void appendOrReplaceKline(List<Kline> list, Kline kline) {
+ if (kline == null) {
+ return;
}
- List<Kline> list_clone = new ArrayList<Kline>();
- try {
- for (int i = 0; i < list.size(); i++) {
- Kline kline = (Kline) list.get(i).clone();
- list_clone.add(kline);
+ for (int i = list.size() - 1; i >= 0; i--) {
+ Kline existing = list.get(i);
+ if (existing.getTs() != null && existing.getTs().equals(kline.getTs())) {
+ list.set(i, kline);
+ return;
}
- } catch (CloneNotSupportedException e) {
- e.printStackTrace();
}
- Realtime realtime = DataCache.getRealtime(symbol);
- Kline hobiOne = DataCache.getKline_hobi().get(symbol + "_" + line);
-
- Kline lastOne = null;
- if (list != null && list.size() > 0) {
- lastOne = list.get(list.size() - 1);
- }
- if (realtime != null && hobiOne != null && lastOne != null) {
- list_clone.add(this.klineService.bulidKline(realtime, lastOne, hobiOne, line));
- }
- Collections.sort(list_clone); // 按时间升序
- return list_clone;
-
+ list.add(kline);
}
@Override
--
Gitblit v1.9.3