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 はパラメータとして任意の次元の配列を受け入れます。しかし、検索は常に最初(ゼロ)の次元に適用されます。

例:

#property description "The indicator displays larger timeframe'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);
//--- バーを計算する start 変数
  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])
             {
              //--- (最後と最後から2 番目のバーの間の領域を記入せずに)ローソク足の主な部分を描画する
              FillCandleMain(open,close,high,low,ExtStartPos,i-1,i-2,ExtIndexMax,ExtIndexMin);
              //--- ローソク足の終わりの部分を埋める (最後と最後から2 番目のバーの間の領域)
              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)
             {
              //--- 主要指標バッファの最後と最後から2 番目のバーの間の領域をクリアする
              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);
    }
//--- 指標期間が1週間または一ヶ月の場合は、期間は正しい
  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;
    }
 }
//+-------------------------------------------------------------------------------------+
//| ローソク足の終わりの部分をクリアする     |
//| (最後と最後から2 番目のバーの間の領域)                                                                              |
//+-------------------------------------------------------------------------------------+
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;
 }