You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:35:56