package com.yami.trading.huobi.hobi.internal;
|
|
|
import cn.hutool.http.HttpRequest;
|
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSON;
|
import com.yami.trading.bean.data.domain.Kline;
|
import com.yami.trading.bean.item.domain.Item;
|
import com.yami.trading.huobi.data.internal.KlineService;
|
import com.yami.trading.service.item.ItemService;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.retry.annotation.Backoff;
|
import org.springframework.retry.annotation.Retryable;
|
import org.springframework.stereotype.Component;
|
import java.util.*;
|
|
/**
|
* 马来西亚 行情 跟 K线数据
|
* <p>
|
* https://klse.i3investor.com/web/stock/list
|
* https://klse.i3investor.com/wapi/web/stock/listing/datatables [行情接口]
|
* <p>
|
* https://klse.i3investor.com/web/stock/chart/0012 [k线接口]
|
*/
|
@Component
|
public class InvestorDataServiceImpl {
|
|
@Autowired
|
private KlineService klineService;
|
|
@Autowired
|
private ItemService itemService;
|
|
//每天K线
|
private String klineDay = "https://klse.i3investor.com/mqtraderapi/app/stk-chart/get-price-hist?timeFrame=day&securityCode=%s&liveDelay=delayed&OriAdj=adj";
|
|
//分钟K
|
private String klineUrl = "https://klse.i3investor.com/mqtraderapi/app/stk-chart/get-price-hist?timeFrame=%s&securityCode=%s&liveDelay=delayed&OriAdj=adj";
|
|
/**
|
* 1day 历史数据 : 周期 1年
|
* 1week,1mon 历史数据 : 周期 5年
|
* 请求 350次
|
*/
|
public Map<String, List<Kline>> getDailyWeekMonthHistory(String symbol) {
|
Map<String, List<Kline>> map = new HashMap<>();
|
List<Kline> oneDayPeriod = buildOneDayPeriod(symbol);
|
map.put(Kline.PERIOD_1WEEK, klineService.calculateKline(symbol, 7, Kline.PERIOD_1WEEK, oneDayPeriod));
|
map.put(Kline.PERIOD_1MON, klineService.calculateKline(symbol, 30, Kline.PERIOD_1MON, oneDayPeriod));
|
map.put(Kline.PERIOD_1DAY, oneDayPeriod);
|
map.put(Kline.PERIOD_5DAY, klineService.calculateKline(symbol, 5, Kline.PERIOD_5DAY, oneDayPeriod));
|
map.put(Kline.PERIOD_QUARTER, klineService.calculateKline(symbol, 90, Kline.PERIOD_QUARTER, oneDayPeriod));
|
map.put(Kline.PERIOD_YEAR, klineService.calculateKline(symbol, 365, Kline.PERIOD_YEAR, oneDayPeriod));
|
return map;
|
}
|
|
public List<Kline> buildOneDayPeriod(String currency) {
|
return getTimeseriesByPeriodOneDay(currency);
|
}
|
|
|
/**
|
* Inv支持120分钟的,讲120分钟的,
|
* Hourly
|
* 4hourly 3月
|
*/
|
public List<Kline> getTimeseriesForFourHourly(String currency) {
|
return getTimeseriesByPeriodMinute(currency, "hour", Kline.PERIOD_4HOUR);
|
}
|
|
/**
|
* Hourly
|
* 1hourly 2个小时
|
*/
|
public List<Kline> getTimeseriesForTwoHourly(String currency) {
|
return getTimeseriesByPeriodMinute(currency, "hour", Kline.PERIOD_2HOUR);
|
}
|
|
/**
|
* Hourly
|
* 1hourly 1月
|
*/
|
public List<Kline> getTimeseriesForOneHourly(String currency) {
|
return getTimeseriesByPeriodMinute(currency, "hour", Kline.PERIOD_60MIN);
|
}
|
|
/**
|
* Minute
|
* 30minute 10天
|
* 15minute 5天
|
* 5minute 2天
|
* 1minute 1天
|
*/
|
public List<Kline> getTimeseriesOneMinute(String currency) {
|
return getTimeseriesByPeriodMinute(currency, "min5", Kline.PERIOD_1MIN);
|
|
}
|
|
/**
|
* Minute
|
* 30minute 10天
|
* 15minute 5天
|
* 5minute 2天
|
* 1minute 1天
|
*/
|
public List<Kline> getTimeseriesFiveMinute(String currency) {
|
return getTimeseriesByPeriodMinute(currency, "min5", Kline.PERIOD_5MIN);
|
|
}
|
|
/**
|
* Minute
|
* 30minute 10天
|
* 15minute 5天
|
* 5minute 2天
|
* 1minute 1天
|
*/
|
public List<Kline> getTimeseriesFifteenMinute(String currency) {
|
return getTimeseriesByPeriodMinute(currency, "min10",Kline.PERIOD_15MIN);
|
|
}
|
|
/**
|
* Minute
|
* 30minute 15
|
* 15minute 15
|
* 5minute 15
|
* 1minute 15
|
*/
|
public List<Kline> getTimeseriesThirtyMinute(String currency) {
|
return getTimeseriesByPeriodMinute(currency, "min30",Kline.PERIOD_30MIN);
|
}
|
|
@Retryable(
|
value = {RuntimeException.class}, // 需要重试的异常类型
|
maxAttempts = 5, // 最大重试次数
|
backoff = @Backoff(delay = 2000) // 退避策略:每次重试之间的延迟
|
)
|
public List<Kline> getTimeseriesByPeriodMinute(String currency,String timeFrame, String period) {
|
List<Kline> resList = new ArrayList<>();
|
Item item = itemService.findBySymbol(currency);
|
if (Objects.isNull(item)) {
|
return resList;
|
}
|
String url = String.format(klineUrl, timeFrame, item.getStockCode());
|
String body = HttpRequest
|
.get(url)
|
//.setHttpProxy("127.0.0.1", 7890)
|
.execute()
|
.body();
|
JSONObject bodyJson = JSON.parseObject(body);
|
JSONArray data = bodyJson.getJSONArray("d");
|
if (Objects.isNull(data)) {
|
return resList;
|
}
|
for (int i = 0; i < data.size(); i++) {
|
JSONArray klineData = data.getJSONArray(i);
|
Kline kline = new Kline();
|
kline.setSymbol(currency);
|
kline.setPeriod(period);
|
kline.setTs(klineData.getLong(0));
|
kline.setOpen(klineData.getDouble(1));
|
kline.setHigh(klineData.getDouble(2));
|
kline.setLow(klineData.getDouble(3));
|
kline.setClose(klineData.getDouble(4));
|
kline.setVolume(klineData.getDouble(5));
|
kline.setAmount(0);
|
resList.add(kline);
|
}
|
return resList;
|
|
}
|
|
@Retryable(
|
value = {RuntimeException.class}, // 需要重试的异常类型
|
maxAttempts = 5, // 最大重试次数
|
backoff = @Backoff(delay = 2000) // 退避策略:每次重试之间的延迟
|
)
|
public List<Kline> getTimeseriesByPeriodOneDay(String currency) {
|
List<Kline> resList = new ArrayList<>();
|
Item item = itemService.findBySymbol(currency);
|
if (Objects.isNull(item)) {
|
return resList;
|
}
|
String url = String.format(klineDay, item.getStockCode());
|
String body = HttpRequest.get(url)
|
//.setHttpProxy("127.0.0.1", 7890)
|
.execute()
|
.body();
|
JSONObject bodyJson = JSON.parseObject(body);
|
JSONArray data = bodyJson.getJSONArray("d");
|
if (Objects.isNull(data)) {
|
return resList;
|
}
|
for (int i = 0; i < data.size(); i++) {
|
JSONArray klineData = data.getJSONArray(i);
|
Kline kline = new Kline();
|
kline.setSymbol(currency);
|
kline.setPeriod(Kline.PERIOD_1DAY);
|
kline.setTs(klineData.getLong(0));
|
kline.setOpen(klineData.getDouble(1));
|
kline.setHigh(klineData.getDouble(2));
|
kline.setLow(klineData.getDouble(3));
|
kline.setClose(klineData.getDouble(4));
|
kline.setVolume(klineData.getDouble(5));
|
kline.setAmount(0);
|
resList.add(kline);
|
}
|
return resList;
|
}
|
|
|
}
|