ArrayMinimum

搜索多维度数值数组的第一维度中的最低元素。

int  ArrayMinimum(

   const void&   array[],             // 用来搜索的数组

   int           start=0,             // 启动用于检测的指标

   int           count=WHOLE_ARRAY    // 检测元素数量

   );

参量

array[]

[in]  搜索数字数组

start=0

[in]  标引开始检测

count=WHOLE_ARRAY

[in]  搜索元素数量,默认搜索全部数组 (count=WHOLE_ARRAY).

返回值

函数返回发现元素的标引索引,考虑数组系列,失败返回-1

注释

搜索最小值时考虑 AS_SERIES 标识值。

函数ArrayMaximum 和 ArrayMinimum 接受任何维度的数组为参数。然而,搜索却始终应用于第一(0)维度。

示例:

#property description "The indicator displays larger time frame's candlesticks on the current one."

//--- 指标设置

#property indicator_chart_window

#property indicator_buffers 16

#property indicator_plots   8

//---- 图 1

#property indicator_label1  "BearBody"

#property indicator_color1  clrSeaGreen,clrSeaGreen

//---- 图 2

#property indicator_label2  "BearBodyEnd"

#property indicator_color2  clrSeaGreen,clrSeaGreen

//---- 图 3

#property indicator_label3  "BearShadow"

#property indicator_color3  clrSalmon,clrSalmon

//---- 图 4

#property indicator_label4  "BearShadowEnd"

#property indicator_color4  clrSalmon,clrSalmon

//---- 图 5

#property indicator_label5  "BullBody"

#property indicator_color5  clrOlive,clrOlive

//---- 图 6

#property indicator_label6  "BullBodyEnd"

#property indicator_color6  clrOlive,clrOlive

//---- 图 7

#property indicator_label7  "BullShadow"

#property indicator_color7  clrSkyBlue,clrSkyBlue

//---- 图 8

#property indicator_label8  "BullShadowEnd"

#property indicator_color8  clrSkyBlue,clrSkyBlue

//--- 预定义常量

#define INDICATOR_EMPTY_VALUE 0.0

//--- 输入参数

input ENUM_TIMEFRAMES InpPeriod=PERIOD_H4;              // 指标计算的时间范围

input datetime        InpDateStart=D'2013.01.01 00:00'; // 分析起始日期

//--- 熊市蜡烛图的指标缓冲区

double   ExtBearBodyFirst[];

double   ExtBearBodySecond[];

double   ExtBearBodyEndFirst[];

double   ExtBearBodyEndSecond[];

double   ExtBearShadowFirst[];

double   ExtBearShadowSecond[];

double   ExtBearShadowEndFirst[];

double   ExtBearShadowEndSecond[];

//--- 牛市蜡烛图的指标缓冲区

double   ExtBullBodyFirst[];

double   ExtBullBodySecond[];

double   ExtBullBodyEndFirst[];

double   ExtBullBodyEndSecond[];

double   ExtBullShadowFirst[];

double   ExtBullShadowSecond[];

double   ExtBullShadowEndFirst[];

double   ExtBullShadowEndSecond[];

//--- 全局变量

datetime ExtTimeBuff[];      // 较大时间帧的时间缓冲区

int      ExtSize=0;          // 时间缓冲区大小

int      ExtCount=0;         // 时间缓冲区的标引

int      ExtStartPos=0;      // 指标计算的初始位置

bool     ExtStartFlag=true;  // 接收初始位置的辅助标识

datetime ExtCurrentTime[1];  // 生成较大时间帧柱形的最近时间

datetime ExtLastTime;        // 较大时间帧的最近时间,执行计算

bool     ExtBearFlag=true;   // 标记定义编写数据订单熊市指标缓冲区

bool     ExtBullFlag=true;   // 标记定义编写数据订单牛市指标缓冲区

int      ExtIndexMax=0;      // 数组中最大元素标引

int      ExtIndexMin=0;      // 数组中最小元素标引

int      ExtDirectionFlag=0; // 当前蜡烛图的价格移动方向

//--- 正确绘制蜡烛图开盘价和收盘价之间的转换

const double ExtEmptyBodySize=0.2*SymbolInfoDouble(Symbol(),SYMBOL_POINT);

//+------------------------------------------------------------------+

//| 填写蜡烛图的基本部分                                                |

//+------------------------------------------------------------------+

void FillCandleMain(const double &open[],const double &close[],

                    const double &high[],const double &low[],

                    const int start,const int last,const int fill_index,

                    int &index_max,int &index_min)

  {

//--- 在数组中找出最大和最小元素的标引

   index_max=ArrayMaximum(high,ExtStartPos,last-start+1); // 最高极值

   index_min=ArrayMinimum(low,ExtStartPos,last-start+1);  // 最低极值

//--- 定义当前时间帧填充多少柱

   int count=fill_index-start+1;

//--- 如果首柱的收盘价超过最后的柱,那么蜡烛图为熊市

   if(open[start]>close[last])

     {

      //--- 如果蜡烛图之前牛市,清空牛市指标缓冲区的值

      if(ExtDirectionFlag!=-1)

         ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count);

      //--- 熊市蜡烛图

      ExtDirectionFlag=-1;

      //--- 生成蜡烛图

      FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start],

                     close[last],high[index_max],low[index_min],start,count,ExtBearFlag);

      //--- 退出函数

      return;

     }

//--- 如果首柱的收盘价少于最后的柱,那么蜡烛图为牛市

   if(open[start]<close[last])

     {

      //--- 如果蜡烛图之前为熊市,清空熊市指标缓冲区的值

      if(ExtDirectionFlag!=1)

         ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,start,count);

      //--- 牛市蜡烛图

      ExtDirectionFlag=1;

      //--- 生成蜡烛图

      FormCandleMain(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,close[last],

                     open[start],high[index_max],low[index_min],start,count,ExtBullFlag);

      //--- 退出函数            

      return;

     }

//--- 如果您在这部分函数,首柱开盘价等于

//--- 最后柱的收盘价;这种蜡烛图被认为熊市图

//--- 如果在那之前蜡烛图为牛市,清空牛市指标缓冲区的值

   if(ExtDirectionFlag!=-1)

      ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count);

//--- 熊市蜡烛图

   ExtDirectionFlag=-1;

//--- 如果收盘和开盘价相同,使用切换来正确显示

   if(high[index_max]!=low[index_min])

      FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start],

                     open[start]-ExtEmptyBodySize,high[index_max],low[index_min],start,count,ExtBearFlag);

   else

      FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,

                     open[start],open[start]-ExtEmptyBodySize,high[index_max],

                     high[index_max]-ExtEmptyBodySize,start,count,ExtBearFlag);

  }

//+------------------------------------------------------------------+

//| 填充蜡烛图末端                                                     |

//+------------------------------------------------------------------+

void FillCandleEnd(const double &open[],const double &close[],

                   const double &high[],const double &low[],

                   const int start,const int last,const int fill_index,

                   const int index_max,const int index_min)

  {

//--- 单柱时不要绘制

   if(last-start==0)

      return;

//--- 如果首柱的收盘价超过最后的柱,蜡烛图为熊市

   if(open[start]>close[last])

     {

      //--- 生成蜡烛图末端

      FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,

                    open[start],close[last],high[index_max],low[index_min],fill_index,ExtBearFlag);

      //--- 退出函数

      return;

     }

//--- 如果首柱的收盘价小于最后的柱,蜡烛图为牛市

   if(open[start]<close[last])

     {

      //--- 生成蜡烛图末端

      FormCandleEnd(ExtBullBodyEndFirst,ExtBullBodyEndSecond,ExtBullShadowEndFirst,ExtBullShadowEndSecond,

                    close[last],open[start],high[index_max],low[index_min],fill_index,ExtBullFlag);

      //--- 退出函数

      return;

     }

//--- 如果您在这部分函数,首柱开盘价等于

//--- 最后柱的收盘价;这种蜡烛图被认为熊市图

//--- 生成蜡烛图末端

   if(high[index_max]!=low[index_min])

      FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start],

                    open[start]-ExtEmptyBodySize,high[index_max],low[index_min],fill_index,ExtBearFlag);

   else

      FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start],

                    open[start]-ExtEmptyBodySize,high[index_max],high[index_max]-ExtEmptyBodySize,fill_index,ExtBearFlag);

  }

//+------------------------------------------------------------------+

//| 自定义指标初始化函数                                                |

//+------------------------------------------------------------------+

int OnInit()

  {

//--- 检查指标周期

   if(!CheckPeriod((int)Period(),(int)InpPeriod))

      return(INIT_PARAMETERS_INCORRECT);

//--- 在前景显示价格数据

   ChartSetInteger(0,CHART_FOREGROUND,0,1);

//--- 绑定指标缓冲区

   SetIndexBuffer(0,ExtBearBodyFirst);

   SetIndexBuffer(1,ExtBearBodySecond);

   SetIndexBuffer(2,ExtBearBodyEndFirst);

   SetIndexBuffer(3,ExtBearBodyEndSecond);

   SetIndexBuffer(4,ExtBearShadowFirst);

   SetIndexBuffer(5,ExtBearShadowSecond);

   SetIndexBuffer(6,ExtBearShadowEndFirst);

   SetIndexBuffer(7,ExtBearShadowEndSecond);

   SetIndexBuffer(8,ExtBullBodyFirst);

   SetIndexBuffer(9,ExtBullBodySecond);

   SetIndexBuffer(10,ExtBullBodyEndFirst);

   SetIndexBuffer(11,ExtBullBodyEndSecond);

   SetIndexBuffer(12,ExtBullShadowFirst);

   SetIndexBuffer(13,ExtBullShadowSecond);

   SetIndexBuffer(14,ExtBullShadowEndFirst);

   SetIndexBuffer(15,ExtBullShadowEndSecond);

//--- 设置一些属性值来创建指标

   for(int i=0;i<8;i++)

     {

      PlotIndexSetInteger(i,PLOT_DRAW_TYPE,DRAW_FILLING); // 图形结构类型

      PlotIndexSetInteger(i,PLOT_LINE_STYLE,STYLE_SOLID); // 绘制线型风格

      PlotIndexSetInteger(i,PLOT_LINE_WIDTH,1);           // 绘制线型宽度

     }

//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| 自定义指标迭代函数                                                 |

//+------------------------------------------------------------------+

int OnCalculate(const int rates_total,

                const int prev_calculated,

                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[])

  {

//--- 如果没有计算的柱

   if(prev_calculated==0)

     {

      //--- 接收较大时间帧柱形的到达时间

      if(!GetTimeData())

         return(0);

     }

//--- 设置直接索引

   ArraySetAsSeries(time,false);

   ArraySetAsSeries(high,false);

   ArraySetAsSeries(low,false);

   ArraySetAsSeries(open,false);

   ArraySetAsSeries(close,false);

//--- 启动计算柱形的变量

   int start=prev_calculated;

//--- 如果生成柱形,重新计算上面的指标值

   if(start!=0 && start==rates_total)

      start--;

//--- 循环计算指标值

   for(int i=start;i<rates_total;i++)

     {

      //--- 用空值填充指标缓冲区的i元素

      FillIndicatorBuffers(i);

      //--- 从InpDateStart日期开始计算柱形

      if(time[i]>=InpDateStart)

        {

         //--- 定义值第一时间显示的持仓

         if(ExtStartFlag)

           {

            //--- 存储最初柱形的数量

            ExtStartPos=i;

            //--- 定义超过time[i]的较大时间帧的初始日期

            while(time[i]>=ExtTimeBuff[ExtCount])

               if(ExtCount<ExtSize-1)

                  ExtCount++;

            //--- 改变标识值以便不在这模块再次运行

            ExtStartFlag=false;

           }

         //--- 检查数组中是否有任何元素

         if(ExtCount<ExtSize)

           {

            //--- 等候当前时间帧的值到达较大时间帧的值

            if(time[i]>=ExtTimeBuff[ExtCount])

              {

               //---  绘制蜡烛图的主要部分(不填写最后和倒数第二柱之间的区域)

               FillCandleMain(open,close,high,low,ExtStartPos,i-1,i-2,ExtIndexMax,ExtIndexMin);

               //--- 填充蜡烛图末端(最后和倒数第二柱之间的区域)

               FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin);

               //--- 切换初始持仓以绘制下一个蜡烛图

               ExtStartPos=i;

               //--- 增加数组计数器

               ExtCount++;

              }

            else

               continue;

           }

         else

           {

            //--- 重置数组的值

            ResetLastError();

            //--- 接收来自较大时间帧的最后日期

            if(CopyTime(Symbol(),InpPeriod,0,1,ExtCurrentTime)==-1)

              {

               Print("Data copy error, code = ",GetLastError());

               return(0);

              }

            //--- 如果新日期靠后,停止生成蜡烛图

            if(ExtCurrentTime[0]>ExtLastTime)

              {

               //--- 在主要指标缓冲区清空最后和倒数第二柱之间的区域

               ClearEndOfBodyMain(i-1);

               //--- 使用辅助指标缓冲区填充该区域

               FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin);

               //--- 切换初始持仓以绘制下一个蜡烛图

               ExtStartPos=i;

               //--- 重置价格方向标识

               ExtDirectionFlag=0;

               //--- 存储新的最近日期

               ExtLastTime=ExtCurrentTime[0];

              }

            else

              {

               //--- 生成蜡烛图

               FillCandleMain(open,close,high,low,ExtStartPos,i,i,ExtIndexMax,ExtIndexMin);

              }

           }

        }

     }

//--- 返回prev_calculated值以便下次调用

   return(rates_total);

  }

//+------------------------------------------------------------------+

//| 检查指定指标周期的正确性                                            |

//+------------------------------------------------------------------+

bool CheckPeriod(int current_period,int high_period)

  {

//--- 指标周期应该超过显示它的时间帧

   if(current_period>=high_period)

     {

      Print("Error! The value of the indicator period should exceed the value of the current time frame!");

      return(false);

     }

//--- 如果指标周期是周或月份,周期则是正确的

   if(high_period>32768)

      return(true);

//--- 转变周期值到分钟

   if(high_period>30)

      high_period=(high_period-16384)*60;

   if(current_period>30)

      current_period=(current_period-16384)*60;

//--- 指标周期应该是它显示的时间帧的几倍

   if(high_period%current_period!=0)

     {

      Print("Error! The value of the indicator period should be multiple of the value of the current time frame!");

      return(false);

     }

//--- 指标周期应该超过它显示的时间帧的3或更多倍

   if(high_period/current_period<3)

     {

      Print("Error! The indicator period should exceed the current time frame 3 or more times!");

      return(false);

     }

//--- 指标周期在当前时间帧是正确的

   return(true);

  }

//+------------------------------------------------------------------+

//| 接收来自较大时间帧的时间数据                                         |

//+------------------------------------------------------------------+

bool GetTimeData(void)

  {

//--- 重置错误的值

   ResetLastError();

//--- 复制当前时间的所有数据

   if(CopyTime(Symbol(),InpPeriod,InpDateStart,TimeCurrent(),ExtTimeBuff)==-1)

     {

      //--- 接收错误代码

      int code=GetLastError();

      //--- 打印错误信息

      PrintFormat("Data copy error! %s",code==4401

                  ? "History is still being uploaded!"

                  : "Code = "+IntegerToString(code));

      //--- 返回false,反复尝试下载数据

      return(false);

     }

//--- 接收数组大小

   ExtSize=ArraySize(ExtTimeBuff);

//--- 为数组设置循环指数为零

   ExtCount=0;

//--- 在时间帧设置当前蜡烛图位置为零

   ExtStartPos=0;

   ExtStartFlag=true;

//--- 存储来自较大时间帧的最近时间值

   ExtLastTime=ExtTimeBuff[ExtSize-1];

//--- 成功执行

   return(true);

  }

//+--------------------------------------------------------------------------+

//| 函数形成了蜡烛图的主要部分。根据标识的                                         |

//| 值,函数定义了要使用哪个数据和数组                                             |

//| 以便正确显示                                                               |

//+--------------------------------------------------------------------------+

void FormCandleMain(double &body_fst[],double &body_snd[],

                    double &shadow_fst[],double &shadow_snd[],

                    const double fst_value,const double snd_value,

                    const double fst_extremum,const double snd_extremum,

                    const int start,const int count,const bool flag)

  {

//--- 检查标识的值

   if(flag)

     {

      //--- 生成蜡烛图主体

      FormMain(body_fst,body_snd,fst_value,snd_value,start,count);

      //--- 生成蜡烛图影子

      FormMain(shadow_fst,shadow_snd,fst_extremum,snd_extremum,start,count);

     }

   else

     {

      //--- 生成蜡烛图主体

      FormMain(body_fst,body_snd,snd_value,fst_value,start,count);

      //--- 生成蜡烛图影子

      FormMain(shadow_fst,shadow_snd,snd_extremum,fst_extremum,start,count);

     }

  }

//+--------------------------------------------------------------------------------+

//| 函数形成了蜡烛图的末端。根据标识的值,                                                |

//| 函数定义了要使用哪个数据和数组                                                      |

//| 以便正确显示。                                                                    |

//+--------------------------------------------------------------------------------+

void FormCandleEnd(double &body_fst[],double &body_snd[],

                   double &shadow_fst[],double &shadow_snd[],

                   const double fst_value,const double snd_value,

                   const double fst_extremum,const double snd_extremum,

                   const int end,bool &flag)

  {

//--- 检查标识的值

   if(flag)

     {

      //--- 生成蜡烛图主体的末端

      FormEnd(body_fst,body_snd,fst_value,snd_value,end);

      //--- 生成蜡烛图影子的末端

      FormEnd(shadow_fst,shadow_snd,fst_extremum,snd_extremum,end);

      //--- 改变标识值到相反方向

      flag=false;

     }

   else

     {

      //--- 生成蜡烛图主体的末端

      FormEnd(body_fst,body_snd,snd_value,fst_value,end);

      //--- 生成蜡烛图影子的末端

      FormEnd(shadow_fst,shadow_snd,snd_extremum,fst_extremum,end);

      //--- 改变标识值到相反方向

      flag=true;

     }

  }

//+-------------------------------------------------------------------------------------+

//| 清空蜡烛图末端(最后和倒数第二柱之间的区域)                                                |

//|                                                                                     |

//+-------------------------------------------------------------------------------------+

void ClearEndOfBodyMain(const int ind)

  {

   ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,ind,1);

   ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,ind,1);

  }

//+------------------------------------------------------------------+

//| 清空蜡烛图                                                        |

//+------------------------------------------------------------------+

void ClearCandle(double &body_fst[],double &body_snd[],double &shadow_fst[],

                 double &shadow_snd[],const int start,const int count)

  {

//--- 检查

   if(count!=0)

     {

      //--- 以空值填充指标缓冲区

      ArrayFill(body_fst,start,count,INDICATOR_EMPTY_VALUE);

      ArrayFill(body_snd,start,count,INDICATOR_EMPTY_VALUE);

      ArrayFill(shadow_fst,start,count,INDICATOR_EMPTY_VALUE);

      ArrayFill(shadow_snd,start,count,INDICATOR_EMPTY_VALUE);

     }

  }

//+------------------------------------------------------------------+

//| 生成蜡烛图的主要部分                                                |

//+------------------------------------------------------------------+

void FormMain(double &fst[],double &snd[],const double fst_value,

              const double snd_value,const int start,const int count)

  {

//--- 检查

   if(count!=0)

     {

      //--- 用值填充指标缓冲区

      ArrayFill(fst,start,count,fst_value);

      ArrayFill(snd,start,count,snd_value);

     }

  }

//+------------------------------------------------------------------+

//| 生成蜡烛图末端                                                     |

//+------------------------------------------------------------------+

void FormEnd(double &fst[],double &snd[],const double fst_value,

             const double snd_value,const int last)

  {

//--- 用值填充指标缓冲区

   ArrayFill(fst,last-1,2,fst_value);

   ArrayFill(snd,last-1,2,snd_value);

  }

//+------------------------------------------------------------------+

//| 通过空值填充指标缓冲区的i元素                                        |

//+------------------------------------------------------------------+

void FillIndicatorBuffers(const int i)

  {

//--- 在指标缓冲区单元设置空值

   ExtBearBodyFirst[i]=INDICATOR_EMPTY_VALUE;

   ExtBearBodySecond[i]=INDICATOR_EMPTY_VALUE;

   ExtBearShadowFirst[i]=INDICATOR_EMPTY_VALUE;

   ExtBearShadowSecond[i]=INDICATOR_EMPTY_VALUE;

   ExtBearBodyEndFirst[i]=INDICATOR_EMPTY_VALUE;

   ExtBearBodyEndSecond[i]=INDICATOR_EMPTY_VALUE;

   ExtBearShadowEndFirst[i]=INDICATOR_EMPTY_VALUE;

   ExtBearShadowEndSecond[i]=INDICATOR_EMPTY_VALUE;

   ExtBullBodyFirst[i]=INDICATOR_EMPTY_VALUE;

   ExtBullBodySecond[i]=INDICATOR_EMPTY_VALUE;

   ExtBullShadowFirst[i]=INDICATOR_EMPTY_VALUE;

   ExtBullShadowSecond[i]=INDICATOR_EMPTY_VALUE;

   ExtBullBodyEndFirst[i]=INDICATOR_EMPTY_VALUE;

   ExtBullBodyEndSecond[i]=INDICATOR_EMPTY_VALUE;

   ExtBullShadowEndFirst[i]=INDICATOR_EMPTY_VALUE;

   ExtBullShadowEndSecond[i]=INDICATOR_EMPTY_VALUE;

  }