diff --git a/交易/weex-结构优化.py b/交易/weex-结构优化.py index d0a66b8..9280e3e 100644 --- a/交易/weex-结构优化.py +++ b/交易/weex-结构优化.py @@ -258,12 +258,12 @@ class WEEXApiClient: logger.error("获取余额失败:已重试3次仍未成功") return None - def get_position_status(self) -> Tuple[bool, Optional[Dict]]: + def get_position_status(self) -> Tuple[bool, Optional[List]]: """ 获取持仓状态 Returns: - (success, position_data): success为是否成功,position_data为持仓信息 + (success, position_data): success为是否成功,position_data为持仓信息列表 """ json_data = { 'filterContractIdList': [10000002], @@ -449,16 +449,16 @@ class PositionManager: def __init__(self, trading_executor: TradingExecutor): self.trading_executor = trading_executor self.current_position: int = self.POSITION_NONE - self.position_data: Optional[Dict] = None + self.position_data: Optional[List] = None - def update_position(self, position_data: Optional[Dict]) -> None: + def update_position(self, position_data: Optional[List]) -> None: """ 更新持仓状态 Args: - position_data: 持仓数据字典 + position_data: 持仓数据列表 """ - self.position_datas = position_data + self.position_data = position_data # 修复:统一使用position_data if not position_data: self.current_position = self.POSITION_NONE @@ -549,70 +549,29 @@ class MessageSender: send_dingtalk_message(f"{prefix}{message_content}") @staticmethod - def format_position_message(position_data: Optional[Dict], + def format_position_message(position_data: Optional[List], + current_position: int, current_price: float, available_balance: float) -> str: """ 格式化持仓信息消息 Args: - position_data: 持仓数据 + position_data: 持仓数据列表 + current_position: 当前持仓方向 (-1:空, 0:无, 1:多) current_price: 当前价格 available_balance: 可用余额 """ - if position_data: - # 提取持仓信息 - fill_size = float(position_data['fillSize']) # 持仓量,单位:ETH - fill_value = float(position_data['fillValue']) # 成交名义价值 USDT - open_avg_price = fill_value / fill_size if fill_size > 0 else 0 # 开仓均价 - - position_side = position_data.get('positionSide', '') - legacy_direction = position_data.get('legacyOrderDirection', '') - - # 确定方向 - if legacy_direction == 'OPEN_SHORT': - direction = "空" - elif legacy_direction == 'OPEN_LONG': - direction = "多" - else: - direction = "无" - - # 计算浮动盈亏 - if direction in ["多", "空"] and open_avg_price > 0: - if direction == "多": - unrealized_pnl = fill_size * (current_price - open_avg_price) - pnl_rate = (current_price - open_avg_price) / open_avg_price * 100 - else: - unrealized_pnl = fill_size * (open_avg_price - current_price) - pnl_rate = (open_avg_price - current_price) / open_avg_price * 100 - - pnl_str = f"{unrealized_pnl:+.2f} USDT ({pnl_rate:+.2f}%)" - - # 当前持仓名义价值 - current_value = fill_size * current_price - - return ( - "**【WEEX ETHUSDT 永续持仓监控】**\n\n" - f"**持仓方向**:{direction}\n" - f"**当前现价**:{current_price:.2f} USDT\n" - f"**开仓均价**:{open_avg_price:.2f} USDT\n" - f"**持仓数量(eth)**:{fill_size:.3f} ETH\n" - f"**持仓数量(usdt)**:{fill_value / 100:.2f} USDT\n" - f"**名义价值**:{current_value:.2f} USDT\n" - f"**浮动盈亏**:{pnl_str}\n" - f"**账户可用余额**:{available_balance:.2f} USDT" - ) - else: - pnl_str = "0.00 USDT" - - return ( - "**【WEEX ETHUSDT 永续持仓监控】**\n\n" - f"**持仓方向**:无\n" - f"**当前现价**:{current_price:.2f} USDT\n" - f"**账户可用余额**:{available_balance:.2f} USDT" - ) - + # 根据current_position确定持仓方向 + if current_position == PositionManager.POSITION_LONG: + direction = "多" + elif current_position == PositionManager.POSITION_SHORT: + direction = "空" else: + direction = "无" + + # 如果没有持仓,直接返回无持仓消息 + if current_position == PositionManager.POSITION_NONE: return ( "**【WEEX ETHUSDT 永续持仓监控】**\n\n" f"**持仓方向**:无\n" @@ -620,6 +579,77 @@ class MessageSender: f"**账户可用余额**:{available_balance:.2f} USDT" ) + # 如果有持仓,尝试从position_data中提取持仓信息 + if position_data and isinstance(position_data, list) and len(position_data) > 0: + try: + # 从列表中查找最新的开仓记录 + open_order = None + total_fill_size = 0.0 + total_fill_value = 0.0 + + for order in reversed(position_data): # 从最新到最旧遍历 + legacy_direction = order.get("legacyOrderDirection", "") + + # 查找对应方向的开仓记录 + if current_position == PositionManager.POSITION_LONG and legacy_direction == "OPEN_LONG": + fill_size = float(order.get('fillSize', 0)) + fill_value = float(order.get('fillValue', 0)) + if fill_size > 0: + total_fill_size += fill_size + total_fill_value += fill_value + if open_order is None: + open_order = order + elif current_position == PositionManager.POSITION_SHORT and legacy_direction == "OPEN_SHORT": + fill_size = float(order.get('fillSize', 0)) + fill_value = float(order.get('fillValue', 0)) + if fill_size > 0: + total_fill_size += fill_size + total_fill_value += fill_value + if open_order is None: + open_order = order + + # 如果遇到平仓记录,停止累计 + if (current_position == PositionManager.POSITION_LONG and legacy_direction == "CLOSE_LONG") or \ + (current_position == PositionManager.POSITION_SHORT and legacy_direction == "CLOSE_SHORT"): + break + + if total_fill_size > 0: + # 计算开仓均价 + open_avg_price = total_fill_value / total_fill_size if total_fill_size > 0 else 0 + + # 计算浮动盈亏 + if direction == "多": + unrealized_pnl = total_fill_size * (current_price - open_avg_price) + pnl_rate = (current_price - open_avg_price) / open_avg_price * 100 if open_avg_price > 0 else 0 + else: # 空 + unrealized_pnl = total_fill_size * (open_avg_price - current_price) + pnl_rate = (open_avg_price - current_price) / open_avg_price * 100 if open_avg_price > 0 else 0 + + pnl_str = f"{unrealized_pnl:+.2f} USDT ({pnl_rate:+.2f}%)" + current_value = total_fill_size * current_price + + return ( + "**【WEEX ETHUSDT 永续持仓监控】**\n\n" + f"**持仓方向**:{direction}\n" + f"**当前现价**:{current_price:.2f} USDT\n" + f"**开仓均价**:{open_avg_price:.2f} USDT\n" + f"**持仓数量(eth)**:{total_fill_size:.3f} ETH\n" + f"**持仓数量(usdt)**:{total_fill_value / 100:.2f} USDT\n" + f"**名义价值**:{current_value:.2f} USDT\n" + f"**浮动盈亏**:{pnl_str}\n" + f"**账户可用余额**:{available_balance:.2f} USDT" + ) + except Exception as e: + logger.warning(f"解析持仓数据失败: {e}") + + # 如果无法解析持仓数据,至少显示持仓方向 + return ( + "**【WEEX ETHUSDT 永续持仓监控】**\n\n" + f"**持仓方向**:{direction}\n" + f"**当前现价**:{current_price:.2f} USDT\n" + f"**账户可用余额**:{available_balance:.2f} USDT" + ) + # ==================== 时间工具类 ==================== class TimeUtils: @@ -859,8 +889,10 @@ class WeexTransaction: current_price = float(self.kline_3["close"]) if balance is not None: position_info = self.position_manager.position_data + current_pos = self.position_manager.current_position msg = MessageSender.format_position_message( position_info, + current_pos, current_price, balance )