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.impl.StrongLevelCalculationServiceImpl;
|
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<ContractOrder> partyContractOrders) {
|
|
try {
|
ContractOrder order = contractOrderService.findByOrderNoRedis(order_no);
|
if (order == null || !ContractOrder.STATE_SUBMITTED.equals(order.getState())) {
|
/**
|
* 状态已改变,退出处理
|
*/
|
return;
|
}
|
List<Realtime> 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<ContractOrder> partyContractOrders) {
|
|
Item item = itemService.findBySymbol(order.getSymbol());
|
|
|
if(null != order.getProfitLossRatio() && order.getProfitLossRatio() > 0){//根据后台设置的盈亏比来
|
order.setProfit(order.getDepositOpen().multiply(new BigDecimal((order.getProfitLossRatio()/100))).setScale(2, RoundingMode.DOWN));
|
}else{
|
/*
|
* 根据偏 差点数和手数算出盈亏金额
|
*/
|
/**
|
* 偏差点位
|
*/
|
BigDecimal point = currentPrice.subtract(order.getTradeAvgPrice());
|
BigDecimal amount = point.multiply(new BigDecimal("0.01")).multiply(order.getVolumeOpen()).setScale(4, BigDecimal.ROUND_DOWN);
|
if (ContractOrder.DIRECTION_BUY.equals(order.getDirection())) {
|
order.setProfit(amount);
|
} else{
|
order.setProfit(amount.negate());
|
}
|
}
|
|
double faceValue = 0.01; // 合约面值(固定面值不能调整)
|
double maintenanceMarginRate = 0.004; // 维持保证金率(固定不变)
|
|
|
/**
|
* 全仓收益加入保证金计算
|
*/
|
BigDecimal earnings;
|
|
if (order.getLocationType() == 1) {
|
earnings = BigDecimal.ZERO;
|
|
// 统计非当前订单的其他收益
|
/*List<ContractOrder> 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<String, Object> moneyAll = walletService.getMoneyAll(order.getPartyId());
|
|
Wallet wallet = walletService.saveWalletByPartyId(order.getPartyId());
|
earnings = earnings.add(wallet.getMoney());
|
earnings = earnings.add(order.getDepositOpen());
|
} else {
|
// 如果不符合条件,直接使用 order.getDepositOpen() 作为收益
|
earnings = order.getDepositOpen().add(order.getAddDepositOpen());
|
}
|
|
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.calculateEmptyLiquidationPrice(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;
|
}
|
}
|
/**
|
* 强平计算
|
*/
|
//重新计算强平
|
BigDecimal forceClosePrice = new BigDecimal(order.getForceClosePrice());
|
if (currentPrice.compareTo(new BigDecimal(order.getForceClosePrice())) <= 0) {//达到强平价
|
BigDecimal point = forceClosePrice.subtract(order.getTradeAvgPrice());
|
BigDecimal amount = point.multiply(new BigDecimal("0.01")).multiply(order.getVolumeOpen()).setScale(4, BigDecimal.ROUND_DOWN);
|
if (ContractOrder.DIRECTION_BUY.equals(order.getDirection())) {
|
order.setProfit(amount);
|
} else{
|
order.setProfit(amount.negate());
|
}
|
//强平利润固定-100%
|
order.setProfit(order.getDepositOpen().add(order.getAddDepositOpen()).negate());
|
//全仓强平利润+账户余额
|
if (order.getLocationType() == 1) {
|
Wallet wallet = this.walletService.findByUserId(order.getPartyId());
|
order.setProfit(order.getProfit().subtract(wallet.getMoney()));
|
}
|
}
|
this.contractOrderService.updateByIdBuffer(order);
|
//判断是全仓还是逐仓
|
if (order.getLocationType() == 1) {
|
// /**
|
// * 收益
|
// */
|
// BigDecimal profit = BigDecimal.ZERO;
|
//
|
// List<ContractOrder> 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.compareTo(new BigDecimal(order.getForceClosePrice())) <= 0) {//达到强平价
|
/**
|
* 触发全仓强平
|
*/
|
log.info("------------------currentPrice-------------:"+currentPrice);
|
log.info("------------------order.getForceClosePrice()-------------"+order.getForceClosePrice());
|
log.info("------------------开多强平-------------");
|
this.contractOrderService.allClose(order.getPartyId());
|
}
|
}else{
|
if (currentPrice.compareTo(new BigDecimal(order.getForceClosePrice()))>= 0) {//达到强平价
|
/**
|
* 触发全仓强平
|
*/
|
log.info("------------------currentPrice-------------:"+currentPrice);
|
log.info("------------------order.getForceClosePrice()-------------"+order.getForceClosePrice());
|
log.info("------------------开空强平-------------");
|
this.contractOrderService.allClose(order.getPartyId());
|
|
}
|
}
|
} else {
|
if(order.getDirection().equals("buy")){
|
if (currentPrice.compareTo(new BigDecimal(order.getForceClosePrice())) <= 0) {//达到强平价
|
this.contractOrderService.saveClose(order.getPartyId().toString(), order.getOrderNo(),"强平");
|
}
|
}else{
|
if (currentPrice.compareTo(new BigDecimal(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;
|
}
|
|
public static void main(String[] args) {
|
StrongLevelCalculationService strongLevelCalculationService = new StrongLevelCalculationServiceImpl();
|
double forceClosePrice = strongLevelCalculationService.calculateLiquidationPrice(100,
|
0.01, 67704.80, 1.477
|
, 0.004, 0.0005);
|
}
|
}
|