|
|
@@ -4,17 +4,31 @@ import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.jsoup.Connection;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Propagation;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+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 javax.annotation.Resource;
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.net.InetSocketAddress;
|
|
|
import java.net.Proxy;
|
|
|
import java.security.InvalidKeyException;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.Map;
|
|
|
+import java.time.Duration;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
* Coin ServiceImpl
|
|
|
@@ -32,6 +46,16 @@ public class CoinServiceImpl implements CoinService {
|
|
|
// 私钥,由系统随机生成,用于签名的生成。
|
|
|
private static final String secretKey = "1fdd0fc2976bea80189ba13710e12825ca3ef6c5e25a0d76fd03f8f6cd4a61d9";
|
|
|
|
|
|
+ @Resource
|
|
|
+ private CoinMapper coinMapper;
|
|
|
+
|
|
|
+ @Autowired(required = false)
|
|
|
+ private WxCpService wxCpService;
|
|
|
+ @Autowired(required = false)
|
|
|
+ private WorkWeixinProperties properties;
|
|
|
+
|
|
|
+ private final Map<String, String> orderMap = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
static {
|
|
|
// API KEY作为一个字符串。
|
|
|
basicHeaderMap.put("ACCESS-KEY", "bg_433d37306df0e8901c6d107c6d9e9111");
|
|
|
@@ -47,90 +71,97 @@ public class CoinServiceImpl implements CoinService {
|
|
|
basicHeaderMap.put("locale", "zh-CN");
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
|
|
+ public void syncData(String startTime, String endTime, String pageSize) {
|
|
|
+ // 获取全部历史委托
|
|
|
+ Map<String, String> paramMap = new LinkedHashMap<>();
|
|
|
+ paramMap.put("productType", "umcbl");
|
|
|
+ paramMap.put("startTime", startTime);
|
|
|
+ paramMap.put("endTime", endTime);
|
|
|
+ paramMap.put("pageSize", pageSize);
|
|
|
+
|
|
|
+ String signQueryString = paramMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"));
|
|
|
+
|
|
|
+ JSONObject response = requestApi4Common("/api/mix/v1/order/historyProductType", signQueryString, null, JsoupUtil.HTTP_GET, paramMap);
|
|
|
+
|
|
|
+ JSONArray orderList = response.getJSONObject("data").getJSONArray("orderList");
|
|
|
+ coinMapper.insertHistoryOrderList(JSONArray.parseArray(orderList.toJSONString(), CoinHistoryOrder.class));
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
@Override
|
|
|
+ //@Async("coinTaskExecutor")
|
|
|
public String monitorJob() {
|
|
|
+ Timer timer = new Timer();
|
|
|
+ timer.scheduleAtFixedRate(new TimerTask() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ // 全部历史委托监控
|
|
|
+ Map<String, String> paramMap = new LinkedHashMap<>();
|
|
|
+ paramMap.put("productType", "umcbl");
|
|
|
+ paramMap.put("startTime", String.valueOf(DateUtils.localDateTimeToMilliseconds(LocalDateTime.now().minusSeconds(10))));
|
|
|
+ paramMap.put("endTime", String.valueOf(System.currentTimeMillis()));
|
|
|
+ paramMap.put("pageSize", "100");
|
|
|
+
|
|
|
+ String signQueryString = paramMap.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"));
|
|
|
+ JSONObject response = requestApi4Common("/api/mix/v1/order/historyProductType", signQueryString, null, JsoupUtil.HTTP_GET, paramMap);
|
|
|
+ JSONArray orderList = response.getJSONObject("data").getJSONArray("orderList");
|
|
|
+
|
|
|
+ System.out.println(LocalDateTime.now() + ":" + orderList.size());
|
|
|
+ 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, LocalDateTime.now()).getSeconds() < 5 && !orderMap.containsKey(order.getString("orderId"))) {
|
|
|
+ orderMap.put(orderId, "1");
|
|
|
+ monitorAlarm(order);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, 0, 2000);
|
|
|
+
|
|
|
+ try {
|
|
|
+ Thread.sleep(100000);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 获取全部合约仓位信息V2
|
|
|
- *
|
|
|
- * @author lvzhiqiang
|
|
|
- * 2023/9/5 15:23
|
|
|
- */
|
|
|
@Override
|
|
|
- public String findAllPositionv2() {
|
|
|
- JSONObject result = handleAllPositionV2();
|
|
|
- JSONArray data = result.getJSONArray("data");
|
|
|
-
|
|
|
- StringBuffer sb = new StringBuffer("total:".concat(String.valueOf(data.size())).concat("<br/>"));
|
|
|
- sb.append("<table border=\"1\" cellspacing=\"0\"><tr>");
|
|
|
- sb.append("<th>币对名称</th>");
|
|
|
- sb.append("<th>保证金币种</th>");
|
|
|
- sb.append("<th>持仓方向</th>");
|
|
|
- sb.append("<th>当前委托待成交的数量</th>");
|
|
|
- sb.append("<th>保证金数量</th>");
|
|
|
- sb.append("<th>自动追加保证金</th>");
|
|
|
- sb.append("<th>仓位可用</th>");
|
|
|
- sb.append("<th>仓位冻结</th>");
|
|
|
- sb.append("<th>仓位总数量</th>");
|
|
|
- sb.append("<th>杠杆倍数</th>");
|
|
|
- sb.append("<th>已实现盈亏</th>");
|
|
|
- sb.append("<th>平均开仓价</th>");
|
|
|
- sb.append("<th>保证金模式</th>");
|
|
|
- sb.append("<th>持仓模式</th>");
|
|
|
- sb.append("<th>未实现盈亏</th>");
|
|
|
- sb.append("<th>预估强平价</th>");
|
|
|
- sb.append("<th>维持保证金率</th>");
|
|
|
- sb.append("<th>标记价格</th>");
|
|
|
- sb.append("<th>最近更新时间</th>");
|
|
|
- sb.append("</tr>");
|
|
|
-
|
|
|
- for (int i = 0; i < data.size(); i++) {
|
|
|
- JSONObject jsonObject = data.getJSONObject(i);
|
|
|
- sb.append("<tr>");
|
|
|
-
|
|
|
- sb.append("<td>").append(jsonObject.getString("symbol")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("marginCoin")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("holdSide")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("openDelegateCount")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("margin")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("autoMargin")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("available")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("locked")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("total")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("leverage")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("achievedProfits")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("averageOpenPrice")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("marginMode")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("holdMode")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("unrealizedPL")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("liquidationPrice")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("keepMarginRate")).append("</td>");
|
|
|
- sb.append("<td>").append(jsonObject.getString("marketPrice")).append("</td>");
|
|
|
- sb.append("<td>").append(DateUtils.timeToString(jsonObject.getLong("cTime"))).append("</td>");
|
|
|
-
|
|
|
- sb.append("</tr>");
|
|
|
- }
|
|
|
- sb.append("</table>");
|
|
|
+ @Async("coinTaskExecutor")
|
|
|
+ public void monitorAlarm(JSONObject order) {
|
|
|
+ String title = "监控告警明细";
|
|
|
+ String content = order.getString("symbol") + "触发";
|
|
|
+ String logUrl = "https://lvzhiqiang.top";
|
|
|
+ String btnTxt = "日志详情";
|
|
|
|
|
|
- return sb.toString();
|
|
|
+ WxCpMessage wxCpMessage = WxCpMessage.TEXTCARD().agentId(properties.getAgentId())
|
|
|
+ .toUser("LvZhiQiang")
|
|
|
+ .toParty("")
|
|
|
+ .toTag("")
|
|
|
+ .title(title).description(content)
|
|
|
+ .url(logUrl).btnTxt(btnTxt)
|
|
|
+ .build();
|
|
|
+ try {
|
|
|
+ WxCpMessageSendResult sendResult = wxCpService.getMessageService().send(wxCpMessage);
|
|
|
+ System.out.println(sendResult);
|
|
|
+ } catch (WxErrorException e) {
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 处理全部合约仓位信息V2
|
|
|
+ * 请求通用API方法
|
|
|
*/
|
|
|
- @Override
|
|
|
- public JSONObject handleAllPositionV2() {
|
|
|
- String requestPath = "/api/mix/v1/position/allPosition-v2";
|
|
|
+ private JSONObject requestApi4Common(String requestPath, String signQueryString, String signBody, String httpMethod, Map<String, String> paramMap) {
|
|
|
String timestamp = String.valueOf(System.currentTimeMillis());
|
|
|
- String queryString = "productType=umcbl";
|
|
|
+
|
|
|
Map<String, String> headerMap = new HashMap<>();
|
|
|
headerMap.putAll(basicHeaderMap);
|
|
|
try {
|
|
|
- String accessSign = CheckSign4Bitget.generate(timestamp, "GET", requestPath, queryString, null, secretKey);
|
|
|
+ String accessSign = CheckSign4Bitget.generate(timestamp, "GET", requestPath, signQueryString, signBody, secretKey);
|
|
|
headerMap.put("ACCESS-TIMESTAMP", timestamp);
|
|
|
headerMap.put("ACCESS-SIGN", accessSign);
|
|
|
} catch (CloneNotSupportedException e) {
|
|
|
@@ -141,13 +172,11 @@ public class CoinServiceImpl implements CoinService {
|
|
|
throw new RuntimeException(e);
|
|
|
}
|
|
|
|
|
|
- Map<String, String> paramMap = new HashMap<>();
|
|
|
- paramMap.put("productType", "umcbl");
|
|
|
try {
|
|
|
String requestUrl = mainUrl + requestPath;
|
|
|
- //Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 1080));
|
|
|
- Proxy proxy = Proxy.NO_PROXY;
|
|
|
- Connection.Response response = JsoupUtil.requestBody(requestUrl, JsoupUtil.HTTP_GET, proxy, headerMap, paramMap);
|
|
|
+ Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 1080));
|
|
|
+ //Proxy proxy = Proxy.NO_PROXY;
|
|
|
+ Connection.Response response = JsoupUtil.requestBody(requestUrl, httpMethod, proxy, headerMap, paramMap);
|
|
|
|
|
|
return JSONObject.parseObject(response.body());
|
|
|
} catch (Exception e) {
|
|
|
@@ -155,8 +184,81 @@ public class CoinServiceImpl implements CoinService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public JSONArray mainSearch(JSONObject params) {
|
|
|
+ JSONArray result = new JSONArray();
|
|
|
+ if (params.getString("nameEn").equals("allPositionv2")) {
|
|
|
+ Map<String, String> paramMap = new HashMap<>();
|
|
|
+ paramMap.put("productType", "umcbl");
|
|
|
+
|
|
|
+ String signQueryString = "productType=umcbl";
|
|
|
+
|
|
|
+ JSONObject response = requestApi4Common(params.getString("url"), signQueryString, null, JsoupUtil.HTTP_GET, paramMap);
|
|
|
+
|
|
|
+ result = response.getJSONArray("data");
|
|
|
+
|
|
|
+ renderMainSearch4AllPositionv2(result);
|
|
|
+ } else if (params.getString("nameEn").equals("orderMarginCoinCurrent")) {
|
|
|
+ Map<String, String> paramMap = new LinkedHashMap<>();
|
|
|
+ paramMap.put("productType", "umcbl");
|
|
|
+ paramMap.put("marginCoin", "USDT");
|
|
|
+
|
|
|
+ String signQueryString = "productType=umcbl&marginCoin=USDT";
|
|
|
+
|
|
|
+ JSONObject response = requestApi4Common(params.getString("url"), signQueryString, null, JsoupUtil.HTTP_GET, paramMap);
|
|
|
+
|
|
|
+ result = response.getJSONArray("data");
|
|
|
+
|
|
|
+ renderMainSearch4OrderMarginCoinCurrent(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void renderMainSearch4OrderMarginCoinCurrent(JSONArray result) {
|
|
|
+ for (int i = 0; i < result.size(); i++) {
|
|
|
+ JSONObject jsonObject = result.getJSONObject(i);
|
|
|
+
|
|
|
+ jsonObject.put("orderType", jsonObject.getString("orderType").equals("limit") ? "限价" : "市价");
|
|
|
+ jsonObject.put("marginMode", jsonObject.getString("marginMode").equals("fixed") ? "逐仓" : "全仓");
|
|
|
+
|
|
|
+ jsonObject.put("cTime", DateUtils.longToString(jsonObject.getLong("cTime")));
|
|
|
+ jsonObject.put("uTime", DateUtils.longToString(jsonObject.getLong("uTime")));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void renderMainSearch4AllPositionv2(JSONArray result) {
|
|
|
+ for (int i = 0; i < result.size(); i++) {
|
|
|
+ JSONObject jsonObject = result.getJSONObject(i);
|
|
|
+ jsonObject.put("cTime", DateUtils.longToString(jsonObject.getLong("cTime")));
|
|
|
+ jsonObject.put("margin", new BigDecimal(jsonObject.getString("margin")).setScale(4, RoundingMode.HALF_UP));
|
|
|
+ jsonObject.put("averageOpenPrice", new BigDecimal(jsonObject.getString("averageOpenPrice")).setScale(4, RoundingMode.HALF_UP));
|
|
|
+ jsonObject.put("unrealizedPL", new BigDecimal(jsonObject.getString("unrealizedPL")).setScale(4, RoundingMode.HALF_UP));
|
|
|
+ jsonObject.put("liquidationPrice", new BigDecimal(jsonObject.getString("liquidationPrice")).setScale(4, RoundingMode.HALF_UP));
|
|
|
+
|
|
|
+ //未实现盈亏
|
|
|
+ if (jsonObject.getBigDecimal("unrealizedPL").compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ jsonObject.put("unrealizedPLStyle", " style=\"color:#FFFFFF;background-color:#F1493F;\"");
|
|
|
+ } else {
|
|
|
+ jsonObject.put("unrealizedPLStyle", " style=\"color:#FFFFFF;background-color:#1DA2B4;\"");
|
|
|
+ }
|
|
|
+ //标记价格
|
|
|
+ jsonObject.put("marketPriceStyle", " style=\"color:#252B31;background-color:#C4ADE9;font-weight:bold;\"");
|
|
|
+ //币对名称
|
|
|
+ String symbol = jsonObject.getString("symbol").replace("USDT_UMCBL", "");
|
|
|
+ jsonObject.put("symbol", "<strong style=\"background-color:#F1B90d;\"><font color=\"#242A30\">" + symbol + "</font></strong>USDT_UMCBL");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public static void main(String[] args) {
|
|
|
CoinServiceImpl coinService = new CoinServiceImpl();
|
|
|
- System.out.println(coinService.handleAllPositionV2());
|
|
|
+ JSONObject params = new JSONObject();
|
|
|
+ /*params.put("nameEn", "allPositionv2");
|
|
|
+ params.put("url", "/api/mix/v1/position/allPosition-v2");*/
|
|
|
+
|
|
|
+ /*params.put("nameEn", "orderMarginCoinCurrent");
|
|
|
+ params.put("url", "/api/mix/v1/order/marginCoinCurrent");*/
|
|
|
+
|
|
|
+ System.out.println(coinService.mainSearch(params));
|
|
|
}
|
|
|
}
|