import logging
import pandas as pd
from decimal import Decimal
from core.smc.SMCStruct import SMCStruct


class SMCLiquidity(SMCStruct):
    EQUAL_HIGH_COL = "equal_high"
    EQUAL_LOW_COL = "equal_low"
    LIQU_HIGH_COL = "liqu_high"
    LIQU_LOW_COL = "liqu_low"
    EQUAL_HIGH_INDEX_KEY = "equal_high_index"
    EQUAL_LOW_INDEX_KEY = "equal_low_index"
    HAS_EQ_KEY = "has_EQ"
    LIQU_HIGH_DIFF_COL = "liqu_high_diff"
    LIQU_LOW_DIFF_COL = "liqu_low_diff"

    # 新增等高等低点识别相关常量
    EQUAL_POINTS_TIMESTAMP_COL = "equal_points_timestamp"
    EQUAL_POINTS_INDEX_COL = "equal_points_index"
    EQUAL_POINTS_PRICE_COL = "equal_points_price"
    EQUAL_POINTS_TYPE_COL = "equal_points_type"
    EXTREME_INDEX_COL = "extreme_index"
    EXTREME_VALUE_COL = "extreme_value"
    ATR_TOLERANCE_COL = "atr_tolerance"
    IS_EXTREME_COL = "is_extreme"
    HAS_EQUAL_POINTS_COL = "has_equal_points"

    def __init__(self):
        super().__init__()
        self.logger = logging.getLogger(__name__)
        # 调试配置
        self.debug_enabled = False
        self.debug_level = 'INFO'  # 'DEBUG', 'INFO', 'WARNING', 'ERROR'
        self.debug_info_cache = {}

    def _identify_liquidity_pivots(self, data, pivot_length=1):
        """
        识别流动性的高点和低点
        """

        df = data.copy()

        # 识别高点
        df[self.LIQU_HIGH_COL] = Decimal(0.0)
        for i in range(pivot_length, len(df) - pivot_length):
            if df[self.HIGH_COL].iloc[i] == max(
                df[self.HIGH_COL].iloc[i - pivot_length : i + pivot_length + 1]
            ):
                df.loc[df.index[i], self.LIQU_HIGH_COL] = df[self.HIGH_COL].iloc[i]
        # 识别低点
        df[self.LIQU_LOW_COL] = Decimal(0.0)
        for i in range(pivot_length, len(df) - pivot_length):
            if df[self.LOW_COL].iloc[i] == min(
                df[self.LOW_COL].iloc[i - pivot_length : i + pivot_length + 1]
            ):
                df.loc[df.index[i], self.LIQU_LOW_COL] = df[self.LOW_COL].iloc[i]

        return df

    def find_EQH_EQL(self, data, trend, end_idx=-1, atr_offset=0.1) -> dict:
        """_summary_
        识别等高等低流动性
        Args:
            data (_type_): _description_
            trend (_type_): _description_
            end_idx (int, optional): _description_. Defaults to -1.
            atr_offset (float, optional): _description_. Defaults to 0.1.

        Returns:
            dict: _description_
        """

        df = data.copy() if end_idx == -1 else data.copy().iloc[: end_idx + 1]

        check_columns = [self.LIQU_HIGH_COL, self.LIQU_LOW_COL]

        try:
            self.check_columns(df, check_columns)
        except ValueError as e:
            # self.logger.warning(f"DataFrame must contain columns {check_columns} : {str(e)}")
            df = self._identify_liquidity_pivots(df)

        df = df[(df[self.LIQU_HIGH_COL] > 0) | (df[self.LIQU_LOW_COL] > 0)]
        # 初始化结果列
        df[self.EQUAL_HIGH_COL] = 0
        df[self.EQUAL_LOW_COL] = 0
        atr_df = self.calculate_atr(df)
        df[self.ATR_COL] = atr_df[self.ATR_COL]
        # 跟踪前一个高点和低点
        previous_high = None
        previous_high_index = None
        previous_high_pos = -1
        previous_low = None
        previous_low_index = None
        previous_low_pos = -1
        for i in range(len(df) - 1, -1, -1):
            offset = self.toDecimal(df[self.ATR_COL].iloc[i] * atr_offset)

            if trend == self.BULLISH_TREND:
                current_high = df[self.LIQU_HIGH_COL].iloc[i]
                if current_high == 0:
                    continue

                if previous_high is None:
                    previous_high = current_high
                    previous_high_index = df.index[i]
                    previous_high_pos = i
                    continue

                max_val = max(current_high, previous_high)
                min_val = min(current_high, previous_high)

                if abs(max_val - min_val) <= offset:  # EQH|EQL
                    df.loc[df.index[i], self.EQUAL_HIGH_COL] = previous_high_index
                    df.loc[df.index[previous_high_pos], self.EQUAL_HIGH_COL] = (
                        previous_high_index
                    )

                else:
                    # 倒序遍历，等高线被高点破坏，则更新等高点位置
                    if current_high > previous_high:
                        previous_high = current_high
                        previous_high_index = df.index[i]
                        previous_high_pos = i

            else:
                current_low = df[self.LIQU_LOW_COL].iloc[i]
                if current_low == 0:
                    continue

                # current_low = df[self.EQUAL_LOW_COL].iloc[i]
                if previous_low is None:
                    previous_low = current_low
                    previous_low_index = df.index[i]
                    previous_low_pos = i
                    continue

                max_val = max(current_low, previous_low)
                min_val = min(current_low, previous_low)

                if abs(max_val - min_val) <= offset:  # EQH|EQL
                    df.loc[df.index[i], self.EQUAL_LOW_COL] = previous_low_index
                    df.loc[df.index[previous_low_pos], self.EQUAL_LOW_COL] = (
                        previous_low_index
                    )

                else:
                    # 倒序遍历，等高线被高点破坏，则更新等高点位置
                    if current_low < previous_low:
                        previous_low = current_low
                        previous_low_index = df.index[i]
                        previous_low_pos = i

        # 筛选有效结构且在prd范围内的数据
        last_EQ = {}
        if trend == self.BULLISH_TREND:
            mask = df[self.EQUAL_HIGH_COL] > 0
            valid_EQH_df = df[mask]
            if not valid_EQH_df.empty:
                last_EQ[self.HAS_EQ_KEY] = True
                last_EQ[self.EQUAL_HIGH_COL] = valid_EQH_df.iloc[-1][self.LIQU_HIGH_COL]
                last_EQ[self.EQUAL_HIGH_INDEX_KEY] = valid_EQH_df.iloc[-1][
                    self.EQUAL_HIGH_COL
                ]
                last_EQ[self.TIMESTAMP_COL] = valid_EQH_df.iloc[-1][self.TIMESTAMP_COL]
        else:
            mask = df[self.EQUAL_LOW_COL] > 0
            valid_EQL_df = df[mask]
            if not valid_EQL_df.empty:
                last_EQ[self.HAS_EQ_KEY] = True
                last_EQ[self.EQUAL_LOW_COL] = valid_EQL_df.iloc[-1][self.LIQU_LOW_COL]
                last_EQ[self.EQUAL_LOW_INDEX_KEY] = valid_EQL_df.iloc[-1][
                    self.EQUAL_LOW_COL
                ]
                last_EQ[self.TIMESTAMP_COL] = valid_EQL_df.iloc[-1][self.TIMESTAMP_COL]

        return last_EQ

    def identify_dynamic_trendlines(
        self, data, trend, start_idx=-1, end_idx=-1, ratio=0.8
    ) -> tuple:
        """
        识别动态趋势线或隧道
        Args:
            data (pd.DataFrame): _description_

        Returns:
            pd.DataFrame: _description_
        """

        df = (
            data.copy()
            if start_idx == -1 or end_idx == -1
            else data.copy().iloc[start_idx - 1 : end_idx + 2]
        )  # 考虑poivt值，前后各增加一个

        check_columns = [self.LIQU_HIGH_COL]

        try:
            self.check_columns(df, check_columns)
        except ValueError as e:
            self.logger.warning(
                f"DataFrame must contain columns {check_columns} : {str(e)}"
            )
            df = self._identify_liquidity_pivots(df)
        diff_ratio = 0.0
        if trend == self.BEARISH_TREND:
            # 判断Bearish趋势是高点不断升高,
            liqu_bear_df = df[df[self.LIQU_HIGH_COL] > 0]
            liqu_bear_df[self.LIQU_HIGH_DIFF_COL] = liqu_bear_df[
                self.LIQU_HIGH_COL
            ].diff()
            # self.logger.info(f"dynamic_trendlines:\n {liqu_bear_df[[self.TIMESTAMP_COL,self.LIQU_HIGH_COL,self.LIQU_HIGH_DIFF_COL]]}")
            diff_ratio = self.toDecimal(
                liqu_bear_df[self.LIQU_HIGH_DIFF_COL].dropna().lt(0).mean(), 2
            )
            if diff_ratio >= ratio:
                return diff_ratio, True
        else:
            # Bullish趋势是低点不断降低
            liqu_bullish_df = df[df[self.LIQU_LOW_COL] > 0]
            liqu_bullish_df[self.LIQU_LOW_DIFF_COL] = liqu_bullish_df[
                self.LIQU_LOW_COL
            ].diff()
            # self.logger.info(f"dynamic_trendlines:\n {liqu_bullish_df[[self.TIMESTAMP_COL,self.LIQU_LOW_COL,self.LIQU_LOW_DIFF_COL]]}")
            diff_ratio = self.toDecimal(
                liqu_bullish_df[self.LIQU_LOW_DIFF_COL].dropna().gt(0).mean(), 2
            )
            if diff_ratio >= ratio:
                return diff_ratio, True

        return diff_ratio, False

    def find_extreme_point_in_range(self, data, point_type="high"):
        """在当前K线范围内找到极值点（最高点或最低点）

        Args:
            data: 价格数据DataFrame
            point_type: 'high' 或 'low'

        Returns:
            (extreme_index, extreme_value) 极值点索引和值

        Raises:
            ValueError: 当输入数据无效时
        """
        # 输入验证
        if data.empty:
            self.logger.warning("输入数据为空，无法找到极值点")
            return None, None

        if point_type not in ["high", "low"]:
            raise ValueError("point_type必须是'high'或'low'")

        # 验证必需的列存在
        required_col = self.HIGH_COL if point_type == "high" else self.LOW_COL
        if required_col not in data.columns:
            raise ValueError(f"DataFrame必须包含列: {required_col}")

        try:
            if point_type == "high":
                extreme_index = data[self.HIGH_COL].idxmax()
                extreme_value = data[self.HIGH_COL].loc[extreme_index]
            else:  # point_type == 'low'
                extreme_index = data[self.LOW_COL].idxmin()
                extreme_value = data[self.LOW_COL].loc[extreme_index]

            # 验证找到的极值点是有效的
            if pd.isna(extreme_value):
                self.logger.warning(f"找到的{point_type}极值点包含NaN值")
                return None, None

            self.logger.debug(
                f"找到{point_type}极值点: 索引={extreme_index}, 值={extreme_value}"
            )
            return extreme_index, extreme_value

        except Exception as e:
            self.logger.error(f"查找极值点时发生错误: {str(e)}")
            return None, None

    def is_swing_point(self, data, index, point_type="high", lookback=1):
        """验证某个点是否为有效的swing point

        Args:
            data: 价格数据DataFrame
            index: 要验证的点的索引
            point_type: 'high' 或 'low'
            lookback: 左右两边需要比较的K线数量

        Returns:
            bool: 如果是有效的swing point返回True，否则返回False
        """
        result, _ = self.is_swing_point_enhanced(data, index, point_type, lookback)
        return result

    def is_swing_point_enhanced(self, data, index, point_type="high", lookback=1):
        """增强版swing point验证，提供详细的验证失败原因

        Args:
            data: 价格数据DataFrame
            index: 要验证的点的索引
            point_type: 'high' 或 'low'
            lookback: 左右两边需要比较的K线数量

        Returns:
            tuple: (is_valid, validation_info)
                - is_valid: bool, 是否为有效的swing point
                - validation_info: dict, 详细的验证信息
        """
        validation_info = {
            'is_valid': False,
            'index': index,
            'point_type': point_type,
            'lookback': lookback,
            'current_value': None,
            'position': None,
            'boundary_check': {'passed': False, 'reason': ''},
            'left_neighbors': [],
            'right_neighbors': [],
            'validation_failures': [],
            'error_message': None
        }

        try:
            # 边界检查和基本验证
            if data.empty:
                validation_info['boundary_check']['reason'] = "输入数据为空"
                return False, validation_info

            if point_type not in ["high", "low"]:
                validation_info['boundary_check']['reason'] = f"无效的point_type: {point_type}"
                return False, validation_info

            if index not in data.index:
                validation_info['boundary_check']['reason'] = f"索引 {index} 不在数据范围内"
                return False, validation_info

            # 检查价格列是否存在
            price_col = self.HIGH_COL if point_type == "high" else self.LOW_COL
            if price_col not in data.columns:
                validation_info['boundary_check']['reason'] = f"DataFrame缺少必需的列: {price_col}"
                return False, validation_info

            # 获取索引在DataFrame中的位置
            try:
                position = data.index.get_loc(index)
                validation_info['position'] = position
            except KeyError:
                validation_info['boundary_check']['reason'] = f"无法获取索引 {index} 的位置"
                return False, validation_info

            # 检查是否有足够的数据进行比较
            if position < lookback:
                validation_info['boundary_check']['reason'] = f"左边数据不足，位置={position}, 需要lookback={lookback}"
                return False, validation_info

            if position >= len(data) - lookback:
                validation_info['boundary_check']['reason'] = f"右边数据不足，位置={position}, 数据长度={len(data)}, 需要lookback={lookback}"
                return False, validation_info

            validation_info['boundary_check']['passed'] = True

            current_value = data[price_col].loc[index]
            validation_info['current_value'] = current_value

            if pd.isna(current_value):
                validation_info['validation_failures'].append("当前值为NaN")
                return False, validation_info

            # 检查左边的邻居
            for i in range(1, lookback + 1):
                left_index = data.index[position - i]
                left_value = data[price_col].loc[left_index]
                
                neighbor_info = {
                    'index': left_index,
                    'value': left_value,
                    'distance': i,
                    'is_nan': pd.isna(left_value),
                    'comparison_result': None,
                    'passes_check': None
                }

                if pd.isna(left_value):
                    neighbor_info['comparison_result'] = "跳过NaN值"
                    neighbor_info['passes_check'] = True  # NaN值不影响验证
                else:
                    if point_type == "high":
                        # 对于swing high，当前点应该比左边的点高
                        passes = current_value >= left_value
                        neighbor_info['comparison_result'] = f"当前值{current_value} {'≥' if passes else '<'} 左邻居{left_value}"
                        neighbor_info['passes_check'] = passes
                        if not passes:
                            validation_info['validation_failures'].append(
                                f"左邻居检查失败: 当前值{current_value} < 左邻居{left_value} (距离={i})"
                            )
                    else:  # point_type == 'low'
                        # 对于swing low，当前点应该比左边的点低
                        passes = current_value <= left_value
                        neighbor_info['comparison_result'] = f"当前值{current_value} {'≤' if passes else '>'} 左邻居{left_value}"
                        neighbor_info['passes_check'] = passes
                        if not passes:
                            validation_info['validation_failures'].append(
                                f"左邻居检查失败: 当前值{current_value} > 左邻居{left_value} (距离={i})"
                            )

                validation_info['left_neighbors'].append(neighbor_info)

            # 检查右边的邻居
            for i in range(1, lookback + 1):
                if position + i >= len(data):
                    break
                    
                right_index = data.index[position + i]
                right_value = data[price_col].loc[right_index]
                
                neighbor_info = {
                    'index': right_index,
                    'value': right_value,
                    'distance': i,
                    'is_nan': pd.isna(right_value),
                    'comparison_result': None,
                    'passes_check': None
                }

                if pd.isna(right_value):
                    neighbor_info['comparison_result'] = "跳过NaN值"
                    neighbor_info['passes_check'] = True  # NaN值不影响验证
                else:
                    if point_type == "high":
                        # 对于swing high，当前点应该比右边的点高
                        passes = current_value >= right_value
                        neighbor_info['comparison_result'] = f"当前值{current_value} {'≥' if passes else '<'} 右邻居{right_value}"
                        neighbor_info['passes_check'] = passes
                        if not passes:
                            validation_info['validation_failures'].append(
                                f"右邻居检查失败: 当前值{current_value} < 右邻居{right_value} (距离={i})"
                            )
                    else:  # point_type == 'low'
                        # 对于swing low，当前点应该比右边的点低
                        passes = current_value <= right_value
                        neighbor_info['comparison_result'] = f"当前值{current_value} {'≤' if passes else '>'} 右邻居{right_value}"
                        neighbor_info['passes_check'] = passes
                        if not passes:
                            validation_info['validation_failures'].append(
                                f"右邻居检查失败: 当前值{current_value} > 右邻居{right_value} (距离={i})"
                            )

                validation_info['right_neighbors'].append(neighbor_info)

            # 判断最终结果
            is_valid = len(validation_info['validation_failures']) == 0
            validation_info['is_valid'] = is_valid

            return is_valid, validation_info

        except Exception as e:
            error_msg = f"验证swing point时发生错误: {str(e)}"
            validation_info['error_message'] = error_msg
            self.logger.error(error_msg)
            return False, validation_info

    def find_extreme_point_in_range_with_swing_validation(
        self, data, point_type="high", lookback=1
    ):
        """在当前K线范围内找到有效的swing point极值点

        Args:
            data: 价格数据DataFrame
            point_type: 'high' 或 'low'
            lookback: swing point验证的lookback周期

        Returns:
            (extreme_index, extreme_value) 极值点索引和值，如果没有有效的swing point则返回None
        """
        # 输入验证
        if data.empty:
            self.logger.warning("输入数据为空，无法找到极值点")
            return None, None

        if point_type not in ["high", "low"]:
            raise ValueError("point_type必须是'high'或'low'")

        # 验证必需的列存在
        required_col = self.HIGH_COL if point_type == "high" else self.LOW_COL
        if required_col not in data.columns:
            raise ValueError(f"DataFrame必须包含列: {required_col}")

        try:
            price_col = self.HIGH_COL if point_type == "high" else self.LOW_COL

            # 找到所有可能的极值点（排除边界点，因为它们无法验证swing point）
            valid_range = (
                data.iloc[lookback:-lookback]
                if len(data) > 2 * lookback
                else pd.DataFrame()
            )

            if valid_range.empty:
                self.logger.warning(
                    f"数据量不足以进行swing point验证，需要至少 {2 * lookback + 1} 个数据点"
                )
                return None, None

            # 在有效范围内找到极值
            if point_type == "high":
                extreme_index = valid_range[price_col].idxmax()
                extreme_value = valid_range[price_col].loc[extreme_index]
            else:
                extreme_index = valid_range[price_col].idxmin()
                extreme_value = valid_range[price_col].loc[extreme_index]

            # 验证是否为有效的swing point
            if self.is_swing_point(data, extreme_index, point_type, lookback):
                self.logger.debug(
                    f"找到有效的{point_type} swing point: 索引={extreme_index}, 值={extreme_value}"
                )
                return extreme_index, extreme_value
            else:
                self.logger.debug(
                    f"找到的{point_type}极值点不是有效的swing point: 索引={extreme_index}"
                )
                return None, None

        except Exception as e:
            self.logger.error(f"查找swing point极值点时发生错误: {str(e)}")
            return None, None

    def find_next_swing_point_in_range(self, data, point_type="high", lookback=1):
        """在当前范围内找到极值swing point（最高点或最低点）
        
        Args:
            data: 价格数据DataFrame
            point_type: 'high' 或 'low'
            lookback: swing point验证的lookback周期
            
        Returns:
            (swing_index, swing_value) 极值swing point的索引和值
        """
        # 输入验证
        if data.empty:
            return None, None
            
        if point_type not in ["high", "low"]:
            raise ValueError("point_type必须是'high'或'low'")
        
        price_col = self.HIGH_COL if point_type == "high" else self.LOW_COL
        
        if price_col not in data.columns:
            raise ValueError(f"DataFrame必须包含列: {price_col}")
        
        try:
            # 首先收集所有有效的swing points
            valid_swing_points = []
            
            for i in range(lookback, len(data) - lookback):
                current_index = data.index[i]
                
                # 验证是否为swing point
                if self.is_swing_point(data, current_index, point_type, lookback):
                    current_value = data[price_col].loc[current_index]
                    valid_swing_points.append((current_index, current_value))
            
            if not valid_swing_points:
                self.logger.debug(f"在范围内未找到{point_type} swing point")
                return None, None
            
            # 从所有有效的swing points中找到极值点
            if point_type == "high":
                # 找最高点
                extreme_index, extreme_value = max(valid_swing_points, key=lambda x: x[1])
            else:  # point_type == "low"
                # 找最低点
                extreme_index, extreme_value = min(valid_swing_points, key=lambda x: x[1])
            
            self.logger.debug(f"找到极值{point_type} swing point: 索引={extreme_index}, 值={extreme_value}，从{len(valid_swing_points)}个候选点中选出")
            return extreme_index, extreme_value
            
        except Exception as e:
            self.logger.error(f"查找极值swing point时发生错误: {str(e)}")
            return None, None

    def check_equal_points_from_extreme(
        self,
        data,
        extreme_index,
        extreme_value,
        atr_value,
        atr_offset,
        point_type="high",
        min_distance=2,
        lookback=1,
    ):
        """从极值点向前搜索等点（只考虑有效的swing points）

        Args:
            data: 价格数据DataFrame
            extreme_index: 极值点索引
            extreme_value: 极值点价格值
            atr_value: ATR值
            atr_offset: ATR偏移量
            point_type: 'high' 或 'low'
            min_distance: 最小间隔距离，相邻节点不算等点（默认为2，即至少间隔1个节点）
            lookback: swing point验证的lookback周期

        Returns:
            符合条件的等点列表，每个元素包含index, value, timestamp

        Raises:
            ValueError: 当输入参数无效时
        """
        # 输入验证
        if data.empty:
            self.logger.warning("输入数据为空，无法搜索等点")
            return []

        if point_type not in ["high", "low"]:
            raise ValueError("point_type必须是'high'或'low'")

        if extreme_index not in data.index:
            raise ValueError(f"极值点索引 {extreme_index} 不在数据范围内")

        if min_distance < 1:
            raise ValueError("min_distance必须大于等于1")

        # 计算容差
        try:
            tolerance = self.calculate_atr_tolerance(atr_value, atr_offset)
        except ValueError as e:
            self.logger.error(f"计算容差失败: {str(e)}")
            return []

        equal_points = []
        price_col = self.HIGH_COL if point_type == "high" else self.LOW_COL

        # 验证价格列存在
        if price_col not in data.columns:
            raise ValueError(f"DataFrame必须包含列: {price_col}")

        try:
            # 获取极值点在DataFrame中的位置
            extreme_position = data.index.get_loc(extreme_index)

            # 从极值点索引向前搜索（按需求从最大值索引向前寻找）
            # 但要排除相邻的节点（距离小于min_distance的节点）
            for i in range(extreme_position):
                current_index = data.index[i]
                current_value = data[price_col].loc[current_index]

                # 跳过NaN值
                if pd.isna(current_value):
                    continue

                # 验证该点是否为有效的swing point
                if not self.is_swing_point(data, current_index, point_type, lookback):
                    self.logger.debug(f"跳过非swing point: 索引={current_index}")
                    continue

                # 检查距离约束：相邻节点不算等点
                distance = extreme_position - i
                if distance < min_distance:
                    self.logger.debug(
                        f"跳过相邻节点: 索引={current_index}, 距离={distance} < {min_distance}"
                    )
                    continue

                # 检查是否在容差范围内
                price_diff = abs(
                    self.toDecimal(current_value) - self.toDecimal(extreme_value)
                )
                if price_diff <= tolerance:
                    # 检查中间是否有更极端的点（关键的SMC规则）
                    if self._has_intermediate_more_extreme_point_simple(data, current_index, extreme_index, point_type):
                        self.logger.debug(f"跳过等点候选: 索引={current_index}，因为中间有更极端的点")
                        continue
                    
                    equal_point = {
                        "index": current_index,
                        "value": current_value,
                        "timestamp": data[self.TIMESTAMP_COL].loc[current_index]
                        if self.TIMESTAMP_COL in data.columns
                        else None,
                        "price_diff": price_diff,
                        "tolerance_used": tolerance,
                        "distance_from_extreme": distance,
                    }
                    equal_points.append(equal_point)

            self.logger.debug(
                f"找到 {len(equal_points)} 个{point_type}等点（仅swing points），极值点索引: {extreme_index}，排除了相邻节点（最小距离: {min_distance}）"
            )

        except Exception as e:
            self.logger.error(f"搜索等点时发生错误: {str(e)}")
            return []

        return equal_points

    def _has_intermediate_more_extreme_point_simple(self, data, first_extreme_index, second_extreme_index, point_type):
        """检查两个极值点之间是否有更极端的点（简化版，用于单点检查）
        
        Args:
            data: 价格数据DataFrame
            first_extreme_index: 第一个极值点索引（较早的）
            second_extreme_index: 第二个极值点索引（较晚的）
            point_type: 'high' 或 'low'
            
        Returns:
            bool: 如果中间有更极端的点返回True，否则返回False
        """
        try:
            # 获取两个极值点的位置
            first_position = data.index.get_loc(first_extreme_index)
            second_position = data.index.get_loc(second_extreme_index)
            
            # 确保first在second之前
            if first_position >= second_position:
                first_position, second_position = second_position, first_position
                first_extreme_index, second_extreme_index = second_extreme_index, first_extreme_index
            
            # 获取两个极值点的价格
            price_col = self.HIGH_COL if point_type == 'high' else self.LOW_COL
            first_value = data[price_col].loc[first_extreme_index]
            second_value = data[price_col].loc[second_extreme_index]
            
            # 计算等点的参考值（两个点的最极端值）
            if point_type == 'high':
                reference_value = max(first_value, second_value)
            else:
                reference_value = min(first_value, second_value)
            
            # 检查中间区域的所有点
            intermediate_data = data.iloc[first_position+1:second_position]
            
            for idx, row in intermediate_data.iterrows():
                intermediate_value = row[price_col]
                
                if pd.isna(intermediate_value):
                    continue
                
                # 检查中间点是否更极端
                violation_detected = False
                if point_type == 'high':
                    # 对于高点，如果中间有更高的点，则破坏等高点关系
                    if intermediate_value > reference_value:
                        violation_detected = True
                else:  # point_type == 'low'
                    # 对于低点，如果中间有更低的点，则破坏等低点关系
                    if intermediate_value < reference_value:
                        violation_detected = True
                
                if violation_detected:
                    self.logger.debug(
                        f"发现中间违规点破坏了索引{first_extreme_index}({first_value})和{second_extreme_index}({second_value})的等{point_type}点关系: "
                        f"中间点索引={idx}, 值={intermediate_value}"
                    )
                    return True
            
            return False
            
        except Exception as e:
            self.logger.error(f"检查中间极值点时发生错误: {str(e)}")
            return True  # 出错时保守地返回True，避免错误识别

    def check_equal_points_from_all_extremes(
        self,
        data,
        all_extreme_points,
        current_extreme_index,
        current_extreme_value,
        atr_value,
        atr_offset,
        point_type="high",
        min_distance=2,
        lookback=1,
    ):
        """从所有已知极值点中搜索等点（只考虑有效的swing points）

        Args:
            data: 价格数据DataFrame
            all_extreme_points: 所有已找到的极值点列表
            current_extreme_index: 当前极值点索引
            current_extreme_value: 当前极值点价格值
            atr_value: ATR值
            atr_offset: ATR偏移量
            point_type: 'high' 或 'low'
            min_distance: 最小间隔距离，相邻节点不算等点
            lookback: swing point验证的lookback周期

        Returns:
            符合条件的等点列表
        """
        # 输入验证
        if data.empty:
            self.logger.warning("输入数据为空，无法搜索等点")
            return []

        if point_type not in ["high", "low"]:
            raise ValueError("point_type必须是'high'或'low'")

        if current_extreme_index not in data.index:
            raise ValueError(f"当前极值点索引 {current_extreme_index} 不在数据范围内")

        # 计算容差
        try:
            tolerance = self.calculate_atr_tolerance(atr_value, atr_offset)
        except ValueError as e:
            self.logger.error(f"计算容差失败: {str(e)}")
            return []

        equal_points = []
        price_col = self.HIGH_COL if point_type == "high" else self.LOW_COL

        # 验证价格列存在
        if price_col not in data.columns:
            raise ValueError(f"DataFrame必须包含列: {price_col}")

        try:
            # 获取当前极值点在DataFrame中的位置
            current_position = data.index.get_loc(current_extreme_index)

            # 从所有已知极值点中搜索等点
            for extreme_point in all_extreme_points:
                candidate_index = extreme_point['index']
                candidate_value = extreme_point['value']

                # 跳过当前极值点自己
                if candidate_index == current_extreme_index:
                    continue

                # 获取候选点的位置
                candidate_position = data.index.get_loc(candidate_index)

                # 检查距离约束：相邻节点不算等点
                distance = abs(current_position - candidate_position)
                if distance < min_distance:
                    self.logger.debug(
                        f"跳过相邻节点: 索引={candidate_index}, 距离={distance} < {min_distance}"
                    )
                    continue

                # 验证该点是否为有效的swing point
                if not self.is_swing_point(data, candidate_index, point_type, lookback):
                    self.logger.debug(f"跳过非swing point: 索引={candidate_index}")
                    continue

                # 检查是否在容差范围内
                price_diff = abs(
                    self.toDecimal(candidate_value) - self.toDecimal(current_extreme_value)
                )
                if price_diff <= tolerance:
                    # 检查平衡约束
                    if not self.check_balance_constraint(data, candidate_index, current_extreme_index, point_type):
                        self.logger.debug(f"跳过等点候选: 索引={candidate_index}，因为违反平衡约束")
                        continue
                    
                    equal_point = {
                        "index": candidate_index,
                        "value": candidate_value,
                        "timestamp": data[self.TIMESTAMP_COL].loc[candidate_index]
                        if self.TIMESTAMP_COL in data.columns
                        else None,
                        "price_diff": price_diff,
                        "tolerance_used": tolerance,
                        "distance_from_extreme": distance,
                    }
                    equal_points.append(equal_point)

            self.logger.debug(
                f"从{len(all_extreme_points)}个极值点中找到 {len(equal_points)} 个{point_type}等点"
            )

        except Exception as e:
            self.logger.error(f"搜索等点时发生错误: {str(e)}")
            return []

        return equal_points

    def check_balance_constraint(self, data, point1_index, point2_index, point_type):
        """检查两个候选等点之间是否存在被平衡的点
        
        Args:
            data: 价格数据DataFrame
            point1_index: 第一个候选点索引
            point2_index: 第二个候选点索引
            point_type: 'high' 或 'low'
            
        Returns:
            True如果没有平衡约束违反，False如果存在平衡约束违反
        """
        try:
            # 输入验证
            if data.empty:
                self.logger.warning("输入数据为空，无法检查平衡约束")
                return False

            if point_type not in ["high", "low"]:
                raise ValueError("point_type必须是'high'或'low'")

            if point1_index not in data.index or point2_index not in data.index:
                raise ValueError("候选点索引不在数据范围内")

            # 确保point1_index < point2_index（按时间顺序）
            pos1 = data.index.get_loc(point1_index)
            pos2 = data.index.get_loc(point2_index)
            
            start_pos = min(pos1, pos2)
            end_pos = max(pos1, pos2)
            start_idx = data.index[start_pos]
            end_idx = data.index[end_pos]

            price_col = self.HIGH_COL if point_type == "high" else self.LOW_COL

            # 检查中间区域的所有点
            for i in range(start_pos + 1, end_pos):
                current_index = data.index[i]
                current_value = data[price_col].loc[current_index]
                
                if pd.isna(current_value):
                    continue

                # 检查当前点是否被后续点平衡
                for j in range(i + 1, len(data)):
                    future_index = data.index[j]
                    future_value = data[price_col].loc[future_index]
                    
                    if pd.isna(future_value):
                        continue

                    if point_type == "high":
                        # 检查是否存在高点被后续更高点平衡
                        if future_value > current_value:
                            self.logger.debug(
                                f"发现平衡约束违反: 高点{current_index}({current_value})被{future_index}({future_value})平衡"
                            )
                            return False
                    else:  # point_type == 'low'
                        # 检查是否存在低点被后续更低点平衡
                        if future_value < current_value:
                            self.logger.debug(
                                f"发现平衡约束违反: 低点{current_index}({current_value})被{future_index}({future_value})平衡"
                            )
                            return False

            return True  # 没有发现平衡约束违反

        except Exception as e:
            self.logger.error(f"检查平衡约束时发生错误: {str(e)}")
            return False  # 出错时保守地返回False

    def create_equal_points_dataframe(self, equal_points_data, extreme_point_info=None):
        """创建标准的等高等低点DataFrame输出格式
        
        Args:
            equal_points_data: 等点数据列表，每个元素包含index, value, timestamp等信息
            extreme_point_info: 极值点信息字典，包含extreme_index, extreme_value等
            
        Returns:
            pd.DataFrame: 包含所有必需列的DataFrame
        """
        try:
            # 定义DataFrame的标准列结构
            columns = [
                self.TIMESTAMP_COL,           # timestamp: K线时间信息
                self.EQUAL_POINTS_INDEX_COL,  # index: 索引位置
                self.EQUAL_POINTS_PRICE_COL,  # price_value: 实际价格值
                self.EQUAL_POINTS_TYPE_COL,   # point_type: 'equal_high' 或 'equal_low'
                self.EXTREME_INDEX_COL,       # extreme_index: 对应的极值点索引
                self.EXTREME_VALUE_COL,       # extreme_value: 对应的极值点价格
                self.ATR_TOLERANCE_COL,       # atr_tolerance: 使用的ATR容差值
                self.IS_EXTREME_COL,          # is_extreme: 是否为极值点
                self.HAS_EQUAL_POINTS_COL     # has_equal_points: 是否存在等点
            ]

            # 如果没有等点数据，返回空DataFrame但保持列结构
            if not equal_points_data:
                empty_df = pd.DataFrame(columns=columns)
                # 设置正确的数据类型
                empty_df[self.TIMESTAMP_COL] = pd.to_datetime(empty_df[self.TIMESTAMP_COL])
                empty_df[self.EQUAL_POINTS_INDEX_COL] = empty_df[self.EQUAL_POINTS_INDEX_COL].astype('Int64')
                empty_df[self.EQUAL_POINTS_PRICE_COL] = empty_df[self.EQUAL_POINTS_PRICE_COL].astype('float64')
                empty_df[self.EQUAL_POINTS_TYPE_COL] = empty_df[self.EQUAL_POINTS_TYPE_COL].astype('string')
                empty_df[self.EXTREME_INDEX_COL] = empty_df[self.EXTREME_INDEX_COL].astype('Int64')
                empty_df[self.EXTREME_VALUE_COL] = empty_df[self.EXTREME_VALUE_COL].astype('float64')
                empty_df[self.ATR_TOLERANCE_COL] = empty_df[self.ATR_TOLERANCE_COL].astype('float64')
                empty_df[self.IS_EXTREME_COL] = empty_df[self.IS_EXTREME_COL].astype('boolean')
                empty_df[self.HAS_EQUAL_POINTS_COL] = empty_df[self.HAS_EQUAL_POINTS_COL].astype('boolean')
                
                self.logger.debug("创建空的等点DataFrame，保持标准列结构")
                return empty_df

            # 构建DataFrame数据
            df_data = []
            
            for point_data in equal_points_data:
                # 判断是否有等点：优先使用传入的值，否则根据点类型判断
                if 'has_equal_points' in point_data:
                    has_equal_points = point_data.get('has_equal_points')
                else:
                    has_equal_points = point_data.get('point_type', '').startswith('equal_')
                
                row = {
                    self.TIMESTAMP_COL: point_data.get('timestamp'),
                    self.EQUAL_POINTS_INDEX_COL: point_data.get('index'),
                    self.EQUAL_POINTS_PRICE_COL: float(point_data.get('value', 0)),
                    self.EQUAL_POINTS_TYPE_COL: point_data.get('point_type', ''),
                    self.EXTREME_INDEX_COL: extreme_point_info.get('extreme_index') if extreme_point_info else None,
                    self.EXTREME_VALUE_COL: float(extreme_point_info.get('extreme_value', 0)) if extreme_point_info else None,
                    self.ATR_TOLERANCE_COL: float(point_data.get('tolerance_used', 0)),
                    self.IS_EXTREME_COL: point_data.get('is_extreme', False),
                    self.HAS_EQUAL_POINTS_COL: has_equal_points
                }
                df_data.append(row)

            # 创建DataFrame
            result_df = pd.DataFrame(df_data, columns=columns)
            
            # 设置正确的数据类型
            result_df[self.TIMESTAMP_COL] = pd.to_datetime(result_df[self.TIMESTAMP_COL])
            result_df[self.EQUAL_POINTS_INDEX_COL] = result_df[self.EQUAL_POINTS_INDEX_COL].astype('Int64')
            result_df[self.EQUAL_POINTS_PRICE_COL] = result_df[self.EQUAL_POINTS_PRICE_COL].astype('float64')
            result_df[self.EQUAL_POINTS_TYPE_COL] = result_df[self.EQUAL_POINTS_TYPE_COL].astype('string')
            result_df[self.EXTREME_INDEX_COL] = result_df[self.EXTREME_INDEX_COL].astype('Int64')
            result_df[self.EXTREME_VALUE_COL] = result_df[self.EXTREME_VALUE_COL].astype('float64')
            result_df[self.ATR_TOLERANCE_COL] = result_df[self.ATR_TOLERANCE_COL].astype('float64')
            result_df[self.IS_EXTREME_COL] = result_df[self.IS_EXTREME_COL].astype('boolean')
            result_df[self.HAS_EQUAL_POINTS_COL] = result_df[self.HAS_EQUAL_POINTS_COL].astype('boolean')

            # 按时间顺序排序
            if not result_df.empty and self.TIMESTAMP_COL in result_df.columns:
                result_df = result_df.sort_values(by=self.TIMESTAMP_COL).reset_index(drop=True)

            self.logger.debug(f"成功创建等点DataFrame，包含 {len(result_df)} 行数据")
            return result_df

        except Exception as e:
            self.logger.error(f"创建等点DataFrame时发生错误: {str(e)}")
            # 返回空DataFrame但保持列结构
            empty_df = pd.DataFrame(columns=columns)
            return empty_df

    def convert_internal_data_to_dataframe(self, internal_results):
        """将内部数据结构转换为DataFrame格式
        
        Args:
            internal_results: 内部结果数据，包含extreme_points和equal_points信息
            
        Returns:
            pd.DataFrame: 标准格式的DataFrame
        """
        try:
            if not internal_results:
                self.logger.warning("内部结果数据为空")
                return self.create_equal_points_dataframe([])

            all_dataframes = []

            # 处理每个极值点及其等点
            for result in internal_results:
                extreme_info = result.get('extreme_point', {})
                equal_points = result.get('equal_points', [])
                point_type = result.get('point_type', '')

                # 为每个等点添加类型信息
                for point in equal_points:
                    point['point_type'] = f"equal_{point_type}"
                    point['is_extreme'] = False

                # 如果有等点，创建DataFrame
                if equal_points:
                    df = self.create_equal_points_dataframe(equal_points, extreme_info)
                    if not df.empty:
                        all_dataframes.append(df)

                # 如果极值点本身也需要包含在结果中
                if extreme_info and result.get('include_extreme_in_result', False):
                    # 判断该极值点是否有等点
                    has_equal_points_for_extreme = len(equal_points) > 0
                    
                    extreme_point_data = [{
                        'index': extreme_info.get('extreme_index'),
                        'value': extreme_info.get('extreme_value'),
                        'timestamp': extreme_info.get('timestamp'),
                        'point_type': f"extreme_{point_type}",
                        'tolerance_used': extreme_info.get('atr_tolerance', 0),
                        'is_extreme': True,
                        'has_equal_points': has_equal_points_for_extreme
                    }]
                    extreme_df = self.create_equal_points_dataframe(extreme_point_data, extreme_info)
                    if not extreme_df.empty:
                        all_dataframes.append(extreme_df)

            # 合并所有DataFrame
            if all_dataframes:
                final_df = pd.concat(all_dataframes, ignore_index=True)
                # 按时间顺序排序
                if self.TIMESTAMP_COL in final_df.columns:
                    final_df = final_df.sort_values(by=self.TIMESTAMP_COL).reset_index(drop=True)
                
                self.logger.debug(f"成功转换内部数据为DataFrame，总共 {len(final_df)} 行")
                return final_df
            else:
                self.logger.debug("没有有效的等点数据，返回空DataFrame")
                return self.create_equal_points_dataframe([])

        except Exception as e:
            self.logger.error(f"转换内部数据为DataFrame时发生错误: {str(e)}")
            return self.create_equal_points_dataframe([])

    def handle_empty_results(self, point_type=""):
        """处理空结果情况，返回具有正确列结构的空DataFrame
        
        Args:
            point_type: 点类型，用于日志记录
            
        Returns:
            pd.DataFrame: 空的但具有正确列结构的DataFrame
        """
        self.logger.info(f"未找到{point_type}等点，返回空结果")
        return self.create_equal_points_dataframe([])

    def handle_no_extreme_point_found(self, point_type=""):
        """处理无法识别极值点的情况
        
        Args:
            point_type: 点类型，用于日志记录
            
        Returns:
            dict: 包含错误信息的字典
        """
        error_info = {
            'error': True,
            'message': f'无法识别{point_type}极值点',
            'point_type': point_type,
            'has_equal_points': False,
            'extreme_point_found': False
        }
        
        self.logger.warning(f"无法识别{point_type}极值点")
        return error_info

    def validate_and_maintain_time_order(self, df):
        """验证并维护DataFrame的时间顺序
        
        Args:
            df: 输入的DataFrame
            
        Returns:
            pd.DataFrame: 按时间排序的DataFrame
        """
        try:
            if df.empty:
                return df

            # 检查是否有时间戳列
            if self.TIMESTAMP_COL not in df.columns:
                self.logger.warning("DataFrame缺少时间戳列，无法进行时间排序")
                return df

            # 检查时间戳列是否有有效数据
            valid_timestamps = df[self.TIMESTAMP_COL].notna()
            if not valid_timestamps.any():
                self.logger.warning("所有时间戳都为空，无法进行时间排序")
                return df

            # 按时间戳排序
            sorted_df = df.sort_values(by=self.TIMESTAMP_COL).reset_index(drop=True)
            
            # 验证排序结果
            if len(sorted_df) != len(df):
                self.logger.warning("排序后数据行数发生变化")
            
            self.logger.debug(f"成功按时间排序DataFrame，共 {len(sorted_df)} 行")
            return sorted_df

        except Exception as e:
            self.logger.error(f"维护时间顺序时发生错误: {str(e)}")
            return df  # 返回原始DataFrame

    def create_no_match_indication(self, point_type="", search_info=None):
        """创建明确的无匹配指示
        
        Args:
            point_type: 搜索的点类型
            search_info: 搜索相关信息
            
        Returns:
            dict: 包含无匹配指示的字典
        """
        indication = {
            'has_equal_points': False,
            'point_type': point_type,
            'search_completed': True,
            'message': f'未找到{point_type}等点',
            'search_info': search_info or {},
            'result_dataframe': self.create_equal_points_dataframe([])
        }
        
        self.logger.info(f"创建无匹配指示: {point_type}")
        return indication

    def validate_dataframe_structure(self, df):
        """验证DataFrame结构是否符合要求
        
        Args:
            df: 要验证的DataFrame
            
        Returns:
            tuple: (is_valid, validation_info)
        """
        validation_info = {
            'is_valid': False,
            'missing_columns': [],
            'incorrect_dtypes': [],
            'row_count': len(df) if df is not None else 0,
            'has_data': False,
            'time_ordered': False
        }

        try:
            if df is None:
                validation_info['error'] = 'DataFrame为None'
                return False, validation_info

            # 检查必需的列
            required_columns = [
                self.TIMESTAMP_COL,
                self.EQUAL_POINTS_INDEX_COL,
                self.EQUAL_POINTS_PRICE_COL,
                self.EQUAL_POINTS_TYPE_COL,
                self.EXTREME_INDEX_COL,
                self.EXTREME_VALUE_COL,
                self.ATR_TOLERANCE_COL,
                self.IS_EXTREME_COL,
                self.HAS_EQUAL_POINTS_COL
            ]

            for col in required_columns:
                if col not in df.columns:
                    validation_info['missing_columns'].append(col)

            # 检查数据类型（仅在有数据时检查）
            if not df.empty:
                validation_info['has_data'] = True
                
                # 检查时间戳列的数据类型
                if self.TIMESTAMP_COL in df.columns:
                    if not pd.api.types.is_datetime64_any_dtype(df[self.TIMESTAMP_COL]):
                        validation_info['incorrect_dtypes'].append(f"{self.TIMESTAMP_COL}: 应为datetime类型")

                # 检查数值列的数据类型
                numeric_columns = [
                    self.EQUAL_POINTS_PRICE_COL,
                    self.EXTREME_VALUE_COL,
                    self.ATR_TOLERANCE_COL
                ]
                
                for col in numeric_columns:
                    if col in df.columns and not pd.api.types.is_numeric_dtype(df[col]):
                        validation_info['incorrect_dtypes'].append(f"{col}: 应为数值类型")

                # 检查时间顺序
                if self.TIMESTAMP_COL in df.columns and len(df) > 1:
                    timestamps = df[self.TIMESTAMP_COL].dropna()
                    if len(timestamps) > 1:
                        validation_info['time_ordered'] = timestamps.is_monotonic_increasing

            # 判断整体有效性
            validation_info['is_valid'] = (
                len(validation_info['missing_columns']) == 0 and
                len(validation_info['incorrect_dtypes']) == 0
            )

            return validation_info['is_valid'], validation_info

        except Exception as e:
            validation_info['error'] = f"验证过程中发生错误: {str(e)}"
            self.logger.error(f"验证DataFrame结构时发生错误: {str(e)}")
            return False, validation_info

    def validate_input_data(self, data, atr_offset=None):
        """全面的输入数据验证
        
        Args:
            data: 输入的DataFrame
            atr_offset: ATR偏移量参数（可选）
            
        Returns:
            tuple: (is_valid, validation_result)
                - is_valid: bool, 数据是否有效
                - validation_result: dict, 详细的验证结果
        """
        validation_result = {
            'is_valid': False,
            'data_structure': {'valid': False, 'issues': []},
            'required_columns': {'valid': False, 'missing': [], 'present': []},
            'data_types': {'valid': False, 'issues': []},
            'data_quality': {'valid': False, 'issues': []},
            'atr_offset_validation': {'valid': True, 'issues': []},
            'row_count': 0,
            'recommendations': []
        }

        try:
            # 1. 基本数据结构验证
            if data is None:
                validation_result['data_structure']['issues'].append("输入数据为None")
                return False, validation_result

            if not isinstance(data, pd.DataFrame):
                validation_result['data_structure']['issues'].append(f"输入数据类型错误，期望DataFrame，实际为{type(data)}")
                return False, validation_result

            if data.empty:
                validation_result['data_structure']['issues'].append("输入DataFrame为空")
                return False, validation_result

            validation_result['row_count'] = len(data)
            validation_result['data_structure']['valid'] = True

            # 2. 必需列验证
            required_columns = [self.HIGH_COL, self.LOW_COL, self.ATR_COL, self.TIMESTAMP_COL]
            missing_columns = []
            present_columns = []

            for col in required_columns:
                if col in data.columns:
                    present_columns.append(col)
                else:
                    missing_columns.append(col)

            validation_result['required_columns']['missing'] = missing_columns
            validation_result['required_columns']['present'] = present_columns
            validation_result['required_columns']['valid'] = len(missing_columns) == 0

            if missing_columns:
                validation_result['required_columns']['issues'] = [f"缺少必需列: {', '.join(missing_columns)}"]

            # 3. 数据类型验证
            dtype_issues = []

            # 验证价格列（high, low）
            for price_col in [self.HIGH_COL, self.LOW_COL]:
                if price_col in data.columns:
                    if not pd.api.types.is_numeric_dtype(data[price_col]):
                        dtype_issues.append(f"{price_col}列应为数值类型，当前为{data[price_col].dtype}")

            # 验证ATR列
            if self.ATR_COL in data.columns:
                if not pd.api.types.is_numeric_dtype(data[self.ATR_COL]):
                    dtype_issues.append(f"{self.ATR_COL}列应为数值类型，当前为{data[self.ATR_COL].dtype}")

            # 验证时间戳列
            if self.TIMESTAMP_COL in data.columns:
                if not pd.api.types.is_datetime64_any_dtype(data[self.TIMESTAMP_COL]):
                    # 尝试转换为datetime
                    try:
                        pd.to_datetime(data[self.TIMESTAMP_COL])
                        validation_result['recommendations'].append(f"建议将{self.TIMESTAMP_COL}列转换为datetime类型")
                    except:
                        dtype_issues.append(f"{self.TIMESTAMP_COL}列无法转换为datetime类型")

            validation_result['data_types']['issues'] = dtype_issues
            validation_result['data_types']['valid'] = len(dtype_issues) == 0

            # 4. 数据质量验证
            quality_issues = []

            # 检查缺失值
            for col in [self.HIGH_COL, self.LOW_COL, self.ATR_COL]:
                if col in data.columns:
                    null_count = data[col].isnull().sum()
                    if null_count > 0:
                        null_percentage = (null_count / len(data)) * 100
                        quality_issues.append(f"{col}列有{null_count}个缺失值 ({null_percentage:.1f}%)")

            # 检查ATR值的有效性
            if self.ATR_COL in data.columns:
                atr_data = data[self.ATR_COL].dropna()
                if len(atr_data) > 0:
                    # 检查负值或零值
                    invalid_atr = (atr_data <= 0).sum()
                    if invalid_atr > 0:
                        quality_issues.append(f"ATR列有{invalid_atr}个无效值（≤0）")

                    # 检查异常值
                    if len(atr_data) > 1:
                        atr_mean = atr_data.mean()
                        atr_std = atr_data.std()
                        outliers = ((atr_data - atr_mean).abs() > 3 * atr_std).sum()
                        if outliers > 0:
                            validation_result['recommendations'].append(f"ATR列有{outliers}个可能的异常值")

            # 检查价格数据的逻辑性
            if self.HIGH_COL in data.columns and self.LOW_COL in data.columns:
                invalid_price_logic = (data[self.HIGH_COL] < data[self.LOW_COL]).sum()
                if invalid_price_logic > 0:
                    quality_issues.append(f"有{invalid_price_logic}行数据的最高价低于最低价")

            validation_result['data_quality']['issues'] = quality_issues
            validation_result['data_quality']['valid'] = len(quality_issues) == 0

            # 5. ATR偏移量参数验证
            if atr_offset is not None:
                atr_offset_issues = []
                
                if not isinstance(atr_offset, (int, float)):
                    atr_offset_issues.append(f"atr_offset应为数值类型，当前为{type(atr_offset)}")
                elif atr_offset <= 0:
                    atr_offset_issues.append("atr_offset应大于0")
                elif atr_offset > 1.0:
                    validation_result['recommendations'].append("atr_offset大于1.0可能导致容差过大")
                elif atr_offset < 0.01:
                    validation_result['recommendations'].append("atr_offset小于0.01可能导致容差过小")

                validation_result['atr_offset_validation']['issues'] = atr_offset_issues
                validation_result['atr_offset_validation']['valid'] = len(atr_offset_issues) == 0

            # 6. 整体有效性判断
            validation_result['is_valid'] = (
                validation_result['data_structure']['valid'] and
                validation_result['required_columns']['valid'] and
                validation_result['data_types']['valid'] and
                validation_result['data_quality']['valid'] and
                validation_result['atr_offset_validation']['valid']
            )

            # 7. 生成建议
            if validation_result['row_count'] < 10:
                validation_result['recommendations'].append("数据量较少，可能影响分析结果的可靠性")

            if not validation_result['is_valid']:
                validation_result['recommendations'].append("请修复上述验证问题后重试")

            return validation_result['is_valid'], validation_result

        except Exception as e:
            validation_result['error'] = f"验证过程中发生异常: {str(e)}"
            self.logger.error(f"输入数据验证时发生错误: {str(e)}")
            return False, validation_result

    def validate_atr_offset_parameter(self, atr_offset):
        """验证ATR偏移量参数
        
        Args:
            atr_offset: ATR偏移量参数
            
        Returns:
            tuple: (is_valid, message)
        """
        try:
            if atr_offset is None:
                return False, "atr_offset参数不能为None"

            if not isinstance(atr_offset, (int, float)):
                return False, f"atr_offset必须为数值类型，当前为{type(atr_offset)}"

            if atr_offset <= 0:
                return False, "atr_offset必须大于0"

            if atr_offset > 1.0:
                self.logger.warning(f"atr_offset值较大({atr_offset})，可能导致容差过宽")

            if atr_offset < 0.01:
                self.logger.warning(f"atr_offset值较小({atr_offset})，可能导致容差过窄")

            return True, "atr_offset参数有效"

        except Exception as e:
            return False, f"验证atr_offset时发生错误: {str(e)}"

    def handle_missing_or_invalid_data(self, data, column_name):
        """处理缺失或无效数据
        
        Args:
            data: DataFrame数据
            column_name: 列名
            
        Returns:
            pd.Series: 处理后的数据
        """
        try:
            if column_name not in data.columns:
                self.logger.error(f"列 {column_name} 不存在")
                return pd.Series(dtype='float64')

            column_data = data[column_name].copy()

            # 处理缺失值
            null_count = column_data.isnull().sum()
            if null_count > 0:
                self.logger.warning(f"列 {column_name} 有 {null_count} 个缺失值")
                
                # 对于价格数据，可以使用前向填充
                if column_name in [self.HIGH_COL, self.LOW_COL, self.CLOSE_COL, self.OPEN_COL]:
                    column_data = column_data.fillna(method='ffill')
                    remaining_nulls = column_data.isnull().sum()
                    if remaining_nulls > 0:
                        # 如果还有缺失值，使用后向填充
                        column_data = column_data.fillna(method='bfill')

                # 对于ATR数据，可以使用均值填充
                elif column_name == self.ATR_COL:
                    mean_value = column_data.mean()
                    if not pd.isna(mean_value):
                        column_data = column_data.fillna(mean_value)

            # 处理无效值（如负数ATR）
            if column_name == self.ATR_COL:
                invalid_count = (column_data <= 0).sum()
                if invalid_count > 0:
                    self.logger.warning(f"ATR列有 {invalid_count} 个无效值（≤0），将使用均值替换")
                    valid_mean = column_data[column_data > 0].mean()
                    if not pd.isna(valid_mean):
                        column_data[column_data <= 0] = valid_mean

            return column_data

        except Exception as e:
            self.logger.error(f"处理列 {column_name} 的缺失或无效数据时发生错误: {str(e)}")
            return pd.Series(dtype='float64')

    def handle_extreme_point_not_found_error(self, point_type, data_info=None):
        """处理无法识别极值点的错误情况
        
        Args:
            point_type: 点类型 ('high' 或 'low')
            data_info: 数据相关信息
            
        Returns:
            dict: 错误处理结果
        """
        error_result = {
            'success': False,
            'error_type': 'extreme_point_not_found',
            'point_type': point_type,
            'message': f'无法识别{point_type}极值点',
            'data_info': data_info or {},
            'suggested_actions': [],
            'fallback_result': self.create_equal_points_dataframe([])
        }

        # 根据数据情况提供建议
        if data_info:
            if data_info.get('row_count', 0) < 3:
                error_result['suggested_actions'].append('增加数据量，至少需要3个数据点')
            
            if data_info.get('has_null_values', False):
                error_result['suggested_actions'].append('清理数据中的缺失值')
            
            if data_info.get('all_values_equal', False):
                error_result['suggested_actions'].append('检查数据是否包含价格变化')

        self.logger.warning(f"极值点识别失败: {error_result['message']}")
        return error_result

    def handle_atr_calculation_failure(self, atr_value, fallback_value=None):
        """处理ATR计算失败和无效值的情况
        
        Args:
            atr_value: 原始ATR值
            fallback_value: 备用值
            
        Returns:
            tuple: (processed_atr_value, warning_message)
        """
        try:
            # 检查ATR值是否有效
            if pd.isna(atr_value):
                warning_msg = "ATR值为NaN"
                if fallback_value is not None and fallback_value > 0:
                    self.logger.warning(f"{warning_msg}，使用备用值: {fallback_value}")
                    return fallback_value, warning_msg
                else:
                    # 使用默认的小值作为备用
                    default_atr = 0.001
                    self.logger.warning(f"{warning_msg}，使用默认值: {default_atr}")
                    return default_atr, warning_msg

            if atr_value <= 0:
                warning_msg = f"ATR值无效 ({atr_value} ≤ 0)"
                if fallback_value is not None and fallback_value > 0:
                    self.logger.warning(f"{warning_msg}，使用备用值: {fallback_value}")
                    return fallback_value, warning_msg
                else:
                    # 使用绝对值或默认值
                    processed_value = abs(atr_value) if atr_value != 0 else 0.001
                    self.logger.warning(f"{warning_msg}，使用处理后的值: {processed_value}")
                    return processed_value, warning_msg

            # ATR值有效
            return atr_value, None

        except Exception as e:
            error_msg = f"处理ATR值时发生错误: {str(e)}"
            self.logger.error(error_msg)
            default_atr = 0.001
            return default_atr, error_msg

    def calculate_atr_tolerance(self, atr_value, atr_offset):
        """计算ATR容差，包含错误处理
        
        Args:
            atr_value: ATR值
            atr_offset: ATR偏移量
            
        Returns:
            Decimal: 计算得到的容差值
            
        Raises:
            ValueError: 当参数无效时
        """
        try:
            # 处理ATR值
            processed_atr, atr_warning = self.handle_atr_calculation_failure(atr_value)
            if atr_warning:
                self.logger.warning(f"ATR处理警告: {atr_warning}")

            # 验证atr_offset
            is_valid, offset_message = self.validate_atr_offset_parameter(atr_offset)
            if not is_valid:
                raise ValueError(f"ATR偏移量无效: {offset_message}")

            # 计算容差
            tolerance = self.toDecimal(processed_atr * atr_offset)
            
            # 验证计算结果
            if tolerance <= 0:
                raise ValueError(f"计算得到的容差值无效: {tolerance}")

            self.logger.debug(f"计算ATR容差: ATR={processed_atr}, 偏移量={atr_offset}, 容差={tolerance}")
            return tolerance

        except Exception as e:
            error_msg = f"计算ATR容差时发生错误: {str(e)}"
            self.logger.error(error_msg)
            raise ValueError(error_msg)

    def setup_debug_logging(self, enable_debug=True, log_level='INFO'):
        """设置调试日志记录
        
        Args:
            enable_debug: 是否启用调试模式
            log_level: 日志级别
        """
        try:
            self.debug_enabled = enable_debug
            self.debug_level = log_level.upper()
            
            # 设置日志级别
            if self.debug_enabled:
                if self.debug_level == 'DEBUG':
                    self.logger.setLevel(logging.DEBUG)
                elif self.debug_level == 'INFO':
                    self.logger.setLevel(logging.INFO)
                elif self.debug_level == 'WARNING':
                    self.logger.setLevel(logging.WARNING)
                elif self.debug_level == 'ERROR':
                    self.logger.setLevel(logging.ERROR)
                
                self.logger.info(f"调试模式已启用，日志级别: {self.debug_level}")
            else:
                self.logger.setLevel(logging.WARNING)
                self.logger.info("调试模式已禁用")

        except Exception as e:
            print(f"设置调试日志时发生错误: {str(e)}")

    def log_operation_info(self, operation_name, **kwargs):
        """记录操作信息用于调试和监控
        
        Args:
            operation_name: 操作名称
            **kwargs: 其他信息
        """
        try:
            if self.debug_enabled:
                info_msg = f"操作: {operation_name}"
                if kwargs:
                    details = ", ".join([f"{k}={v}" for k, v in kwargs.items()])
                    info_msg += f" - {details}"
                
                self.logger.info(info_msg)
                
                # 缓存调试信息
                if operation_name not in self.debug_info_cache:
                    self.debug_info_cache[operation_name] = []
                
                self.debug_info_cache[operation_name].append({
                    'timestamp': pd.Timestamp.now(),
                    'details': kwargs
                })

        except Exception as e:
            self.logger.error(f"记录操作信息时发生错误: {str(e)}")

    def handle_recursive_search_error(self, error, search_context=None):
        """处理递归搜索过程中的错误
        
        Args:
            error: 异常对象
            search_context: 搜索上下文信息
            
        Returns:
            dict: 错误处理结果
        """
        error_result = {
            'success': False,
            'error_type': 'recursive_search_error',
            'error_message': str(error),
            'search_context': search_context or {},
            'partial_results': [],
            'recovery_attempted': False,
            'fallback_result': self.create_equal_points_dataframe([])
        }

        try:
            # 尝试从搜索上下文中恢复部分结果
            if search_context and 'partial_results' in search_context:
                partial_results = search_context['partial_results']
                if partial_results:
                    error_result['partial_results'] = partial_results
                    error_result['recovery_attempted'] = True
                    
                    # 尝试创建部分结果的DataFrame
                    try:
                        partial_df = self.convert_internal_data_to_dataframe(partial_results)
                        error_result['fallback_result'] = partial_df
                        self.logger.warning(f"递归搜索出错，但恢复了 {len(partial_results)} 个部分结果")
                    except Exception as recovery_error:
                        self.logger.error(f"恢复部分结果时也发生错误: {str(recovery_error)}")

            self.logger.error(f"递归搜索错误: {str(error)}")
            return error_result

        except Exception as handle_error:
            self.logger.error(f"处理递归搜索错误时发生异常: {str(handle_error)}")
            return error_result
        
    def _has_intermediate_more_extreme_point(self, data, all_extreme_points, first_extreme_index, second_extreme_index, point_type):
        """检查两个极值点之间是否有更极端的点（优化版）
        
        Args:
            data: 价格数据DataFrame
            all_extreme_points: 所有极值点列表
            first_extreme_index: 第一个极值点索引（较早的）
            second_extreme_index: 第二个极值点索引（较晚的）
            point_type: 'high' 或 'low'
            
        Returns:
            bool: 如果中间有更极端的点返回True，否则返回False
        """
        try:
            # 获取两个极值点的位置
            first_position = data.index.get_loc(first_extreme_index)
            second_position = data.index.get_loc(second_extreme_index)
            
            # 确保first在second之前
            if first_position >= second_position:
                return False
            
            # 获取两个极值点的价格
            price_col = self.HIGH_COL if point_type == 'high' else self.LOW_COL
            first_value = data[price_col].loc[first_extreme_index]
            second_value = data[price_col].loc[second_extreme_index]
            
            # 计算等点的参考值（两个点的最极端值）
            if point_type == 'high':
                reference_value = max(first_value, second_value)
            else:
                reference_value = min(first_value, second_value)
            
            # 检查所有极值点中的中间点
            intermediate_violations = []
            
            for extreme_point in all_extreme_points:
                extreme_index = extreme_point['index']
                extreme_position = data.index.get_loc(extreme_index)
                
                # 跳过不在中间的点
                if extreme_position <= first_position or extreme_position >= second_position:
                    continue
                
                # 获取中间点的价格
                intermediate_value = extreme_point['value']
                
                # 检查中间点是否更极端
                violation_detected = False
                if point_type == 'high':
                    # 对于高点，如果中间有更高的点，则破坏等高点关系
                    if intermediate_value > reference_value:
                        violation_detected = True
                else:  # point_type == 'low'
                    # 对于低点，如果中间有更低的点，则破坏等低点关系
                    if intermediate_value < reference_value:
                        violation_detected = True
                
                if violation_detected:
                    intermediate_violations.append({
                        'index': extreme_index,
                        'value': intermediate_value,
                        'position': extreme_position
                    })
            
            # 记录详细的违规信息
            if intermediate_violations:
                self.logger.debug(
                    f"发现{len(intermediate_violations)}个中间违规点破坏了索引{first_extreme_index}({first_value})和{second_extreme_index}({second_value})的等{point_type}点关系"
                )
                for violation in intermediate_violations:
                    self.logger.debug(f"  违规点: 索引={violation['index']}, 值={violation['value']}")
                return True
            
            return False
            
        except Exception as e:
            self.logger.error(f"检查中间极值点时发生错误: {str(e)}")
            return True  # 出错时保守地返回True，避免错误识别

    def check_intermediate_violation_comprehensive(self, data, point1_index, point2_index, point_type, tolerance=None):
        """全面检查两点间的中间违规情况
        
        Args:
            data: 价格数据DataFrame
            point1_index: 第一个点的索引
            point2_index: 第二个点的索引
            point_type: 'high' 或 'low'
            tolerance: 可选的容差值，用于更精确的违规检测
            
        Returns:
            dict: 包含详细违规分析的字典
        """
        try:
            # 获取位置信息
            pos1 = data.index.get_loc(point1_index)
            pos2 = data.index.get_loc(point2_index)
            
            # 确保正确的顺序
            if pos1 > pos2:
                pos1, pos2 = pos2, pos1
                point1_index, point2_index = point2_index, point1_index
            
            # 获取价格信息
            price_col = self.HIGH_COL if point_type == 'high' else self.LOW_COL
            value1 = data[price_col].loc[point1_index]
            value2 = data[price_col].loc[point2_index]
            
            # 计算参考值
            if point_type == 'high':
                reference_value = max(value1, value2)
            else:
                reference_value = min(value1, value2)
            
            # 如果提供了容差，调整参考值
            if tolerance is not None:
                if point_type == 'high':
                    reference_value += tolerance  # 高点容差向上
                else:
                    reference_value -= tolerance  # 低点容差向下
            
            # 检查中间区域的所有点
            violations = []
            intermediate_data = data.iloc[pos1+1:pos2]
            
            for i, (idx, row) in enumerate(intermediate_data.iterrows()):
                intermediate_value = row[price_col]
                
                if pd.isna(intermediate_value):
                    continue
                
                violation_detected = False
                if point_type == 'high':
                    violation_detected = intermediate_value > reference_value
                else:
                    violation_detected = intermediate_value < reference_value
                
                if violation_detected:
                    violations.append({
                        'index': idx,
                        'value': intermediate_value,
                        'position': pos1 + 1 + i,
                        'difference_from_reference': abs(intermediate_value - reference_value)
                    })
            
            return {
                'has_violations': len(violations) > 0,
                'violation_count': len(violations),
                'violations': violations,
                'reference_value': reference_value,
                'tolerance_used': tolerance,
                'point1': {'index': point1_index, 'value': value1, 'position': pos1},
                'point2': {'index': point2_index, 'value': value2, 'position': pos2},
                'intermediate_range': {'start': pos1 + 1, 'end': pos2 - 1, 'count': len(intermediate_data)}
            }
            
        except Exception as e:
            self.logger.error(f"检查中间违规时发生错误: {str(e)}")
            return {
                'has_violations': True,  # 出错时保守处理
                'error': str(e)
            }

    def calculate_dynamic_atr_tolerance(self, data, candidate_points, point_type, base_atr_offset=0.1):
        """动态计算ATR容差，基于候选点的价格分布
        
        Args:
            data: 价格数据DataFrame
            candidate_points: 候选点列表，每个元素包含index和value
            point_type: 'high' 或 'low'
            base_atr_offset: 基础ATR偏移量
            
        Returns:
            dict: 包含动态容差计算结果的字典
        """
        if not candidate_points or len(candidate_points) < 2:
            return {
                'dynamic_tolerance': None,
                'base_tolerance': None,
                'adjustment_factor': 1.0,
                'price_differences': [],
                'recommendation': f"候选点不足，使用基础偏移量 {base_atr_offset}"
            }
        
        try:
            # 计算所有候选点之间的价格差异
            price_differences = []
            values = [point['value'] for point in candidate_points]
            
            for i in range(len(values)):
                for j in range(i + 1, len(values)):
                    diff = abs(float(values[i]) - float(values[j]))
                    price_differences.append(diff)
            
            if not price_differences:
                return {
                    'dynamic_tolerance': None,
                    'base_tolerance': None,
                    'adjustment_factor': 1.0,
                    'price_differences': [],
                    'recommendation': "无法计算价格差异"
                }
            
            # 获取ATR值（使用第一个候选点的ATR）
            first_point_index = candidate_points[0]['index']
            atr_value = data[self.ATR_COL].loc[first_point_index]
            
            if pd.isna(atr_value) or atr_value <= 0:
                return {
                    'dynamic_tolerance': None,
                    'base_tolerance': None,
                    'adjustment_factor': 1.0,
                    'price_differences': price_differences,
                    'recommendation': f"ATR值无效: {atr_value}"
                }
            
            # 计算基础容差
            base_tolerance = self.calculate_atr_tolerance(atr_value, base_atr_offset)
            
            # 分析价格差异分布
            max_diff = max(price_differences)
            min_diff = min(price_differences)
            avg_diff = sum(price_differences) / len(price_differences)
            
            # 计算调整因子
            # 如果最大价格差异超过基础容差，需要调整
            if max_diff > float(base_tolerance):
                # 计算需要的最小偏移量
                required_offset = max_diff / float(atr_value)
                adjustment_factor = (required_offset / base_atr_offset) * 1.1  # 10%缓冲
            else:
                adjustment_factor = 1.0
            
            # 计算动态容差
            dynamic_atr_offset = base_atr_offset * adjustment_factor
            dynamic_atr_offset = max(0.01, min(1.0, dynamic_atr_offset))  # 限制范围
            dynamic_tolerance = self.calculate_atr_tolerance(atr_value, dynamic_atr_offset)
            
            # 生成建议
            if adjustment_factor > 1.1:
                recommendation = f"建议增加ATR偏移量至 {dynamic_atr_offset:.3f} 以覆盖最大价格差异 {max_diff:.6f}"
            elif adjustment_factor < 0.9:
                recommendation = f"当前偏移量 {base_atr_offset} 已足够，可考虑降至 {dynamic_atr_offset:.3f}"
            else:
                recommendation = f"当前偏移量 {base_atr_offset} 适合"
            
            return {
                'dynamic_tolerance': dynamic_tolerance,
                'base_tolerance': base_tolerance,
                'dynamic_atr_offset': dynamic_atr_offset,
                'adjustment_factor': adjustment_factor,
                'price_differences': price_differences,
                'price_stats': {
                    'max': max_diff,
                    'min': min_diff,
                    'avg': avg_diff,
                    'count': len(price_differences)
                },
                'atr_value': float(atr_value),
                'recommendation': recommendation
            }
            
        except Exception as e:
            self.logger.error(f"计算动态ATR容差时发生错误: {str(e)}")
            return {
                'dynamic_tolerance': None,
                'base_tolerance': None,
                'adjustment_factor': 1.0,
                'price_differences': [],
                'error': str(e),
                'recommendation': f"计算失败，使用基础偏移量 {base_atr_offset}"
            }

    def _validate_input_data(self, data, atr_offset):
        """验证输入数据的完整性和有效性

        Args:
            data: 输入的DataFrame
            atr_offset: ATR偏移量参数

        Raises:
            ValueError: 当数据验证失败时
        """
        if data.empty:
            raise ValueError("输入数据不能为空")

        required_columns = [self.HIGH_COL, self.LOW_COL, self.TIMESTAMP_COL]
        self.check_columns(data, required_columns)

        # 验证ATR偏移量范围
        if not (0.01 <= atr_offset <= 1.0):
            raise ValueError("atr_offset必须在0.01到1.0之间")

        # 验证数据类型
        for col in [self.HIGH_COL, self.LOW_COL]:
            if not pd.api.types.is_numeric_dtype(data[col]):
                raise ValueError(f"列 {col} 必须是数值类型")

    def calculate_atr_tolerance(self, atr_value, atr_offset):
        """计算基于ATR的容差值（优化版）

        Args:
            atr_value: ATR值
            atr_offset: ATR偏移量

        Returns:
            计算得到的容差值

        Raises:
            ValueError: 当ATR值无效时
        """
        # 验证ATR值
        if pd.isna(atr_value) or atr_value <= 0:
            raise ValueError(f"ATR值必须是正数，当前值: {atr_value}")

        # 验证atr_offset
        if not (0.01 <= atr_offset <= 1.0):
            raise ValueError(f"atr_offset必须在0.01到1.0之间，当前值: {atr_offset}")

        # 使用高精度计算，确保小价差能被正确处理
        tolerance = self.toDecimal(float(atr_value) * float(atr_offset))
        
        # 确保最小容差，防止极小的ATR值导致容差为0
        min_tolerance = self.toDecimal(0.000001)  # 1e-6的最小容差
        if tolerance < min_tolerance:
            self.logger.warning(f"计算的容差{tolerance}过小，使用最小容差{min_tolerance}")
            tolerance = min_tolerance
        
        self.logger.debug(
            f"计算ATR容差: ATR={atr_value}, offset={atr_offset}, tolerance={tolerance}"
        )

        return tolerance

    def suggest_atr_offset(self, data, target_points=None, point_type='high', current_atr_offset=0.1, buffer_ratio=1.2):
        """智能建议ATR偏移量，基于价格差异智能建议偏移量
        
        Args:
            data: 价格数据DataFrame，必须包含ATR列
            target_points: 目标点索引列表，如果为None则自动寻找候选点
            point_type: 点类型 ('high' 或 'low')
            current_atr_offset: 当前使用的ATR偏移量
            buffer_ratio: 缓冲比例，默认1.2（20%缓冲）
            
        Returns:
            dict: 包含建议偏移量和分析信息的字典
        """
        try:
            # 输入验证
            if data.empty:
                return {
                    'suggested_offset': None,
                    'error': "输入数据为空",
                    'analysis': {},
                    'warnings': [],
                    'recommendations': []
                }
            
            if point_type not in ['high', 'low']:
                return {
                    'suggested_offset': None,
                    'error': f"无效的point_type: {point_type}",
                    'analysis': {},
                    'warnings': [],
                    'recommendations': []
                }
            
            # 验证参数范围
            if not (0.01 <= current_atr_offset <= 1.0):
                return {
                    'suggested_offset': None,
                    'error': f"current_atr_offset必须在0.01到1.0之间，当前值: {current_atr_offset}",
                    'analysis': {},
                    'warnings': [],
                    'recommendations': []
                }
            
            if buffer_ratio < 1.0:
                return {
                    'suggested_offset': None,
                    'error': f"buffer_ratio必须大于等于1.0，当前值: {buffer_ratio}",
                    'analysis': {},
                    'warnings': [],
                    'recommendations': []
                }
            
            # 确保数据包含ATR列
            df = self.ensure_atr_column(data)
            
            # 如果没有提供目标点，自动寻找候选点
            if target_points is None:
                target_points = self._find_candidate_points_for_analysis(df, point_type)
            
            if not target_points or len(target_points) < 2:
                return {
                    'suggested_offset': current_atr_offset,
                    'error': None,
                    'analysis': {
                        'candidate_points_count': len(target_points) if target_points else 0,
                        'reason': '候选点不足，无法进行价格差异分析'
                    },
                    'warnings': ['候选点数量不足，建议使用默认偏移量'],
                    'recommendations': [f'当前偏移量 {current_atr_offset} 可能适用']
                }
            
            # 验证目标点在数据中存在
            valid_points = []
            price_col = self.HIGH_COL if point_type == 'high' else self.LOW_COL
            
            for point_idx in target_points:
                if point_idx in df.index and not pd.isna(df[price_col].loc[point_idx]):
                    valid_points.append(point_idx)
            
            if len(valid_points) < 2:
                return {
                    'suggested_offset': current_atr_offset,
                    'error': None,
                    'analysis': {
                        'valid_points_count': len(valid_points),
                        'reason': '有效候选点不足'
                    },
                    'warnings': ['有效候选点数量不足'],
                    'recommendations': [f'当前偏移量 {current_atr_offset} 可能适用']
                }
            
            # 计算价格差异
            price_differences = []
            point_values = []
            atr_values = []
            
            for point_idx in valid_points:
                price_value = df[price_col].loc[point_idx]
                atr_value = df[self.ATR_COL].loc[point_idx]
                
                if not pd.isna(atr_value) and atr_value > 0:
                    point_values.append(float(price_value))
                    atr_values.append(float(atr_value))
            
            if len(point_values) < 2:
                return {
                    'suggested_offset': current_atr_offset,
                    'error': None,
                    'analysis': {
                        'valid_atr_points_count': len(point_values),
                        'reason': '有效ATR值不足'
                    },
                    'warnings': ['有效ATR值数量不足'],
                    'recommendations': [f'当前偏移量 {current_atr_offset} 可能适用']
                }
            
            # 计算所有点之间的价格差异
            for i in range(len(point_values)):
                for j in range(i + 1, len(point_values)):
                    diff = abs(point_values[i] - point_values[j])
                    price_differences.append(diff)
            
            # 使用平均ATR值进行计算
            avg_atr = sum(atr_values) / len(atr_values)
            max_price_diff = max(price_differences)
            min_price_diff = min(price_differences)
            avg_price_diff = sum(price_differences) / len(price_differences)
            
            # 计算当前偏移量的容差
            current_tolerance = avg_atr * current_atr_offset
            
            # 计算最小所需偏移量
            min_required_offset = max_price_diff / avg_atr
            
            # 添加缓冲
            suggested_offset = min_required_offset * buffer_ratio
            
            # 限制在合理范围内
            suggested_offset = max(0.01, min(1.0, suggested_offset))
            
            # 分析当前偏移量的充足性
            sufficient_for_max = current_tolerance >= max_price_diff
            sufficient_for_avg = current_tolerance >= avg_price_diff
            coverage_ratio = current_tolerance / max_price_diff if max_price_diff > 0 else float('inf')
            
            # 生成警告和建议
            warnings = []
            recommendations = []
            
            if not sufficient_for_max:
                warnings.append(f"当前ATR偏移量 {current_atr_offset} 不足以覆盖最大价格差异 {max_price_diff:.6f}")
                recommendations.append(f"建议使用ATR偏移量 {suggested_offset:.3f} 以覆盖所有价格差异")
            elif coverage_ratio > 2.0:
                recommendations.append(f"当前偏移量可能过大，可考虑降至 {min_required_offset * 1.1:.3f}")
            else:
                recommendations.append(f"当前偏移量 {current_atr_offset} 适合当前数据")
            
            # 测试常用偏移量的效果
            common_offsets = [0.01, 0.05, 0.1, 0.15, 0.2, 0.3, 0.5]
            offset_analysis = []
            
            for offset in common_offsets:
                tolerance = avg_atr * offset
                covers_max = tolerance >= max_price_diff
                covers_avg = tolerance >= avg_price_diff
                covered_diffs = sum(1 for diff in price_differences if tolerance >= diff)
                coverage_percentage = (covered_diffs / len(price_differences)) * 100
                
                offset_analysis.append({
                    'offset': offset,
                    'tolerance': tolerance,
                    'covers_max_diff': covers_max,
                    'covers_avg_diff': covers_avg,
                    'coverage_percentage': coverage_percentage,
                    'covered_differences': covered_diffs,
                    'total_differences': len(price_differences)
                })
            
            # 构建详细分析
            analysis = {
                'input_data': {
                    'target_points_count': len(target_points),
                    'valid_points_count': len(valid_points),
                    'point_type': point_type,
                    'current_atr_offset': current_atr_offset,
                    'buffer_ratio': buffer_ratio
                },
                'atr_analysis': {
                    'avg_atr_value': avg_atr,
                    'atr_values_range': {'min': min(atr_values), 'max': max(atr_values)},
                    'current_tolerance': current_tolerance
                },
                'price_difference_analysis': {
                    'price_differences': price_differences,
                    'max_difference': max_price_diff,
                    'min_difference': min_price_diff,
                    'avg_difference': avg_price_diff,
                    'difference_count': len(price_differences)
                },
                'offset_calculation': {
                    'min_required_offset': min_required_offset,
                    'suggested_offset': suggested_offset,
                    'buffer_applied': buffer_ratio,
                    'tolerance_with_suggested': avg_atr * suggested_offset
                },
                'current_offset_assessment': {
                    'sufficient_for_max': sufficient_for_max,
                    'sufficient_for_avg': sufficient_for_avg,
                    'coverage_ratio': coverage_ratio,
                    'covered_differences': sum(1 for diff in price_differences if current_tolerance >= diff)
                },
                'offset_comparison': offset_analysis
            }
            
            self.logger.debug(f"ATR偏移量建议分析完成: 建议={suggested_offset:.3f}, 当前={current_atr_offset}, 最小需要={min_required_offset:.3f}")
            
            return {
                'suggested_offset': suggested_offset,
                'error': None,
                'analysis': analysis,
                'warnings': warnings,
                'recommendations': recommendations
            }
            
        except Exception as e:
            error_msg = f"计算ATR偏移量建议时发生错误: {str(e)}"
            self.logger.error(error_msg)
            return {
                'suggested_offset': None,
                'error': error_msg,
                'analysis': {},
                'warnings': [error_msg],
                'recommendations': []
            }

    def _find_candidate_points_for_analysis(self, data, point_type='high', max_points=10):
        """寻找用于ATR偏移量分析的候选点
        
        Args:
            data: 价格数据DataFrame
            point_type: 点类型 ('high' 或 'low')
            max_points: 最大候选点数量
            
        Returns:
            候选点索引列表
        """
        try:
            price_col = self.HIGH_COL if point_type == 'high' else self.LOW_COL
            
            if price_col not in data.columns:
                self.logger.warning(f"数据中缺少列: {price_col}")
                return []
            
            # 寻找swing points作为候选点
            candidate_points = []
            
            # 从数据中间部分开始搜索，避免边界问题
            lookback = 1
            start_idx = lookback
            end_idx = len(data) - lookback
            
            for i in range(start_idx, min(end_idx, start_idx + max_points)):
                current_index = data.index[i]
                if self.is_swing_point(data, current_index, point_type, lookback):
                    candidate_points.append(current_index)
            
            return candidate_points[:max_points]
            
        except Exception as e:
            self.logger.error(f"寻找候选点时发生错误: {str(e)}")
            return []

    def check_atr_offset_sufficiency(self, atr_value, atr_offset, price_differences):
        """检查ATR偏移量是否足够处理给定的价格差异列表
        
        Args:
            atr_value: ATR值
            atr_offset: 当前ATR偏移量
            price_differences: 价格差异列表
            
        Returns:
            dict: 包含充足性分析的字典
        """
        if not price_differences:
            return {
                'sufficient': True,
                'max_difference': 0,
                'current_tolerance': 0,
                'coverage_ratio': float('inf'),
                'recommendations': []
            }
        
        current_tolerance = float(atr_value) * atr_offset
        max_difference = max(price_differences)
        sufficient = current_tolerance >= max_difference
        coverage_ratio = current_tolerance / max_difference if max_difference > 0 else float('inf')
        
        recommendations = []
        if not sufficient:
            suggestion = self.suggest_atr_offset(atr_value, max_difference)
            if suggestion['suggested_offset']:
                recommendations.append(f"建议使用ATR偏移量 {suggestion['suggested_offset']:.3f}")
        
        # 分析每个价格差异
        difference_analysis = []
        for diff in price_differences:
            covered = current_tolerance >= diff
            difference_analysis.append({
                'difference': diff,
                'covered': covered,
                'required_offset': diff / float(atr_value) if atr_value > 0 else float('inf')
            })
        
        return {
            'sufficient': sufficient,
            'max_difference': max_difference,
            'current_tolerance': current_tolerance,
            'coverage_ratio': coverage_ratio,
            'recommendations': recommendations,
            'difference_analysis': difference_analysis,
            'covered_count': sum(1 for analysis in difference_analysis if analysis['covered']),
            'total_count': len(difference_analysis)
        }

    def ensure_atr_column(self, data):
        """确保DataFrame包含ATR列，如果不存在则计算

        Args:
            data: 输入的DataFrame

        Returns:
            包含ATR列的DataFrame
        """
        df = data.copy()

        if self.ATR_COL not in df.columns:
            self.logger.info("ATR列不存在，正在计算ATR值")
            try:
                # 使用基类的ATR计算方法
                df = self.calculate_atr(df)
            except Exception as e:
                self.logger.error(f"计算ATR时发生错误: {str(e)}")
                raise ValueError(f"无法计算ATR: {str(e)}")

        # 验证ATR列的有效性
        if df[self.ATR_COL].isna().all():
            raise ValueError("ATR列包含全部NaN值")

        return df

    def collect_point_information(
        self,
        data,
        extreme_index,
        extreme_value,
        equal_points,
        point_type,
        atr_tolerance,
    ):
        """收集点的全面信息

        Args:
            data: 原始数据DataFrame
            extreme_index: 极值点索引
            extreme_value: 极值点价格值
            equal_points: 等点列表
            point_type: 点类型 ('high' 或 'low')
            atr_tolerance: 使用的ATR容差

        Returns:
            包含详细信息的字典列表
        """
        collected_points = []

        # 添加极值点信息
        extreme_point_info = {
            self.EQUAL_POINTS_TIMESTAMP_COL: data[self.TIMESTAMP_COL].loc[extreme_index]
            if self.TIMESTAMP_COL in data.columns
            else None,
            self.EQUAL_POINTS_INDEX_COL: extreme_index,
            self.EQUAL_POINTS_PRICE_COL: extreme_value,
            self.EQUAL_POINTS_TYPE_COL: f"extreme_{point_type}",
            self.EXTREME_INDEX_COL: extreme_index,
            self.EXTREME_VALUE_COL: extreme_value,
            self.ATR_TOLERANCE_COL: atr_tolerance,
            self.IS_EXTREME_COL: True,
            self.HAS_EQUAL_POINTS_COL: len(equal_points) > 0,
        }
        collected_points.append(extreme_point_info)

        # 添加等点信息
        for equal_point in equal_points:
            equal_point_info = {
                self.EQUAL_POINTS_TIMESTAMP_COL: equal_point["timestamp"],
                self.EQUAL_POINTS_INDEX_COL: equal_point["index"],
                self.EQUAL_POINTS_PRICE_COL: equal_point["value"],
                self.EQUAL_POINTS_TYPE_COL: f"equal_{point_type}",
                self.EXTREME_INDEX_COL: extreme_index,
                self.EXTREME_VALUE_COL: extreme_value,
                self.ATR_TOLERANCE_COL: atr_tolerance,
                self.IS_EXTREME_COL: False,
                self.HAS_EQUAL_POINTS_COL: True,
            }
            collected_points.append(equal_point_info)

        # 按时间顺序排序
        collected_points.sort(
            key=lambda x: x[self.EQUAL_POINTS_TIMESTAMP_COL]
            if x[self.EQUAL_POINTS_TIMESTAMP_COL] is not None
            else pd.Timestamp.min
        )

        self.logger.debug(
            f"收集了 {len(collected_points)} 个点的信息（包括1个极值点和{len(equal_points)}个等点）"
        )

        return collected_points

    def create_result_dataframe(self, collected_points, debug=False):
        """创建结果DataFrame

        Args:
            collected_points: 收集的点信息列表
            debug: 是否包含调试信息列

        Returns:
            格式化的结果DataFrame
        """
        # 基础列结构
        base_columns = [
            self.EQUAL_POINTS_TIMESTAMP_COL,
            self.EQUAL_POINTS_INDEX_COL,
            self.EQUAL_POINTS_PRICE_COL,
            self.EQUAL_POINTS_TYPE_COL,
            self.EXTREME_INDEX_COL,
            self.EXTREME_VALUE_COL,
            self.ATR_TOLERANCE_COL,
            self.IS_EXTREME_COL,
            self.HAS_EQUAL_POINTS_COL,
        ]
        
        # 如果启用调试模式，添加调试列
        debug_columns = []
        if debug:
            debug_columns = [
                'is_swing_point',
                'atr_value', 
                'debug_atr_tolerance',  # 重命名以避免与基础列冲突
                'price_difference',
                'intermediate_violation',
                'debug_info'
            ]
        
        all_columns = base_columns + debug_columns
        
        if not collected_points:
            # 返回空DataFrame但保持正确的列结构
            empty_df = pd.DataFrame(columns=all_columns)
            self.logger.info(f"未找到等点，返回空DataFrame{'（包含调试列）' if debug else ''}")
            return empty_df

        # 创建DataFrame
        result_df = pd.DataFrame(collected_points)

        # 设置正确的数据类型
        result_df[self.EQUAL_POINTS_PRICE_COL] = result_df[
            self.EQUAL_POINTS_PRICE_COL
        ].astype(float)
        result_df[self.EXTREME_VALUE_COL] = result_df[self.EXTREME_VALUE_COL].astype(
            float
        )
        result_df[self.ATR_TOLERANCE_COL] = result_df[self.ATR_TOLERANCE_COL].astype(
            float
        )
        result_df[self.IS_EXTREME_COL] = result_df[self.IS_EXTREME_COL].astype(bool)
        result_df[self.HAS_EQUAL_POINTS_COL] = result_df[
            self.HAS_EQUAL_POINTS_COL
        ].astype(bool)

        # 如果有时间戳列，确保是datetime类型
        if self.EQUAL_POINTS_TIMESTAMP_COL in result_df.columns:
            result_df[self.EQUAL_POINTS_TIMESTAMP_COL] = pd.to_datetime(
                result_df[self.EQUAL_POINTS_TIMESTAMP_COL]
            )

        self.logger.info(f"创建结果DataFrame，包含 {len(result_df)} 行数据{'（包含调试列）' if debug else ''}")

        return result_df

    def recursive_extreme_search(
        self,
        data,
        start_index=0,
        point_type="high",
        atr_offset=0.1,
        max_depth=10,
        min_distance=2,
        debug=False,
    ):
        """递归搜索后续极值点并判断等点

        Args:
            data: 价格数据DataFrame
            start_index: 开始搜索的索引位置（在DataFrame中的位置，不是索引值）
            point_type: 'high' 或 'low'
            atr_offset: ATR偏移量
            max_depth: 最大递归深度，防止无限递归
            min_distance: 最小间隔距离，相邻节点不算等点
            debug: 是否启用调试模式

        Returns:
            包含所有识别出的极值点和等点信息的DataFrame

        Raises:
            ValueError: 当输入参数无效时
        """
        # 输入验证
        self._validate_input_data(data, atr_offset)

        if point_type not in ["high", "low"]:
            raise ValueError("point_type必须是'high'或'low'")

        if max_depth <= 0:
            raise ValueError("max_depth必须大于0")

        # 确保数据包含ATR列
        df = self.ensure_atr_column(data)

        all_collected_points = []
        all_extreme_points = []  # 跟踪所有找到的极值点
        current_start = start_index
        depth = 0

        self.logger.info(f"开始递归搜索{point_type}极值点，起始位置: {current_start}")
        
        if debug:
            self.logger.info(f"调试模式已启用，将收集详细的搜索过程信息")

        search_end_position = len(df)  # 初始搜索结束位置
        
        while depth < max_depth and current_start < search_end_position:
            # 获取当前搜索范围的数据（从current_start到search_end_position）
            search_data = df.iloc[current_start:search_end_position]

            if search_data.empty or len(search_data) < 3:  # 需要至少3个点来验证swing point
                self.logger.debug(f"搜索数据不足，递归结束，深度: {depth}")
                break

            # 在当前范围内找到有效的swing point极值点
            extreme_index, extreme_value = (
                self.find_extreme_point_in_range_with_swing_validation(
                    search_data, point_type, lookback=1
                )
            )

            if extreme_index is None or extreme_value is None:
                self.logger.debug(f"未找到{point_type}极值点，递归结束，深度: {depth}")
                break

            # 获取ATR值
            atr_value = df[self.ATR_COL].loc[extreme_index]
            if pd.isna(atr_value) or atr_value <= 0:
                self.logger.warning(f"极值点 {extreme_index} 的ATR值无效: {atr_value}")
                # 尝试使用附近的ATR值
                atr_value = self._get_valid_atr_value(df, extreme_index)
                if atr_value is None:
                    break

            # 将当前极值点添加到极值点列表
            current_extreme_point = {
                "index": extreme_index,
                "value": extreme_value,
                "timestamp": df[self.TIMESTAMP_COL].loc[extreme_index]
                if self.TIMESTAMP_COL in df.columns
                else None,
            }
            all_extreme_points.append(current_extreme_point)

            # 从所有已知极值点中搜索等点
            equal_points = self.check_equal_points_from_all_extremes(
                df,
                all_extreme_points,
                extreme_index,
                extreme_value,
                atr_value,
                atr_offset,
                point_type,
                min_distance,
                lookback=1,
            )

            # 计算容差
            tolerance = self.calculate_atr_tolerance(atr_value, atr_offset)

            # 收集点信息
            points_info = self.collect_point_information(
                df, extreme_index, extreme_value, equal_points, point_type, tolerance
            )

            all_collected_points.extend(points_info)

            # 更新下一次搜索的范围
            # 找到极值点在原始DataFrame中的位置
            extreme_position_in_original = df.index.get_loc(extreme_index)
            
            # 关键修复：下一次搜索应该在当前极值点之前的范围内进行
            # 这样才能找到所有可能的等高点
            search_end_position = extreme_position_in_original
            
            if search_end_position <= current_start + 2:  # 需要至少3个点来验证swing point
                self.logger.debug(f"搜索范围太小（{current_start} 到 {search_end_position}），无法继续搜索")
                break

            depth += 1
            self.logger.debug(
                f"完成第 {depth} 层递归，找到极值点: {extreme_index}，等点数量: {len(equal_points)}"
            )

        self.logger.info(
            f"递归搜索完成，总深度: {depth}，总点数: {len(all_collected_points)}"
        )

        # 创建结果DataFrame
        result_df = self.create_result_dataframe(all_collected_points)

        return result_df

    def _get_valid_atr_value(self, data, target_index, search_range=5):
        """获取有效的ATR值

        Args:
            data: 数据DataFrame
            target_index: 目标索引
            search_range: 搜索范围

        Returns:
            有效的ATR值或None
        """
        try:
            target_position = data.index.get_loc(target_index)

            # 在目标位置附近搜索有效的ATR值
            for offset in range(1, search_range + 1):
                # 向前搜索
                if target_position - offset >= 0:
                    atr_val = data[self.ATR_COL].iloc[target_position - offset]
                    if not pd.isna(atr_val) and atr_val > 0:
                        self.logger.debug(
                            f"使用位置 {target_position - offset} 的ATR值: {atr_val}"
                        )
                        return atr_val

                # 向后搜索
                if target_position + offset < len(data):
                    atr_val = data[self.ATR_COL].iloc[target_position + offset]
                    if not pd.isna(atr_val) and atr_val > 0:
                        self.logger.debug(
                            f"使用位置 {target_position + offset} 的ATR值: {atr_val}"
                        )
                        return atr_val

        except Exception as e:
            self.logger.error(f"获取有效ATR值时发生错误: {str(e)}")

        return None

    def identify_equal_points_in_range(
        self,
        data,
        atr_offset=0.1,
        end_idx=-1,
        point_type=None,
        max_depth=10,
        min_distance=2,
        debug=False,
    ):
        """在当前K线范围内识别极值点并判断是否存在等点（增强版主要集成方法）

        Args:
            data: 包含OHLC和ATR数据的DataFrame
            atr_offset: ATR偏移量用于容差计算
            end_idx (int, optional): _description_. Defaults to -1.
            point_type: 指定搜索类型 ('high', 'low', 或 None 表示两者都搜索)
            max_depth: 最大递归深度
            min_distance: 最小间隔距离，相邻节点不算等点（默认为2，即至少间隔1个节点）
            debug: 是否启用详细调试信息输出和收集

        Returns:
            包含等点信息的DataFrame，如果debug=True则包含额外的调试信息列

        Raises:
            ValueError: 当输入参数无效时
        """

        df_data = data if end_idx == -1 else data.copy().iloc[: end_idx + 1]
        
        # 设置调试模式
        original_debug_enabled = self.debug_enabled
        if debug:
            self.debug_enabled = True
            self.debug_info_cache = {}
            self.logger.info("启用调试模式，将收集详细的等点识别信息")
        
        try:
            # 输入验证
            self._validate_input_data(df_data, atr_offset)

            if point_type is not None and point_type not in [self.HIGH_COL, self.LOW_COL]:
                raise ValueError("point_type必须是'high'、'low'或None")

            # 确保数据包含ATR列
            df = self.ensure_atr_column(df_data)

            # 如果启用调试模式，收集初始分析信息
            if debug:
                debug_info = self.collect_debug_info(df, atr_offset, point_type)
                self.debug_info_cache['initial_analysis'] = debug_info

            all_results = []

            # 根据point_type决定搜索类型
            search_types = [point_type] if point_type else [self.HIGH_COL, self.LOW_COL]

            for search_type in search_types:
                self.logger.info(f"开始识别{search_type}等点")

                try:
                    # 执行递归搜索
                    result_df = self.recursive_extreme_search(
                        df,
                        start_index=0,
                        point_type=search_type,
                        atr_offset=atr_offset,
                        max_depth=max_depth,
                        min_distance=min_distance,
                        debug=debug,
                    )

                    if not result_df.empty:
                        all_results.append(result_df)

                except Exception as e:
                    self.logger.error(f"识别{search_type}等点时发生错误: {str(e)}")
                    if debug:
                        self.debug_info_cache[f'{search_type}_error'] = str(e)
                    continue

            # 合并所有结果
            if all_results:
                combined_result = pd.concat(all_results, ignore_index=True)
                # 按时间戳排序
                if self.EQUAL_POINTS_TIMESTAMP_COL in combined_result.columns:
                    combined_result = combined_result.sort_values(
                        self.EQUAL_POINTS_TIMESTAMP_COL
                    )
                    combined_result = combined_result.reset_index(drop=True)

                # 如果启用调试模式，添加调试信息列
                if debug:
                    combined_result = self._add_debug_columns(combined_result, df, atr_offset)

                self.logger.info(f"识别完成，总共找到 {len(combined_result)} 个点")
                return combined_result
            else:
                # 返回空DataFrame但保持正确的列结构
                empty_result = self.create_result_dataframe([], debug=debug)
                self.logger.info("未找到任何等点")
                return empty_result
                
        finally:
            # 恢复原始调试设置
            self.debug_enabled = original_debug_enabled

    def collect_debug_info(self, data, atr_offset, point_type=None):
        """收集详细的调试信息
        
        Args:
            data: 价格数据DataFrame
            atr_offset: ATR偏移量
            point_type: 点类型 ('high', 'low', 或 None)
            
        Returns:
            包含调试信息的字典
        """
        debug_info = {
            'data_summary': {
                'total_rows': len(data),
                'date_range': {
                    'start': data[self.TIMESTAMP_COL].min() if self.TIMESTAMP_COL in data.columns else None,
                    'end': data[self.TIMESTAMP_COL].max() if self.TIMESTAMP_COL in data.columns else None
                },
                'price_range': {
                    'high_min': data[self.HIGH_COL].min() if self.HIGH_COL in data.columns else None,
                    'high_max': data[self.HIGH_COL].max() if self.HIGH_COL in data.columns else None,
                    'low_min': data[self.LOW_COL].min() if self.LOW_COL in data.columns else None,
                    'low_max': data[self.LOW_COL].max() if self.LOW_COL in data.columns else None
                }
            },
            'atr_analysis': {
                'atr_offset': atr_offset,
                'atr_stats': {
                    'mean': data[self.ATR_COL].mean() if self.ATR_COL in data.columns else None,
                    'min': data[self.ATR_COL].min() if self.ATR_COL in data.columns else None,
                    'max': data[self.ATR_COL].max() if self.ATR_COL in data.columns else None,
                    'std': data[self.ATR_COL].std() if self.ATR_COL in data.columns else None
                }
            },
            'search_config': {
                'point_type': point_type,
                'search_types': [point_type] if point_type else [self.HIGH_COL, self.LOW_COL]
            }
        }
        
        # 如果指定了点类型，进行ATR偏移量建议分析
        if point_type:
            try:
                suggestion_result = self.suggest_atr_offset(data, point_type=point_type, current_atr_offset=atr_offset)
                debug_info['atr_offset_suggestion'] = suggestion_result
            except Exception as e:
                debug_info['atr_offset_suggestion'] = {'error': str(e)}
        
        return debug_info

    def _add_debug_columns(self, result_df, original_data, atr_offset):
        """为结果DataFrame添加调试信息列
        
        Args:
            result_df: 原始结果DataFrame
            original_data: 原始价格数据
            atr_offset: ATR偏移量
            
        Returns:
            增强了调试信息的DataFrame
        """
        if result_df.empty:
            return result_df
        
        # 添加调试列
        debug_columns = {
            'is_swing_point': [],
            'atr_value': [],
            'debug_atr_tolerance': [],  # 重命名以避免与基础列冲突
            'price_difference': [],
            'intermediate_violation': [],
            'debug_info': []
        }
        
        for idx, row in result_df.iterrows():
            point_index = row[self.EQUAL_POINTS_INDEX_COL]
            point_type = 'high' if row[self.EQUAL_POINTS_TYPE_COL] in ['equal_high', 'extreme_high'] else 'low'
            
            # 验证是否为swing point
            is_swing, swing_info = self.is_swing_point_enhanced(original_data, point_index, point_type)
            debug_columns['is_swing_point'].append(is_swing)
            
            # 获取ATR值和容差
            if point_index in original_data.index and self.ATR_COL in original_data.columns:
                atr_val = original_data[self.ATR_COL].loc[point_index]
                tolerance = self.calculate_atr_tolerance(atr_val, atr_offset) if not pd.isna(atr_val) else None
                # 转换为float以确保数值类型
                tolerance = float(tolerance) if tolerance is not None else None
            else:
                atr_val = None
                tolerance = None
            
            debug_columns['atr_value'].append(atr_val)
            debug_columns['debug_atr_tolerance'].append(tolerance)
            
            # 计算与极值点的价格差异
            if not row[self.IS_EXTREME_COL]:  # 如果不是极值点
                extreme_value = row[self.EXTREME_VALUE_COL]
                current_value = row[self.EQUAL_POINTS_PRICE_COL]
                price_diff = abs(float(current_value) - float(extreme_value))
            else:
                price_diff = 0.0
            
            debug_columns['price_difference'].append(price_diff)
            
            # 检查中间违规（简化版）
            debug_columns['intermediate_violation'].append(False)  # 可以后续增强
            
            # 构建详细调试信息
            atr_str = f"{atr_val:.6f}" if atr_val is not None and not pd.isna(atr_val) else "N/A"
            tolerance_str = f"{tolerance:.6f}" if tolerance is not None and not pd.isna(tolerance) else "N/A"
            debug_info_str = f"swing_valid={is_swing}, atr={atr_str}, tolerance={tolerance_str}, price_diff={price_diff:.6f}"
            debug_columns['debug_info'].append(debug_info_str)
        
        # 添加调试列到DataFrame
        for col_name, col_data in debug_columns.items():
            result_df[col_name] = col_data
        
        return result_df

    def get_equal_points_summary(self, result_df):
        """获取等点识别结果的摘要信息

        Args:
            result_df: identify_equal_points_in_range方法返回的结果DataFrame

        Returns:
            包含摘要信息的字典
        """
        if result_df.empty:
            return {
                "total_points": 0,
                "extreme_points": 0,
                "equal_high_points": 0,
                "equal_low_points": 0,
                "has_equal_points": False,
            }

        summary = {
            "total_points": len(result_df),
            "extreme_points": len(result_df[result_df[self.IS_EXTREME_COL] == True]),
            "equal_high_points": len(
                result_df[result_df[self.EQUAL_POINTS_TYPE_COL] == "equal_high"]
            ),
            "equal_low_points": len(
                result_df[result_df[self.EQUAL_POINTS_TYPE_COL] == "equal_low"]
            ),
            "has_equal_points": len(result_df[result_df[self.IS_EXTREME_COL] == False])
            > 0,
        }

        # 添加时间范围信息
        if (
            self.EQUAL_POINTS_TIMESTAMP_COL in result_df.columns
            and not result_df[self.EQUAL_POINTS_TIMESTAMP_COL].isna().all()
        ):
            summary["time_range"] = {
                "start": result_df[self.EQUAL_POINTS_TIMESTAMP_COL].min(),
                "end": result_df[self.EQUAL_POINTS_TIMESTAMP_COL].max(),
            }

        return summary

    def recursive_extreme_search(self, data, start_index, point_type="high", atr_offset=0.1, max_recursion_depth=10):
        """递归搜索后续极值点并判断等点
        
        Args:
            data: 价格数据DataFrame
            start_index: 开始搜索的索引位置
            point_type: 'high' 或 'low'
            atr_offset: ATR偏移量
            max_recursion_depth: 最大递归深度，防止无限递归
            
        Returns:
            包含所有识别出的极值点和等点信息的DataFrame
        """
        self.logger.debug(f"recursive_extreme_search - 开始递归搜索，起始索引: {start_index}, 类型: {point_type}")
        
        # 输入验证
        if data.empty:
            self.logger.warning("recursive_extreme_search - 输入数据为空")
            return pd.DataFrame()
            
        if point_type not in ["high", "low"]:
            raise ValueError("point_type必须是'high'或'low'")
            
        if start_index not in data.index:
            self.logger.warning(f"recursive_extreme_search - 起始索引 {start_index} 不在数据范围内")
            return pd.DataFrame()
            
        if max_recursion_depth <= 0:
            self.logger.debug("recursive_extreme_search - 达到最大递归深度，停止搜索")
            return pd.DataFrame()
        
        try:
            # 获取起始位置在DataFrame中的位置
            start_position = data.index.get_loc(start_index)
            
            # 从起始位置向后搜索（索引变大的方向）
            remaining_data = data.iloc[start_position + 1:]  # 从下一个位置开始
            
            self.logger.debug(f"recursive_extreme_search - 搜索范围: 从位置 {start_position + 1} 到 {len(data) - 1}，共 {len(remaining_data)} 个数据点")
            
            if remaining_data.empty:
                self.logger.debug("recursive_extreme_search - 没有更多数据可搜索，递归结束")
                return pd.DataFrame()
            
            # 在剩余数据中找到下一个极值点（使用swing point验证）
            next_extreme_index, next_extreme_value = self.find_next_swing_point_in_range(
                remaining_data, point_type=point_type, lookback=1
            )
            
            if next_extreme_index is None:
                self.logger.debug(f"recursive_extreme_search - 在剩余数据中未找到{point_type} swing point，递归结束")
                return pd.DataFrame()
            
            self.logger.debug(f"recursive_extreme_search - 找到下一个{point_type}极值点: 索引={next_extreme_index}, 值={next_extreme_value}")
            
            # 获取ATR值用于容差计算
            if self.ATR_COL not in data.columns:
                # 如果没有ATR列，计算ATR
                atr_data = self.calculate_atr(data)
                data = data.copy()
                data[self.ATR_COL] = atr_data[self.ATR_COL]
            
            atr_value = data[self.ATR_COL].loc[next_extreme_index]
            
            # 对新找到的极值点执行等点判断
            # 这里我们需要在整个数据集中搜索等点，而不仅仅是在剩余数据中
            equal_points = self.check_equal_points_from_extreme(
                data=data,
                extreme_index=next_extreme_index,
                extreme_value=next_extreme_value,
                atr_value=atr_value,
                atr_offset=atr_offset,
                point_type=point_type,
                min_distance=2,
                lookback=1
            )
            
            # 构建当前结果
            current_results = []
            
            # 添加极值点本身
            extreme_point_data = {
                self.EQUAL_POINTS_TIMESTAMP_COL: data[self.TIMESTAMP_COL].loc[next_extreme_index] if self.TIMESTAMP_COL in data.columns else None,
                self.EQUAL_POINTS_INDEX_COL: next_extreme_index,
                self.EQUAL_POINTS_PRICE_COL: next_extreme_value,
                self.EQUAL_POINTS_TYPE_COL: f"equal_{point_type}",
                self.EXTREME_INDEX_COL: next_extreme_index,
                self.EXTREME_VALUE_COL: next_extreme_value,
                self.ATR_TOLERANCE_COL: self.calculate_atr_tolerance(atr_value, atr_offset),
                self.IS_EXTREME_COL: True,
                self.HAS_EQUAL_POINTS_COL: len(equal_points) > 0
            }
            current_results.append(extreme_point_data)
            
            # 添加找到的等点
            for equal_point in equal_points:
                equal_point_data = {
                    self.EQUAL_POINTS_TIMESTAMP_COL: equal_point.get("timestamp"),
                    self.EQUAL_POINTS_INDEX_COL: equal_point["index"],
                    self.EQUAL_POINTS_PRICE_COL: equal_point["value"],
                    self.EQUAL_POINTS_TYPE_COL: f"equal_{point_type}",
                    self.EXTREME_INDEX_COL: next_extreme_index,
                    self.EXTREME_VALUE_COL: next_extreme_value,
                    self.ATR_TOLERANCE_COL: equal_point.get("tolerance_used"),
                    self.IS_EXTREME_COL: False,
                    self.HAS_EQUAL_POINTS_COL: True
                }
                current_results.append(equal_point_data)
            
            # 创建当前结果的DataFrame
            current_df = pd.DataFrame(current_results)
            
            # 递归搜索下一个极值点
            next_results_df = self.recursive_extreme_search(
                data=data,
                start_index=next_extreme_index,
                point_type=point_type,
                atr_offset=atr_offset,
                max_recursion_depth=max_recursion_depth - 1
            )
            
            # 合并结果
            if not next_results_df.empty:
                combined_df = pd.concat([current_df, next_results_df], ignore_index=True)
            else:
                combined_df = current_df
            
            self.logger.debug(f"recursive_extreme_search - 递归搜索完成，总共找到 {len(combined_df)} 个点")
            return combined_df
            
        except Exception as e:
            self.logger.error(f"recursive_extreme_search - 递归搜索时发生错误: {str(e)}")
            return pd.DataFrame()

    def identify_equal_points_in_range(self, data, atr_offset=0.1, point_type="high"):
        """在当前K线范围内识别极值点并判断是否存在等点，然后递归搜索后续极值点
        
        Args:
            data: 包含OHLC和ATR数据的DataFrame
            atr_offset: ATR偏移量用于容差计算
            point_type: 'high' 或 'low'
            
        Returns:
            包含等点信息的DataFrame
        """
        self.logger.debug(f"identify_equal_points_in_range - 开始识别等点，类型: {point_type}")
        
        # 输入验证
        if data.empty:
            self.logger.warning("identify_equal_points_in_range - 输入数据为空")
            return pd.DataFrame()
            
        if point_type not in ["high", "low"]:
            raise ValueError("point_type必须是'high'或'low'")
        
        # 验证必需的列存在
        required_cols = [self.HIGH_COL, self.LOW_COL, self.TIMESTAMP_COL]
        missing_cols = [col for col in required_cols if col not in data.columns]
        if missing_cols:
            raise ValueError(f"DataFrame必须包含列: {missing_cols}")
        
        try:
            # 计算ATR（如果不存在）
            if self.ATR_COL not in data.columns:
                atr_data = self.calculate_atr(data)
                data = data.copy()
                data[self.ATR_COL] = atr_data[self.ATR_COL]
            
            # 第一步：在当前范围内找到极值点
            extreme_index, extreme_value = self.find_extreme_point_in_range_with_swing_validation(
                data, point_type=point_type, lookback=1
            )
            
            if extreme_index is None:
                self.logger.debug(f"identify_equal_points_in_range - 在当前范围内未找到有效的{point_type}极值点")
                return pd.DataFrame()
            
            self.logger.debug(f"identify_equal_points_in_range - 找到初始{point_type}极值点: 索引={extreme_index}, 值={extreme_value}")
            
            # 获取ATR值
            atr_value = data[self.ATR_COL].loc[extreme_index]
            
            # 第二步：从极值点向前搜索等点
            equal_points = self.check_equal_points_from_extreme(
                data=data,
                extreme_index=extreme_index,
                extreme_value=extreme_value,
                atr_value=atr_value,
                atr_offset=atr_offset,
                point_type=point_type,
                min_distance=2,
                lookback=1
            )
            
            # 构建初始结果
            initial_results = []
            
            # 添加初始极值点
            extreme_point_data = {
                self.EQUAL_POINTS_TIMESTAMP_COL: data[self.TIMESTAMP_COL].loc[extreme_index],
                self.EQUAL_POINTS_INDEX_COL: extreme_index,
                self.EQUAL_POINTS_PRICE_COL: extreme_value,
                self.EQUAL_POINTS_TYPE_COL: f"equal_{point_type}",
                self.EXTREME_INDEX_COL: extreme_index,
                self.EXTREME_VALUE_COL: extreme_value,
                self.ATR_TOLERANCE_COL: self.calculate_atr_tolerance(atr_value, atr_offset),
                self.IS_EXTREME_COL: True,
                self.HAS_EQUAL_POINTS_COL: len(equal_points) > 0
            }
            initial_results.append(extreme_point_data)
            
            # 添加找到的等点
            for equal_point in equal_points:
                equal_point_data = {
                    self.EQUAL_POINTS_TIMESTAMP_COL: equal_point.get("timestamp"),
                    self.EQUAL_POINTS_INDEX_COL: equal_point["index"],
                    self.EQUAL_POINTS_PRICE_COL: equal_point["value"],
                    self.EQUAL_POINTS_TYPE_COL: f"equal_{point_type}",
                    self.EXTREME_INDEX_COL: extreme_index,
                    self.EXTREME_VALUE_COL: extreme_value,
                    self.ATR_TOLERANCE_COL: equal_point.get("tolerance_used"),
                    self.IS_EXTREME_COL: False,
                    self.HAS_EQUAL_POINTS_COL: True
                }
                initial_results.append(equal_point_data)
            
            # 创建初始结果DataFrame
            initial_df = pd.DataFrame(initial_results)
            
            # 第三步：递归搜索后续极值点
            recursive_results_df = self.recursive_extreme_search(
                data=data,
                start_index=extreme_index,
                point_type=point_type,
                atr_offset=atr_offset,
                max_recursion_depth=10
            )
            
            # 合并所有结果
            if not recursive_results_df.empty:
                final_df = pd.concat([initial_df, recursive_results_df], ignore_index=True)
            else:
                final_df = initial_df
            
            # 按时间戳排序
            if self.EQUAL_POINTS_TIMESTAMP_COL in final_df.columns:
                final_df = final_df.sort_values(self.EQUAL_POINTS_TIMESTAMP_COL).reset_index(drop=True)
            
            self.logger.debug(f"identify_equal_points_in_range - 完成等点识别，总共找到 {len(final_df)} 个点")
            return final_df
            
        except Exception as e:
            self.logger.error(f"identify_equal_points_in_range - 识别等点时发生错误: {str(e)}")
            return pd.DataFrame()
    def recursive_extreme_search(self, data, start_index, point_type="high", atr_offset=0.1, max_depth=10):
        """递归搜索后续极值点并判断等点
        
        Args:
            data: 价格数据DataFrame
            start_index: 开始搜索的索引位置
            point_type: 'high' 或 'low'
            atr_offset: ATR偏移量
            max_depth: 最大递归深度，防止无限递归
            
        Returns:
            包含所有识别出的极值点和等点信息的DataFrame
        """
        try:
            # 输入验证
            is_valid, validation_result = self.validate_input_data(data, atr_offset)
            if not is_valid:
                # 如果只是缺少ATR列，尝试自动计算
                if (validation_result.get('required_columns', {}).get('missing') == ['atr'] and
                    len(validation_result.get('required_columns', {}).get('present', [])) >= 3):
                    self.logger.info("递归搜索：缺少ATR列，自动计算ATR...")
                    try:
                        data = self.calculate_atr(data)
                        # 重新验证
                        is_valid, validation_result = self.validate_input_data(data, atr_offset)
                        if not is_valid:
                            self.logger.error(f"递归搜索：计算ATR后数据验证仍失败: {validation_result}")
                            return self.handle_empty_results(point_type)
                    except Exception as atr_error:
                        self.logger.error(f"递归搜索：自动计算ATR失败: {str(atr_error)}")
                        return self.handle_empty_results(point_type)
                else:
                    self.logger.error(f"递归搜索输入数据验证失败: {validation_result}")
                    return self.handle_empty_results(point_type)

            if point_type not in ["high", "low"]:
                raise ValueError("point_type必须是'high'或'low'")

            if start_index not in data.index:
                raise ValueError(f"起始索引 {start_index} 不在数据范围内")

            if max_depth <= 0:
                self.logger.warning("达到最大递归深度，停止搜索")
                return self.handle_empty_results(point_type)

            self.log_operation_info("recursive_extreme_search", 
                                  start_index=start_index, 
                                  point_type=point_type, 
                                  max_depth=max_depth)

            # 获取起始位置
            start_position = data.index.get_loc(start_index)
            
            # 从起始位置向后搜索的数据
            search_data = data.iloc[start_position:]
            
            if len(search_data) < 3:  # 需要足够的数据进行swing point验证
                self.logger.debug("搜索数据不足，结束递归")
                return self.handle_empty_results(point_type)

            # 在搜索范围内找到下一个极值swing point
            extreme_index, extreme_value = self.find_next_swing_point_in_range(
                search_data, point_type, lookback=1
            )

            if extreme_index is None:
                self.logger.debug("未找到下一个极值点，结束递归")
                return self.handle_empty_results(point_type)

            # 对找到的极值点进行等点分析
            atr_value = data[self.ATR_COL].loc[extreme_index]
            processed_atr, _ = self.handle_atr_calculation_failure(atr_value)

            # 搜索等点
            equal_points = self.check_equal_points_from_extreme(
                data, extreme_index, extreme_value, processed_atr, atr_offset, 
                point_type, min_distance=2, lookback=1
            )

            # 构建当前结果
            current_results = []
            
            # 添加极值点信息
            extreme_point_info = {
                'extreme_index': extreme_index,
                'extreme_value': extreme_value,
                'timestamp': data[self.TIMESTAMP_COL].loc[extreme_index] if self.TIMESTAMP_COL in data.columns else None,
                'atr_tolerance': processed_atr * atr_offset
            }

            # 为等点添加类型信息
            for point in equal_points:
                point['point_type'] = f"equal_{point_type}"
                point['is_extreme'] = False

            current_result = {
                'extreme_point': extreme_point_info,
                'equal_points': equal_points,
                'point_type': point_type,
                'search_depth': max_depth,
                'include_extreme_in_result': True  # 标记要在结果中包含极值点
            }
            current_results.append(current_result)

            # 递归搜索下一个极值点
            if max_depth > 1:
                try:
                    # 从当前极值点位置继续搜索
                    next_results_df = self.recursive_extreme_search(
                        data, extreme_index, point_type, atr_offset, max_depth - 1
                    )
                    
                    # 如果递归返回了结果，合并到当前结果中
                    if not next_results_df.empty:
                        # 先转换当前结果为DataFrame
                        current_df = self.convert_internal_data_to_dataframe(current_results)
                        
                        # 合并两个DataFrame
                        if not current_df.empty:
                            combined_df = pd.concat([current_df, next_results_df], ignore_index=True)
                            # 按时间戳排序
                            if self.TIMESTAMP_COL in combined_df.columns:
                                combined_df = combined_df.sort_values(by=self.TIMESTAMP_COL).reset_index(drop=True)
                            
                            self.logger.debug(f"递归搜索完成，合并结果共 {len(combined_df)} 行")
                            return combined_df
                        else:
                            return next_results_df
                        
                except Exception as recursive_error:
                    self.logger.warning(f"递归搜索出错: {str(recursive_error)}")
                    # 继续使用当前结果

            # 转换为DataFrame格式
            result_df = self.convert_internal_data_to_dataframe(current_results)
            
            self.logger.debug(f"递归搜索完成，找到 {len(current_results)} 个极值点")
            return result_df

        except Exception as e:
            error_context = {
                'start_index': start_index,
                'point_type': point_type,
                'max_depth': max_depth,
                'data_size': len(data) if data is not None else 0
            }
            error_result = self.handle_recursive_search_error(e, error_context)
            self.logger.error(f"递归搜索发生错误: {str(e)}")
            return error_result['fallback_result']

    def identify_equal_points_in_range(self, data, atr_offset=0.1, end_idx=-1, point_type="high", max_search_depth=10):  # noqa: F811
        """在当前K线范围内识别极值点并递归搜索后续极值点以判断是否存在等点
        
        Args:
            data: 包含OHLC和ATR数据的DataFrame
            atr_offset: ATR偏移量用于容差计算
            point_type: 'high' 或 'low'
            max_search_depth: 最大搜索深度，控制递归搜索的极值点数量
            
        Returns:
            包含所有极值点和等点信息的DataFrame
        """
        
        data = (
            data
            if end_idx == -1
            else data.copy().iloc[: end_idx + 1]
        )  
               
        try:
            # 输入验证
            is_valid, validation_result = self.validate_input_data(data, atr_offset)
            if not is_valid:
                # 如果只是缺少ATR列，尝试自动计算
                if (validation_result.get('required_columns', {}).get('missing') == ['atr'] and
                    len(validation_result.get('required_columns', {}).get('present', [])) >= 3):
                    self.logger.info("缺少ATR列，自动计算ATR...")
                    try:
                        data = self.calculate_atr(data)
                        # 重新验证
                        is_valid, validation_result = self.validate_input_data(data, atr_offset)
                        if not is_valid:
                            self.logger.error(f"计算ATR后数据验证仍失败: {validation_result}")
                            return self.handle_empty_results(point_type)
                    except Exception as atr_error:
                        self.logger.error(f"自动计算ATR失败: {str(atr_error)}")
                        return self.handle_empty_results(point_type)
                else:
                    self.logger.error(f"输入数据验证失败: {validation_result}")
                    return self.handle_empty_results(point_type)

            self.log_operation_info("identify_equal_points_in_range", 
                                  point_type=point_type, 
                                  atr_offset=atr_offset,
                                  data_size=len(data),
                                  max_search_depth=max_search_depth)

            # 使用递归搜索来找到所有极值点和等点
            result_df = self.recursive_extreme_search(
                data, data.index[0], point_type, atr_offset, max_search_depth
            )
            
            if not result_df.empty:
                unique_extremes = result_df[self.EXTREME_INDEX_COL].dropna().nunique()
                total_points = len(result_df)
                self.logger.info(f"成功识别 {unique_extremes} 个{point_type}极值点，总共 {total_points} 个点（包含等点）")
            else:
                self.logger.info(f"未找到{point_type}极值点或等点")
            
            return result_df

        except Exception as e:
            self.logger.error(f"识别等点时发生错误: {str(e)}")
            return self.handle_empty_results(point_type)