//@version=6 indicator("缠论简化版V2", shorttitle="缠论V2", overlay=true, max_lines_count=100, max_labels_count=100) // ================== 参数设置 ================== show_fenxing = input.bool(true, "显示分型", group="显示设置") show_bi = input.bool(true, "显示笔", group="显示设置") show_zhongshu = input.bool(true, "显示中枢", group="显示设置") show_signals = input.bool(true, "显示买卖点", group="显示设置") // 缠论参数 fractal_length = input.int(2, "分型识别周期", minval=1, maxval=5, group="缠论参数") min_bars_between = input.int(5, "分型最小间隔", minval=3, maxval=20, group="缠论参数") bi_color = input.color(color.blue, "笔的颜色", group="颜色设置") zhongshu_color = input.color(color.gray, "中枢颜色", group="颜色设置") // ================== 数据类型定义 ================== type FractalPoint int bar_index float price string fractal_type // "top" or "bottom" // ================== 全局变量 ================== var fractal_points = array.new() var bi_lines = array.new() var zhongshu_boxes = array.new() // ================== 分型识别 ================== // 检查基本分型条件 is_basic_top_fractal = fractal_length > 0 and high[fractal_length] > high[fractal_length-1] and high[fractal_length] > high[fractal_length+1] and low[fractal_length] > low[fractal_length-1] and low[fractal_length] > low[fractal_length+1] is_basic_bottom_fractal = fractal_length > 0 and low[fractal_length] < low[fractal_length-1] and low[fractal_length] < low[fractal_length+1] and high[fractal_length] < high[fractal_length-1] and high[fractal_length] < high[fractal_length+1] // 检查距离过滤 check_distance_filter(new_bar, new_type) => if array.size(fractal_points) == 0 true else last_fractal = array.get(fractal_points, array.size(fractal_points) - 1) bar_distance = new_bar - last_fractal.bar_index // 如果距离太近,则不添加新分型 if bar_distance < min_bars_between false // 如果是相同类型且距离不够远,也不添加 else if last_fractal.fractal_type == new_type and bar_distance < min_bars_between * 2 false else true // ================== 添加分型 ================== current_bar = bar_index - fractal_length // 检查顶分型 if is_basic_top_fractal and check_distance_filter(current_bar, "top") new_fractal = FractalPoint.new(current_bar, high[fractal_length], "top") array.push(fractal_points, new_fractal) // 保持数组大小 if array.size(fractal_points) > 50 array.shift(fractal_points) // 检查底分型 if is_basic_bottom_fractal and check_distance_filter(current_bar, "bottom") new_fractal = FractalPoint.new(current_bar, low[fractal_length], "bottom") array.push(fractal_points, new_fractal) // 保持数组大小 if array.size(fractal_points) > 50 array.shift(fractal_points) // ================== 显示分型 ================== if show_fenxing if is_basic_top_fractal and check_distance_filter(current_bar, "top") label.new(current_bar, high[fractal_length], "T", color=color.red, style=label.style_label_down, size=size.small) if is_basic_bottom_fractal and check_distance_filter(current_bar, "bottom") label.new(current_bar, low[fractal_length], "B", color=color.green, style=label.style_label_up, size=size.small) // ================== 构建笔 ================== // 重建所有笔(当有新分型时) rebuild_bi() => // 清空现有笔 for i = 0 to array.size(bi_lines) - 1 line.delete(array.get(bi_lines, i)) array.clear(bi_lines) // 构建新笔 if array.size(fractal_points) >= 2 for i = 0 to array.size(fractal_points) - 2 current_fractal = array.get(fractal_points, i) next_fractal = array.get(fractal_points, i + 1) // 连接相邻的反向分型 if current_fractal.fractal_type != next_fractal.fractal_type and show_bi new_line = line.new( current_fractal.bar_index, current_fractal.price, next_fractal.bar_index, next_fractal.price, color=bi_color, width=2, style=line.style_solid) array.push(bi_lines, new_line) // 当分型数组发生变化时重建笔 var last_fractal_count = 0 current_fractal_count = array.size(fractal_points) if current_fractal_count != last_fractal_count rebuild_bi() last_fractal_count := current_fractal_count // ================== 中枢识别 ================== // 简化的中枢识别 if array.size(bi_lines) >= 3 and show_zhongshu // 检查最近是否需要添加新中枢 if array.size(bi_lines) >= 3 line1 = array.get(bi_lines, array.size(bi_lines) - 3) line2 = array.get(bi_lines, array.size(bi_lines) - 2) line3 = array.get(bi_lines, array.size(bi_lines) - 1) // 获取价格区间 h1 = math.max(line.get_y1(line1), line.get_y2(line1)) l1 = math.min(line.get_y1(line1), line.get_y2(line1)) h2 = math.max(line.get_y1(line2), line.get_y2(line2)) l2 = math.min(line.get_y1(line2), line.get_y2(line2)) h3 = math.max(line.get_y1(line3), line.get_y2(line3)) l3 = math.min(line.get_y1(line3), line.get_y2(line3)) // 计算重叠区域 overlap_high = math.min(math.min(h1, h2), h3) overlap_low = math.max(math.max(l1, l2), l3) // 形成中枢 if overlap_high > overlap_low start_bar = math.min(line.get_x1(line1), line.get_x2(line1)) end_bar = math.max(line.get_x1(line3), line.get_x2(line3)) // 检查是否需要添加新中枢 should_add = true if array.size(zhongshu_boxes) > 0 last_box = array.get(zhongshu_boxes, array.size(zhongshu_boxes) - 1) if math.abs(box.get_right(last_box) - end_bar) < 10 should_add := false if should_add zs_box = box.new(start_bar, overlap_high, end_bar, overlap_low, border_color=zhongshu_color, bgcolor=color.new(zhongshu_color, 80)) array.push(zhongshu_boxes, zs_box) // ================== 买卖点识别 ================== var last_signal_bar = 0 if array.size(zhongshu_boxes) > 0 and array.size(fractal_points) > 0 and show_signals latest_zs = array.get(zhongshu_boxes, array.size(zhongshu_boxes) - 1) zs_high = box.get_top(latest_zs) zs_low = box.get_bottom(latest_zs) zs_right = box.get_right(latest_zs) // 检查最新分型 if array.size(fractal_points) > 0 latest_fractal = array.get(fractal_points, array.size(fractal_points) - 1) // 确保信号间隔 if latest_fractal.bar_index > last_signal_bar + 5 and latest_fractal.bar_index > zs_right // 买点:底分型跌破中枢下沿 if latest_fractal.fractal_type == "bottom" and latest_fractal.price < zs_low label.new(latest_fractal.bar_index, latest_fractal.price, "买", color=color.green, style=label.style_label_up, size=size.normal) last_signal_bar := latest_fractal.bar_index // 卖点:顶分型突破中枢上沿 if latest_fractal.fractal_type == "top" and latest_fractal.price > zs_high label.new(latest_fractal.bar_index, latest_fractal.price, "卖", color=color.red, style=label.style_label_down, size=size.normal) last_signal_bar := latest_fractal.bar_index // ================== 清理旧对象 ================== if array.size(zhongshu_boxes) > 10 old_box = array.shift(zhongshu_boxes) box.delete(old_box) // ================== 信息面板 ================== if barstate.islast var info_table = table.new(position.top_right, 2, 4, bgcolor=color.white, border_width=1) table.cell(info_table, 0, 0, "缠论V2", text_color=color.black, text_size=size.small) table.cell(info_table, 1, 0, "", text_color=color.black) table.cell(info_table, 0, 1, "分型数", text_color=color.black) table.cell(info_table, 1, 1, str.tostring(array.size(fractal_points)), text_color=color.black) table.cell(info_table, 0, 2, "笔数", text_color=color.black) table.cell(info_table, 1, 2, str.tostring(array.size(bi_lines)), text_color=color.black) table.cell(info_table, 0, 3, "中枢数", text_color=color.black) table.cell(info_table, 1, 3, str.tostring(array.size(zhongshu_boxes)), text_color=color.black) // ================== 警报 ================== alertcondition(is_basic_bottom_fractal and check_distance_filter(current_bar, "bottom"), title="缠论买点", message="发现底分型") alertcondition(is_basic_top_fractal and check_distance_filter(current_bar, "top"), title="缠论卖点", message="发现顶分型")