为何Elliott Wave检测函数在目标序列存在时返回False?
问题背景
用户提供的代码用于识别数值列表中的Elliott Wave模式,列表前半段数值符合模式判定条件(目标序列为["uptrend", "downtrend", "uptrend", "downtrend", "uptrend"],且满足以最小值开头、第二个最小值不低于第一个、第三个最小值不低于第一个最大值、第三浪为最长浪),但函数始终返回False,需定位并修复问题。
核心问题点
子序列判断逻辑错误
原代码中if ["uptrend", "downtrend", "uptrend", "downtrend", "uptrend"] in wave_patterns:是检查目标列表是否是wave_patterns的单个元素,而非检查wave_patterns中是否包含该连续子序列。正确逻辑应该是遍历wave_patterns,验证是否存在连续5个元素匹配目标序列。额外条件代码无法执行
检查第二个最小值、第三个最小值、第三浪长度的代码块位于if-else分支之后,而if-else分支已经通过return返回了结果,导致这部分验证代码永远不会被执行。局部极值提取规则过严
中间极值的判断要求同时大于/小于前后两个元素(如values[i] > values[i-1] and values[i] > values[i+1] and values[i] > values[i-2] and values[i] > values[i+2]),导致很多有效局部极值被遗漏,比如列表中索引2的103这类局部低点无法被识别,直接影响后续趋势序列的准确性。索引越界风险
for循环结束后,变量i的值为len(extrema_list)-2,此时访问extrema_list[i+5]会触发索引越界错误。
修正后的代码
values = [100, 105, 103, 107, 110, 115, 119, 117, 117, 116, 115, 110, 115, 113, 116, 120, 125, 123, 127, 130, 135, 140, 135, 137, 134, 130, 125, 121, 126, 132, 130, 135, 137, 143, 145, 140, 133, 135, 136, 130, 127, 130, 134, 129, 125, 120, 117, 120, 118, 120, 117, 115, 110, 100, 90, 80, 95, 100, 105, 110, 115,110, 108, 115, 120, 125] threshold = 4 # minimum difference required for a local maxima or minima # 创建存储局部极值的字典 extrema = {} # 处理第一个元素 if values[0] > values[1]: extrema[0] = values[0] elif values[0] < values[1]: extrema[0] = values[0] # 处理中间元素,放宽极值判断规则 for i in range(1, len(values)-1): is_max = values[i] > values[i-1] and values[i] > values[i+1] is_min = values[i] < values[i-1] and values[i] < values[i+1] if is_max: if values[i] - min(values[i-1], values[i+1]) > threshold: extrema[i] = values[i] elif is_min: if max(values[i-1], values[i+1]) - values[i] > threshold: extrema[i] = values[i] # 处理最后一个元素 if values[-1] > values[-2]: extrema[len(values)-1] = values[-1] elif values[-1] < values[-2]: extrema[len(values)-1] = values[-1] print("提取到的局部极值:", extrema) def check_elliott_wave(extrema): wave_patterns = [] intervals_pattern = [] extrema_list = sorted(extrema.items()) print("排序后的极值列表:", extrema_list) # 至少需要6个极值才能组成5浪结构 if len(extrema_list) < 6: return False # 检查是否以局部最小值开头 if extrema_list[0][1] >= extrema_list[1][1]: return False # 生成趋势序列 for i in range(len(extrema_list)-1): current = extrema_list[i][1] next_ = extrema_list[i+1][1] trend = "uptrend" if current < next_ else "downtrend" wave_patterns.append(trend) print("生成的趋势序列:", wave_patterns) # 检查是否存在目标连续子序列 target_sequence = ["uptrend", "downtrend", "uptrend", "downtrend", "uptrend"] found = False start_idx = -1 for i in range(len(wave_patterns) - len(target_sequence) + 1): if wave_patterns[i:i+len(target_sequence)] == target_sequence: found = True start_idx = i break if not found: return False # 验证额外条件 # 第二个最小值不低于第一个最小值 if extrema_list[start_idx+2][1] < extrema_list[start_idx][1]: return False # 第三个最小值不低于第一个最大值 if extrema_list[start_idx+4][1] < extrema_list[start_idx+1][1]: return False # 第三浪长度是最长的 wave1_len = extrema_list[start_idx+1][1] - extrema_list[start_idx][1] wave3_len = extrema_list[start_idx+3][1] - extrema_list[start_idx+2][1] wave5_len = extrema_list[start_idx+5][1] - extrema_list[start_idx+4][1] if wave3_len <= wave1_len or wave3_len <= wave5_len: return False # 记录符合条件的区间 intervals_pattern = [ (extrema_list[start_idx][1], extrema_list[start_idx+1][1]), (extrema_list[start_idx+1][1], extrema_list[start_idx+2][1]), (extrema_list[start_idx+2][1], extrema_list[start_idx+3][1]), (extrema_list[start_idx+3][1], extrema_list[start_idx+4][1]), (extrema_list[start_idx+4][1], extrema_list[start_idx+5][1]) ] print("符合条件的Elliott Wave区间:", intervals_pattern) return True # 测试函数 print("函数返回结果:", check_elliott_wave(extrema))
内容的提问来源于stack exchange,提问作者BenjaminDiLorenzo

