package com.yami.trading.service.future; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yami.trading.bean.data.domain.Realtime; import com.yami.trading.bean.future.domain.FuturesLock; import com.yami.trading.bean.future.domain.FuturesOrder; import com.yami.trading.bean.future.domain.FuturesPara; import com.yami.trading.bean.future.domain.FuturesRedisKeys; import com.yami.trading.bean.future.domain.ProfitLossConfig; import com.yami.trading.bean.future.dto.TFuturesOrderDTO; import com.yami.trading.bean.future.query.FuturesOrderQuery; import com.yami.trading.bean.item.domain.Item; import com.yami.trading.bean.model.Log; import com.yami.trading.bean.model.User; import com.yami.trading.bean.model.UserRecom; import com.yami.trading.bean.syspara.domain.Syspara; import com.yami.trading.common.constants.Constants; import com.yami.trading.common.constants.TipConstants; import com.yami.trading.common.exception.BusinessException; import com.yami.trading.common.exception.YamiShopBindException; import com.yami.trading.common.util.Arith; import com.yami.trading.common.util.DateTimeTools; import com.yami.trading.common.util.DateUtil; import com.yami.trading.common.util.DateUtils; import com.yami.trading.common.util.RandomUtil; import com.yami.trading.common.util.RedisUtil; import com.yami.trading.common.util.StringUtils; import com.yami.trading.common.util.ThreadUtils; import com.yami.trading.dao.future.FuturesOrderMapper; import com.yami.trading.service.RechargeBonusService; import com.yami.trading.service.WalletService; import com.yami.trading.service.data.DataService; import com.yami.trading.service.item.ItemService; import com.yami.trading.service.syspara.SysparaService; import com.yami.trading.service.system.LogService; import com.yami.trading.service.system.TipService; import com.yami.trading.service.user.UserDataService; import com.yami.trading.service.user.UserRecomService; import com.yami.trading.service.user.UserService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** * 交割合约订单Service * * @author lucas * @version 2023-04-08 */ @Service @Transactional public class FuturesOrderService extends ServiceImpl { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @PostConstruct public void init() { List list = this.findSubmitted(null); for (FuturesOrder order : list) { cache.put(order.getOrderNo(), order); } } @Autowired private UserService userService; @Autowired private LogService logService; @Autowired private SysparaService sysparaService; @Autowired private WalletService walletService; @Autowired private UserRecomService userRecomService; @Autowired private ItemService itemService; @Autowired private FuturesParaService futuresParaService; @Autowired(required = false) @Qualifier("dataService") private DataService dataService; @Autowired private TipService tipService; @Autowired private UserDataService userDataService; @Autowired private RechargeBonusService rechargeBonusService; @Autowired private ProfitLossConfigService profitLossConfigService; // @Autowired // private ExchangeRateService exchangeRateService; protected Map cache = new ConcurrentHashMap(); public IPage getPaged(IPage page, String loginPartyId, String symbol, String type, String date, String startTime, String endTime, String symbolType) { String state = ""; if ("orders".equals(type)) { state = FuturesOrder.STATE_SUBMITTED; } else if ("hisorders".equals(type)) { state = FuturesOrder.STATE_CREATED; } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(StrUtil.isNotBlank(symbol), "symbol", symbol); queryWrapper.eq(StrUtil.isNotBlank(state), "state", state); queryWrapper.eq(StringUtils.isNotEmpty(date), "date_format(create_time,'%Y-%m-%d')", date); List symbols = itemService.findByType(symbolType).stream().map(Item::getSymbol).collect(Collectors.toList()); symbols.add("-1"); // 如果没有传symbol,才需要做symbolType过滤 if (StringUtils.isNotEmpty(symbolType) && StringUtils.isEmptyString(symbol)) { queryWrapper.in(StringUtils.isNotEmpty(symbolType), "symbol", symbols); } queryWrapper.ge(StrUtil.isNotBlank(startTime), "create_time", startTime + " 00:00:00"); queryWrapper.le(StrUtil.isNotBlank(endTime), "create_time", endTime + " 23:59:59"); queryWrapper.orderByDesc("create_time"); queryWrapper.eq("party_id", loginPartyId); return baseMapper.selectPage(page, queryWrapper); } public List> bulidData(List list) { List> data = new ArrayList(); for (int i = 0; i < list.size(); i++) { FuturesOrder order = list.get(i); Map map = bulidOne(order); data.add(map); } return data; } public IPage listRecord(Page page, FuturesOrderQuery query) { IPage tFuturesOrderDTOIPage = baseMapper.listRecord(page, query); Map orderNoSubmitted = findSubmitted(null).stream().collect(Collectors.toMap(FuturesOrder::getOrderNo, f -> f)); tFuturesOrderDTOIPage.getRecords().forEach(dto -> { String timeUnitCn = FuturesPara.TIMENUM.valueOf(dto.getTimeunit()).getCn(); FuturesOrder order = orderNoSubmitted.get(dto.getOrderNo()); if (order == null) { dto.setRemainTime("0:0:0"); } dto.setTimenumStr(dto.getTimenum() + timeUnitCn); }); return tFuturesOrderDTOIPage; } public List findSubmitted(String orderNo) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("state", FuturesOrder.STATE_SUBMITTED); queryWrapper.eq(StrUtil.isNotBlank(orderNo), "order_no", orderNo); return list(queryWrapper); } public List findSubmitted(String partyID, List symbols) { symbols.add("-1"); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("party_id", partyID); queryWrapper.eq("state", FuturesOrder.STATE_SUBMITTED); queryWrapper.in( "symbol", symbols); return list(queryWrapper); } public FuturesOrder findSubmittedByOrderNo(String orderNo) { List submitted = findSubmitted(orderNo); if (CollectionUtil.isEmpty(submitted)) { return null; } return submitted.get(0); } public FuturesOrder cacheByOrderNo(String order_no) { FuturesOrder futuresOrder = (FuturesOrder) RedisUtil .get(FuturesRedisKeys.FUTURES_SUBMITTED_ORDERNO + order_no); // FuturesOrder futuresOrder = cache.get(order_no); if (null == futuresOrder) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("order_no", order_no); return getOne(queryWrapper); } return futuresOrder; } /** * 修改订单场控 * * @param orderNo * @param porfitOrLoss * @param operaName * @return */ public String saveOrderPorfitOrLoss(String orderNo, String porfitOrLoss, String operaName) { String message = ""; boolean lock = false; while (true) { try { if (!FuturesLock.add(orderNo)) { continue; } lock = true; FuturesOrder futuresOrder = (FuturesOrder) RedisUtil.get(FuturesRedisKeys.FUTURES_SUBMITTED_ORDERNO + orderNo); if (futuresOrder == null) { message = "订单已结算或不存在"; break; } // 获取 单个订单 交割合约总资产、总未实现盈利 Map futuresAssetsOld = this.walletService.getMoneyFuturesByOrder(futuresOrder); String oldProfitLoss = futuresOrder.getProfitLoss(); futuresOrder.setProfitLoss(porfitOrLoss); RedisUtil.set(FuturesRedisKeys.FUTURES_SUBMITTED_ORDERNO + futuresOrder.getOrderNo(), futuresOrder); cache.put(futuresOrder.getOrderNo(), futuresOrder); Double futuresAssets = (Double) RedisUtil.get(FuturesRedisKeys.FUTURES_ASSETS_PARTY_ID + futuresOrder.getPartyId().toString()); Double futuresAssetsProfit = (Double) RedisUtil.get(FuturesRedisKeys.FUTURES_ASSETS_PROFIT_PARTY_ID + futuresOrder.getPartyId().toString()); // 获取 单个订单 交割合约总资产、总未实现盈利 Map futuresAssetsOrder = this.walletService.getMoneyFuturesByOrder(futuresOrder); RedisUtil.set(FuturesRedisKeys.FUTURES_ASSETS_PARTY_ID + futuresOrder.getPartyId().toString(), Arith.add(null == futuresAssets ? 0.000D : futuresAssets, futuresAssetsOrder.get("money_futures") - futuresAssetsOld.get("money_futures"))); RedisUtil.set(FuturesRedisKeys.FUTURES_ASSETS_PROFIT_PARTY_ID + futuresOrder.getPartyId().toString(), Arith.add(null == futuresAssetsProfit ? 0.000D : futuresAssetsProfit, futuresAssetsOrder.get("money_futures_profit") - futuresAssetsOld.get("money_futures_profit"))); User party = userService.getById(futuresOrder.getPartyId()); Log log = new Log(); log.setCategory(Constants.LOG_CATEGORY_OPERATION); log.setOperator(operaName); log.setUsername(party.getUserName()); log.setUserId(party.getUserId()); log.setCreateTime(new Date()); log.setLog("手动修改交割订单场控。订单号[" + futuresOrder.getOrderNo() + "],原订单场控[" + Constants.PROFIT_LOSS_TYPE.get(oldProfitLoss) + "],修改后订单场控为[" + Constants.PROFIT_LOSS_TYPE.get(porfitOrLoss) + "]."); this.logService.save(log); // todo 老代码没有入库 updateById(futuresOrder); /** * 100毫秒业务处理 */ ThreadUtils.sleep(100); } catch (Throwable e) { log.error("error:", e); message = "修改错误"; } finally { if (lock) { FuturesLock.remove(orderNo); break; } } } return message; } /** * 业绩交易奖励 */ public void saveRecomProfit(String partyId, BigDecimal volume) { String futures_bonus_parameters = sysparaService.find("futures_bonus_parameters").getSvalue(); if (StrUtil.isEmpty(futures_bonus_parameters)) { return; } String[] futuresBonusArray = futures_bonus_parameters.split(","); List listParents = this.userRecomService.getParents(partyId); if (listParents.size() == 0) { return; } int loop = 0; int loopMax = futuresBonusArray.length; // int loopMax = 3; for (int i = 0; i < listParents.size(); i++) { if (loop >= loopMax) { break; } String recomUserId = listParents.get(i).getRecomUserId(); User party_parent = this.userService.getById(recomUserId); if (!Constants.SECURITY_ROLE_MEMBER.equals(party_parent.getRoleName())) { continue; } loop++; BigDecimal pip_amount = new BigDecimal(futuresBonusArray[i]); BigDecimal getMoney = volume.multiply(pip_amount); walletService.updateMoney("",recomUserId, getMoney, BigDecimal.ZERO, Constants.MONEYLOG_CATEGORY_REWARD, Constants.WALLET, Constants.MONEYLOG_CONTENT_REWARD, "第" + (i + 1) + "代用户产生了交易,佣金收益[" + getMoney + "]"); ThreadUtils.sleep(200); } } public FuturesOrder saveOpen(FuturesOrder futuresOrder, String paraId) { Item item = this.itemService.findBySymbol(futuresOrder.getSymbol()); if (item == null) { throw new BusinessException("参数错误"); } FuturesPara futuresPara = this.futuresParaService.getById(paraId); if (futuresPara == null) { throw new BusinessException("参数错误"); } List realtime_list = this.dataService.realtime(futuresOrder.getSymbol()); Realtime realtime = null; if (realtime_list.size() > 0) { realtime = realtime_list.get(0); } if (null == realtime) { throw new BusinessException(1, "请稍后再试"); } Double volume = futuresOrder.getVolume(); if (volume < futuresPara.getUnitAmount()) { throw new BusinessException("下单不能小于最小金额限制"); } if (futuresPara.getUnitMaxAmount().doubleValue() > 0 && volume > futuresPara.getUnitMaxAmount().doubleValue()) { throw new BusinessException("金额不在购买区间"); } checkSubmitOrder(futuresOrder.getPartyId().toString(), futuresPara); futuresOrder.setOrderNo(DateUtil.getToday("yyMMddHHmmss") + RandomUtil.getRandomNum(8)); futuresOrder.setTimenum(futuresPara.getTimenum()); futuresOrder.setTimeunit(futuresPara.getTimeunit()); DecimalFormat df = new DecimalFormat("#.##"); DecimalFormat df1 = new DecimalFormat("#.####"); futuresOrder.setFee(Double.valueOf(df.format(Arith.mul(futuresPara.getUnitFee().doubleValue(), volume)))); /** * 随机生成 */ // 生成5-26之间的随机数,包括26 // int randNum = rand.nextInt(22)+5; int result = (int) Arith.mul(futuresPara.getProfitRatio().doubleValue(), 10000) + (int) (Math.random() * (((int) Arith.mul(futuresPara.getProfitRatioMax().doubleValue(), 10000) - (int) Arith.mul(futuresPara.getProfitRatio().doubleValue(), 10000)) + 1)); futuresOrder.setProfitRatio(Double.parseDouble(df1.format(Arith.div(result, 10000)))); futuresOrder.setTradeAvgPrice(realtime.getClose()); futuresOrder.setCloseAvgPrice(realtime.getClose()); futuresOrder.setCreateTime(new Date()); futuresOrder.setState(FuturesOrder.STATE_SUBMITTED); futuresOrder.setCreateTimeTs(System.currentTimeMillis() / 1000); Integer profitRatioCardinality = Objects.isNull(futuresPara.getProfitRatioCardinality()) ? 1000 : futuresPara.getProfitRatioCardinality(); futuresOrder.setProfitRatioCardinality(profitRatioCardinality); futuresOrder.setFuturesParaId(paraId); switch (futuresPara.getTimeunit()) { case FuturesPara.TIMENUM_SECOND: futuresOrder .setSettlementTime(futuresOrder.getCreateTimeTs() + futuresPara.getTimenum()); break; case FuturesPara.TIMENUM_MINUTE: futuresOrder .setSettlementTime(futuresOrder.getCreateTimeTs() + futuresPara.getTimenum() * 60); break; case FuturesPara.TIMENUM_HOUR: futuresOrder.setSettlementTime(futuresOrder.getCreateTimeTs() + futuresPara.getTimenum() * 60 * 60); break; case FuturesPara.TIMENUM_DAY: futuresOrder.setSettlementTime(futuresOrder.getCreateTimeTs() + futuresPara.getTimenum() * 60 * 60 * 24); break; } //汇率转换 String type = item.getType(); // double fee = exchangeRateService.getUsdtByType(BigDecimal.valueOf(futuresOrder.getFee()), type).doubleValue(); // volume = exchangeRateService.getUsdtByType(BigDecimal.valueOf(volume), type).doubleValue(); BigDecimal moneyCost = new BigDecimal(volume).add(BigDecimal.valueOf(futuresOrder.getFee())).negate(); // 钱包扣费 walletService.updateMoney(futuresOrder.getSymbol(), futuresOrder.getPartyId(), moneyCost, BigDecimal.ZERO, Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET, Constants.DELIVERY_MONEYLOG_CONTENT_CONTRACT_OPEN, "交割合约,订单号[" + futuresOrder.getOrderNo() + "]"); checkProfitAndLoss(futuresOrder); save(futuresOrder); this.refreshCache(futuresOrder, realtime.getClose()); // //ICE盘定制交易手续费返佣 rechargeBonusService.saveTradeBounsHandle(futuresOrder.getPartyId(),1, futuresOrder.getFee(),futuresOrder.getOrderNo(),futuresOrder.getSymbol()); User party = this.userService.getById(futuresOrder.getPartyId()); if (Constants.SECURITY_ROLE_MEMBER.equals(party.getRoleName())) { // tipService.saveTip(futuresOrder.getUuid().toString(), TipConstants.FUTURES_ORDER, // party.getUserId()); Syspara isUnionStocks = sysparaService.find("is-union-stocks"); if(isUnionStocks != null && isUnionStocks.getBoolean()){ // 提示 if(TipConstants.ACTION_FUTURES_ITEM_MAP_NEW.get(item.getType()) != null){ tipService.saveTip(futuresOrder.getUuid(), TipConstants.ACTION_FUTURES_ITEM_MAP_NEW.get(item.getType()),party.getUserId()); } }else{ // 提示 if (TipConstants.ACTION_FUTURES_ITEM_MAP.get(type) != null) { tipService.saveTip(futuresOrder.getUuid(), TipConstants.ACTION_FUTURES_ITEM_MAP.get(type), party.getUserId()); } } } // saveRecomProfit(futuresOrder.getPartyId().toString(),futuresOrder.getVolume()); return futuresOrder; } private String fomatTime(long time) { long h = time >= 3600D ? new Double(Math.floor(Arith.div(time, 3600D, 2))).longValue() : 0L; long m = time - (h * 3600D) >= 60D ? new Double(Math.floor(Arith.div(time - (h * 3600D), 60D, 2))).longValue() : 0L; long s = new Double(time - (h * 3600D + m * 60D)).longValue(); if (s < 0) { s = 0; } return String.format("%d:%d:%d", h, m, s); } /** * 缓存计算更新 * * @param order * @param close */ public void refreshCache(FuturesOrder order, Double close) { if (order.getState().equals(FuturesOrder.STATE_CREATED)) { return; } long remain_time = DateUtils.calcTimeBetween("s", new Date(), order.getSettlementTime()*1000); order.setRemainTime(fomatTime(remain_time)); order.setCloseAvgPrice(close); double futures_loss_part = Double.valueOf(this.sysparaService.find("futures_loss_part").getSvalue()); double closeAvgPrice = order.getCloseAvgPrice().doubleValue(); double tradeAvgPrice = order.getTradeAvgPrice().doubleValue(); if (FuturesOrder.DIRECTION_BUY.equals(order.getDirection())) { /* * 0 买涨 */ if (closeAvgPrice >= tradeAvgPrice) { DecimalFormat df = new DecimalFormat("#.##"); order.setProfit(Double.valueOf(df.format(Arith.mul(order.getVolume(), order.getProfitRatio())))); } if (closeAvgPrice <= tradeAvgPrice) { if (futures_loss_part == 2) { DecimalFormat df = new DecimalFormat("#.##"); order.setProfit(Arith.sub(0, Double.valueOf(df.format(Arith.mul(order.getVolume(), order.getProfitRatio()))))); } else { order.setProfit(Arith.sub(0, order.getVolume())); } } } else { /* * 1 买跌 */ if (closeAvgPrice <= tradeAvgPrice) { DecimalFormat df = new DecimalFormat("#.##"); order.setProfit(Double.valueOf(df.format(Arith.mul(order.getVolume(), order.getProfitRatio())))); } if (closeAvgPrice >= tradeAvgPrice) { if (futures_loss_part == 2) { DecimalFormat df = new DecimalFormat("#.##"); order.setProfit(Arith.sub(0, Double.valueOf(df.format(Arith.mul(order.getVolume(), order.getProfitRatio()))))); } else { order.setProfit(Arith.sub(0, order.getVolume())); } } } FuturesOrder futuresOld = (FuturesOrder) RedisUtil.get(FuturesRedisKeys.FUTURES_SUBMITTED_ORDERNO + order.getOrderNo()); RedisUtil.set(FuturesRedisKeys.FUTURES_SUBMITTED_ORDERNO + order.getOrderNo(), order); cache.put(order.getOrderNo(), order); // 暂时先更新下,有问题再看 todo updateById(order); Object futuresAssetsObj = RedisUtil.get(FuturesRedisKeys.FUTURES_ASSETS_PARTY_ID + order.getPartyId().toString()); Object futuresAssetsProfitObj = RedisUtil.get(FuturesRedisKeys.FUTURES_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString()); Double futuresAssets; Double futuresAssetsProfit; if (futuresAssetsObj instanceof BigDecimal) { futuresAssets = ((BigDecimal) futuresAssetsObj).doubleValue(); } else { futuresAssets = (Double) futuresAssetsObj; } if (futuresAssetsProfitObj instanceof BigDecimal) { futuresAssetsProfit = ((BigDecimal) futuresAssetsProfitObj).doubleValue(); } else { futuresAssetsProfit = (Double) futuresAssetsProfitObj; } Map futuresAssetsOrder = this.walletService.getMoneyFuturesByOrder(order); if (null != futuresOld) { // 获取 单个订单 交割合约总资产、总未实现盈利 Map futuresAssetsOld = this.walletService.getMoneyFuturesByOrder(futuresOld); RedisUtil.set(FuturesRedisKeys.FUTURES_ASSETS_PARTY_ID + order.getPartyId().toString(), Arith.add(null == futuresAssets ? 0.000D : futuresAssets, futuresAssetsOrder.get("money_futures") - futuresAssetsOld.get("money_futures"))); RedisUtil.set(FuturesRedisKeys.FUTURES_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString(), Arith.add(null == futuresAssetsProfit ? 0.000D : futuresAssetsProfit, futuresAssetsOrder.get("money_futures_profit") - futuresAssetsOld.get("money_futures_profit"))); } else { RedisUtil.set(FuturesRedisKeys.FUTURES_ASSETS_PARTY_ID + order.getPartyId().toString(), Arith.add(null == futuresAssets ? 0.000D : futuresAssets, futuresAssetsOrder.get("money_futures"))); RedisUtil.set(FuturesRedisKeys.FUTURES_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString(), Arith.add(null == futuresAssetsProfit ? 0.000D : futuresAssetsProfit, futuresAssetsOrder.get("money_futures_profit"))); } } /** * 购买时检查是否有全局场控配置 * * @param order */ public void checkProfitAndLoss(FuturesOrder order) { Syspara profit_loss_symbol = sysparaService.find("profit_loss_symbol"); if (profit_loss_symbol == null) { return; } String ProfitLoss_symbol = profit_loss_symbol.getSvalue(); if (StrUtil.isEmpty(ProfitLoss_symbol) || !order.getSymbol().equals(ProfitLoss_symbol)) { return; } Syspara profit_loss_type = sysparaService.find("profit_loss_type"); if (profit_loss_type == null) { return; } String ProfitLoss_type = profit_loss_type.getSvalue(); if (StrUtil.isEmpty(ProfitLoss_type)) { return; } String profitLoss = null; switch (ProfitLoss_type) { // case ProfitAndLossConfig.TYPE_PROFIT: // ProfitLoss = "profit"; // break; // case ProfitAndLossConfig.TYPE_LOSS: // ProfitLoss = "loss"; // break; // case ProfitAndLossConfig.TYPE_BUY_PROFIT: // if (FuturesOrder.DIRECTION_BUY.equals(order.getDirection())) { // ProfitLoss = "profit"; // } // break; // case ProfitAndLossConfig.TYPE_SELL_PROFIT: // if (FuturesOrder.DIRECTION_SELL.equals(order.getDirection())) { // ProfitLoss = "profit"; // } // break; case ProfitLossConfig.TYPE_BUY_PROFIT_SELL_LOSS: if (FuturesOrder.DIRECTION_BUY.equals(order.getDirection())) { profitLoss = "profit"; } if (FuturesOrder.DIRECTION_SELL.equals(order.getDirection())) { profitLoss = "loss"; } break; case ProfitLossConfig.TYPE_SELL_PROFIT_BUY_LOSS: if (FuturesOrder.DIRECTION_SELL.equals(order.getDirection())) { profitLoss = "profit"; } if (FuturesOrder.DIRECTION_BUY.equals(order.getDirection())) { profitLoss = "loss"; } break; } order.setProfitLoss(profitLoss); } /** * 检验是否已经有持仓单,有则无法下单 * * @param partyId */ public void checkSubmitOrder(final String partyId, final FuturesPara futuresPara) { boolean button = sysparaService.find("futures_order_only_one_button").getBoolean(); if (!button) { return; } List submittedOrders = findSubmitted(null); CollectionUtils.filter(submittedOrders, new Predicate() { @Override public boolean evaluate(Object arg0) { FuturesOrder order = (FuturesOrder) arg0; // 是否存在交割单 boolean flag = order != null && partyId.equals(order.getPartyId().toString()); // 是否存在相同产品 flag = flag && order.getSymbol().equals(futuresPara.getSymbol())// symbol是否一致 && order.getTimenum().equals(futuresPara.getTimenum())// 时间是否一致 && order.getTimeunit().equals(futuresPara.getTimeunit());// 时间单位是否一致 return flag; } }); if (!CollectionUtils.isEmpty(submittedOrders)) { throw new YamiShopBindException("您已存在订单"); } } public void pushAsynRecom(FuturesOrder futuresOrder) { String futures_bonus_parameters = sysparaService.find("futures_bonus_parameters").getSvalue(); if (StrUtil.isEmpty(futures_bonus_parameters)) { return; } RedisUtil.pushSync(FuturesRedisKeys.FUTURES_RECOM_QUEUE_UPDATE, new FuturesRecomMessage(futuresOrder.getOrderNo(), futuresOrder.getPartyId().toString(), new BigDecimal(futuresOrder.getVolume()), futuresOrder.getCreateTime())); } public void saveClose(FuturesOrder order) { if (order.getState().equals(FuturesOrder.STATE_CREATED)) { return; } order.setCloseTime(System.currentTimeMillis() / 1000); order.setState(FuturesOrder.STATE_CREATED); String ProfitLoss = null; /** * 计算盈亏状态 */ if (FuturesOrder.DIRECTION_BUY.equals(order.getDirection())) { /* * 0 买涨 */ if (order.getCloseAvgPrice() >= order.getTradeAvgPrice()) { ProfitLoss = "profit"; } if (order.getCloseAvgPrice() <= order.getTradeAvgPrice()) { ProfitLoss = "loss"; } } else { /* * 1 买跌 */ if (order.getCloseAvgPrice() <= order.getTradeAvgPrice()) { ProfitLoss = "profit"; } if (order.getCloseAvgPrice() >= order.getTradeAvgPrice()) { ProfitLoss = "loss"; } } /** * 交割场控是否生效 0为开启, 1为不开启 */ // double ProfitAndLossConfig_on = 0; // 24小时内交割合约客户最高赢率(正式用户交割盈利/正式用户交割金额),高于设定的值时客户必亏,低于时则不限制(范例:10,为最高赢10%),为空则不限制 double futures_most_prfit_level = 0; futures_most_prfit_level = Double.valueOf(sysparaService.find("futures_most_prfit_level").getSvalue()); if (futures_most_prfit_level > 0) { List futuresOrders24Hour = new ArrayList(); futuresOrders24Hour = findByHourAndSate("created", Constants.SECURITY_ROLE_MEMBER); double futures24Amount = 0; double futures24Profit = 0; /** * 客户赢钱率=纯盈利金额除以交割订单总金额 */ double futures_ratio = 0; if (futuresOrders24Hour != null && futuresOrders24Hour.size() != 0) { for (int i = 0; i < futuresOrders24Hour.size(); i++) { FuturesOrder orders = futuresOrders24Hour.get(i); futures24Amount = Arith.add(futures24Amount, orders.getVolume()); if (orders.getProfit() > 0) { futures24Profit = Arith.add(futures24Profit, orders.getProfit()); } } futures_ratio = Arith.div(futures24Profit, futures24Amount); /** * 赢钱率大于设置的百分比时,客户固定为亏损,并且交割场控不生效 */ if (futures_ratio >= futures_most_prfit_level) { logger.warn("---> FuturesOrderService.saveClose 当前订单:{} 执行结算时发现命中全局修正条件," + "futures24Profit:{}, futures24Amount:{}, futures_ratio:{}, futures_most_prfit_level:{}", order.getOrderNo(), futures24Profit, futures24Amount, futures_ratio, futures_most_prfit_level); ProfitLoss = "loss"; // ProfitAndLossConfig_on = 1; } } } /** * 场控修正 */ Item bySymbol = itemService.findBySymbol(order.getSymbol()); String symbolType = bySymbol!=null?bySymbol.getType():""; ProfitLossConfig profitAndLossConfig = profitLossConfigService .findByPartyId(order.getPartyId().toString(), bySymbol.getType()); // if (profitAndLossConfig != null && ProfitAndLossConfig_on == 0) { // && (StringUtils.isEmptyString(profitAndLossConfig.getSymbol())// 字符为空则表示所有币种场控 // || order.getSymbol().equals(profitAndLossConfig.getSymbol()))// 指定币种场控 if (profitAndLossConfig != null) { logger.warn("---> FuturesOrderService.saveClose 当前订单:{} 执行结算时发现为当前用户配置了盈亏配置:{}", order.getOrderNo(), profitAndLossConfig.getType()); switch (profitAndLossConfig.getType()) { case ProfitLossConfig.TYPE_PROFIT: ProfitLoss = "profit"; break; case ProfitLossConfig.TYPE_LOSS: ProfitLoss = "loss"; break; case ProfitLossConfig.TYPE_BUY_PROFIT: if (FuturesOrder.DIRECTION_BUY.equals(order.getDirection())) { ProfitLoss = "profit"; } break; case ProfitLossConfig.TYPE_SELL_PROFIT: if (FuturesOrder.DIRECTION_SELL.equals(order.getDirection())) { ProfitLoss = "profit"; } break; case ProfitLossConfig.TYPE_BUY_PROFIT_SELL_LOSS: if (FuturesOrder.DIRECTION_BUY.equals(order.getDirection())) { ProfitLoss = "profit"; } if (FuturesOrder.DIRECTION_SELL.equals(order.getDirection())) { ProfitLoss = "loss"; } break; case ProfitLossConfig.TYPE_SELL_PROFIT_BUY_LOSS: if (FuturesOrder.DIRECTION_SELL.equals(order.getDirection())) { ProfitLoss = "profit"; } if (FuturesOrder.DIRECTION_BUY.equals(order.getDirection())) { ProfitLoss = "loss"; } break; } } /** * 订单是否有场控设置 */ if (!StringUtils.isEmptyString(order.getProfitLoss())) { ProfitLoss = order.getProfitLoss(); logger.warn("---> FuturesOrderService.saveClose 当前订单:{} 执行结算时发现当前订单配置了盈亏标记:{}", order.getOrderNo(), order.getProfitLoss()); } Item item = itemService.findBySymbol(order.getSymbol()); /** * 行情修正 */ Integer rofitRatioCardinality = Objects.isNull(order.getProfitRatioCardinality()) ? 1000 : order.getProfitRatioCardinality(); double random = Math.random() * rofitRatioCardinality + 1; random = Double.parseDouble(String.format("%.2f", random)); if (FuturesOrder.DIRECTION_BUY.equals(order.getDirection())) { if ("profit".equals(ProfitLoss) && order.getCloseAvgPrice() <= order.getTradeAvgPrice()) { order.setCloseAvgPrice(Arith.add(order.getTradeAvgPrice(), Arith.mul(item.getPips(), random))); } else if ("loss".equals(ProfitLoss) && order.getCloseAvgPrice() >= order.getTradeAvgPrice()) { order.setCloseAvgPrice(Arith.sub(order.getTradeAvgPrice(), Arith.mul(item.getPips(), random))); } } else { if ("profit".equals(ProfitLoss) && order.getCloseAvgPrice() >= order.getTradeAvgPrice()) { order.setCloseAvgPrice(Arith.sub(order.getTradeAvgPrice(), Arith.mul(item.getPips(), random))); } else if ("loss".equals(ProfitLoss) && order.getCloseAvgPrice() <= order.getTradeAvgPrice()) { order.setCloseAvgPrice(Arith.add(order.getTradeAvgPrice(), Arith.mul(item.getPips(), random))); } } Double volume = order.getVolume(); if ("profit".equals(ProfitLoss)) { /** * 盈利 */ DecimalFormat df = new DecimalFormat("#.##"); Double profit = Double.valueOf(df.format(Arith.mul(volume, order.getProfitRatio()))); order.setProfit(profit); //汇率转换 // BigDecimal profitUSDT = exchangeRateService.getUsdtByType(BigDecimal.valueOf(profit), symbolType); // BigDecimal volumeUSDT = exchangeRateService.getUsdtByType(BigDecimal.valueOf(volume), symbolType); BigDecimal amount = BigDecimal.valueOf(profit).add(BigDecimal.valueOf(volume)); walletService.updateMoney(order.getSymbol(), order.getPartyId(), amount, BigDecimal.ZERO, Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET, Constants.DELIVERY_MONEYLOG_CONTENT_CONTRACT_CLOSE, "交割合约盈利,订单号[" + order.getOrderNo() + "]"); String future_profit_bonus_parameters = sysparaService.find("future_profit_bonus_parameters").getSvalue(); if (StringUtils.isNotEmpty(future_profit_bonus_parameters)) { saveParentFeeProfit(order, future_profit_bonus_parameters); } // miner_bonus_parameters = sysparaService.find("miner_first_bonus_parameters").getValue(); } else { /** * 亏损 */ double futures_loss_part = Double.valueOf(sysparaService.find("futures_loss_part").getSvalue()); if (futures_loss_part == 2) { /** * 盈亏都按百分比 start */ // order.setProfit(Arith.sub(0, Arith.mul(volume, order.getProfitRatio())));// 亏损的时候,- 盈亏率*购买金额 /** * 盈亏都按百分比 start */ } else { /** * 盈利按百分比,亏损全损 */ order.setProfit(Arith.sub(0, volume));// 8.14 亏损的时候,-购买金额 } //汇率转换 // BigDecimal profitUSDT = exchangeRateService.getUsdtByType(BigDecimal.valueOf(order.getProfit()), symbolType); // BigDecimal volumeUSDT = exchangeRateService.getUsdtByType(BigDecimal.valueOf(volume), symbolType); BigDecimal amount = BigDecimal.valueOf(volume).add(BigDecimal.valueOf(order.getProfit())); walletService.updateMoney(order.getSymbol(), order.getPartyId(), amount, BigDecimal.ZERO, Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET, Constants.DELIVERY_MONEYLOG_CONTENT_CONTRACT_CLOSE, "交割合约亏损退还,订单号[" + order.getOrderNo() + "]"); } updateById(order); cache.remove(order.getOrderNo()); FuturesOrder futuresOld = (FuturesOrder) RedisUtil.get(FuturesRedisKeys.FUTURES_SUBMITTED_ORDERNO + order.getOrderNo()); RedisUtil.del(FuturesRedisKeys.FUTURES_SUBMITTED_ORDERNO + order.getOrderNo()); Double futuresAssets = (Double) RedisUtil.get(FuturesRedisKeys.FUTURES_ASSETS_PARTY_ID + order.getPartyId().toString()); Double futuresAssetsProfit = (Double) RedisUtil.get(FuturesRedisKeys.FUTURES_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString()); if (null != futuresOld) { // 获取 单个订单 交割合约总资产、总未实现盈利 Map futuresAssetsOld = this.walletService.getMoneyFuturesByOrder(futuresOld); RedisUtil.set(FuturesRedisKeys.FUTURES_ASSETS_PARTY_ID + order.getPartyId().toString(), Arith.add(null == futuresAssets ? 0.000D : futuresAssets, 0 - futuresAssetsOld.get("money_futures"))); RedisUtil.set(FuturesRedisKeys.FUTURES_ASSETS_PROFIT_PARTY_ID + order.getPartyId().toString(), Arith.add(null == futuresAssetsProfit ? 0.000D : futuresAssetsProfit, 0 - futuresAssetsOld.get("money_futures_profit"))); } this.userDataService.saveFuturesClose(order); //删除提示 // tipService.deleteTip(order.getUuid()); User party = userService.getById(order.getPartyId()); party.setWithdrawLimitNowAmount(new BigDecimal(Arith.add(party.getWithdrawLimitNowAmount().doubleValue(), volume))); userService.updateById(party); // if (Constants.SECURITY_ROLE_MEMBER.equals(party.getRoleName())) { // tipService.deleteTip(order.getPartyId().toString()); // } tipService.deleteTip(order.getUuid()); } public List findByHourAndSate(String state, String rolename) { return baseMapper.findByHourAndSate(state, rolename, new Date()); } /** * 推荐人手续费奖励 */ public void saveParentFeeProfit(FuturesOrder order, String bonus) { List list_parents = this.userRecomService.getParents(order.getPartyId()); if (CollectionUtils.isNotEmpty(list_parents)) { String[] bonus_array = bonus.split(","); int loop = 0; for (int i = 0; i < list_parents.size(); i++) { if (loop >= 3) { break; } User partyParent = userService.getById(list_parents.get(i).getRecomUserId()); if (!Constants.SECURITY_ROLE_MEMBER.equals(partyParent.getRoleName())) { continue; } loop++; /** * 交易手续费 推荐人收益 */ BigDecimal pip_amount = new BigDecimal(bonus_array[loop - 1]); BigDecimal get_money = new BigDecimal(order.getFee()).multiply(pip_amount); walletService.updateMoney("",order.getPartyId(), get_money, BigDecimal.ZERO, Constants.MONEYLOG_CATEGORY_CONTRACT, Constants.WALLET, Constants.MONEYLOG_CONTENT_REWARD, "第" + (i + 1) + "代下级用户,交割盈利手续费推荐奖励金"); } } } public List findByPartyIdAndToday(String partyId) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("party_id", partyId); queryWrapper.eq(" DateDiff(create_time,NOW())", 0); return list(queryWrapper); } /** * 根据用户批量赎回订单 * * @param partyId */ public void saveCloseAllByPartyId(final String partyId) { List submittedOrders = findSubmitted(null); CollectionUtils.filter(submittedOrders, new Predicate() { @Override public boolean evaluate(Object arg0) { // TODO Auto-generated method stub FuturesOrder order = (FuturesOrder) arg0; // 是否存在交割单 boolean flag = partyId.equals(order.getPartyId()); return flag; } }); for (FuturesOrder order : submittedOrders) { saveClose(order); } } public List cacheSubmitted() { return new ArrayList(cache.values()); } public List queryByDate(int page, int pageSize, String date) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("date_format(create_time,'%Y-%m-%d')", date); Page iPage = new Page(); iPage.setSize(pageSize); iPage.setCurrent(page); return baseMapper.selectPage(iPage, queryWrapper).getRecords(); } /** * 注意: 此处对时间戳进行了时区转换,外层调用方法不要再做转换了!!! * * @param order * @return */ public Map bulidOne(FuturesOrder order) { FuturesOrder order_cache = (FuturesOrder) RedisUtil .get(FuturesRedisKeys.FUTURES_SUBMITTED_ORDERNO + order.getOrderNo()); if (order_cache != null) { order = order_cache; } List paras = futuresParaService.getBySymbolSort(order.getSymbol()); Item item = this.itemService.findBySymbol(order.getSymbol()); if (item == null) { throw new YamiShopBindException("参数错误"); } String decimals = "#."; for (int i = 0; i < item.getDecimals(); i++) { decimals = decimals + "#"; } if (item.getDecimals() == 0) { decimals = "#"; } DecimalFormat df = new DecimalFormat("#.##"); DecimalFormat df_symbol = new DecimalFormat(decimals); df_symbol.setRoundingMode(RoundingMode.FLOOR);// 向下取整 Map map = new HashMap(); map.put("order_no", order.getOrderNo()); map.put("name", item.getName()); map.put("symbol", order.getSymbol()); // 注意:此处转换了时间戳后,外层务必不要再转换了 long initOpenTimestamp = DateTimeTools.transferShowTimeToClientTime(order.getCreateTimeTs()); map.put("open_time", initOpenTimestamp); if (order.getCloseTime() != null) { initOpenTimestamp = DateTimeTools.transferShowTimeToClientTime(order.getCloseTime()); map.put("close_time", initOpenTimestamp); } else { map.put("close_time", "--"); } map.put("direction", order.getDirection()); map.put("open_price", df_symbol.format(order.getTradeAvgPrice())); map.put("state", order.getState()); map.put("amount", order.getVolume()); map.put("fee", order.getFee()); /** * 收益 */ if (order.getProfit() > 0) { // if ("submitted".equals(order.getState())) { // map.put("profit", df.format(Arith.mul(order.getVolume(), ratio_min)) + " " + "~ " // + df.format(Arith.mul(order.getVolume(), ratio_max))); // } else { map.put("profit", df.format(order.getProfit())); // } map.put("profit_state", "1"); } else { map.put("profit", order.getProfit()); map.put("profit_state", "0"); } map.put("volume", order.getVolume()); long settlementTimestamp = DateTimeTools.transferShowTimeToClientTime(order.getSettlementTime()); map.put("settlement_time", settlementTimestamp);// 交割时间 map.put("close_price", df_symbol.format(order.getCloseAvgPrice())); map.put("remain_time", StrUtil.isEmpty(order.getRemainTime()) ? "0:0:0" : order.getRemainTime()); map.put("time_num", order.getTimenum()); map.put("time_unit", order.getTimeunit().substring(0, 1)); return map; } }