package com.yami.trading.service.contract; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.yami.trading.bean.contract.domain.ContractOrder; import com.yami.trading.bean.data.domain.Realtime; import com.yami.trading.bean.item.domain.Item; import com.yami.trading.bean.model.Wallet; import com.yami.trading.common.util.ThreadUtils; import com.yami.trading.service.StrongLevelCalculationService; 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 lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.List; import java.util.Map; @Slf4j @Service public class ContractOrderCalculationServiceImpl implements ContractOrderCalculationService { @Autowired private ItemService itemService; /** * 平仓线 110%(订金价值 /收益=110%) */ public BigDecimal order_close_line = new BigDecimal("1.1"); /** * 平仓方式 1全仓 2单个持仓 */ public int order_close_line_type = 1; @Autowired private ContractOrderService contractOrderService; @Qualifier("dataService") @Autowired @Lazy private DataService dataService; @Autowired private WalletService walletService; @Autowired private StrongLevelCalculationService strongLevelCalculationService; private SysparaService sysparaService; public void saveCalculation(String order_no, List partyContractOrders) { try { ContractOrder order = contractOrderService.findByOrderNoRedis(order_no); if (order == null || !ContractOrder.STATE_SUBMITTED.equals(order.getState())) { /** * 状态已改变,退出处理 */ return; } List list = this.dataService.realtime(order.getSymbol()); if (list.size() == 0) { return; } Realtime realtime = list.get(0); BigDecimal close = realtime.getClose(); BigDecimal add = order.getTradeAvgPrice().add(order.getPips()); BigDecimal subtract = order.getTradeAvgPrice().subtract(order.getPips()); if (ContractOrder.DIRECTION_BUY.equals(order.getDirection())) { /* * 0 买涨 */ if (close.compareTo(add) >= 0) { settle(order, "profit", close, partyContractOrders); } if (close.compareTo(subtract) <= 0) { settle(order, "loss", close, partyContractOrders); } } else { /* * 1 买跌 */ if (close.compareTo(subtract) <= 0) { settle(order, "profit", close, partyContractOrders); } if (close.compareTo(add) >= 0) { settle(order, "loss", close, partyContractOrders); } } } catch (Throwable e) { log.error("ContractOrderCalculatio run fail", e); } } /** * 盈亏计算 收益=(平仓均价-开仓均价)*面值*张数 * * USDT保证金合约做多:收益=(平仓均价-开仓均价)*面值*张数 * USDT保证金合约做空:收益=(开仓均价-平仓均价)*面值*张数 * 以BTC为例,BTC一张合约面值为0.01BTC,在价格19000的时候,开了10张多单。当价格涨到20000的时候,小明的收益=(20000-19000)*0.01*10=100USDT * 币本位合约: * 做多:收益=面值*张数/开仓价-面值*张数/平仓价 * 做空:收益=面值*张数/平仓价-面值*张数/开仓价 * 以BTC为例,BTC一张合约面值为100美元,小明在价格20000的时候,开了5张空单。当价格下跌到19000的时候,小明的收益=100*5/19000-100*5/20000=0. * * @param profit_loss profit 盈 loss亏 * @param currentPrice 当前点位 */ public void settle(ContractOrder order, String profit_loss, BigDecimal currentPrice, List partyContractOrders) { /** * 偏差点位 */ BigDecimal point = currentPrice.subtract(order.getTradeAvgPrice()); /* * 根据偏 差点数和手数算出盈亏金额 */ BigDecimal amount = point.multiply(new BigDecimal("0.01")).multiply(order.getVolumeOpen()).setScale(4, BigDecimal.ROUND_DOWN);; Item item = itemService.findBySymbol(order.getSymbol()); // if ("profit".equals(profit_loss)) { // /** // * 盈 正数 // */ // order.setProfit(amount); // } else if ("loss".equals(profit_loss)) { // order.setProfit(amount); // // } order.setProfit(amount); double faceValue = 0.01; // 合约面值(固定面值不能调整) double maintenanceMarginRate = 0.004; // 维持保证金率(固定不变) /** * 全仓收益加入保证金计算 */ BigDecimal earnings; if (order.getLocationType() == 1) { earnings = BigDecimal.ZERO; // 统计非当前订单的其他收益 List list = contractOrderService.list(new LambdaQueryWrapper<>(ContractOrder.class) .eq(ContractOrder::getState, ContractOrder.STATE_SUBMITTED) .eq(ContractOrder::getPartyId, order.getPartyId()) .ne(ContractOrder::getOrderNo, order.getOrderNo()) ); // 提前计算 currentPrice 与 order.getTradeAvgPrice() 的差值,避免重复计算 BigDecimal priceDifference = currentPrice.subtract(order.getTradeAvgPrice()); // 计算所有订单的收益 for (ContractOrder contractOrder : list) { BigDecimal profit = priceDifference .multiply(new BigDecimal("0.01")) .multiply(contractOrder.getVolumeOpen()) .setScale(4, RoundingMode.DOWN); earnings = earnings.add(profit); // 累加收益 } // 获取当前账户余额并加到收益中 Map moneyAll = walletService.getMoneyAll(order.getPartyId()); earnings = earnings.add(new BigDecimal(moneyAll.get("money_all_coin").toString())); } else { // 如果不符合条件,直接使用 order.getDepositOpen() 作为收益 earnings = order.getDepositOpen(); } if(ContractOrder.DIRECTION_BUY.equals(order.getDirection())){ double forceClosePrice = strongLevelCalculationService.calculateLiquidationPrice(earnings.doubleValue(), faceValue, order.getVolumeOpen().doubleValue(), order.getTradeAvgPrice().doubleValue() , maintenanceMarginRate, item.getUnitFee().doubleValue()); order.setForceClosePrice(BigDecimal.valueOf(forceClosePrice).toString()); }else{ double forceClosePrice = strongLevelCalculationService.calculateLiquidationPrice(earnings.doubleValue(), faceValue, order.getVolumeOpen().doubleValue(), order.getTradeAvgPrice().doubleValue() , maintenanceMarginRate, item.getUnitFee().doubleValue()); order.setForceClosePrice(BigDecimal.valueOf(forceClosePrice).toString()); } /** * 多次平仓价格不对,后续修 */ order.setCloseAvgPrice(currentPrice); this.contractOrderService.updateByIdBuffer(order); /** * 止盈价 */ BigDecimal profitStop = order.getStopPriceProfit(); if (profitStop != null && profitStop.compareTo(BigDecimal.ZERO) > 0 && ContractOrder.DIRECTION_BUY.equals(order.getDirection())) { /* * 买涨 */ if (currentPrice.compareTo(profitStop) >= 0) { this.contractOrderService.saveClose(order.getPartyId().toString(), order.getOrderNo(),null); return; } } else if (profitStop != null && profitStop.compareTo(BigDecimal.ZERO) > 0 && ContractOrder.DIRECTION_SELL.equals(order.getDirection())) { /** * 买跌 */ if (currentPrice.compareTo(profitStop) <= 0) { this.contractOrderService.saveClose(order.getPartyId().toString(), order.getOrderNo(),null); return; } } /** * 止亏线 */ BigDecimal loss_stop = order.getStopPriceLoss(); if (loss_stop != null && loss_stop.compareTo(BigDecimal.ZERO) > 0 && ContractOrder.DIRECTION_BUY.equals(order.getDirection())) { /* * 买涨 */ if (currentPrice.compareTo(loss_stop) <= 0) { this.contractOrderService.saveClose(order.getPartyId().toString(), order.getOrderNo(),null); return; } } else if (loss_stop != null && loss_stop.compareTo(BigDecimal.ZERO) > 0 && ContractOrder.DIRECTION_SELL.equals(order.getDirection())) { /** * 买跌 */ if (currentPrice.compareTo(loss_stop) >= 0) { this.contractOrderService.saveClose(order.getPartyId().toString(), order.getOrderNo(),null); return; } } /** * 强平计算 */ //判断是全仓还是逐仓 if (order.getLocationType() == 1) { // /** // * 收益 // */ // BigDecimal profit = BigDecimal.ZERO; // // List list = partyContractOrders; // for (int i = 0; i < list.size(); i++) { // ContractOrder close_line = list.get(i); // profit = profit.add(close_line.getProfit()).add(close_line.getDeposit()); // } // Wallet wallet = this.walletService.findByUserId(order.getPartyId().toString()); this.contractOrderService.updateByIdBuffer(order); // if (profit.add(wallet.getMoney()).compareTo(BigDecimal.ZERO) <= 0) { //判断买涨还是买跌"buy":买(多) "sell":卖(空) if(order.getDirection().equals("buy")){ if (currentPrice.toString().compareTo(order.getForceClosePrice()) <= 0) {//达到强平价 /** * 触发全仓强平 */ this.contractOrderService.allClose(order.getPartyId()); } }else{ if (currentPrice.toString().compareTo(order.getForceClosePrice())>= 0) {//达到强平价 /** * 触发全仓强平 */ this.contractOrderService.allClose(order.getPartyId()); } } } else { if(order.getDirection().equals("buy")){ if (currentPrice.toString().compareTo(order.getForceClosePrice()) <= 0) {//达到强平价 this.contractOrderService.saveClose(order.getPartyId().toString(), order.getOrderNo(),"强平"); } }else{ if (currentPrice.toString().compareTo(order.getForceClosePrice()) >= 0) {//达到强平价 this.contractOrderService.saveClose(order.getPartyId().toString(), order.getOrderNo(),"强平"); } } } } public void setDataService(DataService dataService) { this.dataService = dataService; } public void setSysparaService(SysparaService sysparaService) { this.sysparaService = sysparaService; } public void setContractOrderService(ContractOrderService contractOrderService) { this.contractOrderService = contractOrderService; } public void setWalletService(WalletService walletService) { this.walletService = walletService; } public void setOrder_close_line(BigDecimal order_close_line) { this.order_close_line = order_close_line; } public void setOrder_close_line_type(int order_close_line_type) { this.order_close_line_type = order_close_line_type; } }