package com.bizzan.bitrade.controller;

import com.alibaba.druid.support.logging.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bizzan.bitrade.constant.BooleanEnum;
import com.bizzan.bitrade.engine.ContractCoinMatch;
import com.bizzan.bitrade.engine.ContractCoinMatchFactory;
import com.bizzan.bitrade.engine.FollowAccountMonitor;
import com.bizzan.bitrade.engine.TradingAccountMonitor;
import com.bizzan.bitrade.entity.*;
import com.bizzan.bitrade.entity.transform.AuthMember;
import com.bizzan.bitrade.service.*;
import com.bizzan.bitrade.util.*;
import com.bizzan.bitrade.vo.ContractCoinVo;
import com.bizzan.bitrade.vo.TradingAccount;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.util.Assert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import static com.bizzan.bitrade.constant.SysConstant.SESSION_MEMBER;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 委托订单处理类
 */
@Slf4j
@Api(description="跟单订单处理接口")
//@RestController
//@RequestMapping("/follow-order")
public class FollowOrderController {
    @Autowired
    private MemberWalletService walletService;

    @Autowired
    private CoinService coinService;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Value("${exchange.max-cancel-times:-1}")
    private int maxCancelTimes;

    @Autowired
    private LocaleMessageSourceService msService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private ContractCoinService contractCoinService;

    @Autowired
    private ContractOrderEntrustService contractOrderEntrustService;

    @Autowired
    private MemberTransactionService memberTransactionService;

    @Autowired
    private MemberContractWalletService memberContractWalletService;
    
    @Autowired
    private MemberContractPositionService memberContractPositionService;
    @Autowired
    private FollowWalletService followWalletService;

    @Autowired
    private RestTemplate restTemplate;
	@Autowired
	private RedisLock redisLock;

    @Autowired
    private ContractCoinMatchFactory contractCoinMatchFactory; // 合约引擎工厂

	@Autowired
    private FollowAccountMonitor followAccountMonitor;

    private SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
    private final int defaultVolumeScale = 1;

    /**
     * 合约下单（开仓）- 金本位
     * 二种操作类型：买入开多，卖出开多
     *
     * @param authMember
     * @return
     */
    @ApiOperation(value="开仓下单", notes="合约开仓下单,下单成功后发送follow-swap-order-open给跟单系统")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "contractCoinId",value = "合约交易对ID",required = true,paramType = "form",dataType = "int"),
            @ApiImplicitParam(name = "direction",value = "方向 0：开多  1：开空",required = true,paramType = "form",dataType = "int"),
            @ApiImplicitParam(name = "type",value = "类型 0：市价 1：限价 2：计划委托",required = true,paramType = "form",dataType = "int"),
            @ApiImplicitParam(name = "triggerPrice",value = "触发价格",required = false,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "entrustPrice",value = "委托价格",required = true,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "lossPrice",value = "止损价格",required = false,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "profitPrice",value = "止盈价格",required = false,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "leverage",value = "杠杆",required = true,paramType = "form",dataType = "int"),
            @ApiImplicitParam(name = "volume",value = "委托数量",required = true,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "isPercentage",value = "是否百分比委托 1:百分比",required = false,paramType = "form",dataType = "int")
    })
    //@PostMapping("open")
    public MessageResult openOrder(@SessionAttribute(SESSION_MEMBER) AuthMember authMember,
                                   @RequestParam(value = "contractCoinId") Long contractCoinId,// 合约交易对
                                   @RequestParam(value = "direction") ContractOrderDirection direction,// 1：买（平空）  2：卖（平多）
                                   @RequestParam(value = "type") ContractOrderType type,// 0：市价 1：限价 2：计划委托
                                   @RequestParam(value = "triggerPrice", required = false) BigDecimal triggerPrice,// 触发价格
                                   @RequestParam(value = "entrustPrice") BigDecimal entrustPrice,// 委托价格(计划委托时如为0：市价成交)
                                   @RequestParam(value = "lossPrice", required = false) BigDecimal lossPrice,
                                   @RequestParam(value = "profitPrice", required = false) BigDecimal profitPrice,
                                   @RequestParam(value = "leverage") BigDecimal leverage,// 委托价格
                                   @RequestParam(value = "volume") BigDecimal volume,// 委托数量（张）
                                   @RequestParam(value = "isPercentage", required = false) Integer isPercentage
    ) {

        // 输入合法性检查
        if (contractCoinId == null || direction == null || type == null || leverage == null || volume == null) {
            return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        }
        if (direction != ContractOrderDirection.BUY && direction != ContractOrderDirection.SELL) {
            return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        }
        if (type != ContractOrderType.MARKET_PRICE && type != ContractOrderType.LIMIT_PRICE && type != ContractOrderType.SPOT_LIMIT) {
            return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        }

        // 检查交易对是否存在
        ContractCoin contractCoin = contractCoinService.findOne(contractCoinId);
        if (null == contractCoin) {
            return MessageResult.error(500, msService.getMessage("NONSUPPORT_COIN"));
        }
        
        // 限价单及计划委托单需要输入委托价格
        if (type == ContractOrderType.LIMIT_PRICE || type == ContractOrderType.SPOT_LIMIT) {
            if (null == entrustPrice) {
                return MessageResult.error(500, msService.getMessage("INPUT_COMMISSION_PRICE"));
            }
        }
        // 检查用户合法性
        Member member = memberService.findOne(authMember.getId());
        if (null == member) return MessageResult.error(500, msService.getMessage("ACCOUNT_NOT_EXIST"));
        // 用户是否被禁止交易
        if (member.getTransactionStatus().equals(BooleanEnum.IS_FALSE)) {
            return MessageResult.error(500, msService.getMessage("CANNOT_TRADE"));
        }

        // 检查交易对是否可用
        if (contractCoin.getEnable() != 1 || contractCoin.getExchangeable() != 1) {
            return MessageResult.error(500, msService.getMessage("COIN_FORBIDDEN"));
        }
        // 是否允许开多仓（买涨）
        if (contractCoin.getEnableOpenBuy() == BooleanEnum.IS_FALSE && direction == ContractOrderDirection.BUY) {
            return MessageResult.error(500, msService.getMessage("SUSPEND_LONG1"));
        }
        // 是否允许开空仓（买跌）
        if (contractCoin.getEnableOpenSell() == BooleanEnum.IS_FALSE && direction == ContractOrderDirection.SELL) {
            return MessageResult.error(500, msService.getMessage("SUSPEND_SHORT1"));
        }
        // 是否允许市价开仓做多
        if (contractCoin.getEnableMarketBuy() == BooleanEnum.IS_FALSE && direction == ContractOrderDirection.BUY) {
            return MessageResult.error(500, msService.getMessage("SUSPEND_LONG2"));
        }
        // 是否允许市价开仓做空
        if (contractCoin.getEnableMarketSell() == BooleanEnum.IS_FALSE && direction == ContractOrderDirection.SELL) {
            return MessageResult.error(500, msService.getMessage("SUSPEND_SHORT2"));
        }

        // 检查合约引擎是否存在
        if (!contractCoinMatchFactory.containsContractCoinMatch(contractCoin.getSymbol())) {
            return MessageResult.error(500, msService.getMessage("CONTRACT_ENGINE_ERROR"));
        }
        
        Map<String, BigDecimal> priceMap = followAccountMonitor.getPriceMapAtPresent();
        BigDecimal currentPrice = priceMap.get(contractCoin.getSymbol());
        //memberContractPositionService.adjustMarginByCurrentPrice(member.getId(), priceMap);
        
        FollowAccount followAccount = followWalletService.findOneVO(member.getId());
        followAccount.setCurrentPriceMap(priceMap);
        
        // 计划委托中的触发价格需要大于0
        if(type == ContractOrderType.SPOT_LIMIT) {
            if(triggerPrice.compareTo(BigDecimal.ZERO) <= 0) {
                return MessageResult.error(500, msService.getMessage("TRIGGER_PRICE1"));
            }
            if(entrustPrice.compareTo(BigDecimal.ZERO) < 0) {
                return MessageResult.error(500, msService.getMessage("TRIGGER_PRICE2"));
            }
        }
        
        BigDecimal openPrice = BigDecimal.ZERO;
        
        // 计算市价成交价格（大约）
        openPrice = currentPrice;
        if (direction == ContractOrderDirection.BUY) { // 买入，滑点计算，做多，更高价格成交
            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
                openPrice = currentPrice.add(currentPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
            } else { // 滑点类型：固定额
                openPrice = currentPrice.add(contractCoin.getSpread());
            }
        } else { // 卖出，滑点计算，做空，更低价格成交
            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
                openPrice = currentPrice.subtract(currentPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
            } else { // 滑点类型：固定额
                openPrice = currentPrice.subtract(contractCoin.getSpread());
            }
        }
        if (openPrice.compareTo(BigDecimal.ZERO) <= 0) {
            return MessageResult.error(500, msService.getMessage("CONTRACT_ENGINE_ERROR"));
        }
        
        ContractOrderEntrust orderEntrust = new ContractOrderEntrust();
        
        if (isPercentage!=null && isPercentage==1) {
	        if(volume.compareTo(BigDecimal.ONE)<=0 || volume.compareTo(BigDecimal.valueOf(100))>0) {
	    		return MessageResult.error(500, "百分比必须在1-100之间");
	    	}
        }
		//orderEntrust.setIsPercentage(1);
		orderEntrust.setFollowId(0L);
        log.info("isPercentage={}, volume={}", isPercentage, volume);

        //检查止盈止损合法性
        boolean hasCut = false;
        if(type == ContractOrderType.LIMIT_PRICE || type == ContractOrderType.SPOT_LIMIT) {
        	boolean hasLossPrice = lossPrice!=null && lossPrice.compareTo(BigDecimal.ZERO)>0;
        	boolean hasProfitPrice = profitPrice!=null && profitPrice.compareTo(BigDecimal.ZERO)>0;
        	
        	if(hasLossPrice || hasProfitPrice) {
        		if(type == ContractOrderType.LIMIT_PRICE) {
		        	if(direction == ContractOrderDirection.BUY) {
		        		if(entrustPrice.compareTo(openPrice)>=0)
		        			return MessageResult.error(500, msService.getMessage("LIMIT_PRICE_MUCH"));
		        	} else {
		        		if(entrustPrice.compareTo(openPrice)<=0)
		        			return MessageResult.error(500, msService.getMessage("LIMIT_PRICE_LESS"));
		        	}
        		} else if(type == ContractOrderType.SPOT_LIMIT) {
        			log.info("entrustPrice={}, triggerPrice={}", entrustPrice, triggerPrice);
        			if (entrustPrice.compareTo(BigDecimal.ZERO)<=0)
        				return MessageResult.error(500, "必须先设置委托价才能设置止盈止损");
        			if(direction == ContractOrderDirection.BUY) {
		        		if(entrustPrice.compareTo(triggerPrice)>0)
		        			return MessageResult.error(500, "委托价不能大于触发价格");
		        	} else {
		        		if(entrustPrice.compareTo(triggerPrice)<0)
		        			return MessageResult.error(500, "委托价不能小于触发价格");
		        	}
        		}
        		hasCut = true;
        	}
        	
        	if(hasLossPrice) {
        		if(direction == ContractOrderDirection.BUY) {
        			//if(lossPrice.compareTo(entrustPrice)>=0 || lossPrice.compareTo(openPrice)>=0) {
        			if(lossPrice.compareTo(entrustPrice)>=0) {
        				return MessageResult.error(500, "止损触发价需小于委托价");
        			}
        		} else {
        			//if(lossPrice.compareTo(entrustPrice)<=0 || lossPrice.compareTo(openPrice)<=0) {
        			if(lossPrice.compareTo(entrustPrice)<=0) {
        				return MessageResult.error(500, "止损触发价需大于委托价");
        			}
        		}
        	}
        	if(hasProfitPrice) {
        		if(direction == ContractOrderDirection.BUY) {
        			//if(profitPrice.compareTo(entrustPrice)<=0 || profitPrice.compareTo(openPrice)<=0) {
        			if(profitPrice.compareTo(entrustPrice)<=0) {
        				return MessageResult.error(500, "止盈触发价需大于委托价");
        			}
        		} else {
        			//if(profitPrice.compareTo(entrustPrice)>=0 || profitPrice.compareTo(openPrice)>=0) {
        			if(profitPrice.compareTo(entrustPrice)>=0) {
        				return MessageResult.error(500, "止盈触发价需小于委托价");
        			}
        		}
        	}
        	
        }

        // 新建合约委托单
        orderEntrust.setContractId(contractCoin.getId()); // 合约ID
        orderEntrust.setMemberId(member.getId()); // 用户ID
        orderEntrust.setSymbol(contractCoin.getSymbol()); // 交易对符号
        orderEntrust.setBaseSymbol(contractCoin.getSymbol().split("/")[1]); // 基币/结算币
        orderEntrust.setCoinSymbol(contractCoin.getSymbol().split("/")[0]); // 币种符号
        orderEntrust.setDirection(direction); // 开仓方向：做多/做空
        orderEntrust.setContractOrderEntrustId(GeneratorUtil.getOrderId("CE"));
        orderEntrust.setVolume(volume); // 开仓张数
        orderEntrust.setTradedVolume(BigDecimal.ZERO); // 已交易数量
        orderEntrust.setTradedPrice(BigDecimal.ZERO); // 成交价格
        orderEntrust.setPrincipalUnit("USDT"); // 保证金单位
        orderEntrust.setPrincipalAmount(BigDecimal.ZERO); // 保证金数量
        orderEntrust.setCreateTime(DateUtil.getTimeMillis()); // 开仓时间
        orderEntrust.setType(type);
        orderEntrust.setTriggerPrice(triggerPrice); // 触发价
        orderEntrust.setEntrustPrice(entrustPrice); // 委托价格
        orderEntrust.setLossPrice(lossPrice);
        orderEntrust.setProfitPrice(profitPrice);
        orderEntrust.setEntrustType(ContractOrderEntrustType.OPEN); // 开仓
        orderEntrust.setTriggeringTime(0L); // 触发时间，暂时无效
        orderEntrust.setShareNumber(contractCoin.getShareNumber());
        orderEntrust.setProfitAndLoss(BigDecimal.ZERO); // 盈亏（仅平仓计算）
        orderEntrust.setPatterns(ContractOrderPattern.CROSSED); // 仓位模式
        orderEntrust.setOpenFee(BigDecimal.ZERO); // 开仓手续费
        orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_ING); // 委托状态：委托中
        orderEntrust.setCurrentPrice(currentPrice);
        orderEntrust.setIsBlast(0); // 不是爆仓单
        orderEntrust.setOpenType(type.ordinal());
        orderEntrust.setLeverage(leverage.intValue());
        orderEntrust.setPositionType(ContractPositionType.SEPARATE);
        orderEntrust.setMoneyType(ContractMoneyType.COIN);
        if(type == ContractOrderType.SPOT_LIMIT) { // 是否是计划委托单
            orderEntrust.setIsFromSpot(1);
        }else{
            orderEntrust.setIsFromSpot(0);
        }
        
        if (orderEntrust.getType() != ContractOrderType.SPOT_LIMIT) {
	        //boolean success = followAccountMonitor.genVolumeForOrder(orderEntrust, false);
        	boolean success = true;
	        if(!success) {
	        	return MessageResult.error(500, "可开张数不足");
	        }
        } else {
        	orderEntrust.setDecimalScale(1);
        }

        // 保存委托单
        ContractOrderEntrust retObj = contractOrderEntrustService.save(orderEntrust);


        if (retObj != null) {
            // 发送消息至Exchange系统
            kafkaTemplate.send("swap-order-open", JSON.toJSONString(retObj));
            kafkaTemplate.send("follow-swap-order-open", JSON.toJSONString(retObj));

            //通知钱包变更
            //JSONObject jsonObj = new JSONObject();
            //jsonObj.put("symbol", contractCoin.getSymbol());
            //jsonObj.put("walletId", memberContractWallet.getId());
            //kafkaTemplate.send("member-wallet-change", JSON.toJSONString(jsonObj));

            log.info(">>>>>>>>>>订单提交完成>>>>>>>>>>");
            // 返回结果
            MessageResult result = MessageResult.success(msService.getMessage("SWAP_SUCCESS"));
            result.setData(retObj);
            return result;
        } else {
            // 返回结果
            MessageResult result = MessageResult.error(msService.getMessage("SWAP_FAILED"));
            result.setData(null);
            return result;
        }
    }
    
    @ApiOperation(value="止盈止损单", notes="设置止盈止损单")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "positionId",value = "仓位ID",required = true,paramType = "form",dataType = "int"),
            @ApiImplicitParam(name = "profitPrice",value = "止盈价格",required = true,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "profitEntrustPrice",value = "止盈委托价格",required = false,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "lossPrice",value = "止损价格",required = true,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "lossEntrustPrice",value = "止损委托价格",required = false,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "volume",value = "委托数量",required = true,paramType = "form",dataType = "float")
    })
    //@PostMapping("cut")
    public MessageResult cutOrder(@SessionAttribute(SESSION_MEMBER) AuthMember authMember,
                                   @RequestParam(value = "positionId") Long positionId,// 合约交易对
                                   @RequestParam(value = "profitPrice", required = false) BigDecimal profitPrice,// 触发价格
                                   @RequestParam(value = "profitEntrustPrice", required = false) BigDecimal profitEntrustPrice,// 触发价格
                                   @RequestParam(value = "lossPrice", required = false) BigDecimal lossPrice,// 触发价格
                                   @RequestParam(value = "lossEntrustPrice", required = false) BigDecimal lossEntrustPrice,// 触发价格
                                   @RequestParam(value = "volume") BigDecimal volume,// 委托数量（张）
                                   Long entrustId
    ) {
    	// 输入合法性检查
        if (positionId == null || volume == null) {
            return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        }
        // 检查合约是否存在
        MemberContractPosition memberContractPosition = memberContractPositionService.findOne(positionId);
        ContractCoin contractCoin = memberContractPosition.getCoin();
        if (null == contractCoin) {
            return MessageResult.error(500, msService.getMessage("CONTRACT_NOT_EXIST"));
        }
        if(memberContractPosition.getIsLock()!=null && memberContractPosition.getIsLock() == 1) {
        	return MessageResult.error(501, msService.getMessage("CANNOT_CLOSE"));
        }
        
        ContractOrderDirection direction;
        if(memberContractPosition.getDirection() == ContractOrderDirection.BUY)
        	direction = ContractOrderDirection.SELL;
        else
        	direction = ContractOrderDirection.BUY;
        
        // 检查用户合法性
        Member member = memberService.findOne(authMember.getId());
        if (null == member) return MessageResult.error(500, msService.getMessage("ACCOUNT_NOT_EXIST"));
        // 用户是否被禁止交易
        if (member.getTransactionStatus().equals(BooleanEnum.IS_FALSE)) {
            return MessageResult.error(500, msService.getMessage("CANNOT_TRADE"));
        }
        if(member.getIsLock() == 1) {
        	return MessageResult.error(501, msService.getMessage("CANNOT_CLOSE"));
        }

        log.info("cut volume before scale={}", volume);
        volume = volume.setScale(memberContractPosition.getDecimalScale(), BigDecimal.ROUND_DOWN);
        log.info("cut volume after scale={}", volume);
        if(volume.compareTo(BigDecimal.ZERO) <= 0)
            return MessageResult.error(500, msService.getMessage("INCORRECT_NUMBER_CLOSING_POSITIONS"));//小于1张
        
        //if(volume.compareTo(BigDecimal.ONE) < 0)
        //    return MessageResult.error(500, msService.getMessage("INCORRECT_NUMBER_CLOSING_POSITIONS"));//小于1张
        //if(BigDecimal.valueOf(volume.intValue()).compareTo(volume) != 0)
        //    return MessageResult.error(500, msService.getMessage("INCORRECT_NUMBER_CLOSING_POSITIONS")); // 含有小数

        
        if (memberContractPosition.getAvailablePosition().compareTo(volume) < 0) {
            return MessageResult.error(500, msService.getMessage("WRONG_AMOUNT_COMMISSION"));
        }

        BigDecimal currentPrice = contractCoinMatchFactory.getContractCoinMatch(contractCoin.getSymbol()).getNowPrice();

        if (currentPrice.compareTo(BigDecimal.ZERO) <= 0) {
            return MessageResult.error(500, msService.getMessage("CONTRACT_ENGINE_ERROR"));
        }
        
        // 计划委托中的触发价格需要大于0
        if(profitPrice.compareTo(BigDecimal.ZERO) <= 0 && lossPrice.compareTo(BigDecimal.ZERO) <= 0) {
            return MessageResult.error(500, msService.getMessage("TRIGGER_PRICE1"));
        }
        //log.info("direction={}, profitPrice={}, lossPrice={}, currentPrice={}", direction, profitPrice, lossPrice, currentPrice);
        if(direction == ContractOrderDirection.BUY) {
        	if(profitPrice.compareTo(BigDecimal.ZERO)>0 && profitPrice.compareTo(currentPrice)>=0)
        		return MessageResult.error(500, "止盈触发价需小于最新成交价");
        	if(lossPrice.compareTo(BigDecimal.ZERO)>0 && lossPrice.compareTo(currentPrice)<=0)
        		return MessageResult.error(500, "止损触发价需大于最新成交价");
        } else {
        	if(profitPrice.compareTo(BigDecimal.ZERO)>0 && profitPrice.compareTo(currentPrice)<=0)
        		return MessageResult.error(500, "止盈触发价需大于最新成交价");
        	if(lossPrice.compareTo(BigDecimal.ZERO)>0 && lossPrice.compareTo(currentPrice)>=0)
        		return MessageResult.error(500, "止损触发价需小于最新成交价");
        }

        // 新建合约委托单
        ContractOrderEntrust orderEntrust = new ContractOrderEntrust();
        orderEntrust.setContractId(contractCoin.getId()); // 合约ID
        orderEntrust.setMemberId(member.getId()); // 用户ID
        orderEntrust.setSymbol(contractCoin.getSymbol()); // 交易对符号
        orderEntrust.setBaseSymbol(contractCoin.getSymbol().split("/")[1]); // 基币/结算币
        orderEntrust.setCoinSymbol(contractCoin.getSymbol().split("/")[0]); // 币种符号
        orderEntrust.setDirection(direction); // 平仓方向：平空/平多
        orderEntrust.setContractOrderEntrustId(GeneratorUtil.getOrderId("CE"));
        orderEntrust.setVolume(volume); // 平仓张数
        orderEntrust.setTradedVolume(BigDecimal.ZERO); // 已交易数量
        orderEntrust.setTradedPrice(BigDecimal.ZERO); // 成交价格
        orderEntrust.setPrincipalUnit("USDT"); // 保证金单位
        orderEntrust.setPrincipalAmount(BigDecimal.ZERO); // 保证金数量
        orderEntrust.setCreateTime(DateUtil.getTimeMillis()); // 开仓时间
        orderEntrust.setType(ContractOrderType.SPOT_LIMIT);
        orderEntrust.setProfitPrice(profitPrice); // 触发价
        orderEntrust.setProfitEntrustPrice(profitEntrustPrice); // 委托价格
        orderEntrust.setLossPrice(lossPrice); // 触发价
        orderEntrust.setLossEntrustPrice(lossEntrustPrice); // 委托价格
        orderEntrust.setEntrustType(ContractOrderEntrustType.CLOSE); // 开仓
        orderEntrust.setTriggeringTime(0L); // 触发时间，暂时无效
        orderEntrust.setShareNumber(contractCoin.getShareNumber());
        orderEntrust.setProfitAndLoss(BigDecimal.ZERO); // 盈亏（仅平仓计算）
        orderEntrust.setPatterns(ContractOrderPattern.CROSSED); // 仓位模式
        orderEntrust.setCloseFee(BigDecimal.ZERO);
        orderEntrust.setPositionType(memberContractPosition.getType());
        orderEntrust.setCurrentPrice(currentPrice);
        orderEntrust.setIsBlast(0); // 不是爆仓单
        orderEntrust.setIsFromSpot(1);
        orderEntrust.setIsCut(1);
        orderEntrust.setPositionId(positionId);
        orderEntrust.setLeverage(memberContractPosition.getLeverage().intValue());
        orderEntrust.setUsdtOpenPrice(memberContractPosition.getOpenPrice());
        orderEntrust.setCloseType(CloseType.CUT);
        orderEntrust.setMoneyType(memberContractPosition.getMoneyType());
        orderEntrust.setDecimalScale(memberContractPosition.getDecimalScale());
        orderEntrust.setOpenType(memberContractPosition.getOpenType());
        
        ContractOrderEntrust retObj = null;
        int successCount = memberContractPositionService.freezePosition(positionId, volume);
        if(successCount == 1) {
	        // 保存委托单
	        orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_ING); // 委托状态：委托中
	        retObj = contractOrderEntrustService.save(orderEntrust);
        } else {
        	orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_FAILURE); // 委托状态：委托失败
	        contractOrderEntrustService.save(orderEntrust);
        }
        if (retObj != null) {
            // 发送消息至Exchange系统
            kafkaTemplate.send("swap-order-close", JSON.toJSONString(retObj));


            //通知钱包变更
            //JSONObject jsonObj = new JSONObject();
            //jsonObj.put("symbol", contractCoin.getSymbol());
            //jsonObj.put("walletId", memberContractWallet.getId());
            //kafkaTemplate.send("member-wallet-change", JSON.toJSONString(jsonObj));

            log.info(">>>>>>>>>>订单提交完成>>>>>>>>>>");
            // 返回结果
            MessageResult result = MessageResult.success(msService.getMessage("SWAP_SUCCESS"));
            result.setData(retObj);
            return result;
        } else {
            // 返回结果
            MessageResult result = MessageResult.error(msService.getMessage("SWAP_FAILED"));
            result.setData(null);
            return result;
        }
    }
    
    @ApiOperation(value="修改止盈止损单", notes="修改止盈止损单")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "entrustId",value = "订单ID",required = true,paramType = "form",dataType = "int"),
    		@ApiImplicitParam(name = "positionId",value = "仓位ID",required = true,paramType = "form",dataType = "int"),
            @ApiImplicitParam(name = "profitPrice",value = "止盈价格",required = true,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "profitEntrustPrice",value = "止盈委托价格",required = false,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "lossPrice",value = "止损价格",required = true,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "lossEntrustPrice",value = "止损委托价格",required = false,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "volume",value = "委托数量",required = true,paramType = "form",dataType = "float")
    })
    //@PostMapping("modify-cut")
    public MessageResult modifyCutOrder(@SessionAttribute(SESSION_MEMBER) AuthMember authMember,
    								Long entrustId,
                                   @RequestParam(value = "positionId") Long positionId,// 合约交易对
                                   @RequestParam(value = "profitPrice", required = false) BigDecimal profitPrice,// 触发价格
                                   @RequestParam(value = "profitEntrustPrice", required = false) BigDecimal profitEntrustPrice,// 触发价格
                                   @RequestParam(value = "lossPrice", required = false) BigDecimal lossPrice,// 触发价格
                                   @RequestParam(value = "lossEntrustPrice", required = false) BigDecimal lossEntrustPrice,// 触发价格
                                   @RequestParam(value = "volume") BigDecimal volume// 委托数量（张）
    ) {
    	if(entrustId == null)
        	return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        //return cutOrder(authMember,positionId,profitPrice,profitEntrustPrice,lossPrice,lossEntrustPrice,volume,1,entrustId);
    	ContractOrderEntrust order = contractOrderEntrustService.findOne(entrustId);
    	if(order.getMemberId().longValue() != authMember.getId()) {
    		return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
    	}
    	int result = contractCoinMatchFactory.getContractCoinMatch(order.getSymbol()).modifyContractOrderEntrust(order, profitPrice, lossPrice);
    	if(result == 1)
    		return MessageResult.error(500, "止盈触发价需小于最新成交价");
    	else if(result == 2)
    		return MessageResult.error(500, "止损触发价需大于最新成交价");
    	else if(result == 3)
    		return MessageResult.error(500, "止盈触发价需大于最新成交价");
    	else if(result == 4)
    		return MessageResult.error(500, "止损触发价需小于最新成交价");
    	else if(result == 10)
    		return MessageResult.error(500, msService.getMessage("ILLEGAL_OPERATION"));
    	return MessageResult.success();
    }

    /**
     * 合约平仓
     * 四种操作类型：买入平空，卖出平多
     *
     * @param authMember
     * @return
     */
    @ApiOperation(value="平仓订单", notes="平仓订单")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "positionId",value = "仓位ID",required = true,paramType = "form",dataType = "int"),
    		@ApiImplicitParam(name = "type",value = "类型 0：市价 1：限价 2：计划委托",required = true,paramType = "form",dataType = "int"),
            @ApiImplicitParam(name = "triggerPrice",value = "触发价格",required = false,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "entrustPrice",value = "委托价格",required = true,paramType = "form",dataType = "float"),
            @ApiImplicitParam(name = "volume",value = "委托数量",required = true,paramType = "form",dataType = "float")
    })
    //@PostMapping("close")
    public MessageResult closeOrder(@SessionAttribute(SESSION_MEMBER) AuthMember authMember,
                                    @RequestParam(value = "positionId") Long positionId,// 合约交易对
                                    @RequestParam(value = "type") ContractOrderType type,// 1：市价 2：限价 3：计划委托
                                    @RequestParam(value = "triggerPrice", required = false) BigDecimal triggerPrice,// 触发价格
                                    @RequestParam(value = "entrustPrice") BigDecimal entrustPrice,// 委托价格(计划委托时如为0：市价成交)
                                    @RequestParam(value = "volume") BigDecimal volume// 委托数量（张）
    ) {
        // 输入合法性检查
        if (positionId == null || type == null || volume == null) {
            return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        }
        MemberContractPosition memberContractPosition = memberContractPositionService.findOne(positionId);
        // 检查合约是否存在
        ContractCoin contractCoin = memberContractPosition.getCoin();
        if (null == contractCoin) {
            return MessageResult.error(500, msService.getMessage("CONTRACT_NOT_EXIST"));
        }
        if(memberContractPosition.getIsLock()!=null && memberContractPosition.getIsLock() == 1) {
        	return MessageResult.error(501, msService.getMessage("CANNOT_CLOSE"));
        }
        
        ContractOrderDirection direction;
        if(memberContractPosition.getDirection() == ContractOrderDirection.BUY)
        	direction = ContractOrderDirection.SELL;
        else
        	direction = ContractOrderDirection.BUY;
        
        // 限价单及计划委托单需要输入委托价格
        if (type == ContractOrderType.LIMIT_PRICE || type == ContractOrderType.SPOT_LIMIT) {
            if (null == entrustPrice) {
                return MessageResult.error(500, msService.getMessage("INPUT_COMMISSION_PRICE"));
            }
        }
        // 检查用户合法性
        Member member = memberService.findOne(authMember.getId());
        if (null == member) return MessageResult.error(500, msService.getMessage("ACCOUNT_NOT_EXIST"));
        // 用户是否被禁止交易
        if (member.getTransactionStatus().equals(BooleanEnum.IS_FALSE)) {
            return MessageResult.error(500, msService.getMessage("CANNOT_TRADE"));
        }
        if(member.getIsLock() == 1) {
        	return MessageResult.error(501, msService.getMessage("CANNOT_CLOSE"));
        }

        volume = volume.setScale(memberContractPosition.getDecimalScale(), BigDecimal.ROUND_DOWN);
        if(volume.compareTo(BigDecimal.ZERO) <= 0)
            return MessageResult.error(500, msService.getMessage("INCORRECT_NUMBER_CLOSING_POSITIONS"));//小于1张
        //if(BigDecimal.valueOf(volume.intValue()).compareTo(volume) != 0)
        //    return MessageResult.error(500, msService.getMessage("INCORRECT_NUMBER_CLOSING_POSITIONS")); // 含有小数

        
        if (memberContractPosition.getAvailablePosition().compareTo(volume) < 0) {
            return MessageResult.error(500, msService.getMessage("WRONG_AMOUNT_COMMISSION"));
        }
        

        BigDecimal currentPrice = contractCoinMatchFactory.getContractCoinMatch(contractCoin.getSymbol()).getNowPrice();

        // 计算滑点成交价（市价下单时用此价格）
        BigDecimal dealPrice = currentPrice;
        if (direction == ContractOrderDirection.BUY) { // 买入平空，滑点计算，更低价格
            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
                dealPrice = currentPrice.add(currentPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
            } else { // 滑点类型：固定额
                dealPrice = currentPrice.add(contractCoin.getSpread());
            }
        } else { // 卖出，滑点计算，做空，更低价格成交
            if (contractCoin.getSpreadType() == 1) { // 滑点类型：百分比
                dealPrice = currentPrice.subtract(currentPrice.multiply(contractCoin.getSpread())); // 已当前价成交（或滑点价成交）
            } else { // 滑点类型：固定额
                dealPrice = currentPrice.subtract(contractCoin.getSpread());
            }
        }
        //
        if (dealPrice.compareTo(BigDecimal.ZERO) <= 0) {
            return MessageResult.error(500, msService.getMessage("CONTRACT_ENGINE_ERROR"));
        }
        // 委托价格是否太高或太低(限价单需要在2%的价格范围内下单)
        /*if(type == ContractOrderType.LIMIT_PRICE) {
            if(entrustPrice.compareTo(currentPrice.multiply(BigDecimal.ONE.add(BigDecimal.valueOf(0.02)))) > 0
                    || entrustPrice.compareTo(currentPrice.multiply(BigDecimal.ONE.subtract(BigDecimal.valueOf(0.02)))) < 0) {
                return MessageResult.error(500, msService.getMessage("ORDER_PRICE_OVERRUN"));
            }
        }*/
        ContractOrderEntrust orderEntrust = new ContractOrderEntrust();
        
        BigDecimal tradedPrice = BigDecimal.ZERO;
        if(type == ContractOrderType.MARKET_PRICE) {
        	tradedPrice = dealPrice;
        } else if(type == ContractOrderType.LIMIT_PRICE) {
        	if (direction == ContractOrderDirection.BUY) {
        		if(entrustPrice.compareTo(dealPrice) > 0) {
        			tradedPrice = dealPrice;
        			orderEntrust.setIsLimitPrice(1);
        		}// else
        		//	tradedPrice = entrustPrice;
        	} else {
        		if(entrustPrice.compareTo(dealPrice) < 0) {
        			tradedPrice = dealPrice;
        			orderEntrust.setIsLimitPrice(1);
        		}// else
        		//	tradedPrice = entrustPrice;
        	}
        } else {
        	//tradedPrice = entrustPrice;
        	return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        }

        // 新建合约委托单
        orderEntrust.setContractId(contractCoin.getId()); // 合约ID
        orderEntrust.setMemberId(member.getId()); // 用户ID
        orderEntrust.setSymbol(contractCoin.getSymbol()); // 交易对符号
        orderEntrust.setBaseSymbol(contractCoin.getSymbol().split("/")[1]); // 基币/结算币
        orderEntrust.setCoinSymbol(contractCoin.getSymbol().split("/")[0]); // 币种符号
        orderEntrust.setDirection(direction); // 平仓方向：平空/平多
        orderEntrust.setContractOrderEntrustId(GeneratorUtil.getOrderId("CE"));
        orderEntrust.setVolume(volume); // 平仓张数
        orderEntrust.setTradedVolume(BigDecimal.ZERO); // 已交易数量
        orderEntrust.setTradedPrice(tradedPrice); // 成交价格
        orderEntrust.setPrincipalUnit("USDT"); // 保证金单位
        orderEntrust.setPrincipalAmount(BigDecimal.ZERO); // 保证金数量
        orderEntrust.setCreateTime(DateUtil.getTimeMillis()); // 开仓时间
        orderEntrust.setType(type);
        orderEntrust.setTriggerPrice(triggerPrice); // 触发价
        orderEntrust.setEntrustPrice(entrustPrice); // 委托价格
        orderEntrust.setEntrustType(ContractOrderEntrustType.CLOSE); // 开仓
        orderEntrust.setTriggeringTime(0L); // 触发时间，暂时无效
        orderEntrust.setShareNumber(contractCoin.getShareNumber());
        orderEntrust.setProfitAndLoss(BigDecimal.ZERO); // 盈亏（仅平仓计算）
        orderEntrust.setPatterns(ContractOrderPattern.CROSSED); // 仓位模式
        orderEntrust.setCloseFee(BigDecimal.ZERO);
        orderEntrust.setCurrentPrice(currentPrice);
        orderEntrust.setIsBlast(0); // 不是爆仓单
        orderEntrust.setLeverage(memberContractPosition.getLeverage().intValue());
        orderEntrust.setCloseType(CloseType.CLOSE);
        orderEntrust.setPositionId(positionId);
        orderEntrust.setPositionType(memberContractPosition.getType());
        orderEntrust.setMoneyType(memberContractPosition.getMoneyType());
        orderEntrust.setDecimalScale(memberContractPosition.getDecimalScale());
        if(type == ContractOrderType.SPOT_LIMIT) { // 是否是计划委托单
            orderEntrust.setIsFromSpot(1);
        }else{
            orderEntrust.setIsFromSpot(0);
        }

        if(!redisLock.lockTradingAccount(member.getId()))
        	return MessageResult.error(msService.getMessage("SWAP_FAILED"));
        	
        try {
	        ContractOrderEntrust retObj = null;
	        int successCount = memberContractPositionService.freezePosition(positionId, volume);
	        if(successCount == 1) {
		        // 保存委托单
		        orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_ING); // 委托状态：委托中
		        retObj = contractOrderEntrustService.save(orderEntrust);
	        } else {
	        	orderEntrust.setStatus(ContractOrderEntrustStatus.ENTRUST_FAILURE); // 委托状态：委托中
		        contractOrderEntrustService.save(orderEntrust);
	        }
	
	        if (retObj != null) {
	            // 发送消息至Exchange系统
	            kafkaTemplate.send("swap-order-close", JSON.toJSONString(retObj));
	
	
	            //通知钱包变更
	            //JSONObject jsonObj = new JSONObject();
	            //jsonObj.put("symbol", contractCoin.getSymbol());
	            //jsonObj.put("walletId", memberContractWallet.getId());
	            //kafkaTemplate.send("member-wallet-change", JSON.toJSONString(jsonObj));
	
	            log.info(">>>>>>>>>>订单提交完成>>>>>>>>>>");
	            // 返回结果
	            MessageResult result = MessageResult.success(msService.getMessage("SWAP_SUCCESS"));
	            result.setData(retObj);
	            return result;
	        } else {
	            // 返回结果
	            MessageResult result = MessageResult.error(msService.getMessage("SWAP_FAILED"));
	            result.setData(null);
	            return result;
	        }
        } catch (Exception e) {
        	return MessageResult.error(msService.getMessage("SWAP_FAILED"));
        } finally {
            redisLock.unlockTradingAccount(member.getId());
        }
    }

    /**
     * 一键平仓（市价全平）
     * @param authMember
     * @param contractCoinId
     * @param type 0:市价平多  1:市价平空  2:市价平多+平空
     * @return
     * @throws ParseException 
     */
    @ApiOperation(value="市价平仓", notes="市价平仓")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "positionId",value = "仓位ID",required = true,paramType = "form",dataType = "long")
    })
    //@PostMapping("close-all")
    public MessageResult closeAll(@SessionAttribute(SESSION_MEMBER) AuthMember authMember, Long positionId, boolean isReversed) throws ParseException {
        Member member  = memberService.findOne(authMember.getId());
        if (null == member) {
            return MessageResult.error(msService.getMessage("ACCOUNT_NOT_EXIST"));
        }
        if(member.getIsLock() == 1) {
        	return MessageResult.error(501, msService.getMessage("CANNOT_CLOSE"));
        }

        MemberContractPosition position = memberContractPositionService.findOne(positionId);
        if (null == position) {
            return MessageResult.error(msService.getMessage("CONTRACT_ACCOUNT_NOT_EXIST"));
        }
        if(position.getIsLock()!=null && position.getIsLock() == 1) {
        	return MessageResult.error(501, msService.getMessage("CANNOT_CLOSE"));
        }

        if(position.getStatus() == ContractPositionStatus.DONE) {
        	return MessageResult.error(501, msService.getMessage("CANNOT_CLOSE"));
        }

        ContractCoin contractCoin = position.getCoin();
        if (null == contractCoin) {
            return MessageResult.error(msService.getMessage("CONTRACT_NOT_EXIST"));
        }
        
        //cancelOrdersBeforeAllClose(member.getId(), contractCoinId, contractCoin.getSymbol(), type==0?ContractOrderDirection.SELL:ContractOrderDirection.BUY);

        
        BigDecimal currentPrice = contractCoinMatchFactory.getContractCoinMatch(contractCoin.getSymbol()).getNowPrice();
        if (currentPrice.compareTo(BigDecimal.ZERO) <= 0) {
            return MessageResult.error(500, msService.getMessage("CONTRACT_ENGINE_ERROR"));
        }
        
        CloseType closeType = CloseType.MARKET_CLOSE;
        if(isReversed)
        	closeType = CloseType.REVERSE_OPEN;
        position.setCloseType(closeType);
        
        contractCoinMatchFactory.getContractCoinMatch(contractCoin.getSymbol()).dealAllCloseOrder(position);
        //kafkaTemplate.send("swap-order-close-all", JSON.toJSONString(position));
        
        return MessageResult.success();
    }
    
    /**
     * 一键平仓（市价全平）
     * @param authMember
     * @param contractCoinId
     * @param type 0:市价平多  1:市价平空  2:市价平多+平空
     * @return
     * @throws ParseException 
     */
    @ApiOperation(value="一键全平", notes="一键全平")
    @PostMapping("close-all-coins")
    public MessageResult closeAllCoins(@SessionAttribute(SESSION_MEMBER) AuthMember authMember) throws ParseException {
       
        Member member  = memberService.findOne(authMember.getId());
        if (null == member) {
            return MessageResult.error(msService.getMessage("ACCOUNT_NOT_EXIST"));
        }
        if(member.getIsLock() == 1) {
        	return MessageResult.error(501, msService.getMessage("CANNOT_CLOSE"));
        }

        List<MemberContractPosition> list = memberContractPositionService.findCurrentFollowPositionsByMemberId(authMember.getId());
        log.info("list.size()="+list.size());
        for(MemberContractPosition position : list) {
	        if (null == position) {
	            return MessageResult.error(msService.getMessage("CONTRACT_ACCOUNT_NOT_EXIST"));
	        }
	        
	        if(position.getIsLock()!=null && position.getIsLock() == 1) {
	        	continue;
	        }
	        
        	ContractCoin contractCoin = position.getCoin();
        	
        	if(contractCoin == null || contractCoinMatchFactory.getContractCoinMatch(contractCoin.getSymbol())==null) {
        		log.info("contractCoin={}", contractCoin);
        		continue;
        	}
        	BigDecimal currentPrice = contractCoinMatchFactory.getContractCoinMatch(contractCoin.getSymbol()).getNowPrice();
            if (currentPrice.compareTo(BigDecimal.ZERO) <= 0) {
                return MessageResult.error(500, msService.getMessage("CONTRACT_ENGINE_ERROR"));
            }
	        
            position.setCloseType(CloseType.ONE_KEY_CLOSE);
            //contractCoinMatchFactory.getContractCoinMatch(contractCoin.getSymbol()).dealAllCloseOrder(position, CloseType.ONE_KEY_CLOSE);
            kafkaTemplate.send("swap-order-close-all", JSON.toJSONString(position));
        }
        MessageResult result = MessageResult.success(msService.getMessage("SWAP_SUCCESS"));
        //result.setData(retList);
        return result;

        //return MessageResult.error(msService.getMessage("UNABLE_CLOSE_POSITION"));
    }
    
    @ApiOperation(value="修改订单", notes="修改订单")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "entrustId",value = "订单ID",required = true,paramType = "form",dataType = "long"),
    		@ApiImplicitParam(name = "contractCoinId",value = "合约交易对ID",required = true,paramType = "form",dataType = "long"),
            @ApiImplicitParam(name = "type",value = "类型 0：市价 1：限价 2：计划委托",required = true,paramType = "form",dataType = "int"),
            @ApiImplicitParam(name = "triggerPrice",value = "触发价格",required = true,paramType = "form",dataType = "double"),
            @ApiImplicitParam(name = "entrustPrice",value = "委托价格",required = true,paramType = "form",dataType = "double"),
            @ApiImplicitParam(name = "lossPrice",value = "止损价格",required = true,paramType = "form",dataType = "double"),
            @ApiImplicitParam(name = "profitPrice",value = "止盈价格",required = true,paramType = "form",dataType = "double"),
            @ApiImplicitParam(name = "leverage",value = "杠杆倍数",required = true,paramType = "form",dataType = "double"),
            @ApiImplicitParam(name = "volume",value = "数量",required = true,paramType = "form",dataType = "double")
    })
    //@PostMapping("modify")
    public MessageResult modifyOrder(@SessionAttribute(SESSION_MEMBER) AuthMember authMember,
                                     Long entrustId,
                                     @RequestParam(value = "contractCoinId") Long contractCoinId,// 合约交易对
                                     @RequestParam(value = "direction") ContractOrderDirection direction,// 1：买（平空）  2：卖（平多）
                                     @RequestParam(value = "type") ContractOrderType type,// 0：市价 1：限价 2：计划委托
                                     @RequestParam(value = "triggerPrice", required = false) BigDecimal triggerPrice,// 触发价格
                                     @RequestParam(value = "entrustPrice") BigDecimal entrustPrice,// 委托价格(计划委托时如为0：市价成交)
                                     @RequestParam(value = "lossPrice", required = false) BigDecimal lossPrice,
                                     @RequestParam(value = "profitPrice", required = false) BigDecimal profitPrice,
                                     @RequestParam(value = "leverage") BigDecimal leverage,// 委托价格
                                     @RequestParam(value = "volume") BigDecimal volume// 委托数量（张）
    ) {
        if(entrustId == null)
        	return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        
        //return openOrder(authMember, contractCoinId, direction, type, triggerPrice, entrustPrice, lossPrice, profitPrice, leverage, volume, null, 0, 1, entrustId);
        ContractOrderEntrust order = contractOrderEntrustService.findOne(entrustId);
    	if(order.getMemberId().longValue() != authMember.getId()) {
    		return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
    	}
        int result = contractCoinMatchFactory.getContractCoinMatch(order.getSymbol()).modifyContractOrderEntrust(order, profitPrice, lossPrice);
    	if(result == 5)
    		return MessageResult.error(500, "止赢触发价需小于委托价");
    	else if(result == 6)
    		return MessageResult.error(500, "止损触发价需大于委托价");
    	else if(result == 7)
    		return MessageResult.error(500, "止赢触发价需大于委托价");
    	else if(result == 8)
    		return MessageResult.error(500, "止损触发价需小于委托价");
    	else if(result == 9)
    		return MessageResult.error(500, "必须先设置委托价才能设置止盈止损");
    	else if(result == 10)
    		return MessageResult.error(500, msService.getMessage("ILLEGAL_OPERATION"));
    	return MessageResult.success();
    }

    /**
     * 合约撤销单
     * @param authMember
     * @param entrustId
     * @return
     */
    @ApiOperation(value="撤销订单", notes="撤销订单")
    @ApiImplicitParams(value = {
    		@ApiImplicitParam(name = "entrustId",value = "订单ID",required = true,paramType = "form",dataType = "int")
    })
    //@PostMapping("cancel")
    public MessageResult cancelOrder(@SessionAttribute(SESSION_MEMBER) AuthMember authMember,
                                     Long entrustId
    ) {
    	if(entrustId == null)
        	return MessageResult.error(500, msService.getMessage("ILLEGAL_ARGUMENT"));
        ContractOrderEntrust entrustOrder = contractOrderEntrustService.findOne(entrustId);
        if(entrustOrder == null) {
            return MessageResult.error(500, msService.getMessage("ORDER_NO_EXIST"));
        }
        if(entrustOrder.getMemberId() != authMember.getId()) {
            return MessageResult.error(500, msService.getMessage("ILLEGAL_OPERATION"));
        }
        if(entrustOrder.getStatus() != ContractOrderEntrustStatus.ENTRUST_ING) {
            return MessageResult.error(500, msService.getMessage("DELEGATE_STATUS_ERROR"));
        }

        // 发送消息至Exchange系统
        //kafkaTemplate.send("swap-order-cancel", JSON.toJSONString(entrustOrder));
        BigDecimal releasedPosition = contractCoinMatchFactory.getContractCoinMatch(entrustOrder.getSymbol()).cancelContractOrderEntrust(entrustOrder, false);

        if(releasedPosition.compareTo(BigDecimal.ZERO)>0) {
	        log.info(">>>>>>>>>>订单提交完成>>>>>>>>>>");
	        // 返回结果
	        MessageResult result = MessageResult.success(msService.getMessage("CANCELLATION_SUCCESSFUL"));
	        result.setData(entrustOrder);
	        return result;
        } else {
        	return MessageResult.error(500, msService.getMessage("ORDER_NO_EXIST"));
        }
    }
}