PineScript技术实现:按密度/邻近度分割枢轴高点数组聚类
枢轴高点数组的简易聚类分割方案(PineScript)
问题背景
我正在开发交易策略,目标是绘制支撑阻力(S&R)通道。目前已实现通过枢轴高点(PH)绘制多个支撑阻力线并添加至图表,现有PH数组:[1.09118, 1.09192, 1.10201, 1.076, 1.07898, 1.07614, 1.06937, 1.06714, 1.06866, 1.07396, 1.07396, 1.07448, 1.07814, 1.09038]
需要用简便方法将任意此类数组分割为对应不同聚类的子数组,无需Jenks自然断点法这类复杂实现。例如输入数组[1,2,3,5,10,11,13,65,70],期望输出[[1,2,3,5],[10,11,13],[65,70]]。
实现思路
采用阈值分割法,这是最轻量化的聚类方案,核心逻辑:
- 先对PH数组排序,消除时间维度的干扰
- 设定一个聚类阈值(可作为参数调整,适配不同品种波动)
- 遍历排序后的数组,若当前元素与当前聚类最后一个元素的差值超过阈值,则新建聚类;否则加入当前聚类
修改后的完整PineScript代码
//@version=5 strategy("Support and Resistance with PH Clustering", overlay=true) // ============================================================================================================ // // =============================================TIME RANGE===================================================== // // ============================================================================================================ // // 日期范围筛选设置 i_dateFilter = input(true, "═════ 日期范围筛选 ═════") i_fromYear = input.int(2023, "起始年份", minval = 1900) i_fromMonth = input.int(1, "起始月份", minval = 1, maxval = 12) i_fromDay = input.int(22, "起始日期", minval = 1, maxval = 31) i_toYear = input.int(2023, "结束年份", minval = 1900) i_toMonth = input.int(3, "结束月份", minval = 1, maxval = 12) i_toDay = input.int(23, "结束日期", minval = 1, maxval = 31) // 生成时间范围条件 start = timestamp(i_fromYear, i_fromMonth, i_fromDay, 00, 00) finish = timestamp(i_toYear, i_toMonth, i_toDay, 23, 59) window() => (time >= start and time <= finish) or not i_dateFilter ? true : false // 显示日期范围背景 showDate = input(defval = true, title = "显示日期范围背景") bgcolor(color = showDate and window() ? color.new(color.gray, 90) : na) // ============================================================================================================ // // =============================================枢轴高点聚类==================================================== // // ============================================================================================================ // // 枢轴高点参数 leftBars = input(5, "左侧确认K线数") rightBars = input(5, "右侧确认K线数") ph = ta.pivothigh(close, leftBars, rightBars) plot(ph, style=plot.style_cross, linewidth=5, color= color.blue, offset=-rightBars) // 存储所有枢轴高点的数组 var float[] allPh = array.new_float(0) // 聚类参数 clusterThreshold = input.float(0.003, "聚类阈值", tooltip="根据品种波动调整,EURUSD建议0.002-0.005") var array<float[]> phClusters = array.new_float_array(0) // 收集枢轴高点并实时聚类 if ph and window() line.new(bar_index - rightBars, ph, last_bar_index, ph, color = color.blue) array.push(allPh, ph) // 每次新增PH后重新聚类 array.clear(phClusters) if array.size(allPh) > 0 // 1. 对PH数组升序排序 sortedPh = array.sort(allPh, order.ascending) // 2. 初始化第一个聚类 currentCluster = array.new_float(1, array.get(sortedPh, 0)) array.push(phClusters, currentCluster) // 3. 遍历剩余元素完成聚类 for i from 1 to array.size(sortedPh)-1 currentVal = array.get(sortedPh, i) lastCluster = array.get(phClusters, array.size(phClusters)-1) lastValInCluster = array.get(lastCluster, array.size(lastCluster)-1) if currentVal - lastValInCluster > clusterThreshold // 差值超过阈值,新建聚类 newCluster = array.new_float(1, currentVal) array.push(phClusters, newCluster) else // 加入当前聚类 array.push(lastCluster, currentVal) // 输出聚类结果到图表(用于调试) if barstate.islast label.new(bar_index, high, str.tostring(phClusters), color=color.white, textcolor=color.black, style=label.style_label_down)
效果说明
- 对于示例数组
[1,2,3,5,10,11,13,65,70],将clusterThreshold设为2,即可得到期望的[[1,2,3,5],[10,11,13],[65,70]]聚类结果 - 针对给定的EURUSD PH数组,设置阈值为0.003时,会将数值接近的枢轴高点归为同一聚类,对应同一阻力区间,便于后续绘制支撑阻力通道
内容的提问来源于stack exchange,提问作者PepeW
相关产品推荐
相关产品推荐

