From e0fea5cb1ab3282a645f83c1db8dc56745a3da62 Mon Sep 17 00:00:00 2001 From: yz <3614508250@qq.com> Date: Wed, 19 Jul 2023 16:20:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=80=BB=E6=8C=81=E4=BB=93?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E4=BF=AE=E6=94=B9=20=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E6=AD=A2=E6=8D=9F=E6=AD=A2=E7=9B=88=E5=AE=9A=E6=97=B6=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MemberController.java | 15 +- .../controller/PendingOrderController.java | 66 ++++++- .../controller/TakeStashController.java | 182 ++++++++++++------ .../controller/TradingController.java | 53 ++++- .../forex/trading_trading/dto/PengdingVo.java | 48 +++++ .../trading_trading/dto/TakeStashVO.java | 3 + .../mappers/TakeStashMapper.java | 1 + .../mappers/TrainingMapper.java | 3 + .../service/PendingOrderService.java | 8 +- .../service/ScheduledTask.java | 101 +++++++++- .../service/TakeStashService.java | 8 + .../service/TrainingService.java | 6 + .../util/ForexMarketDateUtil.java | 30 +++ 13 files changed, 436 insertions(+), 88 deletions(-) create mode 100644 src/main/java/com/sztzjy/forex/trading_trading/dto/PengdingVo.java create mode 100644 src/main/java/com/sztzjy/forex/trading_trading/util/ForexMarketDateUtil.java 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 0788227..df8014f 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 @@ -37,6 +37,9 @@ public class MemberController { @Autowired TrainingService trainingService; + @Autowired + TakeStashController takeStashController; + @AnonymousAccess @PostMapping("getMemberById") public ResultEntity getMember(@RequestBody String memberId) { @@ -51,7 +54,17 @@ public class MemberController { String trainingId = jsonObject.getString("trainingId"); Integer schoolId = jsonObject.getInteger("schoolId"); Member member = memberService.selectByNameAndSchoolIdAndTrainingID(name, schoolId, trainingId); - return new ResultEntity(HttpStatus.OK, "获取成员ID", member); + + Double positionProfitLoss = takeStashController.flashTotalPositionProfitLoss(member.getMemberId()); + member.setPositionProfitLoss(positionProfitLoss); //设置持仓盈亏 + Double totalAssets = member.getTotalAssets(); + Double netValue=totalAssets+positionProfitLoss; + member.setNetValue(netValue); //设置净值 + Double marginUsed = member.getMarginUsed(); //获取已用保证金 + member.setAvailableFunds(netValue-marginUsed); //设置可用资金 + member.setMarginLevel(netValue/marginUsed); //设置保证金水平 + + return new ResultEntity(HttpStatus.OK, "获取成员ID",member); } @Permission(codes = PermissionType.TRAINING_MANAGEMENT_SEARCH) diff --git a/src/main/java/com/sztzjy/forex/trading_trading/controller/PendingOrderController.java b/src/main/java/com/sztzjy/forex/trading_trading/controller/PendingOrderController.java index 505d369..d33608f 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/controller/PendingOrderController.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/controller/PendingOrderController.java @@ -4,8 +4,12 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONObject; import com.sztzjy.forex.trading_trading.annotation.AnonymousAccess; +import com.sztzjy.forex.trading_trading.dto.PengdingVo; +import com.sztzjy.forex.trading_trading.dto.TakeStashVO; +import com.sztzjy.forex.trading_trading.entity.ForexMarketData; import com.sztzjy.forex.trading_trading.entity.PendingOrder; import com.sztzjy.forex.trading_trading.service.PendingOrderService; +import com.sztzjy.forex.trading_trading.util.ForexMarketDateUtil; import com.sztzjy.forex.trading_trading.util.RedisUtil; import com.sztzjy.forex.trading_trading.util.ResultEntity; import org.springframework.beans.factory.annotation.Autowired; @@ -15,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; @@ -25,32 +30,39 @@ public class PendingOrderController { @Autowired PendingOrderService pendingOrderService; + @Autowired + ForexMarketDateUtil forexMarketDateController; + @Autowired RedisUtil redisUtil; //查询挂单数据 @AnonymousAccess @PostMapping("getPendingOrder") - public ResultEntity> getPendingOrder(@RequestBody JSONObject jsonObject){ + public ResultEntity> getPendingOrder(@RequestBody JSONObject jsonObject){ String trainingId = String.valueOf(jsonObject.get("trainingId")); String memberId = String.valueOf(jsonObject.get("memberId")); PendingOrder pendingOrder=new PendingOrder(); pendingOrder.setStatus(0); pendingOrder.setTrainingId(trainingId); pendingOrder.setMemberId(memberId); - List pendingOrders = pendingOrderService.selectByExample(pendingOrder); - return new ResultEntity(HttpStatus.OK, "获取挂单数据成功",pendingOrders); + List pendingOrders = pendingOrderService.selectByTrainingIdAndStatusAndMemberId(pendingOrder); + List pengdingVoList=new ArrayList<>(); + for (int i = 0; i < pendingOrders.size(); i++) { + PengdingVo pengdingVo=new PengdingVo(pendingOrders.get(i)); + pengdingVoList.add(pengdingVo); + } + List data = flashPendingCurrentPrice(pengdingVoList).getBody().getData(); + return new ResultEntity(HttpStatus.OK, "获取挂单数据成功",data); } //撤单 撤单成功后 根据pendingOrderId删除redis键 @AnonymousAccess @PostMapping("cancelOrder") - public ResultEntity cancelOrder(@RequestBody String pendingOrderId){ - PendingOrder pendingOrder=new PendingOrder(); - pendingOrder.setPendingOrderId(pendingOrderId); - pendingOrder.setStatus(1); - pendingOrderService.cancelOrder(pendingOrder); - redisUtil.del("pengingOrder_"+pendingOrder.getPendingOrderId()); + public ResultEntity cancelOrder(@RequestBody JSONObject jsonObject){ + String pendingOrderId = String.valueOf(jsonObject.get("pendingOrderId")); + pendingOrderService.cancelOrder(pendingOrderId); + redisUtil.del("pengingOrder_"+pendingOrderId); return new ResultEntity(HttpStatus.OK, "撤单成功"); } @@ -93,4 +105,40 @@ public class PendingOrderController { pendingOrderService.insert(pendingOrder); redisUtil.set("pengingOrder_"+pendingOrder.getPendingOrderId(),pendingOrder.getValidityTime()); } + + //挂单刷新当前价位 + @AnonymousAccess + @PostMapping("flashPendingCurrentPrice") + public ResultEntity> flashPendingCurrentPrice(@RequestBody List pengdingVoList){ + List pengdingVos=new ArrayList<>(); + for (int i = 0; i < pengdingVoList.size(); i++) { + PengdingVo pengdingVo = pengdingVoList.get(i); + if(0!=pengdingVo.getStatus()){ + continue; + } + String buySellType = pengdingVo.getBuySellType(); //买入或卖出 + String tradingCode = pengdingVo.getTradingCode(); //交易品种 + ForexMarketData forexData = forexMarketDateController.getForexMarketDateByCode(tradingCode); + Double nowBuyPic = forexData.getBuyPic(); //当前买价 + Double nowSellPic = Double.valueOf(forexData.getSellPic()); //当前卖价 + if (tradingCode.startsWith("USD")) { //美元在前 + if("buy".equals(buySellType)){ //买 + pengdingVo.setCurrentPrice(nowBuyPic); + }else { //卖 + pengdingVo.setCurrentPrice(nowSellPic); + } + }else { //美元在后 + if("buy".equals(buySellType)){ //买 + pengdingVo.setCurrentPrice(nowBuyPic); + }else { //卖 + pengdingVo.setCurrentPrice(nowSellPic); + } + } + pengdingVos.add(pengdingVo); + } + if(0==pengdingVos.size()){ + return new ResultEntity(HttpStatus.OK, "挂单数据为空",null); + } + return new ResultEntity(HttpStatus.OK, "挂单当前价格刷新",pengdingVos); + } } 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 651d1ec..0afd8c0 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 @@ -9,6 +9,8 @@ import com.sztzjy.forex.trading_trading.entity.Member; import com.sztzjy.forex.trading_trading.entity.TakeStash; import com.sztzjy.forex.trading_trading.service.MemberService; import com.sztzjy.forex.trading_trading.service.TakeStashService; +import com.sztzjy.forex.trading_trading.service.TrainingService; +import com.sztzjy.forex.trading_trading.util.ForexMarketDateUtil; import com.sztzjy.forex.trading_trading.util.RedisUtil; import com.sztzjy.forex.trading_trading.util.ResultEntity; import org.springframework.beans.factory.annotation.Autowired; @@ -18,10 +20,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @RestController @RequestMapping("api/takeStash") @@ -39,18 +38,26 @@ public class TakeStashController { @Autowired MemberService memberService; + @Autowired + ForexMarketDateUtil forexMarketDateController; + + @Autowired + TrainingService trainingService; + //获取当前持仓表 status 0为获取当前持仓/1为挂单持仓/2为历史持仓 @AnonymousAccess @PostMapping("getTakeStashList") public ResultEntity getTakeStashList(@RequestBody TakeStash takeStash) { - List takeStashList = takeStashService.findTakeStashByTrainingIdAndMemberIdAndStatus(takeStash.getTrainingId(),takeStash.getMemberId(), takeStash.getStatus()); - List takeStashVOList=new ArrayList<>(); + List takeStashList = takeStashService.findTakeStashByTrainingIdAndMemberIdAndStatus(takeStash.getTrainingId(), takeStash.getMemberId(), takeStash.getStatus()); + List takeStashVOList = new ArrayList<>(); for (int i = 0; i < takeStashList.size(); i++) { - TakeStashVO takeStashVO=new TakeStashVO(takeStashList.get(i)); + TakeStashVO takeStashVO = new TakeStashVO(takeStashList.get(i)); takeStashVOList.add(takeStashVO); } - takeStashVOList = flashProfitAndLoss(takeStashVOList).getBody().getData(); - return new ResultEntity(HttpStatus.OK, "返回持仓数据",takeStashVOList); + if (takeStash.getStatus() == 0) { + takeStashVOList = flashProfitAndLoss(takeStashVOList).getBody().getData(); + } + return new ResultEntity(HttpStatus.OK, "返回持仓数据", takeStashVOList); } //根据持仓ID获取单个持仓数据 @@ -65,45 +72,78 @@ public class TakeStashController { //持仓盈亏和当前价格刷新 @AnonymousAccess @PostMapping("flashProfitAndLoss") - public ResultEntity> flashProfitAndLoss(@RequestBody List takeStashVOList){ - List takeStashVOS=new ArrayList<>(); + public ResultEntity> flashProfitAndLoss(@RequestBody List takeStashVOList) { + List takeStashVOS = new ArrayList<>(); for (int i = 0; i < takeStashVOList.size(); i++) { TakeStashVO takeStashVO = takeStashVOList.get(i); - if(0!=takeStashVO.getStatus()){ + if (0 != takeStashVO.getStatus()) { continue; } String buySellType = takeStashVO.getBuySellType(); //买入或卖出 String tradingCode = takeStashVO.getTradingCode(); //交易品种 Double priceTransaction = takeStashVO.getPriceTransaction(); //交易价格 Double volumeTransaction = takeStashVO.getVolumeTransaction(); //交易量 - ForexMarketData forexData = getForexMarketDateByCode(tradingCode); + ForexMarketData forexData = forexMarketDateController.getForexMarketDateByCode(tradingCode); Double nowBuyPic = forexData.getBuyPic(); //当前买价 Double nowSellPic = Double.valueOf(forexData.getSellPic()); //当前卖价 Double profitAndLoss; if (tradingCode.startsWith("USD")) { //美元在前 - if("buy".equals(buySellType)){ //买 - profitAndLoss= (nowBuyPic-priceTransaction)*volumeTransaction*100000/nowBuyPic; + if ("buy".equals(buySellType)) { //买 + profitAndLoss = (nowBuyPic - priceTransaction) * volumeTransaction * 100000 / nowBuyPic; takeStashVO.setCurrentPrice(nowBuyPic); - }else { //卖 - profitAndLoss= (nowSellPic-priceTransaction)*volumeTransaction*100000/nowSellPic; + } else { //卖 + profitAndLoss = (nowSellPic - priceTransaction) * volumeTransaction * 100000 / nowSellPic; takeStashVO.setCurrentPrice(nowSellPic); } - }else { //美元在后 - if("buy".equals(buySellType)){ //买 - profitAndLoss= (nowBuyPic-priceTransaction)*volumeTransaction*100000; + } else { //美元在后 + if ("buy".equals(buySellType)) { //买 + profitAndLoss = (nowBuyPic - priceTransaction) * volumeTransaction * 100000; takeStashVO.setCurrentPrice(nowBuyPic); - }else { //卖 - profitAndLoss= (nowSellPic-priceTransaction)*volumeTransaction*100000; + } else { //卖 + profitAndLoss = (nowSellPic - priceTransaction) * volumeTransaction * 100000; takeStashVO.setCurrentPrice(nowSellPic); } } takeStashVO.setProfitAndLoss(profitAndLoss); takeStashVOS.add(takeStashVO); } - if(0==takeStashVOS.size()){ - return new ResultEntity(HttpStatus.OK, "当前持仓数据为空",null); + if (0 == takeStashVOS.size()) { + return new ResultEntity(HttpStatus.OK, "当前持仓数据为空", null); } - return new ResultEntity(HttpStatus.OK, "持仓盈亏和当前价格刷新",takeStashVOS); + return new ResultEntity(HttpStatus.OK, "持仓盈亏和当前价格刷新", takeStashVOS); + } + + //总持仓盈亏刷新 获取member下所有持仓数据 + public Double flashTotalPositionProfitLoss(String memberId){ + List takeStashList = takeStashService.selectAllByMemberIdAndStatus(memberId,0); + Double totalProfitAndLoss = 0.0; + for (int i = 0; i < takeStashList.size(); i++) { + TakeStash takeStash = takeStashList.get(i); + String buySellType = takeStash.getBuySellType(); //买入或卖出 + String tradingCode = takeStash.getTradingCode(); //交易品种 + Double priceTransaction = takeStash.getPriceTransaction(); //交易价格 + Double volumeTransaction = takeStash.getVolumeTransaction(); //交易量 + ForexMarketData forexData = forexMarketDateController.getForexMarketDateByCode(tradingCode); + Double nowBuyPic = forexData.getBuyPic(); //当前买价 + Double nowSellPic = Double.valueOf(forexData.getSellPic()); //当前卖价 + Double profitAndLoss; + if (tradingCode.startsWith("USD")) { //美元在前 + if ("buy".equals(buySellType)) { //买 + profitAndLoss = (nowBuyPic - priceTransaction) * volumeTransaction * 100000 / nowBuyPic; + } else { //卖 + profitAndLoss = (nowSellPic - priceTransaction) * volumeTransaction * 100000 / nowSellPic; + } + } else { //美元在后 + if ("buy".equals(buySellType)) { //买 + profitAndLoss = (nowBuyPic - priceTransaction) * volumeTransaction * 100000; + } else { //卖 + profitAndLoss = (nowSellPic - priceTransaction) * volumeTransaction * 100000; + } + } + totalProfitAndLoss=totalProfitAndLoss+profitAndLoss; + } + return totalProfitAndLoss; + } //修改当前持仓 @@ -123,10 +163,10 @@ public class TakeStashController { if (winOrLossStopBoolean == false) { return new ResultEntity(HttpStatus.BAD_REQUEST, "止损或获利输入错误"); } - if (null!=stopLoss){ + if (null != stopLoss) { takeStash.setStopLoss(stopLoss); } - if( null != stopWin){ + if (null != stopWin) { takeStash.setStopWin(stopWin); } } @@ -134,6 +174,7 @@ public class TakeStashController { return new ResultEntity(HttpStatus.OK, "修改持仓成功"); } + //当前持仓平仓 status设置为2 @AnonymousAccess @PostMapping("closeTakeStash") @@ -147,61 +188,80 @@ public class TakeStashController { String buySellType = takeStashNew.getBuySellType(); String tradingCode = takeStashNew.getTradingCode(); Double volumeTransaction = takeStashNew.getVolumeTransaction(); - ForexMarketData forexData = getForexMarketDateByCode(tradingCode); - Double backFund=0.0; //返还资金 - if (tradingCode.startsWith("USD")) { //美元在前 返还资金表达式为 1000*卖/买价*买卖手 - if("buy".equals(buySellType)){ //如果持仓方向为买 则平仓方向为卖 可用资金=可用资金+当前卖价*1000*买卖手 - backFund=Double.valueOf(forexData.getSellPic())*1000*volumeTransaction; - availableFunds=availableFunds+backFund; - }else if("sell".equals(buySellType)){ //如果持仓方向为卖 则平仓方向为买 可用资金=可用资金+当前买价*1000*买卖手 - backFund=forexData.getBuyPic()*1000*volumeTransaction; - availableFunds=availableFunds+backFund; + Double priceTransaction = takeStashNew.getPriceTransaction(); + ForexMarketData forexData = forexMarketDateController.getForexMarketDateByCode(tradingCode); + Double backFund = 0.0; //返还资金 + Double CumulativeProfitLoss=0.0; //盈亏 + Double nowSellPic = Double.valueOf(forexData.getSellPic());//当前卖价 + Double nowBuyPic = forexData.getBuyPic(); //当前买价 + if (tradingCode.startsWith("USD")) { //美元在前 返还资金表达式为 + if ("buy".equals(buySellType)) { //如果持仓方向为买 则平仓方向为卖 + CumulativeProfitLoss=(nowSellPic - priceTransaction) * volumeTransaction * 100000 / nowSellPic; + backFund = 1000 * volumeTransaction+CumulativeProfitLoss; + availableFunds = availableFunds + backFund; + } else if ("sell".equals(buySellType)) { //如果持仓方向为卖 则平仓方向为买 可用资金=可用资金+当前买价*1000*买卖手 + CumulativeProfitLoss=( priceTransaction-nowBuyPic ) * volumeTransaction * 100000 / nowBuyPic; + backFund = 1000 * volumeTransaction+CumulativeProfitLoss; + availableFunds = availableFunds + backFund; } - }else { //美元在后 - backFund=1000*volumeTransaction; - if("buy".equals(buySellType)){ //如果持仓方向为买 则平仓方向为卖 可用资金=可用资金+1000*买卖手 - availableFunds=availableFunds+backFund; - }else if("sell".equals(buySellType)){ //如果持仓方向为卖 则平仓方向为买 可用资金=可用资金+当前买价*1000*买卖手 - availableFunds=availableFunds+backFund; + } else { //美元在后 + backFund = 1000 * volumeTransaction; + if ("buy".equals(buySellType)) { //如果持仓方向为买 则平仓方向为卖 可用资金=可用资金+1000*买卖手 + CumulativeProfitLoss=(priceTransaction-nowSellPic)*volumeTransaction*100000/nowSellPic; + backFund=1000*volumeTransaction*nowSellPic+CumulativeProfitLoss; + availableFunds = availableFunds + backFund; + } else if ("sell".equals(buySellType)) { //如果持仓方向为卖 则平仓方向为买 可用资金=可用资金+当前买价*1000*买卖手 + CumulativeProfitLoss=( priceTransaction-nowBuyPic)*volumeTransaction*100000/nowBuyPic; + backFund=1000*volumeTransaction*nowBuyPic+CumulativeProfitLoss; + availableFunds = availableFunds + backFund; } } Double marginUsed = member.getMarginUsed();//未修改前member表中成员保证金 Double tradingMargin = takeStashNew.getTradingMargin(); //进仓时使用的保证金 - marginUsed=marginUsed-tradingMargin; //修改成员保证金 + marginUsed = marginUsed - tradingMargin; //修改成员保证金 member.setAvailableFunds(availableFunds); member.setMarginUsed(marginUsed); Integer closingTrades = member.getClosingTrades(); member.setClosingTrades(closingTrades++); + Double cumulativeProfitLoss = member.getCumulativeProfitLoss(); //为修改前member表中的累积盈亏 + member.setCumulativeProfitLoss(cumulativeProfitLoss+CumulativeProfitLoss); //修改累计盈亏 + member.setTotalAssets(member.getInitialCapital()+cumulativeProfitLoss+CumulativeProfitLoss); //设置总资产 memberService.updateByPrimaryKeySelective(member); + TakeStash takeStash = new TakeStash(); takeStash.setStashId(stashId); takeStash.setStatus(2); - takeStash.setProfitAndLossByClose(backFund- tradingMargin); //盈亏=返还资金-进仓时使用的保证金 + takeStash.setProfitAndLossByClose(backFund - tradingMargin); //盈亏=返还资金-进仓时使用的保证金 takeStashService.updateByPrimaryKeySelective(takeStash); return new ResultEntity(HttpStatus.OK, "平仓成功"); } - //监听止损止盈 根据code获取当前买卖价格 如果价格高于/低于止损止盈 则按照止损止盈的值进行平仓 - //获取持仓表中所有状态为0 且止损和止盈部为空的所有数据 获取当前价位如果 - public void monitorStopLossProfit(){ -// takeStashService. - } + public void updateMemberAndTakeStash(String memberId,String stashId,Double backFund,Double CumulativeProfitLoss){ + TakeStash takeStashNew = takeStashService.selectByPrimaryKey(stashId); + Member member = memberService.selectByPrimaryKey(memberId); - //根据tradingCode获取ForexMarketData对象 - public ForexMarketData getForexMarketDateByCode(String tradingCode){ - List forexDateList = redisUtil.get("ForexDateList"); - Map map=new HashMap<>(); - if (forexDateList.size() > 0) { - for (int i = 0; i < forexDateList.size(); i++) { - String getCode = forexDateList.get(i).getCode(); - map.put(getCode,forexDateList.get(i)); - } - } - ForexMarketData forexData = map.get(tradingCode); - return forexData; + Double marginUsed = member.getMarginUsed();//未修改前member表中成员保证金 + Double tradingMargin = takeStashNew.getTradingMargin(); //进仓时使用的保证金 + marginUsed = marginUsed - tradingMargin; //修改成员保证金 + Double availableFunds = member.getAvailableFunds(); //可用资金 + availableFunds=availableFunds+backFund; + member.setAvailableFunds(availableFunds); + member.setMarginUsed(marginUsed); + Integer closingTrades = member.getClosingTrades(); + member.setClosingTrades(closingTrades++); + Double cumulativeProfitLoss = member.getCumulativeProfitLoss(); //为修改前member表中的累积盈亏 + member.setCumulativeProfitLoss(cumulativeProfitLoss+CumulativeProfitLoss); //修改累计盈亏 + member.setTotalAssets(member.getInitialCapital()+cumulativeProfitLoss+CumulativeProfitLoss); //设置总资产 + memberService.updateByPrimaryKeySelective(member); + + TakeStash takeStash = new TakeStash(); + takeStash.setStashId(stashId); + takeStash.setStatus(2); + takeStash.setProfitAndLossByClose(backFund - tradingMargin); //盈亏=返还资金-进仓时使用的保证金 + takeStashService.updateByPrimaryKeySelective(takeStash); } diff --git a/src/main/java/com/sztzjy/forex/trading_trading/controller/TradingController.java b/src/main/java/com/sztzjy/forex/trading_trading/controller/TradingController.java index fc47881..437d4d1 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/controller/TradingController.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/controller/TradingController.java @@ -1,6 +1,7 @@ package com.sztzjy.forex.trading_trading.controller; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONObject; import com.sztzjy.forex.trading_trading.annotation.AnonymousAccess; import com.sztzjy.forex.trading_trading.entity.ForexMarketData; @@ -20,7 +21,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; //学生端 交易 @RestController @@ -96,7 +99,11 @@ public class TradingController { Double buyPic = forexData.getBuyPic();//当前买价 Double sellPic = Double.valueOf(forexData.getSellPic());//当前买价 Double margin = 0.0; //记录所需保证金 + String stashId = IdUtil.simpleUUID(); + Boolean stopLossWinFlag=false; + Double priceTransaction=0.0; //记录当前交易价格(买价或卖价) if (null != stopLoss || null != stopWin) { //判断止损止赢是否合理 如果stopLoss stopWin都为null则跳过 + stopLossWinFlag=true; boolean winOrLossStopBoolean = getWinOrLossStop(stopLoss, stopWin, buySellType, forexData); if (winOrLossStopBoolean == false) { return new ResultEntity(HttpStatus.BAD_REQUEST, "止损或获利输入错误"); @@ -111,33 +118,58 @@ public class TradingController { margin=transactionVolume * 1000; //所需保证金 availableFunds = availableFunds - margin; if ("buy".equals(buySellType)) { - TakeStash takeStash = returnTakeStash(memberId, trainingId, tradingCode, currencyName, buySellType, transactionVolume, buyPic, stopLoss, stopWin , margin); + priceTransaction=buyPic; + TakeStash takeStash = returnTakeStash(stashId,memberId, trainingId, tradingCode, currencyName, buySellType, transactionVolume, buyPic, stopLoss, stopWin , margin); takeStashService.insertTakeStash(takeStash); } else if ("sell".equals(buySellType)) { - TakeStash takeStash = returnTakeStash(memberId, trainingId, tradingCode, currencyName, buySellType, transactionVolume, sellPic, stopLoss, stopWin , margin); + priceTransaction=sellPic; + TakeStash takeStash = returnTakeStash(stashId,memberId, trainingId, tradingCode, currencyName, buySellType, transactionVolume, sellPic, stopLoss, stopWin , margin); takeStashService.insertTakeStash(takeStash); } updateMemberAvailableFundsAndMarginUsed(member, availableFunds,margin); } else { //美元在后 使用可用资金表达式为 买卖手*1000*卖/买价 判断可用资金是否足够 先判断是买还是卖 if ("buy".equals(buySellType)) { - if (availableFunds < transactionVolume * 1000 * buyPic) { + priceTransaction=buyPic; + margin=transactionVolume * 1000 * buyPic; //所需保证金 + if (availableFunds < margin) { return new ResultEntity(HttpStatus.BAD_REQUEST, "可用资金不足"); } - margin=transactionVolume * 1000 * buyPic; //所需保证金 availableFunds = availableFunds - margin; - TakeStash takeStash = returnTakeStash(memberId, trainingId, tradingCode, currencyName, buySellType, transactionVolume, buyPic, stopLoss, stopWin , margin); + TakeStash takeStash = returnTakeStash(stashId,memberId, trainingId, tradingCode, currencyName, buySellType, transactionVolume, buyPic, stopLoss, stopWin , margin); takeStashService.insertTakeStash(takeStash); } else if ("sell".equals(buySellType)) { - if (availableFunds < transactionVolume * 1000 * sellPic) { + priceTransaction=sellPic; + margin=transactionVolume * 1000 * sellPic; //所需保证金 + if (availableFunds < margin) { return new ResultEntity(HttpStatus.BAD_REQUEST, "可用资金不足"); } - margin=transactionVolume * 1000 * sellPic; //所需保证金 availableFunds = availableFunds - margin; - TakeStash takeStash = returnTakeStash(memberId, trainingId, tradingCode, currencyName, buySellType, transactionVolume, sellPic, stopLoss, stopWin , margin); + TakeStash takeStash = returnTakeStash(stashId,memberId, trainingId, tradingCode, currencyName, buySellType, transactionVolume, sellPic, stopLoss, stopWin , margin); takeStashService.insertTakeStash(takeStash); } updateMemberAvailableFundsAndMarginUsed(member, availableFunds, margin); } + //保存持仓数据后 保存到redis中 + if(stopLossWinFlag==true){ + Map map=new HashMap(); + if(stopLoss==null){ + map.put("stopLoss",-1); + }else { + map.put("stopLoss",stopLoss); + } + if(stopWin==null){ + map.put("stopWin",-1); + }else { + map.put("stopWin",stopWin); + } + map.put("stashId",stashId); + map.put("buySellType",buySellType); + map.put("tradingCode",tradingCode); + map.put("transactionVolume",transactionVolume); + map.put("priceTransaction",priceTransaction); + map.put("memberId",memberId); + redisUtil.hmset("trainingId_"+trainingId+"_stashId_"+stashId,map); + } } else if (transactionType.equals("gdkc")) {//挂单开仓 生成的数据为挂单数据 挂单数据生效 判断可用资金是否充足 Double priceCommission = jsonObject.getDouble("priceCommission");//获取用户输入的价位 Date validityTime = jsonObject.getDate("validityTime"); //获取挂单有效期 @@ -171,10 +203,11 @@ public class TradingController { //返回持仓对象 - private TakeStash returnTakeStash(String memberId, String trainingId, String tradingCode,String currencyName, String buySellType, Double transactionVolume, Double buyOrSellPic, Double stopLoss, Double stopWin,Double tradingMargin) { + private TakeStash returnTakeStash(String stashId,String memberId, String trainingId, String tradingCode,String currencyName, String buySellType, Double transactionVolume, Double buyOrSellPic, Double stopLoss, Double stopWin,Double tradingMargin) { TakeStash takeStash = new TakeStash(); Date now = new Date(); String orderNumberStr = DateUtil.format(now, "yyyyMMddHHmmss") + System.currentTimeMillis(); + takeStash.setStashId(stashId); takeStash.setMemberId(memberId); takeStash.setTrainingId(trainingId); takeStash.setTradingCode(tradingCode); @@ -248,4 +281,6 @@ public class TradingController { } return false; } + + } diff --git a/src/main/java/com/sztzjy/forex/trading_trading/dto/PengdingVo.java b/src/main/java/com/sztzjy/forex/trading_trading/dto/PengdingVo.java new file mode 100644 index 0000000..9671828 --- /dev/null +++ b/src/main/java/com/sztzjy/forex/trading_trading/dto/PengdingVo.java @@ -0,0 +1,48 @@ +package com.sztzjy.forex.trading_trading.dto; + +import com.sztzjy.forex.trading_trading.entity.PendingOrder; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Data +@Getter +@Setter +public class PengdingVo { + + + private String pengdingOrderId; + private String memberId; + private String trainingId; + private Date commissionTime; + private String tradingCode; + private String currencyName; + private String commissionNumber; + private String buySellType; + private Double volumeTransaction; + private Double priceCommission; + private Double stopLoss; + private Double stopWin; + private Date validityTime; + private Integer status; + private Double currentPrice; + + public PengdingVo(PendingOrder pendingOrder) { + this.pengdingOrderId = pendingOrder.getPendingOrderId(); + this.memberId = pendingOrder.getMemberId(); + this.trainingId = pendingOrder.getTrainingId(); + this.commissionTime = pendingOrder.getCommissionTime(); + this.tradingCode = pendingOrder.getTradingCode(); + this.currencyName = pendingOrder.getCurrencyName(); + this.commissionNumber = pendingOrder.getCommissionNumber(); + this.buySellType = pendingOrder.getBuySellType(); + this.volumeTransaction = pendingOrder.getVolumeTransaction(); + this.priceCommission = pendingOrder.getPriceCommission(); + this.stopLoss = pendingOrder.getStopLoss(); + this.stopWin = pendingOrder.getStopWin(); + this.validityTime = pendingOrder.getValidityTime(); + this.status = pendingOrder.getStatus(); + } +} diff --git a/src/main/java/com/sztzjy/forex/trading_trading/dto/TakeStashVO.java b/src/main/java/com/sztzjy/forex/trading_trading/dto/TakeStashVO.java index 3ff2e3b..b8892a2 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/dto/TakeStashVO.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/dto/TakeStashVO.java @@ -29,6 +29,7 @@ public class TakeStashVO { this.stopWin = takeStash.getStopWin(); this.timeTransaction = takeStash.getTimeTransaction(); this.status = takeStash.getStatus(); + this.currencyName=takeStash.getCurrencyName(); } private String stashId; @@ -57,4 +58,6 @@ public class TakeStashVO { private Double currentPrice; private Double profitAndLoss; + + private String currencyName; } diff --git a/src/main/java/com/sztzjy/forex/trading_trading/mappers/TakeStashMapper.java b/src/main/java/com/sztzjy/forex/trading_trading/mappers/TakeStashMapper.java index 7519ec1..95a38fe 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/mappers/TakeStashMapper.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/mappers/TakeStashMapper.java @@ -97,4 +97,5 @@ public interface TakeStashMapper { int updateByPrimaryKey(TakeStash record); void updateWinLossByPrimaryKey(TakeStash takeStash); + } \ No newline at end of file diff --git a/src/main/java/com/sztzjy/forex/trading_trading/mappers/TrainingMapper.java b/src/main/java/com/sztzjy/forex/trading_trading/mappers/TrainingMapper.java index 404a32d..22eefbc 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/mappers/TrainingMapper.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/mappers/TrainingMapper.java @@ -129,4 +129,7 @@ public interface TrainingMapper { "SET status = 'ONGOING' " + "WHERE NOW() >= start_time AND NOW() <= end_time AND status <> 'ONGOING'") void updateTrainingStatusToInProgress(); + + @Select("select training_id from sys_training where status=1") + List selectProceedTraining(); } \ No newline at end of file diff --git a/src/main/java/com/sztzjy/forex/trading_trading/service/PendingOrderService.java b/src/main/java/com/sztzjy/forex/trading_trading/service/PendingOrderService.java index 9f61f97..ee2a1af 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/service/PendingOrderService.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/service/PendingOrderService.java @@ -17,15 +17,15 @@ public class PendingOrderService { pendingOrderMapper.insert(pendingOrder); } - public List selectByExample(PendingOrder pendingOrder){ + public List selectByTrainingIdAndStatusAndMemberId(PendingOrder pendingOrder){ PendingOrderExample pendingOrderExample = new PendingOrderExample(); PendingOrderExample.Criteria criteria = pendingOrderExample.createCriteria(); - criteria.andMemberIdEqualTo(pendingOrder.getMemberId()).andTrainingIdEqualTo(pendingOrder.getTrainingId()); + criteria.andMemberIdEqualTo(pendingOrder.getMemberId()).andTrainingIdEqualTo(pendingOrder.getTrainingId()).andStatusEqualTo(pendingOrder.getStatus()); List pendingOrders = pendingOrderMapper.selectByExample(pendingOrderExample); return pendingOrders; } - public void cancelOrder(PendingOrder pendingOrder){ - pendingOrderMapper.updateByPrimaryKeySelective(pendingOrder); + public void cancelOrder(String pendingOrderId){ + pendingOrderMapper.deleteByPrimaryKey(pendingOrderId); } } 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 2872da9..02309f3 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 @@ -2,22 +2,23 @@ package com.sztzjy.forex.trading_trading.service; import cn.hutool.core.util.IdUtil; +import com.sztzjy.forex.trading_trading.annotation.AnonymousAccess; import com.sztzjy.forex.trading_trading.common.mql5API.Mql5API; +import com.sztzjy.forex.trading_trading.controller.TakeStashController; import com.sztzjy.forex.trading_trading.entity.ForexMarketData; import com.sztzjy.forex.trading_trading.entity.mql5Entity.ForexData; import com.sztzjy.forex.trading_trading.mappers.TrainingMapper; import com.sztzjy.forex.trading_trading.util.RedisUtil; import lombok.extern.slf4j.Slf4j; +import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.PostMapping; import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Random; +import java.util.*; /** * 定时任务 @@ -37,6 +38,12 @@ public class ScheduledTask { @Autowired RedisUtil redisUtil; + @Autowired + TrainingService trainingService; + + @Autowired + TakeStashController takeStashController; + @Scheduled(cron = "0 * * * * *") // 修改实训状态 每分钟执行一次 public void updateTrainingStatus() { trainingMapper.updateTrainingStatusToInProgress(); @@ -136,4 +143,90 @@ public class ScheduledTask { return value; } + + //监听止损止盈 根据code获取当前买卖价格 如果价格高于/低于止损止盈 则按照止损止盈的值进行平仓 + //查询实训表中状态为1的所有实训并获取ID 获取持仓表中所有状态为0 且止损和止盈不为空的所有数据 获取当前价位如果 + @Scheduled(cron = "0 */2 * * * ?") + public void monitorStopLossProfit() { + List forexDateList = redisUtil.get("ForexDateList"); + Map forexDateMap = new HashMap(); + for (int i = 0; i < forexDateList.size(); i++) { + String code = forexDateList.get(i).getCode(); + forexDateMap.put(code,forexDateList.get(i)); + } + + List trainingIdList = trainingService.selectProceedTraining(); + for (int i = 0; i < trainingIdList.size(); i++) { + Set stashSet = redisUtil.keys("*stashId*"); + Iterator iterator = stashSet.iterator(); + while (iterator.hasNext()) { + String key = iterator.next(); + Map map = redisUtil.hmget(key); + String tradingCode = String.valueOf(map.get("tradingCode")); + Double stopLoss = (Double) map.get("stopLoss"); + Double stopWin = (Double) map.get("stopWin"); + String stashId = (String) map.get("stashId"); + String memberId = (String) map.get("memberId"); + Double transactionVolume = (Double) map.get("transactionVolume"); + Double priceTransaction = (Double) map.get("priceTransaction"); + String buySellType = String.valueOf(map.get("buySellType")); + ForexMarketData forexMarketData = forexDateMap.get(tradingCode); + if (tradingCode.startsWith("USD")){ //美元在前 + if ("buy".equals(buySellType)) { //开仓方式为买 则平仓方式为卖 先获取卖价 + Double sellPic = Double.valueOf(forexMarketData.getSellPic()); + if(stopLoss!=-1 && sellPic<=stopLoss){ + Double cumulativeProfitLoss=(stopLoss-priceTransaction)*transactionVolume*100000/stopLoss; + Double backFund=transactionVolume*1000+cumulativeProfitLoss; + takeStashController.updateMemberAndTakeStash(memberId,stashId,backFund,cumulativeProfitLoss); + } + if(stopWin!=-1 && sellPic>=stopWin){ + Double cumulativeProfitLoss=0.0; + Double backFund=transactionVolume*1000+(stopWin-priceTransaction)*transactionVolume*100000/stopWin; + takeStashController.updateMemberAndTakeStash(memberId,stashId,backFund,cumulativeProfitLoss); + } + }else { //开仓方式为卖 则平仓方式为买 先获取买价 + Double buyPic = forexMarketData.getBuyPic(); + if(stopLoss!=-1 && buyPic<=stopLoss){ + Double cumulativeProfitLoss=0.0; + Double backFund=transactionVolume*1000+(priceTransaction-stopLoss)*transactionVolume*100000/stopLoss; + takeStashController.updateMemberAndTakeStash(memberId,stashId,backFund,cumulativeProfitLoss); + } + if(stopWin!=-1 && buyPic>=stopWin){ + Double cumulativeProfitLoss=0.0; + Double backFund=transactionVolume*1000+(priceTransaction-stopWin)*transactionVolume*100000/stopWin; + takeStashController.updateMemberAndTakeStash(memberId,stashId,backFund,cumulativeProfitLoss); + } + } + }else { //美元在后 + if ("buy".equals(buySellType)) { //开仓方式为买 则平仓方式为卖 先获取卖价 + Double sellPic = Double.valueOf(forexMarketData.getSellPic()); + if(stopLoss!=-1 && sellPic<=stopLoss){ + Double cumulativeProfitLoss=0.0; + Double backFund=transactionVolume*1000*stopLoss; + takeStashController.updateMemberAndTakeStash(memberId,stashId,backFund,cumulativeProfitLoss); + } + if(stopWin!=-1 && sellPic>=stopWin){ + Double cumulativeProfitLoss=0.0; + Double backFund=transactionVolume*1000*stopWin; + takeStashController.updateMemberAndTakeStash(memberId,stashId,backFund,cumulativeProfitLoss); + } + }else { //开仓方式为卖 则平仓方式为买 先获取买价 + Double buyPic = forexMarketData.getBuyPic(); + if(stopLoss!=-1 && buyPic<=stopLoss){ + Double cumulativeProfitLoss=0.0; + Double backFund=transactionVolume*1000*stopLoss; + takeStashController.updateMemberAndTakeStash(memberId,stashId,backFund,cumulativeProfitLoss); + } + if(stopWin!=-1 && buyPic>=stopWin){ + Double cumulativeProfitLoss=0.0; + Double backFund=transactionVolume*1000*stopWin; + takeStashController.updateMemberAndTakeStash(memberId,stashId,backFund,cumulativeProfitLoss); + } + } + } + } + } + + } + } diff --git a/src/main/java/com/sztzjy/forex/trading_trading/service/TakeStashService.java b/src/main/java/com/sztzjy/forex/trading_trading/service/TakeStashService.java index 627c216..bbdafdc 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/service/TakeStashService.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/service/TakeStashService.java @@ -27,6 +27,14 @@ public class TakeStashService { return takeStashes; } + public List selectAllByMemberIdAndStatus(String memberId, Integer status) { + TakeStashExample example=new TakeStashExample(); + TakeStashExample.Criteria criteria = example.createCriteria(); + criteria.andMemberIdEqualTo(memberId).andStatusEqualTo(status); + List takeStashes = takeStashMapper.selectByExample(example); + return takeStashes; + } + public TakeStash selectByPrimaryKey(String stashId){ TakeStash takeStash = takeStashMapper.selectByPrimaryKey(stashId); return takeStash; diff --git a/src/main/java/com/sztzjy/forex/trading_trading/service/TrainingService.java b/src/main/java/com/sztzjy/forex/trading_trading/service/TrainingService.java index dd41a53..a569efc 100644 --- a/src/main/java/com/sztzjy/forex/trading_trading/service/TrainingService.java +++ b/src/main/java/com/sztzjy/forex/trading_trading/service/TrainingService.java @@ -130,4 +130,10 @@ public class TrainingService { return new PageInfo<>(); } + + //查询正在进行中的实训Id + public List selectProceedTraining(){ + List list=trainingMapper.selectProceedTraining(); + return list; + } } diff --git a/src/main/java/com/sztzjy/forex/trading_trading/util/ForexMarketDateUtil.java b/src/main/java/com/sztzjy/forex/trading_trading/util/ForexMarketDateUtil.java new file mode 100644 index 0000000..ce933e5 --- /dev/null +++ b/src/main/java/com/sztzjy/forex/trading_trading/util/ForexMarketDateUtil.java @@ -0,0 +1,30 @@ +package com.sztzjy.forex.trading_trading.util; + +import com.sztzjy.forex.trading_trading.entity.ForexMarketData; +import com.sztzjy.forex.trading_trading.util.RedisUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ForexMarketDateUtil { + @Autowired + RedisUtil redisUtil; + //根据tradingCode获取ForexMarketData对象 + public ForexMarketData getForexMarketDateByCode(String tradingCode){ + List forexDateList = redisUtil.get("ForexDateList"); + Map map=new HashMap<>(); + if (forexDateList.size() > 0) { + for (int i = 0; i < forexDateList.size(); i++) { + String getCode = forexDateList.get(i).getCode(); + map.put(getCode,forexDateList.get(i)); + } + } + ForexMarketData forexData = map.get(tradingCode); + return forexData; + } +}