|
|
@@ -20,10 +20,7 @@ import top.lvzhiqiang.config.WorkWeixinProperties;
|
|
|
import top.lvzhiqiang.entity.CoinHistoryOrder;
|
|
|
import top.lvzhiqiang.mapper.CoinMapper;
|
|
|
import top.lvzhiqiang.service.CoinService;
|
|
|
-import top.lvzhiqiang.util.CheckSign4Bitget;
|
|
|
-import top.lvzhiqiang.util.DateUtils;
|
|
|
-import top.lvzhiqiang.util.JsoupUtil;
|
|
|
-import top.lvzhiqiang.util.SpringUtils;
|
|
|
+import top.lvzhiqiang.util.*;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
@@ -36,6 +33,9 @@ import java.time.Duration;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
+import java.util.concurrent.ScheduledExecutorService;
|
|
|
+import java.util.concurrent.ScheduledThreadPoolExecutor;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -82,6 +82,10 @@ public class CoinServiceImpl implements CoinService {
|
|
|
private WorkWeixinProperties properties;
|
|
|
|
|
|
private final Map<String, String> orderMap = new ConcurrentHashMap<>();
|
|
|
+ private final Map<String, JSONObject> mixMap = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+
|
|
|
+ private final static ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(10);
|
|
|
|
|
|
Proxy proxy = null;
|
|
|
|
|
|
@@ -134,50 +138,114 @@ public class CoinServiceImpl implements CoinService {
|
|
|
|
|
|
@Override
|
|
|
public String monitorJob() {
|
|
|
- Timer timer = new Timer();
|
|
|
- timer.scheduleAtFixedRate(new TimerTask() {
|
|
|
- @Override
|
|
|
- public void run() {
|
|
|
- LocalDateTime endTime = LocalDateTime.now();
|
|
|
- // 全部历史委托监控
|
|
|
- Map<String, String> paramMap = new LinkedHashMap<>();
|
|
|
- paramMap.put("productType", "umcbl");
|
|
|
- paramMap.put("startTime", String.valueOf(DateUtils.localDateTimeToMilliseconds(endTime.minusMinutes(1))));
|
|
|
- paramMap.put("endTime", String.valueOf(DateUtils.localDateTimeToMilliseconds(endTime)));
|
|
|
- paramMap.put("pageSize", "100");
|
|
|
-
|
|
|
- String signQueryString = paramMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"));
|
|
|
- try {
|
|
|
- JSONObject response = requestApi4Common("/api/mix/v1/order/historyProductType", signQueryString, null, JsoupUtil.HTTP_GET, paramMap);
|
|
|
- JSONArray orderList = response.getJSONObject("data").getJSONArray("orderList");
|
|
|
-
|
|
|
- for (int i = 0; i < orderList.size(); i++) {
|
|
|
- JSONObject order = orderList.getJSONObject(i);
|
|
|
- LocalDateTime cTime = DateUtils.longToLocalDateTime(order.getLong("cTime"));
|
|
|
- String orderId = order.getString("orderId");
|
|
|
- if (Duration.between(cTime, endTime).getSeconds() < 50 && !orderMap.containsKey(orderId)) {
|
|
|
- orderMap.put(orderId, "1");
|
|
|
- SpringUtils.getBean(CoinServiceImpl.class).monitorAlarm(order);
|
|
|
+ scheduler.scheduleWithFixedDelay(() -> {
|
|
|
+ LocalDateTime endTime = LocalDateTime.now();
|
|
|
+ // 全部历史委托监控
|
|
|
+ Map<String, String> paramMap = new LinkedHashMap<>();
|
|
|
+ paramMap.put("productType", "umcbl");
|
|
|
+ paramMap.put("startTime", String.valueOf(DateUtils.localDateTimeToMilliseconds(endTime.minusMinutes(1))));
|
|
|
+ paramMap.put("endTime", String.valueOf(DateUtils.localDateTimeToMilliseconds(endTime)));
|
|
|
+ paramMap.put("pageSize", "100");
|
|
|
+
|
|
|
+ String signQueryString = paramMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"));
|
|
|
+ try {
|
|
|
+ JSONObject response = requestApi4Common("/api/mix/v1/order/historyProductType", signQueryString, null, JsoupUtil.HTTP_GET, paramMap);
|
|
|
+ JSONArray orderList = response.getJSONObject("data").getJSONArray("orderList");
|
|
|
+
|
|
|
+ for (int i = 0; i < orderList.size(); i++) {
|
|
|
+ JSONObject order = orderList.getJSONObject(i);
|
|
|
+ LocalDateTime cTime = DateUtils.longToLocalDateTime(order.getLong("cTime"));
|
|
|
+ String orderId = order.getString("orderId");
|
|
|
+ if (Duration.between(cTime, endTime).getSeconds() < 50 && !orderMap.containsKey(orderId)) {
|
|
|
+ orderMap.put(orderId, "1");
|
|
|
+ String content = order.getString("symbol") + "委托单已经触发,成交均价为" + order.getString("priceAvg");
|
|
|
+ SpringUtils.getBean(CoinServiceImpl.class).monitorAlarm(content, JOB_ALARM_MODE_APP_TEXT_CARD);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ }
|
|
|
+ }, 0, 2, TimeUnit.SECONDS);
|
|
|
+
|
|
|
+ scheduler.scheduleAtFixedRate(() -> {
|
|
|
+ LocalDateTime endTime = LocalDateTime.now();
|
|
|
+ // 全部合约仓位信息V2
|
|
|
+ Map<String, String> paramMap = new HashMap<>();
|
|
|
+ paramMap.put("productType", "umcbl");
|
|
|
+
|
|
|
+ String signQueryString = paramMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"));
|
|
|
+ try {
|
|
|
+ JSONObject response = requestApi4Common("/api/mix/v1/position/allPosition-v2", signQueryString, null, JsoupUtil.HTTP_GET, paramMap);
|
|
|
+ JSONArray mixList = response.getJSONArray("data");
|
|
|
+ for (int i = 0; i < mixList.size(); i++) {
|
|
|
+ JSONObject mixData = mixList.getJSONObject(i);
|
|
|
+
|
|
|
+ String symbol = mixData.getString("symbol");
|
|
|
+ String margin = mixData.getString("margin");
|
|
|
+ String averageOpenPrice = mixData.getString("averageOpenPrice");
|
|
|
+ String key = symbol + margin + averageOpenPrice;
|
|
|
+
|
|
|
+ // 回报率=未实现盈亏/保证金
|
|
|
+
|
|
|
+ // 持仓方向 long:多头 short:空头
|
|
|
+ String holdSide = mixData.getString("holdSide");
|
|
|
+ BigDecimal returnRate = new BigDecimal(mixData.getString("unrealizedPL")).divide(new BigDecimal(margin)).setScale(2, RoundingMode.HALF_UP);
|
|
|
+ for (int j = 1; j <= 10; j++) {
|
|
|
+ BigDecimal grid = BigDecimal.valueOf(0.5).multiply(BigDecimal.valueOf(j));
|
|
|
+ if ("long".equalsIgnoreCase(holdSide)) {
|
|
|
+ if (returnRate.compareTo(grid) < 0) {
|
|
|
+ if (mixMap.containsKey(key)) {
|
|
|
+ mixMap.get(key).put("returnRate", returnRate);
|
|
|
+ } else {
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ jsonObject.put("returnRate", returnRate);
|
|
|
+ mixMap.put(key, jsonObject);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (returnRate.compareTo(grid) > 0) {
|
|
|
+ if (mixMap.containsKey(key)) {
|
|
|
+ mixMap.get(key).put("returnRate", returnRate);
|
|
|
+ if (mixMap.get(key).containsKey(grid.toPlainString())) {
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ mixMap.get(key).put(grid.toPlainString(), true);
|
|
|
+ SpringUtils.getBean(CoinServiceImpl.class).monitorAlarm(symbol.concat("回报率超过").concat(grid.toPlainString()), JOB_ALARM_MODE_CHAT_BOT);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ jsonObject.put("returnRate", returnRate);
|
|
|
+ jsonObject.put(grid.toPlainString(), true);
|
|
|
+ mixMap.put(key, jsonObject);
|
|
|
+
|
|
|
+ SpringUtils.getBean(CoinServiceImpl.class).monitorAlarm(symbol.concat("回报率超过").concat(grid.toPlainString()), JOB_ALARM_MODE_CHAT_BOT);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ("short".equalsIgnoreCase(holdSide)) {
|
|
|
+ // TODO
|
|
|
}
|
|
|
}
|
|
|
- } catch (Exception e) {
|
|
|
}
|
|
|
+ } catch (Exception e) {
|
|
|
}
|
|
|
- }, 0, 2000);
|
|
|
+ }, 0, 5, TimeUnit.SECONDS);
|
|
|
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@Async("coinTaskExecutor")
|
|
|
- public void monitorAlarm(JSONObject order) {
|
|
|
+ public void monitorAlarm(String content, String jobAlarmMode) {
|
|
|
// 判断告警模式
|
|
|
- String jobAlarmMode = JOB_ALARM_MODE;
|
|
|
+ if (StringUtils.isEmpty(JOB_ALARM_MODE)) {
|
|
|
+ jobAlarmMode = JOB_ALARM_MODE;
|
|
|
+ }
|
|
|
|
|
|
// 文本卡片模式发消息
|
|
|
if (JOB_ALARM_MODE_APP_TEXT_CARD.equals(jobAlarmMode)) {
|
|
|
String title = "监控告警明细";
|
|
|
- String content = order.getString("symbol") + "触发";
|
|
|
String logUrl = "https://lvzhiqiang.top";
|
|
|
String btnTxt = "日志详情";
|
|
|
|
|
|
@@ -200,7 +268,6 @@ public class CoinServiceImpl implements CoinService {
|
|
|
if (JOB_ALARM_MODE_CHAT_BOT.equals(jobAlarmMode)) {
|
|
|
WxCpGroupRobotService groupRobotService = wxCpService.getGroupRobotService();
|
|
|
String webhookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=082970da-2a33-422a-81f6-15f9bde87940";
|
|
|
- String content = order.getString("symbol") + "触发";
|
|
|
try {
|
|
|
log.info("企业微信推送消息,send content: {}, userIdSet: {}", content, "LvZhiQiang");
|
|
|
groupRobotService.sendText(webhookUrl, content, Collections.singletonList("LvZhiQiang"), Collections.emptyList());
|