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.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.yami.trading.bean.data.domain.*; import com.yami.trading.bean.data.respDto.TradeTickResp; 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.AllticktradeResult; 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.AllticktradeMadeOptions; 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.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.URLEncoder; 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; @Value("${alltick.trade-kline}") private String tradeKline; /** * 接口调用间隔(毫秒) */ 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 >= 500) { 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); } @Override public List realtimeNewPrice(String symbols,List realtimes) { return xinLangDataService.realtimeNewPrice(symbols,realtimes); } /** * 1day 历史数据 : 周期 1年 * 1week,1mon 历史数据 : 周期 5年 * 请求 350次 */ public Map> getDailyWeekMonthHistory(String 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 < AllticktradeMadeOptions.dayKlineCountPeriod; i++) { String resultStr = null; try { resultStr = getTradeKline(symbol,AllticktradeMadeOptions.dayPeriod,AllticktradeMadeOptions.dayKlineNumPeriod); } catch (Exception e) { logger.error("采集外汇k线图失败:{} " , e); continue; } JSONObject resultJson = JSON.parseObject(resultStr); if(200 != resultJson.getInteger("ret")){ logger.error("采集外汇k线图失败,返回:{} ", resultStr); } JSONObject tempdata = resultJson.getJSONObject("data"); JSONArray dataArray = tempdata.getJSONArray("kline_list"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), AllticktradeResult.class); 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 monthList = getTimeseries(symbol,KlineConstant.PERIOD_1MON,AllticktradeMadeOptions.monthPeriod); map.put(KlineConstant.PERIOD_1MON, monthList); List weekList = getTimeseries(symbol,KlineConstant.PERIOD_1WEEK,AllticktradeMadeOptions.weekPeriod); map.put(KlineConstant.PERIOD_1WEEK, weekList); List dayList = getTimeseries(symbol,KlineConstant.PERIOD_1DAY,AllticktradeMadeOptions.dayPeriod); map.put(KlineConstant.PERIOD_1DAY, dayList); List towHourlyList = getTimeseries(symbol,KlineConstant.PERIOD_2HOUR,AllticktradeMadeOptions.towHourPeriod); map.put(KlineConstant.PERIOD_2HOUR, towHourlyList); List oneHourlyList = getTimeseries(symbol,KlineConstant.PERIOD_60MIN,AllticktradeMadeOptions.hourPeriod); map.put(KlineConstant.PERIOD_60MIN, oneHourlyList); List thirtyMinuteList = getTimeseries(symbol,KlineConstant.PERIOD_30MIN,AllticktradeMadeOptions.thirtyPeriod); map.put(KlineConstant.PERIOD_30MIN, thirtyMinuteList); List fifteenMinuteList = getTimeseries(symbol,KlineConstant.PERIOD_15MIN,AllticktradeMadeOptions.fifteenPeriod); map.put(KlineConstant.PERIOD_15MIN, fifteenMinuteList); List fiveMinuteList = getTimeseries(symbol,KlineConstant.PERIOD_5MIN,AllticktradeMadeOptions.fivePeriod); map.put(KlineConstant.PERIOD_5MIN, fiveMinuteList); List oneMinuteList = getTimeseries(symbol,KlineConstant.PERIOD_1MIN,AllticktradeMadeOptions.minutePeriod); map.put(KlineConstant.PERIOD_1MIN, oneMinuteList); //昨日收盘价 BigDecimal yesterdayLastPrice = realtimeSingleZdf(symbol); Item item = itemService.findBySymbol(symbol); item.setYesterdayLastPrice(yesterdayLastPrice); itemService.updateById(item); return map; } public BigDecimal realtimeSingleZdf(String symbol){ //计算24小时涨跌幅 BigDecimal yesterdayLastPrice = BigDecimal.ZERO; List dayklines = getTimeseries(symbol,KlineConstant.PERIOD_OTHER,AllticktradeMadeOptions.dayPeriod); int decimal = itemService.getDecimal(symbol); long minTimestamp = Long.MAX_VALUE; for (Kline kline : dayklines) { long currentTimestamp = kline.getTs(); if (currentTimestamp < minTimestamp) { minTimestamp = currentTimestamp; yesterdayLastPrice = kline.getClose().setScale(decimal, RoundingMode.HALF_UP); } } return yesterdayLastPrice; } @Override public List getTimeseries(String symbol,String period,int periodType){ List resList = new ArrayList<>(); int klineCount; if (KlineConstant.PERIOD_1MIN.equals(period)) { // klineCount = 1440; // 当天的1分钟K线 klineCount = 1000; } else if (KlineConstant.PERIOD_5MIN.equals(period)) { klineCount = 288; // 当天的5分钟K线 } else if (KlineConstant.PERIOD_15MIN.equals(period)) { klineCount = 192; // 2天的15分钟K线,15分钟间隔 } else if (KlineConstant.PERIOD_30MIN.equals(period)) { klineCount = 480; // 10天的30分钟K线 } else if (KlineConstant.PERIOD_60MIN.equals(period)) { klineCount = 720; // 1个月的60分钟K线 } else if (KlineConstant.PERIOD_2HOUR.equals(period)) { klineCount = 12; // 2个月的120分钟K线 } else if (KlineConstant.PERIOD_4HOUR.equals(period)) { klineCount = 540; // 3个月的4小时K线 } else if (KlineConstant.PERIOD_1DAY.equals(period)) { klineCount = 1 * 365; // 1年的日K线,1天 * 12个月 = 540 } else if (KlineConstant.PERIOD_1WEEK.equals(period)) { klineCount = 52 * 5; // 5年的1周K线 (1年52周,5年共260周) } else if (KlineConstant.PERIOD_1MON.equals(period)) { klineCount = 12 * 5; // 5年的1个月K线,12个月每年,乘以5年 = 60 }else if(KlineConstant.PERIOD_ONE.equals(period)){ klineCount = 1; }else{ klineCount = 2; } String resultStr = null; try { resultStr = getTradeKline(symbol, periodType, klineCount); } catch (Exception e) { logger.error("采集外汇k线图失败:{} ", e); } JSONObject resultJson = JSON.parseObject(resultStr); if (null == resultJson || 200 != resultJson.getInteger("ret")) { logger.error("采集外汇k线图失败,--"+period+"--返回:{} ", resultStr); } JSONObject tempdata = resultJson.getJSONObject("data"); JSONArray dataArray = tempdata.getJSONArray("kline_list"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), AllticktradeResult.class); for (AllticktradeResult result : list) { Kline kline = new Kline(); kline.setSymbol(symbol); kline.setPeriod(period); // 毫秒 kline.setTs(Long.valueOf(result.getTimestamp() + "000")); kline.setOpen(result.getOpen_price()); kline.setClose(result.getClose_price()); kline.setHigh(result.getHigh_price()); kline.setLow(result.getLow_price()); kline.setVolume(result.getTurnover()); kline.setAmount(result.getVolume()); resList.add(kline); } } try { Thread.sleep(1000); } catch (InterruptedException e) { logger.error("延时中断: {}", e); } return resList; } @Override public List realtime24HoruData(String symbols, List realtimes) { List strings = Arrays.asList(symbols.split(",")); for (int i = 0; i < strings.size(); i++) { List dayList = getTimeseries(strings.get(i), KlineConstant.PERIOD_ONE, AllticktradeMadeOptions.dayPeriod); if(dayList.size()>0){ Kline kline = dayList.get(0); for (Realtime realtime : realtimes){ if(realtime.getSymbol().equals(strings.get(i))){ int decimal = itemService.getDecimal(realtime.getSymbol()); realtime.setOpen(kline.getOpen().setScale(decimal, RoundingMode.HALF_UP)); realtime.setHigh(kline.getHigh().setScale(decimal, RoundingMode.HALF_UP)); realtime.setLow(kline.getLow().setScale(decimal, RoundingMode.HALF_UP)); realtime.setAmount(kline.getAmount().setScale(decimal, RoundingMode.HALF_UP)); realtime.setVolume(kline.getVolume().setScale(decimal, RoundingMode.HALF_UP)); } } } } return realtimes; } public List buildOneDayPeriod(List list, String currency) { List resList = new ArrayList<>(); for (AllticktradeResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_1DAY); kline.setTs(Long.parseLong(result.getTimestamp())); kline.setOpen(result.getOpen_price()); kline.setClose(result.getClose_price()); kline.setHigh(result.getHigh_price()); kline.setLow(result.getLow_price()); kline.setVolume(result.getVolume()); 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) { List resList = new ArrayList<>(); // 每次只能取一个月的数据,需要遍历3个月 for (int i = 0; i < TraderMadeOptions.fourHourlyPeriod; i++) { String resultStr = null; try { resultStr = getTradeKline(currency,AllticktradeMadeOptions.fourHourPeriod,AllticktradeMadeOptions.dayKlineNumPeriod); } catch (Exception e) { logger.error("采集外汇k线图失败:{} ", e); continue; } JSONObject resultJson = JSON.parseObject(resultStr); if(null == resultJson || 200 != resultJson.getInteger("ret")){ logger.error("采集外汇k线图失败,返回:{} ", resultStr); } JSONObject tempdata = resultJson.getJSONObject("data"); JSONArray dataArray = tempdata.getJSONArray("kline_list"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), AllticktradeResult.class); for (AllticktradeResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_4HOUR); // 毫秒 kline.setTs(Long.parseLong(result.getTimestamp())); kline.setOpen(result.getOpen_price()); kline.setClose(result.getClose_price()); kline.setHigh(result.getHigh_price()); kline.setLow(result.getLow_price()); kline.setVolume(result.getVolume()); resList.add(kline); } } } return resList; } /** * Hourly * 1hourly 1月 */ public List getTimeseriesForOneHourly(String currency) { List resList = new ArrayList<>(); String resultStr = null; try { resultStr = getTradeKline(currency,AllticktradeMadeOptions.hourPeriod,AllticktradeMadeOptions.dayKlineNumPeriod); } catch (Exception e) { logger.error("采集外汇k线图失败:{} ", e); } JSONObject resultJson = JSON.parseObject(resultStr); if(null == resultJson || 200 != resultJson.getInteger("ret")){ logger.error("采集外汇k线图失败,返回:{} ", resultStr); } JSONObject tempdata = resultJson.getJSONObject("data"); JSONArray dataArray = tempdata.getJSONArray("kline_list"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), AllticktradeResult.class); for (AllticktradeResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_60MIN); // 毫秒 kline.setTs(Long.parseLong(result.getTimestamp())); kline.setOpen(result.getOpen_price()); kline.setClose(result.getClose_price()); kline.setHigh(result.getHigh_price()); kline.setLow(result.getLow_price()); kline.setVolume(result.getVolume()); resList.add(kline); } } return resList; } @Override public List getTimeseriesForTwoHourly(String currency) { List resList = new ArrayList<>(); String resultStr = null; for (int i = 0; i < TraderMadeOptions.fifteenMinutePeriod; i++) { try { resultStr = getTradeKline(currency, AllticktradeMadeOptions.towHourPeriod, AllticktradeMadeOptions.dayKlineNumPeriod); } catch (Exception e) { logger.error("采集外汇k线图失败:{} ", e); } JSONObject resultJson = JSON.parseObject(resultStr); if (null == resultJson || 200 != resultJson.getInteger("ret")) { logger.error("采集外汇k线图失败,返回:{} ", resultStr); } JSONObject tempdata = resultJson.getJSONObject("data"); JSONArray dataArray = tempdata.getJSONArray("kline_list"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), AllticktradeResult.class); for (AllticktradeResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_2HOUR); // 毫秒 kline.setTs(Long.parseLong(result.getTimestamp())); kline.setOpen(result.getOpen_price()); kline.setClose(result.getClose_price()); kline.setHigh(result.getHigh_price()); kline.setLow(result.getLow_price()); kline.setVolume(result.getVolume()); resList.add(kline); } } } return resList; } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesOneMinute(String currency) { List resList = new ArrayList<>(); String resultStr = null; for (int i = 0; i < TraderMadeOptions.fifteenMinutePeriod; i++) { try { resultStr = getTradeKline(currency, AllticktradeMadeOptions.minutePeriod, AllticktradeMadeOptions.dayKlineNumPeriod); } catch (Exception e) { logger.error("采集外汇k线图失败:{} ", e); } JSONObject resultJson = JSON.parseObject(resultStr); if (null == resultJson || 200 != resultJson.getInteger("ret")) { logger.error("采集外汇k线图失败,返回:{} ", resultStr); } JSONObject tempdata = resultJson.getJSONObject("data"); JSONArray dataArray = tempdata.getJSONArray("kline_list"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), AllticktradeResult.class); for (AllticktradeResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_1MIN); // 毫秒 kline.setTs(Long.parseLong(result.getTimestamp())); kline.setOpen(result.getOpen_price()); kline.setClose(result.getClose_price()); kline.setHigh(result.getHigh_price()); kline.setLow(result.getLow_price()); kline.setVolume(result.getVolume()); resList.add(kline); } } } return resList; } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesFiveMinute(String currency) { List resList = new ArrayList<>(); String resultStr = null; for (int i = 0; i < TraderMadeOptions.fifteenMinutePeriod; i++) { try { resultStr = getTradeKline(currency, AllticktradeMadeOptions.fivePeriod, AllticktradeMadeOptions.dayKlineNumPeriod); } catch (Exception e) { logger.error("采集外汇k线图失败:{} ", e); } JSONObject resultJson = JSON.parseObject(resultStr); if (null == resultJson || 200 != resultJson.getInteger("ret")) { logger.error("采集外汇k线图失败,返回:{} ", resultStr); } JSONObject tempdata = resultJson.getJSONObject("data"); JSONArray dataArray = tempdata.getJSONArray("kline_list"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), AllticktradeResult.class); for (AllticktradeResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_5MIN); // 毫秒 kline.setTs(Long.parseLong(result.getTimestamp())); kline.setOpen(result.getOpen_price()); kline.setClose(result.getClose_price()); kline.setHigh(result.getHigh_price()); kline.setLow(result.getLow_price()); kline.setVolume(result.getVolume()); resList.add(kline); } } } return resList; } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesFifteenMinute(String currency) { List resList = new ArrayList<>(); String resultStr = null; for (int i = 0; i < TraderMadeOptions.fifteenMinutePeriod; i++) { try { resultStr = getTradeKline(currency, AllticktradeMadeOptions.fifteenPeriod, AllticktradeMadeOptions.dayKlineNumPeriod); } catch (Exception e) { logger.error("采集外汇k线图失败:{} ", e); } JSONObject resultJson = JSON.parseObject(resultStr); if (null == resultJson || 200 != resultJson.getInteger("ret")) { logger.error("采集外汇k线图失败,返回:{} ", resultStr); } JSONObject tempdata = resultJson.getJSONObject("data"); JSONArray dataArray = tempdata.getJSONArray("kline_list"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), AllticktradeResult.class); for (AllticktradeResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_15MIN); // 毫秒 kline.setTs(Long.parseLong(result.getTimestamp())); kline.setOpen(result.getOpen_price()); kline.setClose(result.getClose_price()); kline.setHigh(result.getHigh_price()); kline.setLow(result.getLow_price()); kline.setVolume(result.getVolume()); resList.add(kline); } } } return resList; } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesThirtyMinute(String currency) { List resList = new ArrayList<>(); String resultStr = null; for (int i = 0; i < TraderMadeOptions.thirtyMinutePeriod; i++) { try { resultStr = getTradeKline(currency,AllticktradeMadeOptions.thirtyPeriod,AllticktradeMadeOptions.dayKlineNumPeriod); } catch (Exception e) { logger.error("采集外汇k线图失败:{} ", e); } JSONObject resultJson = JSON.parseObject(resultStr); if(null == resultJson || 200 != resultJson.getInteger("ret")){ logger.error("采集外汇k线图失败,返回:{} ", resultStr); } JSONObject tempdata = resultJson.getJSONObject("data"); JSONArray dataArray = tempdata.getJSONArray("kline_list"); if (dataArray.size() > 0) { List list = JSONObject.parseArray(JSONObject.toJSONString(dataArray), AllticktradeResult.class); for (AllticktradeResult result : list) { Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(Kline.PERIOD_30MIN); // 毫秒 kline.setTs(Long.parseLong(result.getTimestamp())); kline.setOpen(result.getOpen_price()); kline.setClose(result.getClose_price()); kline.setHigh(result.getHigh_price()); kline.setLow(result.getLow_price()); kline.setVolume(result.getVolume()); resList.add(kline); } } } return resList; } public String getTradeKline(String symbol,int type,int num){ JSONObject json = new JSONObject(); json.put("trace", UUID.randomUUID().toString()); JSONObject data = new JSONObject(); data.put("code", symbol); data.put("kline_type", type); data.put("kline_timestamp_end", 0); data.put("query_kline_num", num); json.put("data", data); try { String url = tradeKline.replace("{1}", URLEncoder.encode(json.toString(), "UTF-8")); HttpGet request = new HttpGet(url); HttpResponse response = HttpHelper.getHttpclient().execute(request); return HttpHelper.responseProc(response); } catch (Exception e) { logger.error("采集外汇k线图失败:==={} ", symbol); } return null; } }