Skip to content

获取5档盘口方法使用错误 #13

Description

@jxie8301-pixel

明明直接使用get_full_tick就可以获取5档盘口,为什么要先订阅一下再用get_full_tick??

def get_order_book(self, codes: Union[str, List[str]]) -> pd.DataFrame:
"""
获取五档行情数据(买卖盘口)

    注意:需要先订阅行情才能获取五档数据

    Args:
        codes: 股票代码

    Returns:
        DataFrame: 包含五档买卖价和量的数据
        字段包括:
        - code: 股票代码
        - lastPrice: 最新价
        - bid1-bid5: 买一到买五价格
        - ask1-ask5: 卖一到卖五价格
        - bidVol1-bidVol5: 买一到买五量
        - askVol1-askVol5: 卖一到卖五量

    Raises:
        ConnectionError: 连接失败
        DataError: 数据获取失败
    """
    if not self.xt:
        raise ConnectionError("xtquant未正确导入,无法获取数据")

    if not self._connected:
        raise ConnectionError("数据服务未连接,请先调用init_data()并确保迅投客户端已启动")

    codes = StockCodeUtils.normalize_codes(codes)

    try:
        # 先订阅行情(重要:必须先订阅才能获取五档数据)
        if isinstance(codes, str):
            codes_list = [codes]
        else:
            codes_list = codes

        # 订阅每只股票的tick行情
        print("[DEBUG] 开始订阅行情...")
        for code in codes_list:
            try:
                # subscribe_quote 订阅行情接口
                # period: 'tick' 分笔, '1d' 日线等
                if hasattr(self.xt, 'subscribe_quote'):
                    result = self.xt.subscribe_quote(code, period='tick')
                    print(f"[DEBUG] {code} 订阅结果: {result}")
            except Exception as e:
                # 订阅失败不中断,继续尝试获取数据
                print(f"[DEBUG] {code} 订阅异常: {e}")

        # 等待让订阅生效并重试获取数据
        import time
        print("[DEBUG] 等待数据推送...")
        time.sleep(2.0)  # 增加到2秒

        # 获取完整tick数据,带重试机制
        tick_data = None
        max_retries = 3
        for attempt in range(max_retries):
            tick_data = self.xt.get_full_tick(codes)
            if tick_data:
                # 检查是否有五档数据
                has_order_book = False
                for code, tick_info in tick_data.items():
                    if tick_info:
                        # 根据官方文档,字段名是 askPrice 和 bidPrice
                        ask_price = tick_info.get('askPrice')
                        bid_price = tick_info.get('bidPrice')
                        # 这些字段可能是数组或单个值
                        # 检查是否有非空值(数组、非None的数字都算有数据)
                        if ask_price is not None or bid_price is not None:
                            has_order_book = True
                            break

                if has_order_book:
                    print(f"[DEBUG] 第{attempt + 1}次尝试成功获取到五档数据")
                    break
                else:
                    print(f"[DEBUG] 第{attempt + 1}次尝试:五档数据为空,等待2秒后重试...")
                    if attempt < max_retries - 1:
                        time.sleep(2.0)
            else:
                print(f"[DEBUG] 第{attempt + 1}次尝试:无法获取tick数据")
                if attempt < max_retries - 1:
                    time.sleep(2.0)

        if not tick_data:
            raise DataError("无法获取五档行情数据")

        result_list = []
        for code, tick_info in tick_data.items():
            if tick_info:
                # 获取askPrice和bidPrice - 根据文档这些可能是数组
                ask_price = tick_info.get('askPrice', 0)
                bid_price = tick_info.get('bidPrice', 0)
                ask_vol = tick_info.get('askVol', 0)
                bid_vol = tick_info.get('bidVol', 0)

                # 处理askPrice和bidPrice可能是数组的情况
                def extract_price_or_vol(value, index=0):
                    """提取价格或量,支持数组或单个值"""
                    if hasattr(value, '__len__') and not isinstance(value, str):
                        # 是数组或列表
                        if len(value) > index:
                            return value[index]
                        return 0
                    # 是单个值
                    if index == 0:
                        return value if value else 0
                    return 0

                # 提取五档行情数据
                order_book_data = {
                    'code': code,
                    'lastPrice': tick_info.get('lastPrice', 0),
                    'open': tick_info.get('open', 0),
                    'high': tick_info.get('high', 0),
                    'low': tick_info.get('low', 0),
                    'preClose': tick_info.get('lastClose', 0),
                    'volume': tick_info.get('volume', 0),
                    'amount': tick_info.get('amount', 0),
                    'time': tick_info.get('time', 0),
                    # 五档买价 - 使用askPrice和bidPrice
                    'bid1': extract_price_or_vol(bid_price, 0),
                    'bid2': extract_price_or_vol(bid_price, 1),
                    'bid3': extract_price_or_vol(bid_price, 2),
                    'bid4': extract_price_or_vol(bid_price, 3),
                    'bid5': extract_price_or_vol(bid_price, 4),
                    # 五档卖价
                    'ask1': extract_price_or_vol(ask_price, 0),
                    'ask2': extract_price_or_vol(ask_price, 1),
                    'ask3': extract_price_or_vol(ask_price, 2),
                    'ask4': extract_price_or_vol(ask_price, 3),
                    'ask5': extract_price_or_vol(ask_price, 4),
                    # 五档买量
                    'bidVol1': extract_price_or_vol(bid_vol, 0),
                    'bidVol2': extract_price_or_vol(bid_vol, 1),
                    'bidVol3': extract_price_or_vol(bid_vol, 2),
                    'bidVol4': extract_price_or_vol(bid_vol, 3),
                    'bidVol5': extract_price_or_vol(bid_vol, 4),
                    # 五档卖量
                    'askVol1': extract_price_or_vol(ask_vol, 0),
                    'askVol2': extract_price_or_vol(ask_vol, 1),
                    'askVol3': extract_price_or_vol(ask_vol, 2),
                    'askVol4': extract_price_or_vol(ask_vol, 3),
                    'askVol5': extract_price_or_vol(ask_vol, 4),
                }
                result_list.append(order_book_data)

        if not result_list:
            raise DataError("未获取到有效的五档行情数据")

        return pd.DataFrame(result_list)

    except Exception as e:
        if isinstance(e, (ConnectionError, DataError)):
            raise
        ErrorHandler.log_error(f"获取五档行情失败: {str(e)}")
        raise DataError(f"获取五档行情失败: {str(e)}")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions