feat(ws): 添加订单更新ID日志记录功能
- 在订单更新日志中增加update_id字段输出
- 提取订单update_id用于日志记录
- 保持原有订单状态更新逻辑不变
1 files added
3 files modified
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 用户私有成交回调。由 {@link com.xcong.excoin.modules.gateApi.wsHandler.handler.UserTradesChannelHandler} |
| | | * 在收到 {@code futures.usertrades} 推送时调用。 |
| | | * |
| | | * @param contract 合约名称 |
| | | * @param orderId 订单 ID |
| | | * @param price 成交价格 |
| | | * @param size 成交数量 |
| | | * @param role 用户角色(maker / taker) |
| | | * @param fee 手续费 |
| | | */ |
| | | public void onUserTrade(String contract, String orderId, BigDecimal price, String size, String role, BigDecimal fee) { |
| | | if (state == StrategyState.STOPPED) { |
| | | return; |
| | | } |
| | | log.info("[Gate] 成交明细, 合约:{}, 订单ID:{}, 价格:{}, 数量:{}, 角色:{}, 手续费:{}", |
| | | contract, orderId, price, size, role, fee); |
| | | } |
| | | |
| | | // ---- 网格队列处理 ---- |
| | | |
| | | /** |
| | |
| | | |
| | | TriggerOrderResponse response = futuresApi.createPriceTriggeredOrder(SETTLE, order); |
| | | String orderId = String.valueOf(response.getId()); |
| | | String orderIdStr = response.getIdString(); |
| | | log.info("[TradeExec] 条件开仓单已创建, trigger:{}, rule:{}, size:{}, id:{}", |
| | | triggerPrice, rule, size, orderId); |
| | | if (onSuccess != null) { |
| | |
| | | import com.xcong.excoin.modules.gateApi.wsHandler.handler.OrdersChannelHandler; |
| | | import com.xcong.excoin.modules.gateApi.wsHandler.handler.PositionClosesChannelHandler; |
| | | import com.xcong.excoin.modules.gateApi.wsHandler.handler.PositionsChannelHandler; |
| | | import com.xcong.excoin.modules.gateApi.wsHandler.handler.UserTradesChannelHandler; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | |
| | | config.getApiKey(), config.getApiSecret(), config.getContract(), gridTradeService)); |
| | | wsClient.addChannelHandler(new OrdersChannelHandler( |
| | | config.getApiKey(), config.getApiSecret(), config.getContract(), gridTradeService)); |
| | | wsClient.addChannelHandler(new UserTradesChannelHandler( |
| | | config.getApiKey(), config.getApiSecret(), config.getContract(), gridTradeService)); |
| | | wsClient.init(); |
| | | log.info("[管理器] WS已连接, 已注册 4 个频道处理器"); |
| | | log.info("[管理器] WS已连接, 已注册 5 个频道处理器"); |
| | | |
| | | // 3. 激活策略,等待首根 K 线触发基底双开 |
| | | gridTradeService.startGrid(); |
| New file |
| | |
| | | package com.xcong.excoin.modules.gateApi.wsHandler.handler; |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.xcong.excoin.modules.gateApi.GateGridTradeService; |
| | | import com.xcong.excoin.modules.gateApi.wsHandler.AbstractPrivateChannelHandler; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * 用户私有成交频道处理器(futures.usertrades)。 |
| | | * |
| | | * <h3>数据用途</h3> |
| | | * 订阅用户私有成交更新推送。当订单成交时,获得真实的成交价格、手续费等信息, |
| | | * 可用于计算实际盈亏。 |
| | | * |
| | | * <h3>关键推送字段</h3> |
| | | * <ul> |
| | | * <li>id:交易 ID</li> |
| | | * <li>contract:合约名称</li> |
| | | * <li>order_id:订单 ID</li> |
| | | * <li>size:成交数量</li> |
| | | * <li>price:成交价格</li> |
| | | * <li>role:用户角色(maker/taker)</li> |
| | | * <li>fee:手续费</li> |
| | | * <li>point_fee:点卡手续费</li> |
| | | * <li>text:订单自定义信息</li> |
| | | * </ul> |
| | | * |
| | | * <h3>回调数据(传给 GateGridTradeService)</h3> |
| | | * contract (String), orderId (String), price (BigDecimal), size (String), role (String), fee (BigDecimal) |
| | | * |
| | | * @author Administrator |
| | | */ |
| | | @Slf4j |
| | | public class UserTradesChannelHandler extends AbstractPrivateChannelHandler { |
| | | |
| | | private static final String CHANNEL_NAME = "futures.usertrades"; |
| | | |
| | | public UserTradesChannelHandler(String apiKey, String apiSecret, |
| | | String contract, |
| | | GateGridTradeService gridTradeService) { |
| | | super(CHANNEL_NAME, apiKey, apiSecret, contract, gridTradeService); |
| | | } |
| | | |
| | | @Override |
| | | public boolean handleMessage(JSONObject response) { |
| | | if (!CHANNEL_NAME.equals(response.getString("channel"))) { |
| | | return false; |
| | | } |
| | | try { |
| | | JSONArray resultArray = response.getJSONArray("result"); |
| | | if (resultArray == null || resultArray.isEmpty()) { |
| | | return true; |
| | | } |
| | | for (int i = 0; i < resultArray.size(); i++) { |
| | | JSONObject trade = resultArray.getJSONObject(i); |
| | | String contract = trade.getString("contract"); |
| | | if (!getContract().equals(contract)) { |
| | | continue; |
| | | } |
| | | String id = trade.getString("id"); |
| | | String orderId = trade.getString("order_id"); |
| | | String size = trade.getString("size"); |
| | | BigDecimal price = trade.getBigDecimal("price"); |
| | | String role = trade.getString("role"); |
| | | BigDecimal fee = trade.getBigDecimal("fee"); |
| | | String text = trade.getString("text"); |
| | | log.info("[{}] 成交更新, id:{}, order_id:{}, price:{}, size:{}, role:{}, fee:{}, text:{}", |
| | | CHANNEL_NAME, id, orderId, price, size, role, fee, text); |
| | | if (getGridTradeService() != null) { |
| | | getGridTradeService().onUserTrade(contract, orderId, price, size, role, fee); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("[{}] 处理数据失败", CHANNEL_NAME, e); |
| | | } |
| | | return true; |
| | | } |
| | | } |