package com.xcong.excoin.modules.okxNewPrice.okxWs; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.CoinEnums; import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.OrderParamEnums; import com.xcong.excoin.modules.okxNewPrice.okxpi.MallUtils; import com.xcong.excoin.modules.okxNewPrice.utils.WsParamBuild; import com.xcong.excoin.utils.RedisUtils; import lombok.extern.slf4j.Slf4j; import org.java_websocket.client.WebSocketClient; import java.math.BigDecimal; /** * @author Administrator */ @Slf4j public class TradeOrderWs { public static final String ORDERWS_CHANNEL = "order"; public static void orderEvent(WebSocketClient webSocketClient, RedisUtils redisUtils, String side) { log.info("开始执行TradeOrderWs......"); if (StrUtil.isBlank( side)){ log.warn("止损了,下次再战..."); return; } String buyCnt = null; String ctval = getRedisValue(redisUtils, InstrumentsWs.INSTRUMENTSWS_CHANNEL, ":ctVal"); String buyCntNormal = getRedisValue(redisUtils, PositionsWs.POSITIONSWS_CHANNEL, ":buyCnt"); String pos = getRedisValue(redisUtils, PositionsWs.POSITIONSWS_CHANNEL, ":pos"); if (OrderParamEnums.ORDERING.getValue().equals(side)) { log.warn("正在下单中,等待下单结束..."); return; } else if (OrderParamEnums.HOLDING.getValue().equals(side)) { return; } else if (OrderParamEnums.INIT.getValue().equals(side)) { side = OrderParamEnums.BUY.getValue(); if (StrUtil.isNotBlank(buyCntNormal) && new BigDecimal(buyCntNormal).compareTo(BigDecimal.ZERO) > 0) { buyCnt = buyCntNormal; }else{ buyCnt = ctval; } } else if (OrderParamEnums.OUT.getValue().equals(side)) { log.info(OrderParamEnums.getNameByValue(OrderParamEnums.OUT.getValue())); side = OrderParamEnums.SELL.getValue(); buyCnt = pos; } else if (OrderParamEnums.BUY.getValue().equals(side)){ side = OrderParamEnums.BUY.getValue(); if (StrUtil.isNotBlank(buyCntNormal) && BigDecimal.ZERO.compareTo(new BigDecimal(buyCntNormal)) > 0) { buyCnt = buyCntNormal; }else{ buyCnt = ctval; } }else if (OrderParamEnums.SELL.getValue().equals(side)){ side = OrderParamEnums.SELL.getValue(); buyCnt = getRedisValue(redisUtils, PositionsWs.POSITIONSWS_CHANNEL, ":pos"); }else{ log.warn("操作信号异常,请检查下单操作..."); return; } // 校验必要参数 if (StrUtil.isBlank(side)) { log.warn("下单参数 side 为空,取消发送"); return; } if (StrUtil.isBlank(buyCnt)) { log.warn("下单数量 buyCnt 为空,取消发送"); return; } try { String clOrdId = MallUtils.getOrderNum(side); JSONArray argsArray = new JSONArray(); JSONObject args = new JSONObject(); args.put("instId", CoinEnums.HE_YUE.getCode()); args.put("tdMode", CoinEnums.CROSS.getCode()); args.put("clOrdId", clOrdId); args.put("side", side); args.put("posSide", CoinEnums.POSSIDE_LONG.getCode()); args.put("ordType", CoinEnums.ORDTYPE_MARKET.getCode()); args.put("sz", buyCnt); argsArray.add(args); String connId = MallUtils.getOrderNum(ORDERWS_CHANNEL); JSONObject jsonObject = WsParamBuild.buildJsonObject(connId, ORDERWS_CHANNEL, argsArray); webSocketClient.send(jsonObject.toJSONString()); log.info("发送下单频道:{},数量:{}", side, buyCnt); boolean setResult = redisUtils.set(ORDERWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":clOrdId", clOrdId, 0) && redisUtils.set(ORDERWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state", CoinEnums.ORDER_FILLED.getCode(), 0) && redisUtils.set(InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state", OrderParamEnums.STATE_4.getValue(), 0); if (!setResult) { log.warn("Redis set operation failed for key: order:{}", CoinEnums.HE_YUE.getCode()); } } catch (Exception e) { log.error("下单构建失败", e); } } /** * 计算盈亏金额。 * * @param faceValue 面值 * @param position 持仓数量 * @param markPrice 标记价格 * @param openPrice 开仓价格 * @param isLong 是否为多头仓位 * @param minTickSz 最小变动单位精度 * @return 盈亏金额,保留指定精度的小数位 */ public BigDecimal profit(BigDecimal faceValue, BigDecimal position, BigDecimal markPrice, BigDecimal openPrice, boolean isLong, int minTickSz) { BigDecimal profit = BigDecimal.ZERO; if (isLong) { profit = markPrice.subtract(openPrice) .multiply(faceValue) .multiply(position); } else { profit = openPrice.subtract(markPrice) .multiply(faceValue) .multiply(position); } return profit.setScale(minTickSz, BigDecimal.ROUND_DOWN); } /** * 统一封装 Redis Key 构建逻辑 * * @param redisUtils Redis 工具类实例 * @param prefix 渠道前缀 * @param suffix 字段后缀 * @return Redis 中存储的值 */ private static String getRedisValue(RedisUtils redisUtils, String prefix, String suffix) { String key = prefix + ":" + CoinEnums.HE_YUE.getCode() + suffix; Object valueObj = redisUtils.get(key); return valueObj == null ? null : String.valueOf(valueObj); } }