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

如何查找数组中数值最接近的K线高点并绘制HLine?

实现数组中接近数值识别的方案

前置修正

你现有代码存在类型错误:totalHigh、FinishingTotalHigh等变量用int类型存储价格会丢失全部小数精度,需要改为double类型。

核心实现逻辑

你需要先明确两个可自定义的规则:

  • 接近阈值:两个高点差值小于该值时判定为数值接近,建议设置为交易品种最小变动价位的3-10倍,比如直盘货币对可设为0.0005
  • 有效聚类最小数量:至少有N个高点互相接近时才判定为有效水平位,建议设为2-3,避免偶然的接近被误判

识别逻辑如下:

  1. 将扫描到的所有高点存入临时数组
  2. 对数组进行升序排序,数值接近的元素会变为相邻状态
  3. 遍历排序后的数组,将差值小于接近阈值的相邻元素归为同一个聚类
  4. 过滤掉元素数量小于有效聚类最小数量的无效聚类
  5. 每个有效聚类的平均值就是你需要绘制水平线的位置

完整修改后代码

extern int candleCount = 100;
// 新增自定义参数
extern double nearThreshold = 0.0005; // 接近阈值,可根据品种调整
extern int minClusterSize = 3; // 有效聚类最少高点数量
extern string linePrefix = "HighClusterLine_"; // 水平线命名前缀

double totalHigh;
double FinishingTotalHigh;
double totalLow;
double FinishingTotalLow;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // 退出时删除所有创建的水平线
   for(int i=ObjectsTotal(0)-1; i>=0; i--)
   {
      string objName = ObjectName(0, i);
      if(StringFind(objName, linePrefix) == 0)
      {
         ObjectDelete(0, objName);
      }
   }
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   totalHigh = 0;
   totalLow = 0;
   double Highest = High[0];
   double Lowest = Low[0];
   
   // 存储所有高点的临时数组
   double highArr[];
   ArrayResize(highArr, candleCount+1);
   
   // 扫描100根K线
   for (int i = 0; i <= candleCount; i++)
   {
      highArr[i] = High[i];
      totalHigh = High[i] + totalHigh;
      totalLow = Low[i] + totalLow;
      
      if (High[i] > Highest) Highest = High[i];
      if (Low[i] < Lowest) Lowest = Low[i];
   }
   FinishingTotalHigh = totalHigh/candleCount;
   FinishingTotalLow = totalLow/candleCount;
   
   // 打印基础结果
   Alert("Highest price found is "+Highest);
   Alert("Lowest price found is "+Lowest);
   Alert("Avg High: "+FinishingTotalHigh);
   Alert("Avg Low: "+FinishingTotalLow);
   
   // --- 新增:识别接近的高点聚类 ---
   // 1. 高点数组排序
   ArraySort(highArr);
   // 2. 划分聚类
   double currentCluster[];
   ArrayResize(currentCluster, 1);
   currentCluster[0] = highArr[0];
   
   // 先删除之前画的线避免重复
   for(int i=ObjectsTotal(0)-1; i>=0; i--)
   {
      string objName = ObjectName(0, i);
      if(StringFind(objName, linePrefix) == 0)
      {
         ObjectDelete(0, objName);
      }
   }
   
   int lineIndex = 0;
   for(int i=1; i<=candleCount; i++)
   {
      if(highArr[i] - currentCluster[ArraySize(currentCluster)-1] < nearThreshold)
      {
         // 差值小于阈值,加入当前聚类
         ArrayResize(currentCluster, ArraySize(currentCluster)+1);
         currentCluster[ArraySize(currentCluster)-1] = highArr[i];
      }
      else
      {
         // 聚类结束,判断是否有效
         if(ArraySize(currentCluster) >= minClusterSize)
         {
            // 计算聚类均值
            double clusterAvg = 0;
            for(int j=0; j<ArraySize(currentCluster); j++)
            {
               clusterAvg += currentCluster[j];
            }
            clusterAvg /= ArraySize(currentCluster);
            // 画水平线
            string lineName = linePrefix + IntegerToString(lineIndex);
            ObjectCreate(0, lineName, OBJ_HLINE, 0, 0, clusterAvg);
            ObjectSetInteger(0, lineName, OBJ_COLOR, clrRed);
            ObjectSetInteger(0, lineName, OBJ_STYLE, STYLE_SOLID);
            ObjectSetInteger(0, lineName, OBJ_WIDTH, 2);
            lineIndex++;
         }
         // 重置聚类
         ArrayResize(currentCluster, 1);
         currentCluster[0] = highArr[i];
      }
   }
   // 处理最后一个聚类
   if(ArraySize(currentCluster) >= minClusterSize)
   {
      double clusterAvg = 0;
      for(int j=0; j<ArraySize(currentCluster); j++)
      {
         clusterAvg += currentCluster[j];
      }
      clusterAvg /= ArraySize(currentCluster);
      string lineName = linePrefix + IntegerToString(lineIndex);
      ObjectCreate(0, lineName, OBJ_HLINE, 0, 0, clusterAvg);
      ObjectSetInteger(0, lineName, OBJ_COLOR, clrRed);
      ObjectSetInteger(0, lineName, OBJ_STYLE, STYLE_SOLID);
      ObjectSetInteger(0, lineName, OBJ_WIDTH, 2);
   }
}
//+------------------------------------------------------------------+

调整说明

你可以根据交易品种的波动幅度调整nearThreshold和minClusterSize参数,波动大的品种阈值可以适当调大,对水平位验证要求高的可以把最小聚类数量调大。

内容的提问来源于stack exchange,提问作者Javier Macias

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:54:10