| | |
| | | // 1. 确定时间戳单位(假设ts是毫秒级,若为秒级需用ofEpochSecond()) |
| | | Instant instant = Instant.ofEpochMilli(ts); |
| | | |
| | | // 2. 将时间戳转换为当地时区的日期(指定时区更准确,如Asia/Tokyo) |
| | | LocalDate tsDate = instant.atZone(ZoneId.of("Asia/Tokyo")).toLocalDate(); |
| | | // 2. 将时间戳转换为当地时区的日期(指定时区更准确,如America/New_York) |
| | | LocalDate tsDate = instant.atZone(ZoneId.of("America/New_York")).toLocalDate(); |
| | | |
| | | // 3. 获取“昨天的日期”(当前日期减1天) |
| | | LocalDate yesterday = LocalDate.now(ZoneId.of("Asia/Tokyo")).minusDays(1); |
| | | LocalDate yesterday = LocalDate.now(ZoneId.of("America/New_York")).minusDays(1); |
| | | |
| | | // 4. 判断是否为昨天 |
| | | boolean isYesterday = tsDate.equals(yesterday); |
| | |
| | | return realtime; |
| | | } |
| | | |
| | | public BeforeClose getBeforeClose(String symbol, String line, Long ts) { |
| | | public BeforeClose getBeforeClose(String symbol, String line, Long ts, Realtime realtime) { |
| | | BeforeClose beforeClose = (BeforeClose) redisTemplate.opsForValue().get(RedisKeys.REAL_TIME_BEFORE_CLOSE + symbol + line); |
| | | if (beforeClose == null) { |
| | | // 直接获取当前时间的毫秒级时间戳(系统默认时区,但值是全球统一的) |
| | | long currentTimeStamp = System.currentTimeMillis(); |
| | | |
| | | // 如果需要严格基于东京时区的当前时间戳(结果和上面一致,因为时间戳是UTC绝对时间) |
| | | //long currentTokyoTimeStamp = Instant.now().atZone(ZoneId.of("Asia/Tokyo")).toInstant().toEpochMilli(); |
| | | RequestDataHelper.set("symbol", symbol); |
| | | QueryWrapper<Realtime> queryWrapper = new QueryWrapper<Realtime>() |
| | | .eq("symbol", symbol) // 直接写数据库字段名(需和表字段一致) |
| | | .ge("ts", ts) |
| | | .le("ts", currentTimeStamp) |
| | | .select("MAX(close) as maxClose", "MIN(close) 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; |
| | | //超出时间重新计算 |
| | | if (beforeClose == null || ts > beforeClose.getTs()) { |
| | | 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"))); |
| | | redisTemplate.opsForValue().set(RedisKeys.REAL_TIME_BEFORE_CLOSE + symbol + line, beforeClose , 1 , TimeUnit.MINUTES); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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 (minClose.compareTo(BigDecimal.ZERO) > 0) { |
| | | beforeClose.setMinClose(minClose); |
| | | } |
| | | } |
| | | return beforeClose; |
| | | } |