Skip to content

自定义指标-价格密集指标

一、指标原理

价格密集指标用于衡量市场价格的噪声程度,其值越高表示价格在特定周期内的波动越密集(噪声大),适合震荡交易;值越低表示价格波动越稀疏(噪声小),适合趋势交易。

计算公式:

  1. 计算周期内每根K线的高低价差(最高价-最低价)。
  2. 累加所有K线的高低价差,得到总和Σ(High-Low)
  3. 计算周期内的整体价格区间(周期内最高价-周期内最低价),即MaxHigh - MinLow
  4. 价格密度 = Σ(High-Low) / (MaxHigh - MinLow)

二、代码实现

cpp
/*
  #property indicator_separate_window
  #property indicator_chart_window
 */
#property indicator_separate_window

#property indicator_buffers 4
#property indicator_plots 1

#property indicator_type1 DRAW_LINE // 画线
#property indicator_color1 clrDarkOrange // 颜色
#property indicator_level1 5
#property indicator_levelwidth 1
#property indicator_levelstyle STYLE_DOT

input int InpPeriod = 20; // 周期
input double InpNoiseThresholdLevel = 5;  // 水平线

double PriceDensityBuffer[];
double SumOfIndHighLowsBuffer[];
double HighestHighBuffer[];
double LowestLowBuffer[];

int OnInit(){
    // 绑定指定的指标缓冲区
    SetIndexBuffer(0,PriceDensityBuffer,INDICATOR_DATA);
    // 辅助计算缓冲区
    SetIndexBuffer(1,SumOfIndHighLowsBuffer,INDICATOR_CALCULATIONS);
    SetIndexBuffer(2,HighestHighBuffer,INDICATOR_CALCULATIONS);
    SetIndexBuffer(3,LowestLowBuffer,INDICATOR_CALCULATIONS);

    // 设置指标值的精度    
    IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
    // 从那根K线开始画 
    PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpPeriod);
    
    IndicatorSetString(INDICATOR_SHORTNAME,"价格密度指标("+IntegerToString(InpPeriod) + ")");

    IndicatorSetDouble(INDICATOR_LEVELVALUE,0,InpNoiseThresholdLevel);
    IndicatorSetInteger(INDICATOR_LEVELCOLOR,0,clrYellow);
    IndicatorSetString(INDICATOR_LEVELTEXT,0,"High values=high noise");
    return INIT_SUCCEEDED;
}


int OnCalculate(const int rates_total, // 当前可用的K线数量
    const int prev_calculated,  // 上次调用OnCalculate的返回值
    const datetime &time[],
    const double &open[],
    const double &high[],
    const double &low[],
    const double &close[],
    const long &tick_volume[],
    const long &volume[],
    const int &spread[])
{
    // 判断K线总数是否足够
    if(rates_total <= InpPeriod) return (0);

    // 确定计算的其实位置, 从哪一根K线开始计算
    // 如果prev_calculated为0, 说明是第一次调用, 从InpPeriod开始计算
    // 否则 从上次计算的K线位置开始计算
    int limit =0 ;
    if(prev_calculated == 0) limit = InpPeriod;
    else limit = prev_calculated;


    for(int i=limit; i<rates_total; i++)
    { 
      // 初始化当前索引i的累积高低差, 最高高价, 最低低价
      SumOfIndHighLowsBuffer[i] = 0;
      HighestHighBuffer[i] = DBL_MIN;
      LowestLowBuffer[i] = DBL_MAX;

      // 在给定周期InpPeriod内 累加每个周期的高低差,并更新最高高价和最低低价
      for(int iLoop= i-1;iLoop>i-InpPeriod;iLoop--){
        SumOfIndHighLowsBuffer[i] += high[iLoop] - low[iLoop];
        if(high[iLoop] > HighestHighBuffer[i]){
          HighestHighBuffer[i] = high[iLoop];
        }
        if(low[iLoop] < LowestLowBuffer[i]){
          LowestLowBuffer[i] = low[iLoop];
        }
      }
      // 更新最高高价和 最低低价
      double highestHigh = MathMax(HighestHighBuffer[i],high[i]);
      double lowestLow = MathMin(LowestLowBuffer[i],low[i]);
      // 计算价格密度 
      if(highestHigh-lowestLow !=0){
        PriceDensityBuffer[i] = (SumOfIndHighLowsBuffer[i] + (high[i]-low[i])) / (highestHigh-lowestLow);
      }else{
        PriceDensityBuffer[i] = 0.0;
      }
    }
    return (rates_total);
}

最终效果

image.png