From 39135376545d5523f13960d922ac89071ea3e864 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Wed, 24 Apr 2024 17:57:46 +0800
Subject: [PATCH] 强制平仓
---
src/main/java/com/nq/service/impl/UserPositionServiceImpl.java | 140 +++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 137 insertions(+), 3 deletions(-)
diff --git a/src/main/java/com/nq/service/impl/UserPositionServiceImpl.java b/src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
index 67784f6..6c3f208 100644
--- a/src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
@@ -119,7 +119,7 @@
SiteProduct siteProduct = iSiteProductService.getProductSetting();
User user = this.iUserService.getCurrentRefreshUser(request);
- if (siteProduct.getRealNameDisplay() && (StringUtils.isBlank(user.getRealName()) || StringUtils.isBlank(user.getIdCard()))) {
+ if (siteProduct.getRealNameDisplay() && user.getIsActive() != 2) {
return ServerResponse.createByErrorMsg("订单失败,请先实名认证", request);
}
// 手续费率
@@ -170,7 +170,7 @@
return ServerResponse.createByErrorMsg("报价0,请稍后再试", request);
}
- BigDecimal buyAmt = nowPrice.multiply(new BigDecimal(buyNum));
+ BigDecimal buyAmt = nowPrice.multiply(new BigDecimal(buyNum)).divide(new BigDecimal(lever));
BigDecimal orderFree = siteSettingBuyFee.multiply(buyAmt);
UserAssets userAssets = iUserAssetsServices.assetsByTypeAndUserId(stock.getStockType(), user.getId());
@@ -315,7 +315,9 @@
@Transactional
public ServerResponse sell(String positionSn, int doType, HttpServletRequest request) {
UserPosition userPosition = this.userPositionMapper.findPositionBySn(positionSn);
- BigDecimal siitteBuyFee = iSiteSettingService.getSiteSetting().getBuyFee();
+ // 手续费率
+ BigDecimal siitteBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ;
+
Boolean b = tradingHourService.timeCheck(userPosition.getStockCode());
if (!b) {
return ServerResponse.createByErrorMsg("订单失败,不在交易时间之内", request);
@@ -358,6 +360,7 @@
PositionProfitVO profitVO = UserPointUtil.getPositionProfitVO(userPosition,
priceServices.getNowPrice(userPosition.getStockCode()));
+
userAssetsServices.availablebalanceChange(stock.getStockType(),
userPosition.getUserId(), EUserAssets.CLOSE_POSITION,
profitVO.getAllProfitAndLose(), "", "");
@@ -1599,6 +1602,137 @@
}
+ @Override
+ @Transactional
+ public void stockConstraint(List<UserPosition> list) {
+ SiteSetting siteSetting = iSiteSettingService.getSiteSetting();
+ BigDecimal siteBuyFee = siteSetting.getBuyFee();
+
+ for (UserPosition position : list) {
+ //平仓检查
+ Result result = getResult(position);
+ if (result == null) continue;
+
+ //利润为0不需要进行强制平仓
+ if(result.signum == 0){
+ continue;
+ }
+ boolean liquidation = false;
+ liquidation = isLiquidation(position, result.signum, result.profit, liquidation);
+ if(liquidation){
+ extracted(position, result.nowPrice, result.stock);
+ }
+ }
+ }
+
+ private Result getResult(UserPosition position) {
+ // 检查订单是否存在
+ if (position == null) {
+ log.info("订单不存在,订单id: {}", position.getId());
+ return null;
+ }
+
+ // 检查用户是否存在
+ User user = this.userMapper.selectById(position.getUserId());
+ if (user == null) {
+ log.info("用户不存在,订单id: {}", position.getId());
+ return null;
+ }
+
+ // 检查是否在交易时间内
+ if (!tradingHourService.timeCheck(position.getStockCode())) {
+ log.info("不在交易时间之内,订单id: {}", position.getId());
+ return null;
+ }
+
+ //判断订单
+ if (1 == position.getIsLock().intValue()) {
+ log.info("订单已终止,订单id: {}", position.getId());
+ return null;
+ }
+
+ // 检查股票是否垫停
+ Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code", position.getStockCode()));
+ if (!priceServices.isLimitDownSell(stock.getStockCode())) {
+ log.info("股票垫停,无法平仓,订单id: {}", position.getId());
+ return null;
+ }
+
+ //最新报价
+ BigDecimal nowPrice = priceServices.getNowPrice(position.getStockCode());
+ if (nowPrice.compareTo(BigDecimal.ZERO) <= 0) {
+ log.info("报价0,平仓失败,订单id: {}", position.getId());
+ return null;
+ }
+
+ //判断订单是否已到强制平仓价格
+ BigDecimal purchaseAmount = position.getBuyOrderPrice().multiply(new BigDecimal(position.getOrderNum()));// 买入价总额
+ BigDecimal nowPriceAmount = nowPrice.multiply(new BigDecimal(position.getOrderNum())); // 现价总额
+
+ BigDecimal profit = nowPriceAmount.subtract(purchaseAmount);//利润
+ int signum = profit.signum(); // -1, 0, 1,分别表示 负数、零、正数
+ Result result = new Result(stock, nowPrice, profit, signum);
+ return result;
+ }
+
+ private static class Result {
+ public final Stock stock;//股票
+ public final BigDecimal nowPrice;//现价
+ public final BigDecimal profit;//利润
+ public final int signum;// -1, 0, 1,分别表示 负数、零、正数
+
+ public Result(Stock stock, BigDecimal nowPrice, BigDecimal profit, int signum) {
+ this.stock = stock;
+ this.nowPrice = nowPrice;
+ this.profit = profit;
+ this.signum = signum;
+ }
+ }
+
+ //判断平仓
+ private static boolean isLiquidation(UserPosition position, int signum, BigDecimal profit, boolean liquidation) {
+ if(position.getOrderDirection().equals("买涨")){
+ //如果买涨 signum 为-1则表示亏损
+ if(signum == -1){
+ //判断亏损金额是否达到保证金金额
+ BigDecimal negate = profit.negate();
+ if (negate.compareTo(position.getOrderTotalPrice()) >= 0){
+ //强制平仓
+ liquidation = true;
+ }
+ }
+ }else{
+ //买跌 signum
+ if(signum == 1){
+ //判断亏损金额是否达到保证金金额
+ if (profit.compareTo(position.getOrderTotalPrice()) >= 0){
+ //强制平仓
+ liquidation = true;
+ }
+ }
+ }
+ return liquidation;
+ }
+
+ //平仓
+ private void extracted(UserPosition position, BigDecimal nowPrice, Stock stock) {
+ // 更新订单信息
+ position.setSellOrderId(GeneratePosition.getPositionId());
+ position.setSellOrderPrice(nowPrice);
+ position.setSellOrderTime(new Date());
+ userPositionMapper.updateById(position);
+
+ // 计算手续费等
+ BigDecimal handlingFee = BigDecimal.ZERO;
+
+ //更新用户资产
+ userAssetsServices.availablebalanceChange(stock.getStockType(),
+ position.getUserId(),
+ EUserAssets.CONSTRAINT_CLOSE_POSITION,
+ position.getOrderTotalPrice(), "", "");
+ log.info("强制平仓成功,订单id: {}", position.getId());
+ }
+
}
--
Gitblit v1.9.3