diff --git a/src/main/java/com/sztzjy/forex/trading_trading/controller/MemberController.java b/src/main/java/com/sztzjy/forex/trading_trading/controller/MemberController.java index 86fdc7c..a9b3612 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/controller/MemberController.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/controller/MemberController.java @@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; @@ -119,8 +120,8 @@ public class MemberController { member.setCumulativeProfitLoss(0.0); } Double totalAssets = initialCapital+cumulativeProfitLoss; //总资产=初始资金+累计盈亏 - Double netValue = bigDecimalUtils.add(totalAssets, positionProfitLoss); - member.setTotalAssets(totalAssets); //设置总资产 + Double netValue = bigDecimalUtils.add(totalAssets, positionProfitLoss,2); + member.setTotalAssets(bigDecimalUtils.add(totalAssets,0.0,2)); //设置总资产 member.setNetValue(netValue); //设置净值 Double marginUsed = member.getMarginUsed(); //获取已用保证金 diff --git a/src/main/java/com/sztzjy/forex/trading_trading/controller/TakeStashController.java b/src/main/java/com/sztzjy/forex/trading_trading/controller/TakeStashController.java index 7b27090..e4ac584 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/controller/TakeStashController.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/controller/TakeStashController.java @@ -19,6 +19,7 @@ import com.sztzjy.forex.trading_trading.util.RedisUtil; import com.sztzjy.forex.trading_trading.util.ResultEntity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -237,9 +238,14 @@ public class TakeStashController { //当前持仓平仓 status设置为2 - @AnonymousAccess + @Transactional @PostMapping("closeTakeStash") public ResultEntity closeTakeStash(@RequestBody JSONObject jsonObject) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + return new ResultEntity(HttpStatus.BAD_REQUEST, "请稍后再试"); + } String stashId = jsonObject.getString("stashId"); String memberId = jsonObject.getString("memberId"); TakeStash takeStashNew = takeStashService.selectByPrimaryKey(stashId); @@ -278,6 +284,14 @@ public class TakeStashController { Double marginUsed = member.getMarginUsed();//未修改前member表中成员保证金 marginUsed = bigDecimalUtils.mul(marginUsed-margin,1,2); //修改成员保证金 + //处理保证金为负数的情况和保证金未释放的情况 + List takeStashList = takeStashService.selectAllByMemberIdAndStatus(memberId, 0); + if (takeStashList==null || takeStashList.size()==0){ + marginUsed=0.0; + } + if(marginUsed<0){ + marginUsed=0.0; + } member.setMarginUsed(marginUsed); Integer closingTrades = member.getClosingTrades(); if(closingTrades==null){ @@ -299,6 +313,7 @@ public class TakeStashController { takeStash.setProfitAndLossByClose(bigDecimalUtils.mul(profitAndLoss,1,2)); takeStash.setTimeTransactionClose(new Date()); takeStashService.updateByPrimaryKeySelective(takeStash); + redisUtil.del("trainingId_"+takeStashNew.getTrainingId()+"_stashId_"+stashId); // wainingService.compareMarginLevels(member.getMemberId(), member.getTrainingId());//更改可用保证金后 调用预警 @@ -323,7 +338,7 @@ public class TakeStashController { margin=transactionVolume*priceTransaction*Constant.LEVERQUANTITY; } return margin; - }else { + }else if(takeStashList.size()>1){ for (int i = 0; i < takeStashList.size(); i++) { TakeStash takeStash = takeStashList.get(i); String buySellTypeTakeStash = takeStash.getBuySellType(); @@ -338,6 +353,8 @@ public class TakeStashController { } totalVolumeTransaction=totalVolumeTransaction+volumeTransactionTakeStash; } + }else { + return 0.0; } if (buyTotalVolumeTransaction>=sellTotalVolumeTransaction){ //设置平仓前 sell\buy的最高交易交易总量 @@ -378,7 +395,7 @@ public class TakeStashController { if(takeStashList.size()==1){ margin=transactionVolume*Constant.LEVERQUANTITY; return margin; - }else { + }else if (takeStashList.size()>1){ for (int i = 0; i < takeStashList.size(); i++) { TakeStash takeStash = takeStashList.get(i); String buySellTypeTakeStash = takeStash.getBuySellType(); @@ -388,6 +405,8 @@ public class TakeStashController { sellTotalVolumeTransaction=sellTotalVolumeTransaction+takeStash.getVolumeTransaction(); } } + }else { + margin=0.0; } if(Constant.BUY_BUYSELLTYPE.equals(buySellType)){ if(buyTotalVolumeTransaction>=sellTotalVolumeTransaction){ diff --git a/src/main/java/com/sztzjy/forex/trading_trading/service/MemberService.java b/src/main/java/com/sztzjy/forex/trading_trading/service/MemberService.java index 1e3d3fa..dcec1af 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/service/MemberService.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/service/MemberService.java @@ -240,19 +240,19 @@ public class MemberService { memberMapper.deleteByExample(example); } - //获取可用资金 + //获取可用资金 可用资金=净值-已用保证金 净值=总资产+未平仓持单的浮动盈亏 public Double getAvailableFunds(Member member) { Double positionProfitLoss = flashTotalPositionProfitLoss(member.getMemberId()); if (positionProfitLoss == null) { positionProfitLoss = 0.0; } Double initialCapital = member.getInitialCapital();//初始资金 - Double totalAssets = initialCapital + positionProfitLoss; - Double netValue = bigDecimalUtils.add(totalAssets, positionProfitLoss); Double cumulativeProfitLoss = member.getCumulativeProfitLoss(); //累计盈亏 if (cumulativeProfitLoss == null) { member.setCumulativeProfitLoss(0.0); } + Double totalAssets = initialCapital + cumulativeProfitLoss; + Double netValue = bigDecimalUtils.add(totalAssets, positionProfitLoss); Double marginUsed = member.getMarginUsed(); //获取已用保证金 if (marginUsed == null) { marginUsed = 0.0; diff --git a/src/main/java/com/sztzjy/forex/trading_trading/service/ScheduledTask.java b/src/main/java/com/sztzjy/forex/trading_trading/service/ScheduledTask.java index 93153fa..fdbe8f4 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/service/ScheduledTask.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/service/ScheduledTask.java @@ -96,15 +96,12 @@ public class ScheduledTask { List forexMarketDataList = ForexMarketData.copyToForexData(forexData); forexMarketDataService.insertAll(forexMarketDataList); redisUtil.set("ForexDateList", forexMarketDataList); + log.info("--------真实数据插入成功------"); } //每10秒执行一次 根据真实汇率数据生成模拟汇率数据 @Scheduled(cron = "0/5 * * * * ?") public void insertSimulatedForexMarketData() { -// if(!timerEnable){ -// return; -// } - //获取batchId相同的最后入库的数据 List forexMarketDataList=redisUtil.get("ForexDateList"); // forexMarketDataList = forexMarketDataService.selectLastForexMarketData(); @@ -116,7 +113,28 @@ public class ScheduledTask { List forexMarketData = new ArrayList<>(); String batchId = IdUtil.simpleUUID(); for (ForexMarketData data : forexMarketDataList) { - Double buyPic = modifyDecimal(data.getBuyPic(), random); + Double buyPic = subtractLastDigit(data.getBuyPic(), random); + BigDecimal sp = BigDecimal.valueOf(buyPic); + int randomNumber = random.nextInt(10); + if(randomNumber==1){ + sp= BigDecimal.valueOf(buyPic-0.0001).setScale(4, BigDecimal.ROUND_UP); + }else if(randomNumber==2){ + sp= BigDecimal.valueOf(buyPic-0.0001).setScale(4, BigDecimal.ROUND_UP); + }else if(randomNumber==3){ + sp= BigDecimal.valueOf(buyPic-0.0001).setScale(4, BigDecimal.ROUND_UP); + }else if(randomNumber==4){ + sp= BigDecimal.valueOf(buyPic-0.0002).setScale(4, BigDecimal.ROUND_UP); + }else if(randomNumber==5){ + sp= BigDecimal.valueOf(buyPic-0.0002).setScale(4, BigDecimal.ROUND_UP); + }else if(randomNumber==6){ + sp= BigDecimal.valueOf(buyPic-0.0003).setScale(4, BigDecimal.ROUND_UP); + }else if(randomNumber==7){ + sp= BigDecimal.valueOf(buyPic-0.0004).setScale(4, BigDecimal.ROUND_UP); + }else if(randomNumber==8){ + sp= BigDecimal.valueOf(buyPic-0.0005).setScale(4, BigDecimal.ROUND_UP); + }else if(randomNumber==9){ + sp= BigDecimal.valueOf(buyPic-0.0006).setScale(4, BigDecimal.ROUND_UP); + } // Double openPriDouble = Double.valueOf(data.getOpenPri()); String diffAmo = bigDecimalUtils.sub(String.valueOf(buyPic), data.getOpenPri()).toString(); ForexMarketData resultData = new ForexMarketData( @@ -131,7 +149,8 @@ public class ScheduledTask { data.getLowPic(), data.getOpenPri(), data.getRanges(), - String.valueOf(modifyDecimal(Double.parseDouble(data.getSellPic()), random)), + sp.toString(), +// String.valueOf(modifyDecimal(Double.parseDouble(data.getSellPic()), random)), data.getYesPic(), diffAmo, data.getDiffPer(), @@ -140,7 +159,7 @@ public class ScheduledTask { } // forexMarketDataService.insertAllByMarketData(forexMarketData); redisUtil.set("ForexDateList", forexMarketData); - log.info("--------插入模拟汇率数据成功------"); +// log.info("--------插入模拟汇率数据成功------"); }catch (Exception e) { log.error("----------插入模拟汇率数据失败:", e.getMessage()); } @@ -177,6 +196,60 @@ public class ScheduledTask { + public double subtractLastDigit(Double num,Random random) { + // 将数字转换为字符串 + String numStr=""; + numStr = Double.toString(num); + + // 提取小数点后的部分 + String decimalPart = numStr.split("\\.")[1]; + Boolean flag=true; + if (decimalPart.startsWith("0")){ + decimalPart="1"+decimalPart.substring(1); + flag=false; + } + + if(decimalPart.length()<=3){ + decimalPart=decimalPart+"0"; + } + if (decimalPart.length()>6){ + decimalPart=decimalPart.substring(0,4); + } + + + // 将提取的小数部分转换为整数 + int decimalInt = Integer.parseInt(decimalPart); + + // 对最后一位进行减一操作 + int randomNumber = random.nextInt(7); + if(randomNumber==1){ + decimalInt=decimalInt-1; + }else if(randomNumber==2){ + decimalInt=decimalInt-2; + }else if(randomNumber==3){ + decimalInt=decimalInt-3; + }else if(randomNumber==4){ + decimalInt=decimalInt+1; + }else if(randomNumber==5){ + decimalInt=decimalInt+2; + }else if(randomNumber==6){ + decimalInt=decimalInt+3; + } + + // 构造新的数字 + String newNumStr = numStr.split("\\.")[0] + "." + decimalInt; + // 将新的数字转换为double类型并返回 + Double v = Double.parseDouble(newNumStr); + if (flag==false){ + v=v-0.1; + } + String formattedNum = String.format("%.4f", v); // 保留小数点后四位 + Double result = Double.parseDouble(formattedNum); + return result; + } + + + //监听止损止盈 根据code获取当前买卖价格 如果价格高于/低于止损止盈 则按照止损止盈的值进行平仓 //查询实训表中状态为1的所有实训并获取ID 获取持仓表中所有状态为0 且止损和止盈不为空的所有数据 获取当前价位如果 @Scheduled(cron = "0 */2 * * * ?") @@ -210,28 +283,44 @@ public class ScheduledTask { Double sellPic = Double.valueOf(forexMarketData.getSellPic()); if(stopLoss!=-1 && sellPic<=stopLoss){ Double margin = takeStashController.startUSDMarginNeed(trainingId, memberId, 0, tradingCode, buySellType, transactionVolume); + if (margin==0.0){ + redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); + continue; + } Double profitLoss=(stopLoss-priceTransaction)*transactionVolume*Constant.PEACEQUANTITY/stopLoss; //止损盈利 - takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,sellPic); + takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,stopLoss); redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); } if(stopWin!=-1 && sellPic>=stopWin){ Double margin = takeStashController.startUSDMarginNeed(trainingId, memberId, 0, tradingCode, buySellType, transactionVolume); + if (margin==0.0){ + redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); + continue; + } Double profitLoss=(stopWin-priceTransaction)*transactionVolume*Constant.PEACEQUANTITY/stopWin; //止盈盈利 - takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,sellPic); + takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,stopWin); redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); } }else { //开仓方式为卖 则平仓方式为买 先获取买价 Double buyPic = forexMarketData.getBuyPic(); if(stopLoss!=-1 && buyPic<=stopLoss){ Double margin = takeStashController.startUSDMarginNeed(trainingId, memberId, 0, tradingCode, buySellType, transactionVolume); + if (margin==0.0){ + redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); + continue; + } Double profitLoss=(priceTransaction-stopLoss)*transactionVolume*Constant.PEACEQUANTITY/stopLoss; - takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,buyPic); + takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,stopLoss); redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); } if(stopWin!=-1 && buyPic>=stopWin){ Double margin = takeStashController.startUSDMarginNeed(trainingId, memberId, 0, tradingCode, buySellType, transactionVolume); + if (margin==0.0){ + redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); + continue; + } Double profitLoss=(priceTransaction-stopWin)*transactionVolume*Constant.PEACEQUANTITY/stopWin; - takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,buyPic); + takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,stopWin); redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); } } @@ -240,28 +329,44 @@ public class ScheduledTask { Double sellPic = Double.valueOf(forexMarketData.getSellPic()); if(stopLoss!=-1 && sellPic<=stopLoss){ Double margin = takeStashController.endUSDMarginNeed( trainingId, memberId,0 , tradingCode, buySellType, transactionVolume, priceTransaction); + if (margin==0.0){ + redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); + continue; + } Double profitLoss=(stopLoss-priceTransaction)*transactionVolume*Constant.PEACEQUANTITY; - takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,sellPic); + takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,stopLoss); redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); } if(stopWin!=-1 && sellPic>=stopWin){ Double margin = takeStashController.endUSDMarginNeed( trainingId, memberId,0 , tradingCode, buySellType, transactionVolume, priceTransaction); + if (margin==0.0){ + redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); + continue; + } Double profitLoss=(stopWin-priceTransaction)*transactionVolume*Constant.PEACEQUANTITY; - takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,sellPic); + takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,stopWin); redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); } }else { //开仓方式为卖 则平仓方式为买 先获取买价 Double buyPic = forexMarketData.getBuyPic(); if(stopLoss!=-1 && buyPic<=stopLoss){ Double margin = takeStashController.endUSDMarginNeed( trainingId, memberId,0 , tradingCode, buySellType, transactionVolume, priceTransaction); + if (margin==0.0){ + redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); + continue; + } Double profitLoss=(priceTransaction-stopLoss)*transactionVolume*Constant.PEACEQUANTITY; - takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,buyPic); + takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,stopLoss); redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); } if(stopWin!=-1 && buyPic>=stopWin){ Double margin = takeStashController.endUSDMarginNeed( trainingId, memberId,0 , tradingCode, buySellType, transactionVolume, priceTransaction); + if (margin==0.0){ + redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); + continue; + } Double profitLoss=(priceTransaction-stopWin)*transactionVolume*Constant.PEACEQUANTITY; - takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,buyPic); + takeStashController.updateMemberAndTakeStash(memberId,stashId,profitLoss,margin,stopWin); redisUtil.del("trainingId_"+trainingId+"_stashId_"+stashId); } } diff --git a/src/main/java/com/sztzjy/forex/trading_trading/util/BigDecimalUtils.java b/src/main/java/com/sztzjy/forex/trading_trading/util/BigDecimalUtils.java index bb06715..4392963 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/util/BigDecimalUtils.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/util/BigDecimalUtils.java @@ -15,6 +15,12 @@ public class BigDecimalUtils { return b1.add(b2).doubleValue(); } + public double add(double v1, double v2,int scale) { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue(); + } + /** * 提供精确的加法运算 *