trading-order-admin/src/main/java/com/yami/trading/admin/controller/AddressController.java
@@ -2,22 +2,28 @@ import com.yami.trading.admin.model.LoginModel; import com.yami.trading.admin.model.UpdateAddressModel; import com.yami.trading.admin.model.channelBlockchain.ChannelBlockchainUpdateModel; import com.yami.trading.bean.model.ChannelBlockchain; import com.yami.trading.common.constants.RedisKeys; import com.yami.trading.common.domain.Result; import com.yami.trading.common.exception.BusinessException; import com.yami.trading.common.exception.YamiShopBindException; import com.yami.trading.common.util.GoogleAuthenticator; import com.yami.trading.common.util.IPHelper; import com.yami.trading.common.util.StringUtils; import com.yami.trading.security.common.bo.UserInfoInTokenBO; import com.yami.trading.security.common.enums.CryptoCurrencyEnum; import com.yami.trading.security.common.enums.SysTypeEnum; import com.yami.trading.security.common.util.LocalKeyStorageAESUtil; import com.yami.trading.security.common.util.SecurityUtils; import com.yami.trading.security.common.vo.TokenInfoVO; import com.yami.trading.service.ChannelBlockchainService; import com.yami.trading.service.system.LogService; import com.yami.trading.sys.model.SysUser; import com.yami.trading.sys.service.SysUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; @@ -30,14 +36,17 @@ * @description: 充值地址 * @create: 2025-08-07 14:44 **/ @Slf4j @RestController @RequestMapping("address") @Api(tags = "充值地址") public class AddressController { @Autowired RedisTemplate redisTemplate; ChannelBlockchainService channelBlockchainService; @Autowired SysUserService sysUserService; /** * 地址列表 @@ -45,18 +54,11 @@ */ @PostMapping("/list") public Result<?> list() { List<CryptoCurrencyEnum> currencyEnums = CryptoCurrencyEnum.getAll(); List<ChannelBlockchain> data = new ArrayList<>(); currencyEnums.forEach(f->{ //List<CryptoCurrencyEnum> currencyEnums = CryptoCurrencyEnum.getAll(); List<ChannelBlockchain> data = channelBlockchainService.list(); data.forEach(f->{ try { String address = LocalKeyStorageAESUtil.loadAndDecrypt(f.getName()); ChannelBlockchain blockchain = new ChannelBlockchain(); blockchain.setBlockchain_name(f.getChain()); blockchain.setAddress(address); blockchain.setCoin(f.getCoin()); blockchain.setAuto(false); blockchain.setImg(null); data.add(blockchain); f.setBlockchain_name(f.getBlockchainName()); } catch (Exception e) { e.getMessage(); } @@ -64,7 +66,7 @@ return Result.succeed(data); } @PostMapping("/update") /*@PostMapping("/update") public Result<?> list(@RequestBody UpdateAddressModel model) { String name = model.getCoin().toLowerCase()+"_"+model.getChain().toLowerCase(); try { @@ -76,34 +78,41 @@ e.getMessage(); } return Result.succeed(); }*/ @ApiOperation("修改 区块链充值地址") @PostMapping("update") public Result update(@RequestBody @Valid ChannelBlockchainUpdateModel model) { String id = model.getId(); String blockchain_name = model.getBlockchainName(); String coin = model.getCoin(); String address = model.getAddress(); ChannelBlockchain channelBlockchain = this.channelBlockchainService.getById(id); /*String error = this.verif(blockchain_name, coin, address, null); if (!StringUtils.isNullOrEmpty(error)) { throw new BusinessException(error); }*/ if (!blockchain_name.isEmpty()) { channelBlockchain.setBlockchain_name(blockchain_name); } if (!coin.isEmpty()) { channelBlockchain.setCoin(coin); } if (!address.isEmpty()) { channelBlockchain.setAddress(address); } channelBlockchainService.updateById(channelBlockchain); return Result.succeed(); } /** * u盾地址列表 * @return */ @GetMapping("/getUDList") public Result<?> getUDList(String partyId) { if (partyId == null || partyId.isEmpty()) { return Result.failed("请选择用户"); } List<CryptoCurrencyEnum> currencyEnums = CryptoCurrencyEnum.getAll(); List<ChannelBlockchain> data = new ArrayList<>(); currencyEnums.forEach(currencyEnum->{ try { String address = (String)redisTemplate.opsForValue().get(RedisKeys.BLOCKCHAIN_ADDRESS + partyId + currencyEnum.getName()); ChannelBlockchain blockchain = new ChannelBlockchain(); blockchain.setBlockchain_name(currencyEnum.getChain()); blockchain.setAddress(address); blockchain.setCoin(currencyEnum.getCoin()); blockchain.setAuto(false); blockchain.setImg(null); data.add(blockchain); } catch (Exception e) { log.error(e.getMessage()); } }); return Result.succeed(data); private String verif(String blockchain_name, String coin, String address, String img) { if (StringUtils.isEmptyString(blockchain_name)) return "请输入链名称"; if (StringUtils.isEmptyString(coin)) return "请输入币种"; if (StringUtils.isEmptyString(address)) return "请输入地址"; return null; } } trading-order-admin/src/main/java/com/yami/trading/admin/model/channelBlockchain/ChannelBlockchainUpdateModel.java
New file @@ -0,0 +1,35 @@ package com.yami.trading.admin.model.channelBlockchain; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel public class ChannelBlockchainUpdateModel { private String id; /** * 币种名称 BTC ETH USDT */ @ApiModelProperty("币种名称") private String coin; /** * 链名称 */ @ApiModelProperty("链名称") private String blockchainName; @ApiModelProperty("地址") private String address; /* @ApiModelProperty("资金密码") private String safeword;*/ // // @ApiModelProperty("超级谷歌验证码") // private String superGoogleAuthCode; } trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java
@@ -123,30 +123,30 @@ return Result.succeed(this.build(data, line, symbol)); } catch (Exception e) { logger.error("getKline error", e); throw new YamiShopBindException("k线图获取失败"); throw new YamiShopBindException(""); } } 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; 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; } 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)); 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