168 lines
7.1 KiB
Plaintext
168 lines
7.1 KiB
Plaintext
//@version=6
|
|
indicator("缠论完美版", shorttitle="完美版", overlay=true, max_lines_count=100, max_labels_count=100)
|
|
|
|
// 参数设置
|
|
min_gap = input.int(10, "分型间隔", minval=5, maxval=30)
|
|
show_debug = input.bool(false, "显示调试信息")
|
|
show_strokes = input.bool(true, "显示笔")
|
|
|
|
// 数据类型
|
|
type Fractal
|
|
int bar_index
|
|
float price
|
|
string type
|
|
|
|
// 全局变量
|
|
var raw_fractals = array.new<Fractal>()
|
|
var final_fractals = array.new<Fractal>()
|
|
var strokes = array.new<line>()
|
|
|
|
// 安全的分型识别 - 添加历史数据检查
|
|
is_top = bar_index >= 2 and high[1] > high[0] and high[1] > high[2] and low[1] > low[0] and low[1] > low[2]
|
|
is_bottom = bar_index >= 2 and low[1] < low[0] and low[1] < low[2] and high[1] < high[0] and high[1] < high[2]
|
|
|
|
// 距离检查
|
|
valid_distance(new_bar) =>
|
|
result = true
|
|
if array.size(raw_fractals) > 0
|
|
last = array.get(raw_fractals, array.size(raw_fractals) - 1)
|
|
if new_bar - last.bar_index < min_gap
|
|
result := false
|
|
result
|
|
|
|
// 添加原始分型 - 简化条件检查
|
|
if is_top and valid_distance(bar_index[1])
|
|
array.push(raw_fractals, Fractal.new(bar_index[1], high[1], "top"))
|
|
if array.size(raw_fractals) > 50 // 减少数组大小限制
|
|
array.shift(raw_fractals)
|
|
|
|
if is_bottom and valid_distance(bar_index[1])
|
|
array.push(raw_fractals, Fractal.new(bar_index[1], low[1], "bottom"))
|
|
if array.size(raw_fractals) > 50 // 减少数组大小限制
|
|
array.shift(raw_fractals)
|
|
|
|
// 显示原始分型(调试)
|
|
if show_debug
|
|
if is_top and valid_distance(bar_index[1])
|
|
label.new(bar_index[1], high[1], "顶", color=color.red, style=label.style_label_down, size=size.tiny)
|
|
if is_bottom and valid_distance(bar_index[1])
|
|
label.new(bar_index[1], low[1], "底", color=color.green, style=label.style_label_up, size=size.tiny)
|
|
|
|
// 核心:结合律过滤 - 添加更多安全检查
|
|
if barstate.isconfirmed and array.size(raw_fractals) > 0
|
|
// 重新构建有效分型
|
|
array.clear(final_fractals)
|
|
|
|
// 第一个分型
|
|
array.push(final_fractals, array.get(raw_fractals, 0))
|
|
|
|
// 从第二个开始处理
|
|
if array.size(raw_fractals) > 1
|
|
i = 1
|
|
while i < array.size(raw_fractals)
|
|
current = array.get(raw_fractals, i)
|
|
|
|
if array.size(final_fractals) > 0
|
|
last_final = array.get(final_fractals, array.size(final_fractals) - 1)
|
|
|
|
if current.type != last_final.type
|
|
// 不同类型:直接加入
|
|
array.push(final_fractals, current)
|
|
i += 1
|
|
else
|
|
// 相同类型:找最极端的
|
|
extreme = current
|
|
j = i + 1
|
|
|
|
// 扫描后续同类型分型
|
|
while j < array.size(raw_fractals)
|
|
next = array.get(raw_fractals, j)
|
|
if next.type == current.type
|
|
if current.type == "top"
|
|
if next.price > extreme.price
|
|
extreme := next
|
|
else
|
|
if next.price < extreme.price
|
|
extreme := next
|
|
j += 1
|
|
else
|
|
break
|
|
|
|
// 加入极值分型
|
|
array.push(final_fractals, extreme)
|
|
i := j
|
|
else
|
|
// 如果final_fractals为空,直接添加
|
|
array.push(final_fractals, current)
|
|
i += 1
|
|
|
|
// 重绘笔 - 修复统计问题
|
|
if array.size(strokes) > 0
|
|
for k = 0 to array.size(strokes) - 1
|
|
line.delete(array.get(strokes, k))
|
|
array.clear(strokes)
|
|
|
|
if show_strokes and array.size(final_fractals) >= 2
|
|
for m = 0 to array.size(final_fractals) - 2
|
|
f1 = array.get(final_fractals, m)
|
|
f2 = array.get(final_fractals, m + 1)
|
|
|
|
// 放宽距离限制,确保所有笔都能绘制
|
|
distance_from_current = bar_index - f1.bar_index
|
|
if distance_from_current <= 500 and distance_from_current >= 0 // 恢复到500根K线
|
|
color_line = f1.type == "bottom" ? color.blue : color.red
|
|
line_obj = line.new(f1.bar_index, f1.price, f2.bar_index, f2.price, color=color_line, width=3)
|
|
array.push(strokes, line_obj)
|
|
|
|
// 显示最终分型 - 添加距离检查
|
|
if barstate.islast and array.size(final_fractals) > 0
|
|
for n = 0 to array.size(final_fractals) - 1
|
|
frac = array.get(final_fractals, n)
|
|
distance_from_current = bar_index - frac.bar_index
|
|
if distance_from_current <= 500 // 恢复到500根K线
|
|
if frac.type == "top"
|
|
label.new(frac.bar_index, frac.price, "T", color=color.yellow, style=label.style_label_down, size=size.normal)
|
|
else
|
|
label.new(frac.bar_index, frac.price, "B", color=color.orange, style=label.style_label_up, size=size.normal)
|
|
|
|
// 改进的信息统计
|
|
if barstate.islast
|
|
var table info = table.new(position.top_right, 2, 7, bgcolor=color.white, border_width=1)
|
|
|
|
raw_count = array.size(raw_fractals)
|
|
final_count = array.size(final_fractals)
|
|
stroke_count = array.size(strokes)
|
|
theoretical_strokes = final_count > 0 ? final_count - 1 : 0
|
|
filter_percent = raw_count > 0 ? math.round((raw_count - final_count) * 100 / raw_count) : 0
|
|
|
|
// 计算实际可绘制的笔数
|
|
drawable_strokes = 0
|
|
if array.size(final_fractals) >= 2
|
|
for m = 0 to array.size(final_fractals) - 2
|
|
f1 = array.get(final_fractals, m)
|
|
distance_from_current = bar_index - f1.bar_index
|
|
if distance_from_current <= 500 and distance_from_current >= 0
|
|
drawable_strokes += 1
|
|
|
|
table.cell(info, 0, 0, "缠论完美版", text_color=color.blue, text_size=size.normal)
|
|
table.cell(info, 1, 0, "V1.2", text_color=color.gray)
|
|
|
|
table.cell(info, 0, 1, "原始分型", text_color=color.black)
|
|
table.cell(info, 1, 1, str.tostring(raw_count), text_color=color.green)
|
|
|
|
table.cell(info, 0, 2, "有效分型", text_color=color.black)
|
|
table.cell(info, 1, 2, str.tostring(final_count), text_color=color.red)
|
|
|
|
table.cell(info, 0, 3, "过滤率", text_color=color.black)
|
|
table.cell(info, 1, 3, str.tostring(filter_percent) + "%", text_color=color.purple)
|
|
|
|
table.cell(info, 0, 4, "笔数", text_color=color.black)
|
|
table.cell(info, 1, 4, str.tostring(stroke_count), text_color=color.blue)
|
|
|
|
table.cell(info, 0, 5, "可绘制笔", text_color=color.black)
|
|
table.cell(info, 1, 5, str.tostring(drawable_strokes), text_color=color.gray)
|
|
|
|
table.cell(info, 0, 6, "状态", text_color=color.black)
|
|
status = stroke_count == drawable_strokes ? "✓正常" : "✗异常"
|
|
status_color = stroke_count == drawable_strokes ? color.green : color.red
|
|
table.cell(info, 1, 6, status, text_color=status_color) |