package com.yami.trading.huobi.hobi.internal; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.common.collect.Lists; import com.yami.trading.bean.data.domain.Kline; import com.yami.trading.bean.etf.domain.EtfMinuteKLine; import com.yami.trading.bean.item.domain.Item; 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.hobi.constant.AllticktradeMadeOptions; import com.yami.trading.huobi.hobi.constant.TraderMadeOptions; import com.yami.trading.huobi.hobi.http.HttpHelper; import com.yami.trading.service.etf.EtfMinuteKLineService; import com.yami.trading.service.item.ItemService; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.checkerframework.checker.units.qual.K; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.net.URLEncoder; import java.util.*; import java.util.stream.Collectors; @Service public class FakeKlineInitService { @Autowired private KlineService klineService; @Autowired private EtfMinuteKLineService etfMinuteKLineService; @Value("${alltick.trade-kline}") private String tradeKline; public final void saveInit(String symbol) { Item bySymbol = itemService.findBySymbol(symbol); // 非机器人的价格,无需初始化 if("0".equalsIgnoreCase(bySymbol.getFake())){ return; } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("symbol", symbol); queryWrapper.lt("ts", System.currentTimeMillis()); queryWrapper.orderByAsc("ts"); List list = etfMinuteKLineService.list(queryWrapper); List klineList = list.stream().map(e -> { Kline kline = BeanUtil.copyProperties(e, Kline.class); kline.setPeriod(Kline.PERIOD_1MIN); return kline; }).collect(Collectors.toList()); // Map> dailyWeekMonthHistoryMap = getDailyWeekMonthHistory(symbol, klineList); Map> hourlyAndMinuteHistoryMap = getHourlyAndMinuteHistory(symbol, klineList); klineService.saveInit(symbol, null, hourlyAndMinuteHistoryMap); } @Autowired private ItemService itemService; /** * 获取分钟数据 */ public Map> getHourlyAndMinuteHistory(String symbol , List klineList) { // Map> map = new HashMap<>(); // // List fourHourlyList = getTimeseriesForFourHourly(symbol, klineList); // map.put(KlineConstant.PERIOD_4HOUR, fourHourlyList); // // List twoHourlyList = getTimeseriesForTwoHourly(symbol, klineList); // map.put(KlineConstant.PERIOD_2HOUR, twoHourlyList); // // List oneHourlyList = getTimeseriesForOneHourly(symbol, klineList); // map.put(KlineConstant.PERIOD_60MIN, oneHourlyList); // // List thirtyMinuteList = getTimeseriesThirtyMinute(symbol, klineList); // map.put(KlineConstant.PERIOD_30MIN, thirtyMinuteList); // // List fifteenMinuteList = getTimeseriesFifteenMinute(symbol, klineList); // map.put(KlineConstant.PERIOD_15MIN, fifteenMinuteList); // // List fiveMinuteList = getTimeseriesFiveMinute(symbol, klineList); // map.put(KlineConstant.PERIOD_5MIN, fiveMinuteList); // // List oneMinuteList = klineList; // map.put(KlineConstant.PERIOD_1MIN, oneMinuteList); // return map; 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); return map; } public List getTimeseries(String symbol,String period,int periodType){ List resList = new ArrayList<>(); // 每次只能取一个月的数据,需要遍历3个月 for (int i = 0; i < TraderMadeOptions.thirtyMinutePeriod; i++) { String resultStr = null; try { resultStr = getTradeKline(symbol,periodType,AllticktradeMadeOptions.dayKlineNumPeriod); } catch (Exception e) { continue; } JSONObject resultJson = JSON.parseObject(resultStr); if(null == resultJson || 200 != resultJson.getInteger("ret")){ } 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.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) { System.out.println(e.getMessage()); } return null; } /** * 1day 历史数据 : 周期 1年 * 1week,1mon 历史数据 : 周期 5年 * 请求 350次 */ public Map> getDailyWeekMonthHistory(String symbol , List klineList) { Map> map = new HashMap<>(); map.put(Kline.PERIOD_1WEEK, buildOneWeekPeriod(symbol, klineList)); map.put(Kline.PERIOD_1MON, buildOneMonthPeriod(symbol, klineList)); map.put(Kline.PERIOD_1DAY, buildOneDayPeriod(symbol, klineList)); map.put(Kline.PERIOD_5DAY, buildFiveDayPeriod(symbol, klineList)); map.put(Kline.PERIOD_QUARTER, buildOneQuarterPeriod(symbol, klineList)); map.put(Kline.PERIOD_YEAR, buildOneYearPeriod(symbol, klineList)); return map; } public List buildOneDayPeriod(String currency, List klineList) { return getTimeseriesByMinute(currency, 390, Kline.PERIOD_1DAY , klineList); } public List buildOneWeekPeriod(String currency, List klineList) { return getTimeseriesByMinute(currency, 390*7, Kline.PERIOD_1WEEK , klineList); } public List buildOneMonthPeriod(String currency, List klineList) { return getTimeseriesByMinute(currency, 390*22, Kline.PERIOD_1MON , klineList); } public List buildOneQuarterPeriod(String currency, List klineList) { return getTimeseriesByMinute(currency, 390*66, Kline.PERIOD_QUARTER , klineList); } public List buildOneYearPeriod(String currency, List klineList) { return getTimeseriesByMinute(currency, 390*220, Kline.PERIOD_YEAR , klineList); } /** * 雪球支持120分钟的,讲120分钟的, * Hourly * 4hourly 3月 */ public List buildFiveDayPeriod(String currency, List klineList) { return getTimeseriesByMinute(currency, 390*5, Kline.PERIOD_5DAY , klineList); } /** * 雪球支持120分钟的,讲120分钟的, * Hourly * 4hourly 3月 */ public List getTimeseriesForFourHourly(String currency, List klineList) { return getTimeseriesByMinute(currency, 240, Kline.PERIOD_4HOUR , klineList); } /** * Hourly * 1hourly 2个小时 */ public List getTimeseriesForTwoHourly(String currency, List klineList) { return getTimeseriesByMinute(currency, 120, Kline.PERIOD_2HOUR , klineList); } /** * Hourly * 1hourly 1月 */ public List getTimeseriesForOneHourly(String currency, List klineList) { return getTimeseriesByMinute(currency, 60, Kline.PERIOD_60MIN, klineList); } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesOneMinute(String currency, List klineList) { return klineList; } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesFiveMinute(String currency, List klineList) { return getTimeseriesByMinute(currency, 5, Kline.PERIOD_5MIN, klineList); } /** * Minute * 30minute 10天 * 15minute 5天 * 5minute 2天 * 1minute 1天 */ public List getTimeseriesFifteenMinute(String currency, List klineList) { return getTimeseriesByMinute(currency, 15, Kline.PERIOD_15MIN, klineList); } /** * Minute * 30minute 15 * 15minute 15 * 5minute 15 * 1minute 15 */ public List getTimeseriesThirtyMinute(String currency, List klineList) { return getTimeseriesByMinute(currency, 30, Kline.PERIOD_30MIN, klineList); } /** * 按多少分钟进行partition聚合 * @param symbol * @param minute * @param klineList * @return */ public List getTimeseriesByMinute(String symbol, int minute, String period, List klineList) { int decimal = itemService.getDecimal(symbol); List result = new ArrayList<>(); // 抽象成minute分钟图,方便前端显示 List> partition = Lists.partition(klineList, minute); for (List list1Min : partition) { Double high = list1Min.get(0).getHigh().doubleValue(); Double low = list1Min.get(0).getLow().doubleValue(); for (Kline kline : list1Min) { if (high <= kline.getHigh().doubleValue()) { high = kline.getHigh().doubleValue(); } if (low >= kline.getLow().doubleValue()) { low = kline.getLow().doubleValue(); } } int lastIndex = list1Min.size() - 1; Kline kline = new Kline(); kline.setSymbol(symbol); kline.setTs(list1Min.get(lastIndex).getTs()); kline.setOpen(list1Min.get(0).getOpen().setScale(decimal, BigDecimal.ROUND_DOWN)); kline.setHigh(new BigDecimal(high).setScale(decimal, BigDecimal.ROUND_DOWN)); kline.setLow(new BigDecimal(low).setScale(decimal, BigDecimal.ROUND_DOWN)); kline.setClose(list1Min.get(lastIndex).getClose().setScale(decimal, BigDecimal.ROUND_DOWN)); kline.setPeriod(period); // 格式化小数点位 // klineOneTop.formatPoint(kline); BigDecimal sumAmount = klineList.stream() .map(Kline::getAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal sumVolume = klineList.stream() .map(Kline::getVolume) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); kline.setAmount(sumAmount); kline.setVolume(sumVolume); result.add(kline); } return result; } }