package com.yami.trading.huobi.hobi.internal; import cn.hutool.core.collection.CollectionUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.yami.trading.bean.data.domain.*; import com.yami.trading.bean.item.domain.Item; import com.yami.trading.common.util.Arith; import com.yami.trading.common.util.StringUtils; import com.yami.trading.common.util.ThreadUtils; import com.yami.trading.common.util.UTCDateUtils; import com.yami.trading.huobi.data.internal.KlineConstant; import com.yami.trading.huobi.data.internal.KlineService; import com.yami.trading.huobi.data.model.TimeseriesResult; import com.yami.trading.huobi.data.websocket.model.market.MarketDepthEvent; import com.yami.trading.huobi.data.websocket.model.market.MarketTrade; import com.yami.trading.huobi.data.websocket.model.market.MarketTradeEvent; import com.yami.trading.huobi.data.websocket.model.market.PriceLevel; import com.yami.trading.huobi.hobi.Config; import com.yami.trading.huobi.hobi.HobiDataService; import com.yami.trading.huobi.hobi.constant.TraderMadeOptions; import com.yami.trading.huobi.hobi.http.HttpHelper; import com.yami.trading.huobi.hobi.http.HttpMethodType; import com.yami.trading.service.item.ItemService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.*; @Component public class HobiDataServiceImpl implements HobiDataService { private static Logger logger = LoggerFactory.getLogger(HobiDataServiceImpl.class); @Autowired private XueQiuDataServiceImpl xueQiuDataService; @Autowired private XinLangDataServiceImpl xinLangDataService; @Autowired private ItemService itemService; @Autowired private KlineService klineService; /** * 接口调用间隔(毫秒) */ private int interval = 100; private int sleep = 100; /** * 最后一次访问接口时间 */ private volatile Date last_time = new Date(); private volatile boolean lock = false; public static void main(String[] args) { HobiDataServiceImpl huobi = new HobiDataServiceImpl(); Map> etcusd = huobi.getDailyWeekMonthHistory("ETCUSD"); System.out.println(etcusd); } // 针对虚拟货币的 @Override public List realtime(int maximum) { List list = new ArrayList(); boolean current_lock = false; if (lock || (new Date().getTime() - last_time.getTime()) < interval) { ThreadUtils.sleep(sleep); if (maximum >= 100) { return list; } else { return realtime(++maximum); } } else { try { current_lock = true; lock = true; Map param = new HashMap(); String result = HttpHelper.getJSONFromHttp(Config.url + Config.tickers, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String status = resultJson.getString("status"); if ("ok".equals(status)) { JSONArray dataArray = resultJson.getJSONArray("data"); Long ts = resultJson.getLongValue("ts"); for (int i = 0; i < dataArray.size(); i++) { JSONObject realtimeJson = dataArray.getJSONObject(i); Realtime realtime = new Realtime(); Item item = itemService.findBySymbol(realtimeJson.getString("symbol")); if (item == null) { continue; } realtime.setSymbol(item.getSymbol()); realtime.setName(item.getName()); realtime.setTs(ts); realtime.setOpen(realtimeJson.getBigDecimal("open")); realtime.setClose(realtimeJson.getBigDecimal("close")); realtime.setHigh(realtimeJson.getBigDecimal("high")); realtime.setLow(realtimeJson.getBigDecimal("low")); realtime.setAmount(realtimeJson.getBigDecimal("amount")); realtime.setVolume(realtimeJson.getBigDecimal("vol")); list.add(realtime); } } else { logger.error(" realtime()error, resultJson [ " + resultJson.toJSONString() + " ]"); } } catch (Exception e) { logger.error("error", e); } finally { if (current_lock) { lock = false; last_time = new Date(); } } } return list; } @Override public List kline(String symbol, String period, Integer num, int maximum) { List list = new ArrayList(); Item item = itemService.findBySymbol(symbol); if (item == null) { return list; } boolean current_lock = false; if (lock || (new Date().getTime() - last_time.getTime()) < interval) { ThreadUtils.sleep(sleep); if (maximum >= 100) { return list; } else { return this.kline(symbol, period, num, ++maximum); } } else { try { current_lock = true; lock = true; Map param = new HashMap(); param.put("symbol", symbol); param.put("period", period); if (num == null) { if (Kline.PERIOD_1MIN.equals(period)) { param.put("size", 1440); } if (Kline.PERIOD_5MIN.equals(period)) { param.put("size", 576); } if (Kline.PERIOD_15MIN.equals(period)) { param.put("size", 576); } if (Kline.PERIOD_30MIN.equals(period)) { param.put("size", 576); } if (Kline.PERIOD_60MIN.equals(period)) { param.put("size", 576); } if (Kline.PERIOD_4HOUR.equals(period)) { param.put("size", 576); } if (Kline.PERIOD_1DAY.equals(period)) { param.put("size", 500); } if (Kline.PERIOD_1MON.equals(period)) { param.put("size", 500); } if (Kline.PERIOD_1WEEK.equals(period)) { param.put("size", 500); } } else { param.put("size", num); } String result = HttpHelper.getJSONFromHttp(Config.url + Config.kline, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String status = resultJson.getString("status"); if ("ok".equals(status)) { JSONArray dataArray = resultJson.getJSONArray("data"); /** * 丢弃第一行数据 */ int start = 1; if (num != null && num == 1) start = 0; for (int i = start; i < dataArray.size(); i++) { JSONObject realtimeJson = dataArray.getJSONObject(i); Kline kline = new Kline(); kline.setSymbol(item.getSymbol()); kline.setPeriod(period); kline.setTs(Long.valueOf(realtimeJson.getString("id") + "000")); kline.setOpen(realtimeJson.getBigDecimal("open")); kline.setClose(realtimeJson.getBigDecimal("close")); kline.setHigh(realtimeJson.getBigDecimal("high")); kline.setLow(realtimeJson.getBigDecimal("low")); kline.setVolume(realtimeJson.getBigDecimal("vol")); list.add(kline); } } } catch (Exception e) { logger.error("error", e); } finally { if (current_lock) { lock = false; last_time = new Date(); } } } return list; } /** * 市场深度数据(20档),包装,数据本地化处理 */ public Depth depthDecorator(String symbol, int maximum) { Depth depth = this.depth(symbol, maximum); Item item = itemService.findBySymbol(symbol); if ((depth == null || item.getAdjustmentValue() == null || item.getAdjustmentValue().intValue() == 0) && (item.getMultiple().intValue() == 0 || item.getMultiple().intValue() == 1)) { return depth; } if(CollectionUtil.isNotEmpty(depth.getAsks()) ){ List asks = depth.getAsks(); for (int i = 0; i < asks.size(); i++) { DepthEntry depthEntry = asks.get(i); /** * 调整交易量倍数和 行情值 */ if (item.getMultiple().doubleValue() > 0) { depthEntry.setAmount(Arith.mul(depthEntry.getAmount(), item.getMultiple().doubleValue())); } else { depthEntry.setAmount(depthEntry.getAmount()); } depthEntry.setPrice(Arith.add(depthEntry.getPrice(), item.getAdjustmentValue().doubleValue())); } } if(CollectionUtil.isNotEmpty(depth.getBids())){ List bids = depth.getBids(); for (int i = 0; i < bids.size(); i++) { DepthEntry depthEntry = bids.get(i); /** * 调整交易量倍数和 行情值 */ if (item.getMultiple().doubleValue() > 0) { depthEntry.setAmount(Arith.mul(depthEntry.getAmount(), item.getMultiple().doubleValue())); } else { depthEntry.setAmount(depthEntry.getAmount()); } depthEntry.setPrice(Arith.add(depthEntry.getPrice(), item.getAdjustmentValue().doubleValue())); } } return depth; } /** * 市场深度数据(20档),包装,数据本地化处理 */ public Depth depthDecorator(MarketDepthEvent event, Item item) { Depth depth = new Depth(); depth.setSymbol(item.getSymbol()); depth.setTs(event.getTs()); double multiple = item.getMultiple().doubleValue() == 0 ? 1 : item.getMultiple().doubleValue(); double adjustmentValue = item.getAdjustmentValue() == null ? 0 : item.getMultiple().doubleValue(); for (PriceLevel priceLevel : event.getDepth().getAsks()) { DepthEntry depthEntry = new DepthEntry(); depthEntry.setPrice(Arith.add(depthEntry.getPrice(), adjustmentValue)); depthEntry.setAmount(Arith.mul(priceLevel.getAmount().doubleValue(), multiple)); depth.getAsks().add(depthEntry); } for (PriceLevel priceLevel : event.getDepth().getBids()) { DepthEntry depthEntry = new DepthEntry(); depthEntry.setPrice(Arith.add(depthEntry.getPrice(), adjustmentValue)); depthEntry.setAmount(Arith.mul(priceLevel.getAmount().doubleValue(), multiple)); depth.getBids().add(depthEntry); } return depth; } @Override public Depth depth(String symbol, int maximum) { boolean current_lock = false; if (StringUtils.isNullOrEmpty(symbol)) { return null; } if (lock || (new Date().getTime() - last_time.getTime()) < interval) { ThreadUtils.sleep(sleep); if (maximum >= 100) { return null; } else { return this.depth(symbol, ++maximum); } } else { try { current_lock = true; lock = true; Map param = new HashMap(); param.put("symbol", symbol); param.put("type", "step2"); String result = HttpHelper.getJSONFromHttp(Config.url + Config.depth, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String status = resultJson.getString("status"); if ("ok".equals(status)) { JSONObject dataJson = resultJson.getJSONObject("tick"); Long ts = resultJson.getLongValue("ts"); Depth depth = new Depth(); Item item = itemService.findBySymbol(symbol); if (item == null) { return null; } depth.setSymbol(item.getSymbol()); depth.setTs(ts); JSONArray bidsArray = dataJson.getJSONArray("bids"); for (int i = 0; i < bidsArray.size(); i++) { JSONArray object = (JSONArray) bidsArray.get(i); DepthEntry depthEntry = new DepthEntry(); depthEntry.setPrice(object.getDouble(0)); depthEntry.setAmount(object.getDouble(1)); depth.getBids().add(depthEntry); } JSONArray asksArray = dataJson.getJSONArray("asks"); for (int i = 0; i < asksArray.size(); i++) { JSONArray object = (JSONArray) asksArray.get(i); DepthEntry depthEntry = new DepthEntry(); depthEntry.setPrice(object.getDouble(0)); depthEntry.setAmount(object.getDouble(1)); depth.getAsks().add(depthEntry); } return depth; } } catch (Exception e) { logger.error("error", e); } finally { if (current_lock) { lock = false; last_time = new Date(); } } } return null; } /** * 获得近期交易记录,包装,数据本地化处理 */ public Trade tradeDecorator(String symbol, int maximum) { Trade trade = this.trade(symbol, maximum); Item item = itemService.findBySymbol(symbol); if ((trade == null || item.getAdjustmentValue() == null || item.getAdjustmentValue().doubleValue() == 0) && (item.getMultiple().doubleValue() == 0 || item.getMultiple().doubleValue() == 1)) { return trade; } if(CollectionUtil.isNotEmpty(trade.getData())){ List data = trade.getData(); for (int i = 0; i < data.size(); i++) { TradeEntry tradeEntry = data.get(i); /** * 调整交易量倍数和 行情值 */ if (item.getMultiple().doubleValue() > 0) { tradeEntry.setAmount(Arith.mul(tradeEntry.getAmount(), item.getMultiple().doubleValue())); } else { tradeEntry.setAmount(tradeEntry.getAmount()); } tradeEntry.setPrice(Arith.add(tradeEntry.getPrice(), item.getAdjustmentValue().doubleValue())); } } return trade; } /** * 获得近期交易记录,包装,数据本地化处理 */ public Trade tradeDecorator(MarketTradeEvent event, Item item) { Trade trade = new Trade(); trade.setSymbol(item.getSymbol()); trade.setTs(event.getTs()); double multiple = item.getMultiple().doubleValue() == 0 ? 1 : item.getMultiple().doubleValue(); double adjustmentValue = item.getAdjustmentValue() == null ? 0 : item.getMultiple().doubleValue(); for (MarketTrade value : event.getList()) { TradeEntry entry = new TradeEntry(); entry.setAmount(Arith.mul(value.getAmount().doubleValue(), multiple)); entry.setPrice(Arith.add(value.getPrice().doubleValue(), adjustmentValue)); entry.setTs(value.getTs()); entry.setPrice(value.getPrice().doubleValue()); entry.setAmount(value.getAmount().doubleValue()); entry.setDirection(value.getDirection()); trade.getData().add(entry); } return trade; } @Override public Trade trade(String symbol, int maximum) { boolean current_lock = false; if (StringUtils.isNullOrEmpty(symbol)) { return null; } if (lock || (new Date().getTime() - last_time.getTime()) < interval) { ThreadUtils.sleep(sleep); if (maximum >= 100) { return null; } else { return this.trade(symbol, ++maximum); } } else { try { current_lock = true; lock = true; Map param = new HashMap(); param.put("symbol", symbol); String result = HttpHelper.getJSONFromHttp(Config.url + Config.trade, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String status = resultJson.getString("status"); if ("ok".equals(status)) { JSONObject dataJson = resultJson.getJSONObject("tick"); Long ts = resultJson.getLongValue("ts"); Trade trade = new Trade(); Item item = itemService.findBySymbol(symbol); if (item == null) { return null; } trade.setSymbol(item.getSymbol()); trade.setTs(ts); JSONArray dataArray = dataJson.getJSONArray("data"); for (int i = 0; i < dataArray.size(); i++) { JSONObject object = dataArray.getJSONObject(i); TradeEntry tradeEntry = new TradeEntry(); tradeEntry.setTs(object.getLong("ts")); tradeEntry.setPrice(object.getDouble("price")); tradeEntry.setAmount(object.getDouble("amount")); tradeEntry.setDirection(object.getString("direction")); trade.getData().add(tradeEntry); } return trade; } } catch (Exception e) { logger.error("error", e); } finally { if (current_lock) { lock = false; last_time = new Date(); } } } return null; } @Override public List symbols() { List list = new ArrayList(); boolean current_lock = false; if (lock || (new Date().getTime() - last_time.getTime()) < interval) { return list; } else { try { current_lock = true; lock = true; Map param = new HashMap(); String result = HttpHelper.getJSONFromHttp(Config.url + Config.symbols, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(result); String status = resultJson.getString("status"); if ("ok".equals(status)) { JSONArray dataArray = resultJson.getJSONArray("data"); for (int i = 0; i < dataArray.size(); i++) { JSONObject realtimeJson = dataArray.getJSONObject(i); Symbols symbols = new Symbols(); symbols.setBaseCurrency(realtimeJson.getString("base-currency")); symbols.setQuoteCurrency(realtimeJson.getString("quote-currency")); symbols.setLeverageRatio(realtimeJson.getBigDecimal("leverage-ratio")); symbols.setPricePrecision(realtimeJson.getIntValue("price-precision")); symbols.setState(realtimeJson.getString("state")); symbols.setSymbol(realtimeJson.getString("symbol")); list.add(symbols); } } else { logger.error(" symbols()error, resultJson [ " + resultJson.toJSONString() + " ]"); } } catch (Exception e) { logger.error("error", e); } finally { if (current_lock) { lock = false; last_time = new Date(); } } } return list; } public void setItemService(ItemService itemService) { this.itemService = itemService; } public boolean isXueQiu(String symbol) { String type = itemService.findBySymbol(symbol).getType(); return type.contains("stock") || (type.equalsIgnoreCase(Item.indices)); } public boolean isXinlang(String symbol) { if("XAUUSD,XAGUSD,OIL".contains(symbol)){ return false; } Item bySymbol = itemService.findBySymbol(symbol); String type = bySymbol.getType(); return Item.forex.contains(type) && Item.forex.equals(bySymbol.getCategory()); } public List realtimeSingle(String symbol) { if (isXueQiu(symbol)) { return xueQiuDataService.realtimeSingle(symbol); } if (isXinlang(symbol)) { return xinLangDataService.realtimeSingle(symbol); } List list = new ArrayList(); try { Map param = new HashMap<>(); param.put("currency", symbol); String result = HttpHelper.getJSONFromHttpNew(TraderMadeOptions.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(); String currency = symbol; currency = realtimeJson.getString("currency"); int decimal = itemService.getDecimal(currency); realtime.setSymbol(currency); realtime.setName(currency); realtime.setTs(realtimeJson.getLong("timestamp")); realtime.setOpen(realtimeJson.getBigDecimal("open").setScale(decimal, RoundingMode.HALF_UP)); realtime.setClose(realtimeJson.getBigDecimal("mid").setScale(decimal, RoundingMode.HALF_UP)); realtime.setHigh(realtimeJson.getBigDecimal("high").setScale(decimal, RoundingMode.HALF_UP)); realtime.setLow(realtimeJson.getBigDecimal("low").setScale(decimal, RoundingMode.HALF_UP)); realtime.setAmount(BigDecimal.ZERO); realtime.setVolume(BigDecimal.ZERO); realtime.setAsk(realtimeJson.getBigDecimal("ask").setScale(decimal, RoundingMode.HALF_UP)); realtime.setBid(realtimeJson.getBigDecimal("bid").setScale(decimal, RoundingMode.HALF_UP)); list.add(realtime); } } else { logger.error(" realtime()error, resultJson [ " + resultJson.toJSONString() + " ]"); } } catch (Exception e) { logger.error("error", e); } return list; } public List realtime(String symbols) { List realtimeList = Collections.synchronizedList(new ArrayList()); Splitter.on(",").omitEmptyStrings().splitToList(symbols).parallelStream().map(this::realtimeSingle).forEach(realtimeList::addAll); return realtimeList; } @Override public List realtimeXueQiu(String symbols) { return xueQiuDataService.realtimeSingle(symbols); } @Override public List realtimeXinLang(String symbols) { return xinLangDataService.realtimeSingle(symbols); } /** * 1day 历史数据 : 周期 1年 * 1week,1mon 历史数据 : 周期 5年 * 请求 350次 */ public Map> getDailyWeekMonthHistory(String symbol) { if (isXueQiu(symbol)) { return xueQiuDataService.getDailyWeekMonthHistory(symbol); }else if(isXinlang(symbol)){ return xinLangDataService.getDailyWeekMonthHistory(symbol); } Map> map = new HashMap<>(); SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); f.setTimeZone(TimeZone.getTimeZone(UTCDateUtils.GMT_TIME_ZONE)); Date now = new Date(); // 每次只能取一年的数据,需要遍历5年 for (int i = 0; i < TraderMadeOptions.weekAndMonthPeriod; i++) { String startDate = UTCDateUtils.addYear(now, -1); String endDate = f.format(now); now = UTCDateUtils.toDate(startDate, "yyyy-MM-dd"); Map param = new HashMap<>(); param.put("currency", symbol); param.put("start_date", startDate); param.put("end_date", endDate); param.put("format", "records"); param.put("api_key", TraderMadeOptions.apiKey); String json = null; try { json = HttpHelper.getJSONFromHttpNew(TraderMadeOptions.timeseries, param, HttpMethodType.GET); } catch (Exception e) { logger.error("采集外汇k线图失败:{} ", param); continue; } JSONObject resultJson = JSON.parseObject(json); JSONArray dataArray = resultJson.getJSONArray("quotes"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), TimeseriesResult.class); Map> monthMap = new LinkedHashMap<>(); Map> weekMap = new LinkedHashMap<>(); for (TimeseriesResult result : list) { String month = result.getDate().substring(0, 7); if (monthMap.containsKey(month)) { monthMap.get(month).add(result); } else { List monthList = new ArrayList<>(); monthList.add(result); monthMap.put(month, monthList); } String firstDateOfWeek = UTCDateUtils.getFirstDateOfWeek(UTCDateUtils.toDate(result.getDate(), "yyyy-MM-dd")); if (weekMap.containsKey(firstDateOfWeek)) { weekMap.get(firstDateOfWeek).add(result); } else { List weekList = new ArrayList<>(); weekList.add(result); weekMap.put(firstDateOfWeek, weekList); } } map.put(Kline.PERIOD_1WEEK, buildOneWeekPeriod(weekMap, symbol)); map.put(Kline.PERIOD_1MON, buildOneMonthPeriod(monthMap, symbol)); // 1day历史数据 : 周期 1年 if (0 == i) { map.put(Kline.PERIOD_1DAY, buildOneDayPeriod(list, symbol)); } } } try { List dayList = map.get(Kline.PERIOD_1DAY); if (CollectionUtil.isNotEmpty(dayList)) { map.put(Kline.PERIOD_5DAY, klineService.calculateKline(symbol, 5, Kline.PERIOD_5DAY, dayList)); } List montList = map.get(Kline.PERIOD_1MON); if (CollectionUtil.isNotEmpty(montList)) { map.put(Kline.PERIOD_QUARTER, klineService.calculateKline(symbol, 3, Kline.PERIOD_1MON, montList)); } } catch (Exception e) { logger.error("外汇计算 5日和季度k线图失败", e); } return map; } /** * 获取分钟数据 */ public Map> getHourlyAndMinuteHistory(String symbol) { Map> map = new HashMap<>(); List fourHourlyList = getTimeseriesForFourHourly(symbol); map.put(KlineConstant.PERIOD_4HOUR, fourHourlyList); List oneHourlyList = getTimeseriesForOneHourly(symbol); map.put(KlineConstant.PERIOD_60MIN, oneHourlyList); List twoHourlyList = getTimeseriesForTwoHourly(symbol); if (CollectionUtil.isEmpty(twoHourlyList)) { try { List hourList = map.get(Kline.PERIOD_60MIN); if (CollectionUtil.isNotEmpty(hourList)) { 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); } List thirtyMinuteList = getTimeseriesThirtyMinute(symbol); map.put(KlineConstant.PERIOD_30MIN, thirtyMinuteList); List fifteenMinuteList = getTimeseriesFifteenMinute(symbol); map.put(KlineConstant.PERIOD_15MIN, fifteenMinuteList); List fiveMinuteList = getTimeseriesFiveMinute(symbol); map.put(KlineConstant.PERIOD_5MIN, fiveMinuteList); List oneMinuteList = getTimeseriesOneMinute(symbol); map.put(KlineConstant.PERIOD_1MIN, oneMinuteList); return map; } public List buildOneDayPeriod(List list, String currency) { if (isXueQiu(currency)) { return xueQiuDataService.buildOneDayPeriod(currency); }if (isXinlang(currency)) { return xinLangDataService.buildOneDayPeriod(currency); } List resList = new ArrayList<>(); for (TimeseriesResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_1DAY); kline.setTs(UTCDateUtils.toDate(result.getDate(), "yyyy-MM-dd").getTime()); kline.setOpen(result.getOpen()); kline.setClose(result.getClose()); kline.setHigh(result.getHigh()); kline.setLow(result.getLow()); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } return resList; } public List buildOneWeekPeriod(Map> weekMap, String currency) { if (isXueQiu(currency)) { return xueQiuDataService.buildOneWeekPeriod(currency); } List resList = new ArrayList<>(); for (List list : weekMap.values()) { BigDecimal high = list.stream().map(TimeseriesResult::getHigh).filter(Objects::nonNull).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO); BigDecimal low = list.stream().map(TimeseriesResult::getLow).filter(Objects::nonNull).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO); Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_1WEEK); // 毫秒 kline.setTs(UTCDateUtils.toDate(list.get(list.size() - 1).getDate()).getTime()); kline.setOpen(list.get(0).getOpen()); kline.setClose(list.get(list.size() - 1).getClose()); kline.setHigh(high); kline.setLow(low); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } return resList; } public List buildOneMonthPeriod(Map> monthMap, String currency) { if (isXueQiu(currency)) { return xueQiuDataService.buildOneMonthPeriod(currency); } List resList = new ArrayList<>(); for (List list : monthMap.values()) { BigDecimal high = list.stream().map(TimeseriesResult::getHigh).filter(Objects::nonNull).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO); BigDecimal low = list.stream().map(TimeseriesResult::getLow).filter(Objects::nonNull).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO); Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_1MON); // 毫秒 kline.setTs(UTCDateUtils.toDate(list.get(list.size() - 1).getDate()).getTime()); kline.setOpen(list.get(0).getOpen()); kline.setClose(list.get(list.size() - 1).getClose()); kline.setHigh(high); kline.setLow(low); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } return resList; } public List buildQuarterPeriod(Map> quarterMap, String currency) { if (isXueQiu(currency)) { return xueQiuDataService.buildOneMonthPeriod(currency); } List resList = new ArrayList<>(); for (List list : quarterMap.values()) { BigDecimal high = list.stream().map(TimeseriesResult::getHigh).filter(Objects::nonNull).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO); BigDecimal low = list.stream().map(TimeseriesResult::getLow).filter(Objects::nonNull).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO); Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_QUARTER); // 毫秒 kline.setTs(UTCDateUtils.toDate(list.get(list.size() - 1).getDate()).getTime()); kline.setOpen(list.get(0).getOpen()); kline.setClose(list.get(list.size() - 1).getClose()); kline.setHigh(high); kline.setLow(low); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } return resList; } public List buildYearPeriod(Map> yearMap, String currency) { if (isXueQiu(currency)) { return xueQiuDataService.buildOneMonthPeriod(currency); } List resList = new ArrayList<>(); for (List list : yearMap.values()) { BigDecimal high = list.stream().map(TimeseriesResult::getHigh).filter(Objects::nonNull).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO); BigDecimal low = list.stream().map(TimeseriesResult::getLow).filter(Objects::nonNull).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO); Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_YEAR); // 毫秒 kline.setTs(UTCDateUtils.toDate(list.get(list.size() - 1).getDate()).getTime()); kline.setOpen(list.get(0).getOpen()); kline.setClose(list.get(list.size() - 1).getClose()); kline.setHigh(high); kline.setLow(low); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } return resList; } /** * Hourly * 4hourly 3月 */ public List getTimeseriesForFourHourly(String currency) { if (isXueQiu(currency)) { return xueQiuDataService.getTimeseriesForFourHourly(currency); } else if (isXinlang(currency)) { return xinLangDataService.getTimeseriesForFourHourly(currency); } List resList = new ArrayList<>(); // 每次只能取一个月的数据,需要遍历3个月 SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd-HH:mm"); f.setTimeZone(TimeZone.getTimeZone(UTCDateUtils.GMT_TIME_ZONE)); // Date now = UTCDateUtils.toDate(UTCDateUtils.addHour(new Date(), -4), "yyyy-MM-dd-HH:mm"); Date now = new Date(); for (int i = 0; i < TraderMadeOptions.fourHourlyPeriod; i++) { String startDate = UTCDateUtils.addDay(now, -30); String endDate = f.format(now); now = UTCDateUtils.toDate(startDate, "yyyy-MM-dd-HH:mm"); Map param = new HashMap<>(); param.put("currency", currency); param.put("start_date", startDate); param.put("end_date", endDate); param.put("interval", "hourly"); param.put("period", "4"); param.put("format", "records"); param.put("api_key", TraderMadeOptions.apiKey); String json = HttpHelper.getJSONFromHttpNew(TraderMadeOptions.timeseries, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(json); JSONArray dataArray = resultJson.getJSONArray("quotes"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), TimeseriesResult.class); for (TimeseriesResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_4HOUR); // 毫秒 kline.setTs(UTCDateUtils.toDate(result.getDate(), "yyyy-MM-dd HH:mm").getTime()); kline.setOpen(result.getOpen()); kline.setClose(result.getClose()); kline.setHigh(result.getHigh()); kline.setLow(result.getLow()); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } } } return resList; } /** * Hourly * 1hourly 1月 */ public List getTimeseriesForOneHourly(String currency) { if (isXueQiu(currency)) { return xueQiuDataService.getTimeseriesForOneHourly(currency); } if (isXinlang(currency)) { return xinLangDataService.getTimeseriesForOneHourly(currency); } List resList = new ArrayList<>(); SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd-HH:mm"); f.setTimeZone(TimeZone.getTimeZone(UTCDateUtils.GMT_TIME_ZONE)); // Date now = UTCDateUtils.toDate(UTCDateUtils.addHour(new Date(), -1), "yyyy-MM-dd-HH:mm"); Date now = new Date(); String startDate = UTCDateUtils.addDay(now, -30); String endDate = f.format(now); Map param = new HashMap<>(); param.put("currency", currency); param.put("start_date", startDate); param.put("end_date", endDate); param.put("interval", "hourly"); param.put("period", "1"); param.put("format", "records"); param.put("api_key", TraderMadeOptions.apiKey); String json = HttpHelper.getJSONFromHttpNew(TraderMadeOptions.timeseries, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(json); JSONArray dataArray = resultJson.getJSONArray("quotes"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), TimeseriesResult.class); for (TimeseriesResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_60MIN); // 毫秒 kline.setTs(UTCDateUtils.toDate(result.getDate(), "yyyy-MM-dd HH:mm").getTime()); kline.setOpen(result.getOpen()); kline.setClose(result.getClose()); kline.setHigh(result.getHigh()); kline.setLow(result.getLow()); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } } return resList; } @Override public List getTimeseriesForTwoHourly(String currency) { if (isXueQiu(currency)) { return xueQiuDataService.getTimeseriesForTwoHourly(currency); } if (isXinlang(currency)) { return xinLangDataService.getTimeseriesForTwoHourly(currency); } return Lists.newArrayList(); } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesOneMinute(String currency) { if (isXueQiu(currency)) { return xueQiuDataService.getTimeseriesOneMinute(currency); } if (isXinlang(currency)) { return xinLangDataService.getTimeseriesOneMinute(currency); } List resList = new ArrayList<>(); SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd-HH:mm"); f.setTimeZone(TimeZone.getTimeZone(UTCDateUtils.GMT_TIME_ZONE)); Date now = new Date(); String startDate = UTCDateUtils.addDay(now, -1); String endDate = f.format(now); Map param = new HashMap<>(); param.put("currency", currency); param.put("start_date", startDate); param.put("end_date", endDate); param.put("interval", "minute"); param.put("period", "1"); param.put("format", "records"); param.put("api_key", TraderMadeOptions.apiKey); String json = HttpHelper.getJSONFromHttpNew(TraderMadeOptions.timeseries, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(json); JSONArray dataArray = resultJson.getJSONArray("quotes"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), TimeseriesResult.class); for (TimeseriesResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_1MIN); // 毫秒 kline.setTs(UTCDateUtils.toDate(result.getDate(), "yyyy-MM-dd HH:mm").getTime()); kline.setOpen(result.getOpen()); kline.setClose(result.getClose()); kline.setHigh(result.getHigh()); kline.setLow(result.getLow()); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } } return resList; } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesFiveMinute(String currency) { if (isXueQiu(currency)) { return xueQiuDataService.getTimeseriesFiveMinute(currency); } if (isXinlang(currency)) { return xinLangDataService.getTimeseriesFiveMinute(currency); } List resList = new ArrayList<>(); SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd-HH:mm"); f.setTimeZone(TimeZone.getTimeZone(UTCDateUtils.GMT_TIME_ZONE)); Date now = new Date(); String startDate = UTCDateUtils.addDay(now, -2); String endDate = f.format(now); Map param = new HashMap<>(); param.put("currency", currency); param.put("start_date", startDate); param.put("end_date", endDate); param.put("interval", "minute"); param.put("period", "5"); param.put("format", "records"); param.put("api_key", TraderMadeOptions.apiKey); String json = HttpHelper.getJSONFromHttpNew(TraderMadeOptions.timeseries, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(json); JSONArray dataArray = resultJson.getJSONArray("quotes"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), TimeseriesResult.class); for (TimeseriesResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_5MIN); // 毫秒 kline.setTs(UTCDateUtils.toDate(result.getDate(), "yyyy-MM-dd HH:mm").getTime()); kline.setOpen(result.getOpen()); kline.setClose(result.getClose()); kline.setHigh(result.getHigh()); kline.setLow(result.getLow()); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } } return resList; } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesFifteenMinute(String currency) { if (isXueQiu(currency)) { return xueQiuDataService.getTimeseriesFifteenMinute(currency); } if (isXinlang(currency)) { return xinLangDataService.getTimeseriesFifteenMinute(currency); } List resList = new ArrayList<>(); SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd-HH:mm"); f.setTimeZone(TimeZone.getTimeZone(UTCDateUtils.GMT_TIME_ZONE)); Date now = new Date(); for (int i = 0; i < TraderMadeOptions.fifteenMinutePeriod; i++) { String startDate = UTCDateUtils.addDay(now, -2); String endDate = f.format(now); now = UTCDateUtils.toDate(startDate, "yyyy-MM-dd-HH:mm"); Map param = new HashMap<>(); param.put("currency", currency); param.put("start_date", startDate); param.put("end_date", endDate); param.put("interval", "minute"); param.put("period", "15"); param.put("format", "records"); param.put("api_key", TraderMadeOptions.apiKey); String json = HttpHelper.getJSONFromHttpNew(TraderMadeOptions.timeseries, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(json); JSONArray dataArray = resultJson.getJSONArray("quotes"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), TimeseriesResult.class); for (TimeseriesResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_15MIN); // 毫秒 kline.setTs(UTCDateUtils.toDate(result.getDate(), "yyyy-MM-dd HH:mm").getTime()); kline.setOpen(result.getOpen()); kline.setClose(result.getClose()); kline.setHigh(result.getHigh()); kline.setLow(result.getLow()); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } } } return resList; } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesThirtyMinute(String currency) { if (isXueQiu(currency)) { return xueQiuDataService.getTimeseriesThirtyMinute(currency); } if (isXinlang(currency)) { return xinLangDataService.getTimeseriesThirtyMinute(currency); } List resList = new ArrayList<>(); SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd-HH:mm"); f.setTimeZone(TimeZone.getTimeZone(UTCDateUtils.GMT_TIME_ZONE)); Date now = new Date(); for (int i = 0; i < TraderMadeOptions.thirtyMinutePeriod; i++) { String startDate = UTCDateUtils.addDay(now, -2); String endDate = f.format(now); now = UTCDateUtils.toDate(startDate, "yyyy-MM-dd-HH:mm"); Map param = new HashMap<>(); param.put("currency", currency); param.put("start_date", startDate); param.put("end_date", endDate); param.put("interval", "minute"); param.put("period", "15"); param.put("format", "records"); param.put("api_key", TraderMadeOptions.apiKey); String json = HttpHelper.getJSONFromHttpNew(TraderMadeOptions.timeseries, param, HttpMethodType.GET); JSONObject resultJson = JSON.parseObject(json); JSONArray dataArray = resultJson.getJSONArray("quotes"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), TimeseriesResult.class); for (TimeseriesResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_30MIN); // 毫秒 kline.setTs(UTCDateUtils.toDate(result.getDate(), "yyyy-MM-dd HH:mm").getTime()); kline.setOpen(result.getOpen()); kline.setClose(result.getClose()); kline.setHigh(result.getHigh()); kline.setLow(result.getLow()); kline.setVolume(BigDecimal.ZERO); resList.add(kline); } } } return resList; } }