From 4130970dd61791e0a5cb0771a9b707084f1ed464 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Thu, 08 May 2025 00:39:05 +0800
Subject: [PATCH] 1

---
 src/main/java/com/nq/utils/task/stock/StockTask.java |  274 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 257 insertions(+), 17 deletions(-)

diff --git a/src/main/java/com/nq/utils/task/stock/StockTask.java b/src/main/java/com/nq/utils/task/stock/StockTask.java
index d4a1b6b..ad227d2 100644
--- a/src/main/java/com/nq/utils/task/stock/StockTask.java
+++ b/src/main/java/com/nq/utils/task/stock/StockTask.java
@@ -1,26 +1,35 @@
 package com.nq.utils.task.stock;
 
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.gson.Gson;
+import com.nq.common.ServerResponse;
 import com.nq.dao.StockMapper;
+import com.nq.dao.UserMapper;
+import com.nq.dao.UserPendingorderMapper;
 import com.nq.dao.UserPositionMapper;
+import com.nq.enums.EConfigKey;
 import com.nq.enums.EStockType;
-import com.nq.pojo.DataStockBean;
-import com.nq.pojo.ReponseBase;
-import com.nq.pojo.Stock;
-import com.nq.pojo.UserPosition;
+import com.nq.enums.EUserAssets;
+import com.nq.pojo.*;
 import com.nq.pojo.reponse.kResponse;
-import com.nq.service.IMandatoryLiquidationService;
-import com.nq.service.IStockService;
-import com.nq.service.IUserPositionService;
+import com.nq.service.*;
 import com.nq.service.impl.StockServiceImpl;
+import com.nq.service.impl.UserServiceImpl;
+import com.nq.utils.ConverterUtil;
+import com.nq.utils.KeyUtils;
+import com.nq.utils.UserPointUtil;
 import com.nq.utils.http.HttpClientRequest;
 import com.nq.utils.redis.RedisKeyConstant;
 import com.nq.utils.redis.RedisKeyUtil;
 import com.nq.utils.redis.RedisShardedPoolUtils;
+import com.nq.utils.stock.GeneratePosition;
+import com.nq.vo.position.PositionProfitVO;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -29,9 +38,12 @@
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 
+import javax.servlet.http.HttpServletRequest;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLEncoder;
@@ -55,12 +67,19 @@
     @Autowired
     UserPositionMapper userPositionMapper;
 
-    private final Lock stockConstraintLock = new ReentrantLock();
-
-
+    @Autowired
+    private UserPendingorderService userPendingorderService;
     @Autowired
     IMandatoryLiquidationService mandatoryLiquidationService;
+    @Autowired
+    IUserAssetsServices iUserAssetsServices;
+    @Autowired
+    IStockConfigServices iStockConfigServices;
 
+    @Autowired
+    IPriceServices priceServices;
+    @Autowired
+    UserMapper userMapper;
 
     private static final Logger log = LoggerFactory.getLogger(StockTask.class);
 
@@ -88,6 +107,226 @@
             }
         }
     }
+
+
+    /**
+     * 挂单
+     */
+    @Scheduled(cron = "0/10 * * * * ?")
+    public void pendingOrder() {
+        ReentrantLock lock = new ReentrantLock();
+        if (lock.tryLock()) { // 尝试获取锁
+            try {
+                pending();
+            }catch (Exception e){
+                e.printStackTrace();
+                log.error("买入挂单定时任务报错:",e.getMessage());
+            }
+            finally {
+                lock.unlock();  // 释放锁
+            }
+        } else {
+            // 如果锁不可用,可以选择不执行或打印日志等
+            System.out.println("买入挂单定时任务  任务正在执行,跳过本次执行。");
+        }
+    }
+
+    /**
+     * 挂单平仓
+     */
+    @Scheduled(cron = "0/10 * * * * ?")
+    public void closeOrder() {
+        ReentrantLock lock = new ReentrantLock();
+        if (lock.tryLock()) { // 尝试获取锁
+            try {
+                closeOutOrder();
+            }catch (Exception e){
+                e.printStackTrace();
+                log.error("平仓挂单定时任务报错:",e.getMessage());
+            }
+            finally {
+                lock.unlock();  // 释放锁
+            }
+        } else {
+            // 如果锁不可用,可以选择不执行或打印日志等
+            System.out.println("平仓挂单定时任务  任务正在执行,跳过本次执行。");
+        }
+    }
+
+    public void closeOutOrder() {
+        List<UserPendingorder> list = userPendingorderService.list(new LambdaQueryWrapper<>(UserPendingorder.class)
+                .eq(UserPendingorder::getPositionType, 1)
+                .eq(UserPendingorder::getHangingOrderType,2));
+        if(CollectionUtil.isNotEmpty(list)){
+            list.forEach(f->{
+                //获取当前价格
+                //股票类型 现价 数据源的处理
+                BigDecimal nowPrice = BigDecimal.ZERO;
+                if(f.getStockType().equals("ST")){
+                    nowPrice = priceServices.getNowPrice(f.getStockCode());
+                }else{
+                    nowPrice = new BigDecimal(RedisShardedPoolUtils.get(RedisKeyConstant.getRedisKey(f.getStockName())));
+                }
+                if((f.getOrderDirection().equals("买涨") && nowPrice.compareTo(f.getSellOrderPrice()) >= 0) || (f.getOrderDirection().equals("买跌") && nowPrice.compareTo(f.getSellOrderPrice()) <= 0)){
+                    closeStockTransferPositions(f);
+                }
+            });
+        }
+    }
+
+    private void closeStockTransferPositions(UserPendingorder f) {
+        UserPosition userPosition = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
+                .eq(UserPosition::getPositionSn, f.getPositionSn())
+                .eq(UserPosition::getUserId, f.getUserId())
+
+        );
+
+        BigDecimal siitteBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.SELL_HANDLING_CHARGE.getCode()).getCValue());
+        //部分平仓
+        if(f.getOrderNum() < userPosition.getOrderNum()){
+            //拆分订单
+            UserPosition position = ConverterUtil.convert(userPosition,UserPosition.class);
+            position.setId(null);
+            position.setPositionSn(KeyUtils.getUniqueKey());
+            //得到均价
+            double buyOrderPrice = position.getOrderTotalPrice().doubleValue() / position.getOrderNum().doubleValue() * position.getOrderLever();
+            position.setOrderNum(userPosition.getOrderNum()-f.getOrderNum());
+            BigDecimal positionBuyAmt = new BigDecimal(buyOrderPrice).multiply(new BigDecimal(position.getOrderNum())).divide(new BigDecimal(position.getOrderLever()));
+            position.setOrderTotalPrice(positionBuyAmt);
+            position.setBuyOrderPrice(new BigDecimal(buyOrderPrice));
+            position.setBuyOrderId(GeneratePosition.getPositionId());
+            //修改拆分订单手续费
+            BigDecimal BuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue());
+            BigDecimal buyPrice = position.getBuyOrderPrice().multiply(new BigDecimal(position.getOrderNum()));
+            BigDecimal xsPrice = buyPrice.multiply(BuyFee);
+            position.setOrderFee(xsPrice);
+            userPositionMapper.insert(position);
+            //得到均价
+            double orderPrice = userPosition.getOrderTotalPrice().doubleValue() / userPosition.getOrderNum().doubleValue() * position.getOrderLever();
+            //修改原订单
+            userPosition.setOrderNum(f.getOrderNum());
+            BigDecimal buyAmt = new BigDecimal(orderPrice).multiply(new BigDecimal(userPosition.getOrderNum())).divide(new BigDecimal(userPosition.getOrderLever()));
+            userPosition.setOrderTotalPrice(buyAmt);
+            userPosition.setOrderFee(userPosition.getOrderFee().subtract(position.getOrderFee()));
+            userPositionMapper.updateById(userPosition);
+        }
+        getObjectServerResponse(userPosition, f.getSellOrderPrice(), siitteBuyFee, f.getStockType());
+        f.setPositionType(2);
+        userPendingorderService.updateById(f);
+    }
+
+    public void getObjectServerResponse( UserPosition userPosition, BigDecimal nowPrice, BigDecimal siitteBuyFee, String stockType) {
+        userPosition.setSellOrderId(GeneratePosition.getPositionId());
+        userPosition.setSellOrderPrice(nowPrice);
+        userPosition.setSellOrderTime(new Date());
+
+        BigDecimal sellOrderTotel = nowPrice.multiply(new BigDecimal(userPosition.getOrderNum()));
+        BigDecimal xsPrice = sellOrderTotel.multiply(siitteBuyFee);
+        userPosition.setOrderFee(userPosition.getOrderFee().add(xsPrice));
+        userPositionMapper.updateById(userPosition);
+
+        iUserAssetsServices.availablebalanceChange(stockType,
+                userPosition.getUserId(),
+                EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT,
+                userPosition.getOrderTotalPrice(), "", "");
+        iUserAssetsServices.availablebalanceChange(stockType,
+                userPosition.getUserId(), EUserAssets.HANDLING_CHARGE,
+                xsPrice, "", "");
+
+        PositionProfitVO profitVO = UserPointUtil.getPositionProfitVO(userPosition,
+                priceServices.getNowPrice(userPosition.getStockCode()));
+
+        iUserAssetsServices.availablebalanceChange(stockType,
+                userPosition.getUserId(), EUserAssets.CLOSE_POSITION,
+                profitVO.getAllProfitAndLose(), "", "");
+    }
+
+    public void pending(){
+        List<UserPendingorder> list = userPendingorderService.list(new LambdaQueryWrapper<>(UserPendingorder.class)
+                .eq(UserPendingorder::getPositionType, 1)
+                .eq(UserPendingorder::getHangingOrderType,1));
+        if(CollectionUtil.isNotEmpty(list)){
+            list.forEach(f->{
+                if(f.getStockGid().equals("ST")){
+                    //获取当前价格
+                    //股票类型 现价 数据源的处理
+                    BigDecimal nowPrice = priceServices.getNowPrice(f.getStockCode());
+                    if((f.getOrderDirection().equals("买涨") && f.getBuyOrderPrice().compareTo(nowPrice) >= 0) || (f.getOrderDirection().equals("买跌") && f.getBuyOrderPrice().compareTo(nowPrice) <= 0)){
+                        stockTransferPositions(f);
+                    }
+                }else{
+                    String price = RedisShardedPoolUtils.get(RedisKeyConstant.getRedisKey(f.getStockName()));
+                    if((f.getOrderDirection().equals("买涨") && f.getBuyOrderPrice().compareTo(new BigDecimal(price)) >= 0) || (f.getOrderDirection().equals("买跌") && f.getBuyOrderPrice().compareTo(new BigDecimal(price)) <= 0)){
+                        hjTransferPositions(f);
+                    }
+                }
+            });
+        }
+    }
+    public void hjTransferPositions(UserPendingorder userPendingorder){
+        UserPosition position = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
+                .eq(UserPosition::getUserId, userPendingorder.getUserId())
+                .eq(UserPosition::getStockCode, userPendingorder.getStockCode())
+                .isNull(UserPosition::getSellOrderId)
+        );
+        User user = userMapper.selectById(userPendingorder.getUserId());
+        BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ;
+        BigDecimal orderFree = siteSettingBuyFee.multiply(userPendingorder.getOrderTotalPrice());
+        UserPosition userPosition = ConverterUtil.convert(userPendingorder, UserPosition.class);
+        if(ObjectUtil.isEmpty(position)){
+            userPosition.setPositionType(user.getAccountType());
+            userPosition.setId(null);
+            userPendingorder.setPositionType(0);
+            userPendingorderService.updateById(userPendingorder);
+            userPositionMapper.insert(userPosition);
+            iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        }else{
+            position.setOrderNum(position.getOrderNum()+userPosition.getOrderNum());
+            position.setOrderTotalPrice(position.getOrderTotalPrice().add(userPosition.getOrderTotalPrice()));
+            position.setOrderFee(position.getOrderFee().add(orderFree));
+            position.setBuyOrderPrice(position.getBuyOrderPrice());
+            position.setAllProfitAndLose(position.getAllProfitAndLose().add(orderFree));
+            userPositionMapper.updateById(position);
+            userPendingorder.setPositionType(0);
+            userPendingorderService.updateById(userPendingorder);
+            iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        }
+    }
+
+    public void stockTransferPositions(UserPendingorder userPendingorder){
+        UserPosition position = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
+                .eq(UserPosition::getUserId, userPendingorder.getUserId())
+                .eq(UserPosition::getStockCode, userPendingorder.getStockCode())
+                .isNull(UserPosition::getSellOrderId)
+        );
+        // 手续费率
+        BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ;
+        BigDecimal orderFree = siteSettingBuyFee.multiply(userPendingorder.getOrderTotalPrice());
+        User user = userMapper.selectById(userPendingorder.getUserId());
+        UserPosition userPosition = ConverterUtil.convert(userPendingorder, UserPosition.class);
+        if(ObjectUtil.isEmpty(position)){
+            userPosition.setPositionType(user.getAccountType());
+            userPosition.setId(null);
+            userPendingorder.setPositionType(0);
+            userPendingorderService.updateById(userPendingorder);
+            userPositionMapper.insert(userPosition);
+            //挂单成功扣除手续费
+            iUserAssetsServices.availablebalanceChange("ST", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        }else{
+            position.setOrderNum(position.getOrderNum()+userPosition.getOrderNum());
+            position.setOrderTotalPrice(position.getOrderTotalPrice().add(userPosition.getOrderTotalPrice()));
+            position.setOrderFee(position.getOrderFee().add(orderFree));
+            double divide = position.getOrderTotalPrice().doubleValue() / position.getOrderNum();
+            position.setBuyOrderPrice(new BigDecimal(divide*position.getOrderLever()));
+            position.setAllProfitAndLose(position.getAllProfitAndLose().add(orderFree));
+            userPositionMapper.updateById(position);
+            userPendingorder.setPositionType(0);
+            userPendingorderService.updateById(userPendingorder);
+            //挂单成功扣除手续费
+            iUserAssetsServices.availablebalanceChange("ST", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
+        }
+    }
+
     //最新价格url
     private static final String PRICE_URL = "https://quote.alltick.io/quote-b-api/trade-tick?token=794ea65dc03c5af582cddec476fbb0d7-c-app&query=";
     //k线url
@@ -140,7 +379,7 @@
         if (lock.tryLock()) { // 尝试获取锁
             try {
                 gold();
-                Thread.sleep(1000);
+                Thread.sleep(2000);
                 getKDate();
             } finally {
                 lock.unlock();  // 释放锁
@@ -224,7 +463,7 @@
                 RedisShardedPoolUtils.set("k_gold_"+entry.getKey(), gold);
             }
 
-            Thread.sleep(1000);
+            Thread.sleep(2000);
             String c = getResp(K_URL+getKQueryData(entry.getValue(),"USOIL"));
             if(StringUtils.isNotEmpty(c)){
                 if(entry.getKey().equals("d")) {
@@ -232,7 +471,7 @@
                 }
                 RedisShardedPoolUtils.set("k_crude_oil_"+entry.getKey(), c);
             }
-            Thread.sleep(1000);
+            Thread.sleep(2000);
         }
     }
 
@@ -264,12 +503,13 @@
             kData.setVo(item.getTurnover());
             kDataList.add(kData);
         }
-        DecimalFormat decimalFormat = new DecimalFormat("#.00");
         double oneC = Double.valueOf(kDataList.get(kDataList.size() - 1).getC());
         double twoC = Double.valueOf(kDataList.get(kDataList.size() - 2).getC());
-        String h = String.valueOf(decimalFormat.format(((oneC - twoC) / oneC * 100)));
-        RedisShardedPoolUtils.set(key+"_H",h);
-        RedisShardedPoolUtils.set(key+"_H",h);
+        String h = String.valueOf(((oneC - twoC) / oneC * 100));
+        BigDecimal bd = new BigDecimal(h);
+        bd = bd.setScale(2, RoundingMode.DOWN);  // RoundingMode.DOWN 表示截断而非四舍五入
+        RedisShardedPoolUtils.set(key+"_H",bd.toString());
+        RedisShardedPoolUtils.set(key+"_H",bd.toString());
     }
 
     public String getResp(String url){

--
Gitblit v1.9.3