如何检测基于Map与数组绘制的Pivot支撑阻力线的交叉穿越?
问题描述
各位技术同仁求助:我尚未找到如何使用ta.crossover(close,????)检测蜡烛突破这些绘制的支撑阻力线的解决方案,恳请帮助。这是价格行为交易策略,欢迎提供相关建议。
现有代码
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ tt1 = "Maximum number of crossover/crossunder. Each time price crosses support/resistance line, it is counted as a cross and when such crosses reaches 'Max crossover/crossunder' the support/resistance line is removed" //@version=5 indicator('Map example [EDITED]', overlay=true, max_lines_count = 500) oc = input.int(title = 'Open & Close Pip Gap', defval = 2, minval = 1) lb = input.int(title = 'Left bars', defval = 1, minval = 1) rb = input.int(title = 'Right bars', defval = 1, minval = 1) max_cross_cnt = input.int(title = 'Max crossover/crossunder', defval = 2, minval = 1, maxval = 10, tooltip = tt1) cross_cnt_as_width = input.bool(title = 'Set line width based on cross count', defval = true) start_date = input.time(timestamp("07 Nov 2024 21:30:00")) var map_sr_cross = map.new<int, int>() var map_sr_type = map.new<int, string>() var color_map = map.new<string, color>() var style_map = map.new<string, string>() if bar_index == 0 color_map.put("S", color.orange) color_map.put("R", color.orange) style_map.put("S", line.style_solid) style_map.put("R", line.style_solid) style_map.put("StR", line.style_dashed) style_map.put("RtS", line.style_dashed) //@function returns color method get(map<string, color> clr, string key) => clr.get(key) //@function returns line style method get(map<string, string> style, string key) => style.get(key) //@function Returns count of price crosses from a map method count(map<int, int> cnt, int key) => cnt.get(key) //@function increments cross count in a map method increment(map<int, int> cnt, int key) => cnt.put(key, cnt.get(key) + 1) //@function Returns type S=support, R=reistance from a map. method get(map <int, string> types, int key) => types.get(key) //@function sets type S=support, R=reistance in a map method set(map <int, string> types, int key, string val ) => types.put(key, val) //@function deletes a map element method delete(map<int, int> lines, int key) => lines.remove(key) method delete(map<int, string> lines, int key) => lines.remove(key) //@function returns crossover/crossunder if price crosses swing point method state(float pp) => (close > pp and open+(oc/10) < pp) ? 'Crossover' : (close < pp and open-(oc/10) > pp) ? 'Crossunder' : na //@function manipulate support/resistance lines based on price action method price_action(array<line> lines) => size = lines.size() if(size > 0) for i = size - 1 to 0 price_point = line.get_y1(lines.get(i)) state = price_point.state() if(not na(state)) bar_id = line.get_x1(lines.get(i)) if(map_sr_cross.count(bar_id) + 1 >= max_cross_cnt) line.delete(lines.get(i)) map_sr_cross.delete(i) map_sr_type.delete(i) if(map_sr_cross.count(bar_id) + 1 < max_cross_cnt) this_sr_type = map_sr_type.get(bar_id) map_sr_type.set(bar_id, this_sr_type == 'R' ? 'S' : 'R') style_key = this_sr_type + 't' + (this_sr_type == 'R' ? 'S' : 'R') map_sr_cross.increment(bar_id) line.set_style(lines.get(i), style_map.get(style_key)) line.set_color(lines.get(i), color_map.get(this_sr_type == 'R' ? 'S' : 'R')) line.set_width(lines.get(i), cross_cnt_as_width ? map_sr_cross.count(bar_id) : 1) //main code ph = ta.pivothigh(close, lb, rb) pl = ta.pivotlow(close, lb, rb) if(ph and time >= start_date) line.new(bar_index-rb, close[rb], bar_index, close[rb], color = color_map.get('R'), style = style_map.get('R'), extend = extend.right) map_sr_cross.put(bar_index-rb, 0) map_sr_type.set(bar_index-rb, 'R') // map_sr_type.put(bar_index-rb, 'R') if(pl and time >= start_date) line.new(bar_index-rb, close[rb], bar_index, close[rb], color = color_map.get('S'), style = style_map.get('S'), extend = extend.right) map_sr_cross.put(bar_index-rb, 0) map_sr_type.set(bar_index-rb, 'S') // map_sr_type.put(bar_index-rb, 'S') //manipulate support/resistance lines based on price action line.all.price_action()
解决方案
要实现用ta.crossover检测蜡烛突破支撑阻力线,核心是获取每条线在当前K线的实时价格,再结合交叉函数判断突破。以下是具体修改方案:
1. 新增存储支撑阻力线的数组
现有代码没有保存创建的line对象,无法遍历获取每条线的价格,需新增全局数组存储所有生成的线:
var array<line> sr_lines = array.new<line>() // 存储所有支撑阻力线
在创建线时,将线对象加入数组:
if(ph and time >= start_date) new_line = line.new(bar_index-rb, close[rb], bar_index, close[rb], color = color_map.get('R'), style = style_map.get('R'), extend = extend.right) array.push(sr_lines, new_line) // 加入数组 map_sr_cross.put(bar_index-rb, 0) map_sr_type.set(bar_index-rb, 'R') if(pl and time >= start_date) new_line = line.new(bar_index-rb, close[rb], bar_index, close[rb], color = color_map.get('S'), style = style_map.get('S'), extend = extend.right) array.push(sr_lines, new_line) // 加入数组 map_sr_cross.put(bar_index-rb, 0) map_sr_type.set(bar_index-rb, 'S')
2. 新增突破检测逻辑
添加方法遍历每条线,获取当前K线对应的线价格(用line.get_y2获取延伸后的最新价格),再用ta.crossover/ta.crossunder判断突破:
// 检测支撑阻力线突破的函数 method detect_breakouts(array<line> lines) => size = array.size(lines) if(size > 0) for i = size - 1 to 0 current_line = array.get(lines, i) line_price = line.get_y2(current_line) // 获取当前线的实时价格 // 向上突破阻力线 if ta.crossover(close, line_price) label.new(bar_index, close, "突破阻力", color=color.green, textcolor=color.white, style=label.style_label_up) // 向下跌破支撑线 if ta.crossunder(close, line_price) label.new(bar_index, close, "跌破支撑", color=color.red, textcolor=color.white, style=label.style_label_down)
在主逻辑中调用该方法:
// 检测突破 sr_lines.detect_breakouts()
3. 优化线删除逻辑
删除线时同步从数组移除元素,避免后续遍历出错:
if(map_sr_cross.count(bar_id) + 1 >= max_cross_cnt) line.delete(current_line) map_sr_cross.delete(i) map_sr_type.delete(i) array.remove(lines, i) // 从数组移除已删除的线
完整修改后代码
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ tt1 = "Maximum number of crossover/crossunder. Each time price crosses support/resistance line, it is counted as a cross and when such crosses reaches 'Max crossover/crossunder' the support/resistance line is removed" //@version=5 indicator('Map example [EDITED]', overlay=true, max_lines_count = 500) oc = input.int(title = 'Open & Close Pip Gap', defval = 2, minval = 1) lb = input.int(title = 'Left bars', defval = 1, minval = 1) rb = input.int(title = 'Right bars', defval = 1, minval = 1) max_cross_cnt = input.int(title = 'Max crossover/crossunder', defval = 2, minval = 1, maxval = 10, tooltip = tt1) cross_cnt_as_width = input.bool(title = 'Set line width based on cross count', defval = true) start_date = input.time(timestamp("07 Nov 2024 21:30:00")) var map_sr_cross = map.new<int, int>() var map_sr_type = map.new<int, string>() var array<line> sr_lines = array.new<line>() // 存储所有支撑阻力线 var color_map = map.new<string, color>() var style_map = map.new<string, string>() if bar_index == 0 color_map.put("S", color.orange) color_map.put("R", color.orange) style_map.put("S", line.style_solid) style_map.put("R", line.style_solid) style_map.put("StR", line.style_dashed) style_map.put("RtS", line.style_dashed) //@function returns color method get(map<string, color> clr, string key) => clr.get(key) //@function returns line style method get(map<string, string> style, string key) => style.get(key) //@function Returns count of price crosses from a map method count(map<int, int> cnt, int key) => cnt.get(key) //@function increments cross count in a map method increment(map<int, int> cnt, int key) => cnt.put(key, cnt.get(key) + 1) //@function Returns type S=support, R=resistance from a map. method get(map <int, string> types, int key) => types.get(key) //@function sets type S=support, R=resistance in a map method set(map <int, string> types, int key, string val ) => types.put(key, val) //@function deletes a map element method delete(map<int, int> lines, int key) => lines.remove(key) method delete(map<int, string> lines, int key) => lines.remove(key) //@function returns crossover/crossunder if price crosses swing point method state(float pp) => (close > pp and open+(oc/10) < pp) ? 'Crossover' : (close < pp and open-(oc/10) > pp) ? 'Crossunder' : na //@function manipulate support/resistance lines based on price action method price_action(array<line> lines) => size = array.size(lines) if(size > 0) for i = size - 1 to 0 current_line = array.get(lines, i) price_point = line.get_y1(current_line) state = price_point.state() if(not na(state)) bar_id = line.get_x1(current_line) if(map_sr_cross.count(bar_id) + 1 >= max_cross_cnt) line.delete(current_line) map_sr_cross.delete(i) map_sr_type.delete(i) array.remove(lines, i) // 从数组移除已删除的线 if(map_sr_cross.count(bar_id) + 1 < max_cross_cnt) this_sr_type = map_sr_type.get(bar_id) map_sr_type.set(bar_id, this_sr_type == 'R' ? 'S' : 'R') style_key = this_sr_type + 't' + (this_sr_type == 'R' ? 'S' : 'R') map_sr_cross.increment(bar_id) line.set_style(current_line, style_map.get(style_key)) line.set_color(current_line, color_map.get(this_sr_type == 'R' ? 'S' : 'R')) line.set_width(current_line, cross_cnt_as_width ? map_sr_cross.count(bar_id) : 1) //@function detect support/resistance breakouts method detect_breakouts(array<line> lines) => size = array.size(lines) if(size > 0) for i = size - 1 to 0 current_line = array.get(lines, i) line_price = line.get_y2(current_line) // 获取当前线的价格 // 向上突破阻力线 if ta.crossover(close, line_price) label.new(bar_index, close, "突破阻力", color=color.green, textcolor=color.white, style=label.style_label_up) // 向下跌破支撑线 if ta.crossunder(close, line_price) label.new(bar_index, close, "跌破支撑", color=color.red, textcolor=color.white, style=label.style_label_down) //main code ph = ta.pivothigh(close, lb, rb) pl = ta.pivotlow(close, lb, rb) if(ph and time >= start_date) new_line = line.new(bar_index-rb, close[rb], bar_index, close[rb], color = color_map.get('R'), style = style_map.get('R'), extend = extend.right) array.push(sr_lines, new_line) map_sr_cross.put(bar_index-rb, 0) map_sr_type.set(bar_index-rb, 'R') if(pl and time >= start_date) new_line = line.new(bar_index-rb, close[rb], bar_index, close[rb], color = color_map.get('S'), style = style_map.get('S'), extend = extend.right) array.push(sr_lines, new_line) map_sr_cross.put(bar_index-rb, 0) map_sr_type.set(bar_index-rb, 'S') //manipulate support/resistance lines based on price action sr_lines.price_action() //detect breakouts sr_lines.detect_breakouts()
关键说明
- 用
array<line>存储线对象,是为了遍历获取每条线的实时价格 line.get_y2()用于获取线在当前K线的价格(线向右延伸,y2是最新端点的价格)ta.crossover(close, line_price)直接判断收盘价是否上穿支撑阻力线,满足需求- 突破后可根据需要添加警报、交易信号等扩展逻辑
内容的提问来源于stack exchange,提问作者brightmemoir 3D
相关产品推荐
相关产品推荐

