| | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.xcong.excoin.modules.okxNewPrice.celue.CaoZuoService; |
| | | import com.xcong.excoin.modules.okxNewPrice.OkxWebSocketClientManager; |
| | | import com.xcong.excoin.modules.okxNewPrice.okxWs.TradeOrderWs; |
| | | import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.CoinEnums; |
| | | import com.xcong.excoin.modules.okxNewPrice.okxWs.param.TradeRequestParam; |
| | | import com.xcong.excoin.modules.okxNewPrice.okxWs.wanggeList.WangGeListEnum; |
| | | import com.xcong.excoin.modules.okxNewPrice.okxWs.wanggeList.WangGeListService; |
| | | import com.xcong.excoin.modules.okxNewPrice.utils.SSLConfig; |
| | | import com.xcong.excoin.rabbit.pricequeue.WebsocketPriceService; |
| | | import com.xcong.excoin.utils.CoinTypeConvert; |
| | | import com.xcong.excoin.utils.RedisUtils; |
| | | import java.math.BigDecimal; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.java_websocket.client.WebSocketClient; |
| | | import org.java_websocket.handshake.ServerHandshake; |
| | | |
| | | import java.net.URI; |
| | | import java.net.URISyntaxException; |
| | | import java.util.Collection; |
| | | import java.util.concurrent.*; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | import java.util.concurrent.atomic.AtomicReference; |
| | |
| | | private final RedisUtils redisUtils; |
| | | private final CaoZuoService caoZuoService; |
| | | private final OkxWebSocketClientManager clientManager; |
| | | private final WangGeListService wangGeListService; |
| | | |
| | | private WebSocketClient webSocketClient; |
| | | private ScheduledExecutorService heartbeatExecutor; |
| | |
| | | }); |
| | | |
| | | public OkxNewPriceWebSocketClient(RedisUtils redisUtils, |
| | | CaoZuoService caoZuoService, OkxWebSocketClientManager clientManager) { |
| | | CaoZuoService caoZuoService, OkxWebSocketClientManager clientManager, |
| | | WangGeListService wangGeListService) { |
| | | this.redisUtils = redisUtils; |
| | | this.caoZuoService = caoZuoService; |
| | | this.clientManager = clientManager; |
| | | this.wangGeListService = wangGeListService; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | private void triggerQuantOperations(String markPx) { |
| | | try { |
| | | // 1. 判断当前价格属于哪个网格 |
| | | WangGeListEnum gridByPriceNew = WangGeListEnum.getGridByPrice(new BigDecimal(markPx)); |
| | | if (gridByPriceNew == null) { |
| | | log.error("当前价格{}不在任何网格范围内,无法触发量化操作", markPx); |
| | | return; |
| | | } |
| | | /** |
| | | * 获取当前网格信息 |
| | | * 根据当前网格的持仓方向获取反方向是否存在持仓 |
| | | * 如果持有,直接止损 |
| | | */ |
| | | Collection<OkxQuantWebSocketClient> allClients = clientManager.getAllClients(); |
| | | //如果为空,则直接返回 |
| | | if (allClients.isEmpty()) { |
| | | return; |
| | | } |
| | | // 获取所有OkxQuantWebSocketClient实例 |
| | | for (OkxQuantWebSocketClient client : clientManager.getAllClients()) { |
| | | // 由于OkxQuantWebSocketClient没有直接暴露账号名称的方法,我们需要从clientManager中获取 |
| | | // 这里可以通过遍历clientMap的方式获取账号名称 |
| | | // 或者修改OkxQuantWebSocketClient,添加getAccountName方法 |
| | | // 暂时使用这种方式获取账号名称 |
| | | String accountName = getAccountNameFromClient(client); |
| | | String accountName = client.getAccountName(); |
| | | if (accountName != null) { |
| | | // 调用CaoZuoService的caoZuo方法,触发量化操作 |
| | | String side = caoZuoService.caoZuo(accountName); |
| | | TradeOrderWs.orderEvent(client.getWebSocketClient(), side, accountName); |
| | | log.info("价格变化触发量化操作: 账号={}, 价格={}, 操作方向={}", accountName, markPx, side); |
| | | /** |
| | | * 处理历史网格的订单 |
| | | * 根据历史网格的开单方向,是否需要止损处理 |
| | | * 如果方向一致就不需要处理 |
| | | * 如果不一致则需要处理 |
| | | */ |
| | | String fangXiang = gridByPriceNew.getFang_xiang(); |
| | | String fangXiangOld = CoinEnums.POSSIDE_LONG.getCode().equals(fangXiang) ? CoinEnums.POSSIDE_SHORT.getCode() : CoinEnums.POSSIDE_LONG.getCode(); |
| | | log.info("历史网格方向为:{}", fangXiangOld); |
| | | if (!fangXiang.equals(fangXiangOld)){ |
| | | TradeRequestParam tradeRequestParamOld = caoZuoService.caoZuoZhiSunEvent(accountName, markPx, fangXiangOld); |
| | | TradeOrderWs.orderEvent(client.getWebSocketClient(), tradeRequestParamOld); |
| | | } |
| | | |
| | | /** |
| | | * 处理当前网格的订单,触发量化操作 |
| | | */ |
| | | log.info("当前价格{}属于网格: {}-{}({}-{})", markPx, gridByPriceNew.getName(),gridByPriceNew.getFang_xiang(), gridByPriceNew.getJiage_xiaxian(), gridByPriceNew.getJiage_shangxian()); |
| | | wangGeListService.initWangGe(markPx); |
| | | TradeRequestParam tradeRequestParam = caoZuoService.caoZuoHandler(accountName, markPx, gridByPriceNew.getFang_xiang()); |
| | | TradeOrderWs.orderEvent(client.getWebSocketClient(), tradeRequestParam); |
| | | log.info("价格变化触发量化操作: 账号={}, 价格={}", accountName, markPx); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("触发量化操作失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 从OkxQuantWebSocketClient实例中获取账号名称 |
| | | * 由于OkxQuantWebSocketClient没有直接暴露账号名称的方法,这里需要通过反射获取 |
| | | * 更好的方式是修改OkxQuantWebSocketClient,添加getAccountName方法 |
| | | */ |
| | | private String getAccountNameFromClient(OkxQuantWebSocketClient client) { |
| | | try { |
| | | // 通过反射获取account字段的值 |
| | | java.lang.reflect.Field accountField = OkxQuantWebSocketClient.class.getDeclaredField("account"); |
| | | accountField.setAccessible(true); |
| | | Object account = accountField.get(client); |
| | | // 调用account的name()方法获取账号名称 |
| | | java.lang.reflect.Method nameMethod = account.getClass().getMethod("name"); |
| | | return (String) nameMethod.invoke(account); |
| | | } catch (Exception e) { |
| | | log.error("获取账号名称失败", e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | private void reconnectWithBackoff() throws InterruptedException { |
| | | int attempt = 0; |
| | | int maxAttempts = 5; |
| | | int maxAttempts = 3; |
| | | long delayMs = 5000; |
| | | |
| | | while (attempt < maxAttempts) { |