package com.yami.trading.huobi.hobi.internal; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; import com.yami.trading.bean.cms.Infomation; import com.yami.trading.bean.data.domain.*; import com.yami.trading.bean.item.domain.Item; import com.yami.trading.common.util.RedisUtil; import com.yami.trading.huobi.data.DataCache; import com.yami.trading.huobi.data.internal.*; import com.yami.trading.huobi.hobi.http.HttpHelper; import com.yami.trading.huobi.hobi.http.HttpMethodType; import com.yami.trading.service.cms.InfomationService; import com.yami.trading.service.item.ItemService; import org.redisson.api.RedissonClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * 完成需求k线图采集 */ @Component public class XueQiuDataServiceImpl { // https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=TSLA&begin=1682695800000&period=120m&type=before&count=-500&indicator=kline"; public final static String klineUrl = "https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol={}&begin={}&period={}&type=before&count=-500&indicator=kline"; ExecutorService executor = Executors.newFixedThreadPool(12); // 根据需要执行的任务数量调整线程池大小 @Autowired private InfomationService infomationService; @Qualifier("redissonClientSpider") @Autowired private RedissonClient redissonClientSpider; /** * live */ public final static String live = "https://onjdo.com/stock/api/live/getLiveRates"; public final static String markets = "https://onjdo.com/stock/api/live/getMarkets"; public final static String pankou = "https://onjdo.com/stock/api/live/getPanKou"; public final static String tradeList = "https://onjdo.com/stock/api/live/getTrade"; public final static String lease = "https://onjdo.com/stock/api/live/lease"; private static Logger logger = LoggerFactory.getLogger(XueQiuDataServiceImpl.class); @Autowired private KlineService klineService; @Autowired private ItemService itemService; public static List pankous(String remarks) { Map param = new HashMap<>(); param.put("currency", remarks); String result = HttpHelper.getJSONFromHttpNew(pankou, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String code = resultJson.getString("code"); if ("ok".equals(code)) { JSONArray dataArray = resultJson.getJSONArray("data"); return dataArray.toJavaList(Depth.class); } return Lists.newArrayList(); } public static List getMarkets(String symbols) { Map param = new HashMap<>(); param.put("currency", symbols); String result = HttpHelper.getJSONFromHttpNew(markets, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String code = resultJson.getString("code"); if ("ok".equals(code)) { JSONArray dataArray = resultJson.getJSONArray("data"); return dataArray.toJavaList(StockMarket.class); } return Lists.newArrayList(); } public static void main(String[] args) { XueQiuDataServiceImpl service = new XueQiuDataServiceImpl(); // List sz300750 = service.buildOneYearPeriod("AAPL"); // System.out.println(sz300750.size()); List markets1 = service.getMarkets("AAPL,OIL"); System.out.println(markets1); } public void lease(String symbol) { Item bySymbol = itemService.findBySymbol(symbol); if(Item.DEFAULT_ACTIVE.equalsIgnoreCase(bySymbol.getCrawlStatus())){ return; } Map param = new HashMap<>(); param.put("currency", symbol); param.put("type", bySymbol.getOpenCloseType()); String result = HttpHelper.getJSONFromHttpNew(lease, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String code = resultJson.getString("code"); if ("ok".equals(code)) { logger.info("{} 采集续约成功", symbol); } } public void getInformation() { String cookie = HttpHelper.getCookie("https://xueqiu.com/"); String url = "https://xueqiu.com/statuses/livenews/list.json?since_id=-1&max_id=-1&count=15"; String json = HttpHelper.sendGetHttp(url, null, cookie); JSONArray items = JSONObject.parseObject(json).getJSONArray("items"); List infomations = new ArrayList<>(); items.forEach(d -> { Infomation infom = new Infomation(); JSONObject data = (JSONObject) d; String dataId = data.getString("id"); infom.setDataId(dataId); String description = data.getString("text"); infom.setDescription(description); String createAt = data.getString("created_at"); infom.setCreatedAt(createAt); infom.setType("1"); String originUrl = data.getString("target"); infom.setOriginUrl(originUrl); String source = getSource(description); infom.setSource(source); infom.setLang("zh-CN"); String key = "infomation" + originUrl; if (RedisUtil.get(key) == null) { infomations.add(infom); // url存一周 RedisUtil.set(key, 1, 60 * 60 * 24 * 7); } }); if (infomations.size() > 1) { infomationService.saveBatch(infomations); } } public Map> getHourlyAndMinuteHistory(String symbol, String cookie) { Map> map = new HashMap<>(); try { CompletableFuture> fourHourlyFuture = CompletableFuture.supplyAsync(() -> getTimeseriesForFourHourly(symbol, cookie), executor); CompletableFuture> oneHourlyFuture = CompletableFuture.supplyAsync(() -> getTimeseriesForOneHourly(symbol, cookie), executor); CompletableFuture> twoHourlyFuture = CompletableFuture.supplyAsync(() -> getTimeseriesForTwoHourly(symbol, cookie), executor); CompletableFuture> thirtyMinuteFuture = CompletableFuture.supplyAsync(() -> getTimeseriesThirtyMinute(symbol, cookie), executor); CompletableFuture> fifteenMinuteFuture = CompletableFuture.supplyAsync(() -> getTimeseriesFifteenMinute(symbol, cookie), executor); CompletableFuture> fiveMinuteFuture = CompletableFuture.supplyAsync(() -> getTimeseriesFiveMinute(symbol, cookie), executor); CompletableFuture> oneMinuteFuture = CompletableFuture.supplyAsync(() -> getTimeseriesOneMinute(symbol, cookie), executor); CompletableFuture allFutures = CompletableFuture.allOf( fourHourlyFuture, oneHourlyFuture, twoHourlyFuture, thirtyMinuteFuture, fifteenMinuteFuture, fiveMinuteFuture, oneMinuteFuture); // 等待所有任务完成 allFutures.join(); map.put(KlineConstant.PERIOD_4HOUR, fourHourlyFuture.get()); map.put(KlineConstant.PERIOD_60MIN, oneHourlyFuture.get()); // 特殊处理两小时数据 List twoHourlyList = twoHourlyFuture.get(); if (twoHourlyList == null || twoHourlyList.isEmpty()) { try { List hourList = oneHourlyFuture.get(); if (hourList != null && !hourList.isEmpty()) { map.put(Kline.PERIOD_2HOUR, klineService.calculateKline(symbol, 2, Kline.PERIOD_2HOUR, hourList)); } } catch (Exception e) { logger.error("计算 120mink线图失败", e); } } else { map.put(KlineConstant.PERIOD_2HOUR, twoHourlyList); } map.put(KlineConstant.PERIOD_30MIN, thirtyMinuteFuture.get()); map.put(KlineConstant.PERIOD_15MIN, fifteenMinuteFuture.get()); map.put(KlineConstant.PERIOD_5MIN, fiveMinuteFuture.get()); map.put(KlineConstant.PERIOD_1MIN, oneMinuteFuture.get()); return map; }catch (Exception e){ logger.error("getHourlyAndMinuteHistory 报错 :{}", symbol); } return map; } public static String getSource(String text) { String pattern = "(([^()]*))$"; // 匹配最后一个括号内的文本 Pattern regex = Pattern.compile(pattern); Matcher matcher = regex.matcher(text); if (matcher.find()) { String endText = matcher.group(1); return endText; } else { return ""; } } /** * 可以多个 */ public void tradeList(String remarks, boolean isUSStock) { Map param = new HashMap<>(); param.put("currency", remarks); String result = HttpHelper.getJSONFromHttpNew(tradeList, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String code = resultJson.getString("code"); if ("ok".equals(code)) { JSONArray dataArray = resultJson.getJSONArray("data"); for (Object o : dataArray) { JSONArray d = (JSONArray) o; List tradeDetails = d.toJavaList(TradeDetails.class); if (tradeDetails.size() >= 1) { String symbol = itemService.getSymbolByRemarks(tradeDetails.get(0).getSymbol()); DataCache.putStockTradeList(symbol, tradeDetails); tradeListToTrade(symbol, tradeDetails); if (isUSStock) { setTradeListToDepth(symbol, tradeDetails); } } } } } public static void setTradeListToDepth(String symbol, List tradeDetails) { Depth depth = new Depth(); depth.setTs(tradeDetails.get(0).getTimestamp() / 1000); depth.setSymbol(symbol); List asks = tradeDetails.stream().filter(t -> t.getSide() == -1).map(t -> { DepthEntry depthEntry = new DepthEntry(); depthEntry.setAmount((double) t.getTrade_volume()); depthEntry.setPrice(t.getCurrent()); return depthEntry; }).collect(Collectors.toList()); List bids = tradeDetails.stream().filter(t -> t.getSide() == 1).map(t -> { DepthEntry depthEntry = new DepthEntry(); depthEntry.setAmount((double) t.getTrade_volume()); depthEntry.setPrice(t.getCurrent()); return depthEntry; }).collect(Collectors.toList()); depth.setAsks(asks); depth.setBids(bids); DepthTimeObject timeObject = new DepthTimeObject(); timeObject.setDepth(depth); DataCache.putDepth(depth.getSymbol(), timeObject); } public static void tradeListToTrade(String symbol, List tradeDetails) { TradeTimeObject timeObject = DataCache.getTrade(symbol); if (timeObject == null) { timeObject = new TradeTimeObject(); } List data = tradeDetails.stream().map(a -> { TradeEntry tradeEntry = new TradeEntry(); tradeEntry.setDirection(a.getSide() == 1 ? "sell" : "buy"); tradeEntry.setAmount((double) a.getTrade_volume()); tradeEntry.setPrice(a.getCurrent()); tradeEntry.setTs(a.getTimestamp() / 1000); return tradeEntry; }).collect(Collectors.toList()); timeObject.put(symbol, data); DataCache.putTrade(symbol, timeObject); } /** * 获取原始的K线图数据 * * @param symbol * @param cookie * @return */ public String getRawTimeseriesByMinute(String symbol, String cookie) { long nowTs = System.currentTimeMillis(); long begin = nowTs; String url = StrUtil.format(klineUrl, symbol, begin, "1m"); return HttpHelper.sendGetHttp(url, null, cookie); } public List realtimeSingle(String symbol) { List list = new ArrayList<>(); try { Map param = new HashMap<>(); param.put("currency", symbol); String result = HttpHelper.getJSONFromHttpNew(live, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String code = resultJson.getString("code"); if ("ok".equals(code)) { JSONArray dataArray = resultJson.getJSONArray("data"); for (int i = 0; i < dataArray.size(); i++) { JSONObject realtimeJson = dataArray.getJSONObject(i); Realtime realtime = new Realtime(); // realtime.setUuid(ApplicationUtil.getCurrentTimeUUID()); String currency; currency = realtimeJson.getString("currency"); int decimal = itemService.getDecimal(currency); String symbolByRemarks = itemService.getSymbolByRemarks(currency); realtime.setSymbol(symbolByRemarks); realtime.setName(symbolByRemarks); Long timestamp = realtimeJson.getLong("timestamp"); if (timestamp.toString().length() > 13) { timestamp = timestamp / 1000; } realtime.setTs(timestamp); realtime.setOpen(realtimeJson.getBigDecimal("open").setScale(decimal, RoundingMode.HALF_UP).doubleValue()); if (realtimeJson.getBigDecimal("mid").compareTo(BigDecimal.ZERO) != 0) { realtime.setClose(realtimeJson.getBigDecimal("mid").setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } else { realtime.setClose(realtimeJson.getBigDecimal("close").setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } realtime.setHigh(realtimeJson.getBigDecimal("high").setScale(decimal, RoundingMode.HALF_UP).doubleValue()); realtime.setLow(realtimeJson.getBigDecimal("low").setScale(decimal, RoundingMode.HALF_UP).doubleValue()); realtime.setMarketCapital(realtimeJson.getLong("marketCapital")); realtime.setFloatMarketCapital(realtimeJson.getLong("floatMarketCapital")); BigDecimal peForecast = realtimeJson.getBigDecimal("peForecast"); if (peForecast != null) { realtime.setPeForecast(peForecast.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } BigDecimal volumeRatio = realtimeJson.getBigDecimal("volumeRatio"); if (volumeRatio != null) { realtime.setVolumeRatio(volumeRatio.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } BigDecimal turnoverRate = realtimeJson.getBigDecimal("turnoverRate"); if (turnoverRate != null) { realtime.setTurnoverRate(turnoverRate.setScale(2, RoundingMode.HALF_UP).doubleValue()); } BigDecimal navps = realtimeJson.getBigDecimal("navps"); if (navps != null) { realtime.setNavps(navps.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } BigDecimal pb = realtimeJson.getBigDecimal("pb"); if (pb != null) { realtime.setPb(pb.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } BigDecimal amplitude = realtimeJson.getBigDecimal("amplitude"); if (amplitude != null) { realtime.setAmplitude(amplitude.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } BigDecimal eps = realtimeJson.getBigDecimal("eps"); if (eps != null) { realtime.setEps(eps.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } BigDecimal chg = realtimeJson.getBigDecimal("chg"); if (chg != null) { realtime.setChg(chg.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } BigDecimal percent = realtimeJson.getBigDecimal("percent"); if (percent != null) { realtime.setPercent(percent.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); } BigDecimal amount = realtimeJson.getBigDecimal("amount"); if (amount == null) { amount = BigDecimal.ZERO; } realtime.setAmount(amount.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); BigDecimal volume = realtimeJson.getBigDecimal("volume"); if (volume == null) { volume = BigDecimal.ZERO; } realtime.setVolume(volume.setScale(decimal, RoundingMode.HALF_UP).doubleValue()); realtime.setAsk(realtimeJson.getBigDecimal("ask").setScale(decimal, RoundingMode.HALF_UP).doubleValue()); realtime.setBid(realtimeJson.getBigDecimal("bid").setScale(decimal, RoundingMode.HALF_UP).doubleValue()); list.add(realtime); } } else { logger.error(" realtime()error, resultJson [ " + resultJson.toJSONString() + " ]"); } } catch (Exception e) { logger.error("error", e); } return list; } /** * 1day 历史数据 : 周期 1年 * 1week,1mon 历史数据 : 周期 5年 * 请求 350次 */ public Map> getDailyWeekMonthHistory(String symbol,String cookie) { Map> map = new HashMap<>(); try { CompletableFuture> oneWeekFuture = CompletableFuture.supplyAsync(() -> buildOneWeekPeriod(symbol, cookie), executor); CompletableFuture> oneMonthFuture = CompletableFuture.supplyAsync(() -> buildOneMonthPeriod(symbol, cookie), executor); CompletableFuture> oneDayFuture = CompletableFuture.supplyAsync(() -> buildOneDayPeriod(symbol, cookie), executor); CompletableFuture> fiveDayFuture = CompletableFuture.supplyAsync(() -> buildFiveDayPeriod(symbol, cookie), executor); CompletableFuture> oneQuarterFuture = CompletableFuture.supplyAsync(() -> buildOneQuarterPeriod(symbol, cookie), executor); CompletableFuture> oneYearFuture = CompletableFuture.supplyAsync(() -> buildOneYearPeriod(symbol, cookie), executor); // 等待所有 CompletableFuture 完成 CompletableFuture.allOf(oneWeekFuture, oneMonthFuture, oneDayFuture, fiveDayFuture, oneQuarterFuture, oneYearFuture).join(); map.put(Kline.PERIOD_1WEEK, oneWeekFuture.get()); map.put(Kline.PERIOD_1MON, oneMonthFuture.get()); map.put(Kline.PERIOD_1DAY, oneDayFuture.get()); map.put(Kline.PERIOD_5DAY, fiveDayFuture.get()); map.put(Kline.PERIOD_QUARTER, oneQuarterFuture.get()); map.put(Kline.PERIOD_YEAR, oneYearFuture.get()); }catch (Exception e){ logger.info("初始化k线图报错:{}", symbol, e) ; } return map; } public List buildOneDayPeriod(String currency, String cookie) { return getTimeseriesByPeriod(currency, "day", Kline.PERIOD_1DAY, 365, cookie); } public List buildOneWeekPeriod(String currency, String cookie) { return getTimeseriesByPeriod(currency, "week", Kline.PERIOD_1WEEK, 365 * 5, cookie); } public List buildOneMonthPeriod(String currency, String cookie) { return getTimeseriesByPeriod(currency, "month", Kline.PERIOD_1MON, 365 * 5, cookie); } public List buildOneQuarterPeriod(String currency , String cookie) { return getTimeseriesByPeriod(currency, "quarter", Kline.PERIOD_QUARTER, 365 * 100, cookie); } public List buildOneYearPeriod(String currency , String cookie) { return getTimeseriesByPeriod(currency, "year", Kline.PERIOD_YEAR, 365 * 100, cookie); } /** * 雪球支持120分钟的,讲120分钟的, * Hourly * 4hourly 3月 */ @Retryable( value = {RuntimeException.class}, // 需要重试的异常类型 maxAttempts = 5, // 最大重试次数 backoff = @Backoff(delay = 2000) // 退避策略:每次重试之间的延迟 ) public List buildFiveDayPeriod(String currency, String cookie) { List result = Lists.newArrayList(); List timeseriesByOneDay = getTimeseriesByPeriod(currency, "day", Kline.PERIOD_1DAY, 1000 , cookie); Collections.sort(timeseriesByOneDay, Kline::compareTo); int lastIndex = timeseriesByOneDay.size() - 1; for (int i = lastIndex; i >= 5; i = i - 5) { // 1天K线最新的5条数据 List klineOneTop5 = new ArrayList<>(); klineOneTop5.add(timeseriesByOneDay.get(i)); klineOneTop5.add(timeseriesByOneDay.get(i - 1)); klineOneTop5.add(timeseriesByOneDay.get(i - 2)); klineOneTop5.add(timeseriesByOneDay.get(i - 3)); klineOneTop5.add(timeseriesByOneDay.get(i - 4)); Double high = null; Double low = null; for (Kline kline : klineOneTop5) { if (high == null || high <= kline.getHigh()) { high = kline.getHigh(); } if (low == null || low >= kline.getLow()) { low = kline.getLow(); } } // 保存K线到数据库 Kline kline = new Kline(); if(itemService != null){ kline.setSymbol(itemService.getSymbolByRemarks(currency)); }else{ kline.setSymbol(cookie); } kline.setTs(klineOneTop5.get(4).getTs()); kline.setOpen(klineOneTop5.get(4).getOpen()); kline.setHigh(high); kline.setLow(low); kline.setClose(klineOneTop5.get(0).getClose()); kline.setPeriod(Kline.PERIOD_5DAY); // 格式化小数点位 if(klineService != null){ klineService.formatPoint(kline); } double sumAmount = klineOneTop5.stream() .map(Kline::getAmount) .filter(amount -> amount != 0) .reduce(0D, Double::sum); double sumVolume = klineOneTop5.stream() .map(Kline::getVolume) .filter(volume -> volume != null) .reduce(0D, Double::sum); kline.setAmount(sumAmount); kline.setVolume(sumVolume); if(klineService != null){ klineService.repairKline(kline); } result.add(kline); } Collections.sort(result); return result; } /** * 雪球支持120分钟的,讲120分钟的, * Hourly * 4hourly 3月 */ @Retryable( value = {RuntimeException.class}, // 需要重试的异常类型 maxAttempts = 5, // 最大重试次数 backoff = @Backoff(delay = 2000) // 退避策略:每次重试之间的延迟 ) public List getTimeseriesForFourHourly(String currency, String cookie) { if(itemService != null){ currency = itemService.findBySymbol(currency).getRemarks(); } List result = Lists.newArrayList(); List timeseriesByMinute = getTimeseriesByMinute(currency, 120, 90, cookie); Collections.sort(timeseriesByMinute, Kline::compareTo); int lastIndex = timeseriesByMinute.size() - 1; for (int i = lastIndex; i >= 1; i = i - 2) { Kline first = timeseriesByMinute.get(i); Kline secnd = timeseriesByMinute.get(i - 1); Kline kline = new Kline(); kline.setPeriod(Kline.PERIOD_4HOUR); if(itemService != null){ kline.setSymbol(itemService.getSymbolByRemarks(currency)); }else{ kline.setSymbol(currency); } Long timestamp = first.getTs(); if (timestamp.toString().length() > 13) { timestamp = timestamp / 1000; } kline.setTs(timestamp); kline.setOpen(secnd.getOpen()); kline.setClose(first.getClose()); kline.setHigh(Math.max(first.getHigh(), secnd.getHigh())); kline.setLow(Math.min(first.getLow(), secnd.getLow())); kline.setAmount(first.getAmount() + secnd.getAmount()); kline.setVolume(first.getVolume() + secnd.getVolume()); if(klineService != null){ klineService.repairKline(kline); } result.add(kline); } Collections.sort(result); return result; } /** * Hourly * 1hourly 2个小时 */ public List getTimeseriesForTwoHourly(String currency, String cookie) { return getTimeseriesByMinute(currency, 120, 300, cookie); } /** * Hourly * 1hourly 1月 */ public List getTimeseriesForOneHourly(String currency, String cookie) { return getTimeseriesByMinute(currency, 60, 300, cookie); } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesOneMinute(String currency, String cookie) { return getTimeseriesByMinute(currency, 1, 15,cookie); } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesFiveMinute(String currency, String cookie) { return getTimeseriesByMinute(currency, 5, 15, cookie); } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesFifteenMinute(String currency, String cookie) { return getTimeseriesByMinute(currency, 15, 15, cookie); } /** * Minute * 30minute 15 * 15minute 15 * 5minute 15 * 1minute 15 */ public List getTimeseriesThirtyMinute(String currency, String cookie) { return getTimeseriesByMinute(currency, 30, 10, cookie); } @Retryable( value = {RuntimeException.class}, // 需要重试的异常类型 maxAttempts = 5, // 最大重试次数 backoff = @Backoff(delay = 2000) // 退避策略:每次重试之间的延迟 ) public List getTimeseriesByPeriod(String currency, String periodXieQiu, String sysPeriod, long limitDays, String cookie) { List resList = new ArrayList<>(); long nowTs = System.currentTimeMillis(); long startTs = System.currentTimeMillis() - limitDays * 24 * 60 * 60 * 1000; long begin = nowTs; if(cookie == null){ cookie = HttpHelper.getCookie("https://xueqiu.com/"); } if(itemService != null){ currency = itemService.findBySymbol(currency).getRemarks(); } Set tsSet = new HashSet<>(); while (begin > startTs) { String url = StrUtil.format(klineUrl, currency, begin, periodXieQiu); String json = HttpHelper.sendGetHttp(url, null, cookie); JSONObject resultJson = JSON.parseObject(json); JSONArray dataArray = resultJson.getJSONObject("data").getJSONArray("item"); List lists = dataArray.toJavaList(List.class); long minTS = begin; for (List result : lists) { Kline kline = new Kline(); if(itemService != null){ kline.setSymbol(itemService.getSymbolByRemarks(currency)); }else{ kline.setSymbol(sysPeriod); } kline.setPeriod(sysPeriod); // 毫秒 long ts = Long.parseLong(result.get(0).toString()); if (Long.toString(ts).length() > 13) { ts = ts / 1000; } if (tsSet.contains(ts)) { continue; } else { tsSet.add(ts); } kline.setTs(ts); kline.setOpen(new BigDecimal(result.get(2).toString()).doubleValue()); kline.setClose(new BigDecimal(result.get(5).toString()).doubleValue()); kline.setHigh(new BigDecimal(result.get(3).toString()).doubleValue()); kline.setLow(new BigDecimal(result.get(4).toString()).doubleValue()); kline.setVolume(new BigDecimal(result.get(1).toString()).doubleValue()); kline.setAmount(new BigDecimal(result.get(9).toString()).doubleValue()); if (klineService != null) { klineService.repairKline(kline); } resList.add(kline); if (ts < minTS) { minTS = ts; } } if (minTS == begin) { break; } begin = minTS; if (begin < startTs) { break; } } Collections.sort(resList); int len = resList.size(); for (int i = 1; i < len; i++) { resList.get(i).setOpen(resList.get(i - 1).getClose()); } return resList; } public List getTimeseriesByMinute(String currency, int minute, long limitDays, String cookie) { return getTimeseriesByPeriod(currency, minute + "m", minute + "min", limitDays, cookie ); } }