配列を使用する関数群

ArrayBsearch

昇順にソートされた多次元数値配列内の指定された値を検索します。検索は最初の次元の要素を介して行われます。

double 型の配列の検索には

int  ArrayBsearch(
const double&   array[],   // 検索対象の配列
double          value      // 検索される値
);

float 型の配列の検索には

int  ArrayBsearch(
const float&   array[]// 検索対象の配列
float          value      // 検索される値
);

long 型の配列の検索には

int  ArrayBsearch(
const long&   array[]// 検索対象の配列
long          value      // 検索される値
);

int 型の配列の検索には

int  ArrayBsearch(
const int&   array[]// 検索対象の配列
int          value      // 検索される値
);

short 型の配列の検索には

int  ArrayBsearch(
const short&   array[]// 検索対象の配列
short          value      // 検索される値
);

char 型の配列の検索には

int  ArrayBsearch(
const char&   array[]// 検索対象の配列
char          value      // 検索される値
);

パラメータ

array[]

[in]  検索される数値配列

value

[in]  検索される数値

戻り値

この関数は、見つかった要素のインデックスを返します。指定された値を持つ要素が配列に存在しない場合は、検索値の範囲で最も近い値を持つ要素のインデックスが返されます。

注意事項

二分探索ではソートされた配列の処理だけが可能です。数値の配列をソートするには ArraySort() 関数を使用します。

例:

#property description “Script based on RSI indicator data displays”
#property description “how often the market was in”
#property description “overbought and oversold areas in the specified time interval.”
//— スクリプトの起動時に入力パラメータのウィンドウを表示する
#property script_show_inputs
//— 入力パラメータ
input int               InpMAPeriod=14;                   // 平均移動線の期間
input ENUM_APPLIED_PRICE InpAppliedPrice=PRICE_CLOSE;       // 価格の種類
input double             InpOversoldValue=30.0;             //売りすぎレベル
input double             InpOverboughtValue=70.0;           //買いすぎレベル
input datetime           InpDateStart=D’2012.01.01 00:00′; //分析開始日
input datetime           InpDateFinish=D’2013.01.01 00:00′; // 分析終了日
//+——————————————————————+
//| スクリプトプログラムを開始する関数                                          |
//+——————————————————————+
void OnStart()
{
double rsi_buff[]; // 指標値の配列
int    size=0;     // 配列サイズ
//— RSI 指標ハンドルを受け取る
ResetLastError();
int rsi_handle=iRSI(Symbol(),Period(),InpMAPeriod,InpAppliedPrice);
if(rsi_handle==INVALID_HANDLE)
{
//— 指標ハンドルの受け取りに失敗
PrintFormat(“Indicator handle receiving error. Error code = %d”,GetLastError());
return;
}
//— 指標が全ての値を計算するまでループ内にとどまる
while(BarsCalculated(rsi_handle)==-1)
{
//— 指標が強制的にスクリプトの動作を完了した場合ループから出る
if(IsStopped())
return;
//— 指標が全ての値を計算出来るように休止する
Sleep(10);
}
//— 一定期間の指標値を複製する
ResetLastError();
if(CopyBuffer(rsi_handle,0,InpDateStart,InpDateFinish,rsi_buff)==-1)
{
PrintFormat(“Failed to copy the indicator values. Error code = %d”,GetLastError());
return;
}
//— 配列のサイズを受け取る
size=ArraySize(rsi_buff);
//— 配列をソートする
ArraySort(rsi_buff);
//— 市場が売り過ぎの領域にあった期間を(百分率で)調べる
double ovs=(double)ArrayBsearch(rsi_buff,InpOversoldValue)*100/(double)size;
//— 市場が買われ過ぎの領域にあった期間を(百分率で)調べる
double ovb=(double)(size-ArrayBsearch(rsi_buff,InpOverboughtValue))*100/(double)size;
//— データを表示するための文字列を形成する
string str=“From “+TimeToString(InpDateStart,TIME_DATE)+” to “
+TimeToString(InpDateFinish,TIME_DATE)+” the market was:”;
string str_ovb=“in overbought area “+DoubleToString(ovb,2)+“% of time”;
string str_ovs=“in oversold area “+DoubleToString(ovs,2)+“% of time”;
//— チャートにデータを表示する
CreateLabel(“top”,5,60,str,clrDodgerBlue);
CreateLabel(“overbought”,5,35,str_ovb,clrDodgerBlue);
CreateLabel(“oversold”,5,10,str_ovs,clrDodgerBlue);
//— チャートを再描画する
ChartRedraw(0);
//— 休止する
Sleep(10000);
}
//+——————————————————————+
//| チャートの左下隅にコメントを表示する                                        |
//+——————————————————————+
void CreateLabel(const string name,const int x,const int y,
const string str,const color clr)
{
//— ラベルを作成する
ObjectCreate(0,name,OBJ_LABEL,0,0,0);
//— 左下隅にラベルを結合する
ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_LOWER);
//— アンカーポイントの位置を変更する
ObjectSetInteger(0,name,OBJPROP_ANCHOR,ANCHOR_LEFT_LOWER);
//— X 方向におけるアンカーポイントからの距離
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
//— Y 方向におけるアンカーポイントからの距離
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
//— ラベルテキスト
ObjectSetString(0,name,OBJPROP_TEXT,str);
//— テキストの色
ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
//— テキストサイズ
ObjectSetInteger(0,name,OBJPROP_FONTSIZE,12);
}

ArrayCopy

配列を別の配列に複製します。

int  ArrayCopy(
void&        dst_array[],        // 複製先の配列
const void&  src_array[],        // ソース配列
int          dst_start=0,        // 複製先の配列の開始インデックス
int          src_start=0,        // ソース配列の開始インデックス
int          count=WHOLE_ARRAY   // 要素の数
);

パラメータ

dst_array[]

[out]  複製先の配列。

src_array[]

[in]  ソース配列。

dst_start=0

[in] 複製先の配列の開始インデックス。デフォルトでは、開始インデックスは 0。

src_start=0

[in]  ソース配列の開始インデックス。デフォルトでは、開始インデックスは 0。

count=WHOLE_ARRAY

[in]  複製する必要がある要素数。デフォルトでは配列全体(count=WHOLE_ARRAY)。

戻り値

複製された要素の数

注意事項

count<0 や count>src_size-src_start の場合、配列の全ての残り部分が複製されます。配列は、左から右に複製されます。シリーズ配列の場合、開始位置は左から右のコピーのために調整されて、正確に定義されます。

配列のタイプが異なる場合は、複製中に、複製元配列の各要素の複製先の要素タイプへの変換が試みられます。文字列配列は文字列配列のみに複製することが出来ます。初期化を必要とするオブジェクトを含むクラスと構造の配列は複製されません。構造体の配列は同じ型の配列のみに複製することが出来ます。

時系列をインデックスとする動的配列では(もしデータサイズのほうが大きければ)複製先の配列のサイズが自動的に複製されたデータサイズに合わせて増加されます。複製先の配列のサイズは自動的に減少しません。

例:

#property description “The indicator highlights the candlesticks that are local”
#property description “highs and lows. Interval length for finding”
#property description “extreme values should be found using an input parameters.”
//— 指標の設定
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots   1
//—- プロット
#property indicator_label1 “Extremums”
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1 clrLightSteelBlue,clrRed,clrBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1  1
//— 定義済み定数
#define INDICATOR_EMPTY_VALUE 0.0
//— 入力パラメータ
input int InpNum=4; // 区間の半分の長さ
//— 指標バッファ
double ExtOpen[];
double ExtHigh[];
double ExtLow[];
double ExtClose[];
double ExtColor[];
//— グローバル変数
int    ExtStart=0; // 極値ではない最初のローソク足のインデックス
int    ExtCount=0; // 区間内の非極値の数
//+——————————————————————+
//| 非極値のローソク足に値を入れる                                           |
//+——————————————————————+
void FillCandles(const double &open[],const double &high[],
const double &low[],const double &close[])
{
//— ローソク足に値を入れる  
ArrayCopy(ExtOpen,open,ExtStart,ExtStart,ExtCount);
ArrayCopy(ExtHigh,high,ExtStart,ExtStart,ExtCount);
ArrayCopy(ExtLow,low,ExtStart,ExtStart,ExtCount);
ArrayCopy(ExtClose,close,ExtStart,ExtStart,ExtCount);
}
//+——————————————————————+
//| カスタム指標を初期化する関数                                            |
//+——————————————————————+
int OnInit()
{
//— 指標バッファマッピング
SetIndexBuffer(0,ExtOpen);
SetIndexBuffer(1,ExtHigh);
SetIndexBuffer(2,ExtLow);
SetIndexBuffer(3,ExtClose);
SetIndexBuffer(4,ExtColor,INDICATOR_COLOR_INDEX);
//— 値を指定するが表示しない
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,INDICATOR_EMPTY_VALUE);
//— データウィンドウに表示するために指標バッファの名称を指定する
PlotIndexSetString(0,PLOT_LABEL,“Open;High;Low;Close”);
//—
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[])
{
//— 時系列にストレート索引付けを設定する
ArraySetAsSeries(open,false);
ArraySetAsSeries(high,false);
ArraySetAsSeries(low,false);
ArraySetAsSeries(close,false);
//— バー計算開始の変数
int start=prev_calculated;
//— 最初の InpNum*2 のバーは計算されない
if(start==0)
{
start+=InpNum*2;
ExtStart=0;
ExtCount=0;
}
//— バーがちょうど形成した場合、次の潜在的な極値をチェックする
if(rates_total-start==1)
start–;
//— 極値チェックが行われるバーのインデックス
int ext;
//— 指標算出ループ
for(int i=start;i<rates_total-1;i++)
{
//— 初めは i 番目のバーに指標は描画されない
ExtOpen[i]=0;
ExtHigh[i]=0;
ExtLow[i]=0;
ExtClose[i]=0;
//— チェックする極値インデックス
ext=i-InpNum;
//— 極大をチェック
if(IsMax(high,ext))
{
//— 極値であるローソク足を強調表示する
ExtOpen[ext]=open[ext];
ExtHigh[ext]=high[ext];
ExtLow[ext]=low[ext];
ExtClose[ext]=close[ext];
ExtColor[ext]=1;
//—極値まで他のローソク足を中間色で強調表示する
FillCandles(open,high,low,close);
//— 変数の色を変更
ExtStart=ext+1;
ExtCount=0;
//— 次の反復に渡す
continue;
}
//— 極小をチェック
if(IsMin(low,ext))
{
//— 極値であるローソク足を強調表示する
ExtOpen[ext]=open[ext];
ExtHigh[ext]=high[ext];
ExtLow[ext]=low[ext];
ExtClose[ext]=close[ext];
ExtColor[ext]=2;
//—極値まで他のローソク足を中間色で強調表示する
FillCandles(open,high,low,close);
//— 変数の値を変更
ExtStart=ext+1;
ExtCount=0;
//— 次の反復に渡す
continue;
}
//— 区間内の非極値の数を増やす
ExtCount++;
}
//— 次の呼び出しのために prev_calculated の値を返す
return(rates_total);
}
//+——————————————————————+
//| 現在の配列要素が極大かどうかを確認する                                    |
//+——————————————————————+
bool IsMax(const double &price[],const int ind)
{
//— 区間開始の変数
int i=ind-InpNum;
//— 区間終了期間
int finish=ind+InpNum+1;
//— 区間の前半をチェックする
for(;i<ind;i++)
{
if(price[ind]<=price[i])
return(false);
}
//— 区間の後半をチェックする
for(i=ind+1;i<finish;i++)
{
if(price[ind]<=price[i])
return(false);
}
//— 極値を発見
return(true);
}
//+——————————————————————+
//| 現在の配列要素が極小かどうかを確認する                                    |
//+——————————————————————+
bool IsMin(const double &price[],const int ind)
{
//— 区間開始の変数
int i=ind-InpNum;
//— 区間終了の変数
int finish=ind+InpNum+1;
//— 区間の前半をチェックする
for(;i<ind;i++)
{
if(price[ind]>=price[i])
return(false);
}
//— 区間の後半をチェックする
for(i=ind+1;i<finish;i++)
{
if(price[ind]>=price[i])
return(false);
}
//— 極値を発見
return(true);
}

ArrayCompare

この関数は 2 つの同型の配列を比較した結果を返します。基本データ型 または 複合型オブジェクトを使用しないカスタム構造体、つまり文字列型、動的配列、クラスや他の複合オブジェクトで出来た構造体を含まないカスタム構造体です。

int  ArrayCompare(
const void&  array1[],            // 1番目の配列
const void&  array2[],            // 2 番目の配列
int          start1=0,            // 1番目の配列の初期オフセット
int          start2=0,            // 2 番目の配列の初期オフセット
int         count=WHOLE_ARRAY   // 比較される要素の数
);

パラメータ

array1[]

[in]  1番目の配列

array2[]

[in]  2 番目の配列

start1=0

[in]  比較開始点となる、1番目の配列内の要素の初期インデックス。デフォルトの開始インデックスは0です。

start2=0

[in]  比較開始点となる、2 番目の配列内の要素の初期インデックス。デフォルトの開始インデックスは0です。

count=WHOLE_ARRAY

[in]  比較される要素の数デフォルトでは両方の配列の全ての要素が比較されます(count=WHOLE_ARRAY)。

戻り値

  • -1( array1[] が array2[] より小さい)
  • 0( array1[] とarray2[] が等しい)
  • 1( array1[] が array2[] より大きい)
  • -2(両配列の型の非互換性や start1、start2 または count 値が配列の範囲外にあることによってエラーが発生)

注意事項

配列のサイズが異なり、いずれかの配列がもう 1 つの配列の忠実なサブセットであって、かつ count= WHOLE_ARRAY である場合、0 が返されず、両配列は等しいとみなされません。この場合、両配列のサイズ比較による戻り値は、array1[] のサイズが array2[] のサイズより小さい場合は -1 でそれ以外は1になります。

ArrayFree

動的配列のバッファを開放し、ゼロ次元のサイズを 0 に設定します。

void  ArrayFree(
void&  array[]      // 配列
);

パラメータ

array[]

[in]  動的配列

戻り値

なし

注意事項

全ての使用メモリは一度に解放され、また配列の主な作業は指標/バッファへのアクセスを含むことを考えると、ArrayFree() 関数を使用する必要性はあまり頻繁でありません。バッファサイズは自動的に端末のエグゼクティブサブシステムによって管理されています。

手動でアプリケーションの複雑な動的環境でメモリを管理する必要がある場合には ArrayFree() 関数は、ユーザが明示的に、すぐにすでに不要な動的配列によって占有されていたメモリを解放することを可能にします。

例:

#include <ControlsDialog.mqh>
#include <ControlsButton.mqh>
#include <ControlsLabel.mqh>
#include <ControlsComboBox.mqh>
//— 定義済み定数
#define X_START 0
#define Y_START 0
#define X_SIZE 280
#define Y_SIZE 300
//+——————————————————————+
//| メモリを使用するための Dialog クラス                                       |
//+——————————————————————+
class CMemoryControl : public CAppDialog
{
private:
//— 配列のサイズ
int               m_arr_size;
//— 配列
char              m_arr_char[];
int               m_arr_int[];
float             m_arr_float[];
double            m_arr_double[];
long              m_arr_long[];
//— ラベル
CLabel            m_lbl_memory_physical;
CLabel            m_lbl_memory_total;
CLabel            m_lbl_memory_available;
CLabel            m_lbl_memory_used;
CLabel            m_lbl_array_size;
CLabel            m_lbl_array_type;
CLabel            m_lbl_error;
CLabel            m_lbl_change_type;
CLabel            m_lbl_add_size;
//— ボタン
CButton           m_button_add;
CButton           m_button_free;
//— コンボボックス
CComboBox         m_combo_box_step;
CComboBox         m_combo_box_type;
//— コンボボックスにおける配列型の現在値
int               m_combo_box_type_value;

public:
CMemoryControl(void);
~CMemoryControl(void);
//— クラスオブジェクトの作成方法
virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
//— チャートイベントハンドラ
virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);

protected:
//— ラベルを作成する
bool              CreateLabel(CLabel &lbl,const string name,const int x,const int y,const string str,const int font_size,const int clr);
//— 制御要素を作成する
bool              CreateButton(CButton &button,const string name,const int x,const int y,const string str,const int font_size,const int clr);
bool              CreateComboBoxStep(void);
bool              CreateComboBoxType(void);
//— イベントハンドラ
void              OnClickButtonAdd(void);
void              OnClickButtonFree(void);
void              OnChangeComboBoxType(void);
//— 現在の配列を使用するメソッド
void              CurrentArrayFree(void);
bool              CurrentArrayAdd(void);
};
//+——————————————————————+
//| 現在の配列のメモリを解放する                                             |
//+——————————————————————+
void CMemoryControl::CurrentArrayFree(void)
{
//— 配列サイズをリセットする
m_arr_size=0;
//— 配列を解放する
if(m_combo_box_type_value==0)
ArrayFree(m_arr_char);
if(m_combo_box_type_value==1)
ArrayFree(m_arr_int);
if(m_combo_box_type_value==2)
ArrayFree(m_arr_float);
if(m_combo_box_type_value==3)
ArrayFree(m_arr_double);
if(m_combo_box_type_value==4)
ArrayFree(m_arr_long);
}
//+——————————————————————+
//| 現在の配列へのメモリ追加を試みる                                         |
//+——————————————————————+
bool CMemoryControl::CurrentArrayAdd(void)
{
//— 使用メモリサイズが物理メモリサイズを超えた場合終了する
if(TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL)/TerminalInfoInteger(TERMINAL_MEMORY_USED)<2)
return(false);
//— 現在のタイプに応じてのメモリの割り当てを試みる
if(m_combo_box_type_value==0 && ArrayResize(m_arr_char,m_arr_size)==-1)
return(false);
if(m_combo_box_type_value==1 && ArrayResize(m_arr_int,m_arr_size)==-1)
return(false);
if(m_combo_box_type_value==2 && ArrayResize(m_arr_float,m_arr_size)==-1)
return(false);
if(m_combo_box_type_value==3 && ArrayResize(m_arr_double,m_arr_size)==-1)
return(false);
if(m_combo_box_type_value==4 && ArrayResize(m_arr_long,m_arr_size)==-1)
return(false);
//— メモリ割り当てが成功
return(true);
}
//+——————————————————————+
//| イベントハンドル                                                       |
//+——————————————————————+
EVENT_MAP_BEGIN(CMemoryControl)
ON_EVENT(ON_CLICK,m_button_add,OnClickButtonAdd)
ON_EVENT(ON_CLICK,m_button_free,OnClickButtonFree)
ON_EVENT(ON_CHANGE,m_combo_box_type,OnChangeComboBoxType)
EVENT_MAP_END(CAppDialog)
//+——————————————————————+
//| コンストラクタ                                                         |
//+——————————————————————+
CMemoryControl::CMemoryControl(void)
{
}
//+——————————————————————+
//| デストラクタ                                                          |
//+——————————————————————+
CMemoryControl::~CMemoryControl(void)
{
}
//+——————————————————————+
//| クラスオブジェクトの作成メソッド                                             |
//+——————————————————————+
bool CMemoryControl::Create(const long chart,const string name,const int subwin,
const int x1,const int y1,const int x2,const int y2)
{
//— 基本クラスオブジェクトを作成する
if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
return(false);
ラ//— 文字列をラベル用に準備する
string str_physical=“Memory physical = “+(string)TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL)+” Mb”;
string str_total=“Memory total = “+(string)TerminalInfoInteger(TERMINAL_MEMORY_TOTAL)+” Mb”;
string str_available=“Memory available = “+(string)TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)+” Mb”;
string str_used=“Memory used = “+(string)TerminalInfoInteger(TERMINAL_MEMORY_USED)+” Mb”;
//— ラベルを作成する
if(!CreateLabel(m_lbl_memory_physical,“physical_label”,X_START+10,Y_START+5,str_physical,12,clrBlack))
return(false);
if(!CreateLabel(m_lbl_memory_total,“total_label”,X_START+10,Y_START+30,str_total,12,clrBlack))
return(false);
if(!CreateLabel(m_lbl_memory_available,“available_label”,X_START+10,Y_START+55,str_available,12,clrBlack))
return(false);
if(!CreateLabel(m_lbl_memory_used,“used_label”,X_START+10,Y_START+80,str_used,12,clrBlack))
return(false);
if(!CreateLabel(m_lbl_array_type,“type_label”,X_START+10,Y_START+105,“Array type = double”,12,clrBlack))
return(false);
if(!CreateLabel(m_lbl_array_size,“size_label”,X_START+10,Y_START+130,“Array size = 0”,12,clrBlack))
return(false);
if(!CreateLabel(m_lbl_error,“error_label”,X_START+10,Y_START+155,“”,12,clrRed))
return(false);
if(!CreateLabel(m_lbl_change_type,“change_type_label”,X_START+10,Y_START+185,“Change type”,10,clrBlack))
return(false);
if(!CreateLabel(m_lbl_add_size,“add_size_label”,X_START+10,Y_START+210,“Add to array”,10,clrBlack))
return(false);
//— 制御要素を作成する
if(!CreateButton(m_button_add,“add_button”,X_START+15,Y_START+245,“Add”,12,clrBlue))
return(false);
if(!CreateButton(m_button_free,“free_button”,X_START+75,Y_START+245,“Free”,12,clrBlue))
return(false);
if(!CreateComboBoxType())
return(false);
if(!CreateComboBoxStep())
return(false);
//— 変数を初期化する
m_arr_size=0;
//— 実行成功
return(true);
}
//+——————————————————————+
//| ボタンを作成する                                                      |
//+——————————————————————+
bool CMemoryControl::CreateButton(CButton &button,const string name,const int x,
const int y,const string str,const int font_size,
const int clr)
{
//— ボタンを作成する
if(!button.Create(m_chart_id,name,m_subwin,x,y,x+50,y+20))
return(false);
//— テキスト
if(!button.Text(str))
return(false);
//— フォントサイズ
if(!button.FontSize(font_size))
return(false);
//— ラベルの色
if(!button.Color(clr))
return(false);
//— ボタンを制御要素に加える
if(!Add(button))
return(false);
//— 実行成功
return(true);
}
//+——————————————————————+
//| 配列サイズのコンボボックスを作成する                                        |
//+——————————————————————+
bool CMemoryControl::CreateComboBoxStep(void)
{
//— コンボボックスを作成する
if(!m_combo_box_step.Create(m_chart_id,“step_combobox”,m_subwin,X_START+100,Y_START+185,X_START+200,Y_START+205))
return(false);
//— コンボボックスに要素を加える
if(!m_combo_box_step.ItemAdd(“100 000”,100000))
return(false);
if(!m_combo_box_step.ItemAdd(“1 000 000”,1000000))
return(false);
if(!m_combo_box_step.ItemAdd(“10 000 000”,10000000))
return(false);
if(!m_combo_box_step.ItemAdd(“100 000 000”,100000000))
return(false);
//— 現在のコンボボックス要素を設定する
if(!m_combo_box_step.SelectByValue(1000000))
return(false);
//—コンボボックス制御要素に加える
if(!Add(m_combo_box_step))
return(false);
//— 実行成功
return(true);
}
//+——————————————————————+
//| 配列型コンボボックスを作成する                                            |
//+——————————————————————+
bool CMemoryControl::CreateComboBoxType(void)
{
//— コンボボックスを作成する
if(!m_combo_box_type.Create(m_chart_id,“type_combobox”,m_subwin,X_START+100,Y_START+210,X_START+200,Y_START+230))
return(false);
//— コンボボックスに要素を加える
if(!m_combo_box_type.ItemAdd(“char”,0))
return(false);
if(!m_combo_box_type.ItemAdd(“int”,1))
return(false);
if(!m_combo_box_type.ItemAdd(“float”,2))
return(false);
if(!m_combo_box_type.ItemAdd(“double”,3))
return(false);
if(!m_combo_box_type.ItemAdd(“long”,4))
return(false);
//— 現在のコンボボックス要素を設定する
if(!m_combo_box_type.SelectByValue(3))
return(false);
//— 現在のコンボボックス要素を格納する
m_combo_box_type_value=3;
//—コンボボックス制御要素に加える
if(!Add(m_combo_box_type))
return(false);
//— 実行成功
return(true);
}
//+——————————————————————+
//| ラベルを作成する                                                      |
//+——————————————————————+
bool CMemoryControl::CreateLabel(CLabel &lbl,const string name,const int x,
const int y,const string str,const int font_size,
const int clr)
{
//— ラベルを作成する
if(!lbl.Create(m_chart_id,name,m_subwin,x,y,0,0))
return(false);
//— テキスト
if(!lbl.Text(str))
return(false);
//— フォントサイズ
if(!lbl.FontSize(font_size))
return(false);
//— 色
if(!lbl.Color(clr))
return(false);
//— ラベルを制御要素に加える
if(!Add(lbl))
return(false);
//— 成功
return(true);
}
//+——————————————————————+
//| 「 Add(追加)」 ボタンクリックのイベントハンドラ                       |
//+——————————————————————+
void CMemoryControl::OnClickButtonAdd(void)
{
//—配列サイズを増やす
m_arr_size+=(int)m_combo_box_step.Value();
//— 現在の配列へのメモリ追加を試みる
if(CurrentArrayAdd())
{
//— メモリ割り当て成功し、画面上に現在のステータスを表示する
m_lbl_memory_available.Text(“Memory available = “+(string)TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)+” Mb”);
m_lbl_memory_used.Text(“Memory used = “+(string)TerminalInfoInteger(TERMINAL_MEMORY_USED)+” Mb”);
m_lbl_array_size.Text(“Array size = “+IntegerToString(m_arr_size));
m_lbl_error.Text(“”);
}
else
{
//— メモリ割り当て失敗し、エラーメッセージを表示する
m_lbl_error.Text(“Array is too large, error!”);
//— 以前の配列サイズを返す
m_arr_size-=(int)m_combo_box_step.Value();
}
}
//+——————————————————————+
//| 「 Free(解放)」 ボタンクリックのイベントハンドラ                           |
//+——————————————————————+
void CMemoryControl::OnClickButtonFree(void)
{
//— 現在の配列のメモリを解放する       
CurrentArrayFree();
//— 画面上に現在のステータスを表示する。
m_lbl_memory_available.Text(“Memory available = “+(string)TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)+” Mb”);
m_lbl_memory_used.Text(“Memory used = “+(string)TerminalInfoInteger(TERMINAL_MEMORY_USED)+” Mb”);
m_lbl_array_size.Text(“Array size = 0”);
m_lbl_error.Text(“”);
}
//+——————————————————————+
//| コンボボックス変更のイベントハンドラ                          |
//+——————————————————————+
void CMemoryControl::OnChangeComboBoxType(void)
{
//— 配列系が変わったかをチェックする
if(m_combo_box_type.Value()!=m_combo_box_type_value)
{
//— 現在の配列のメモリを解放する       
OnClickButtonFree();
//— 他のタイプの配列を使用する
m_combo_box_type_value=(int)m_combo_box_type.Value();
//— 新しい配列型を画面上の表示する
if(m_combo_box_type_value==0)
m_lbl_array_type.Text(“Array type = char”);
if(m_combo_box_type_value==1)
m_lbl_array_type.Text(“Array type = int”);
if(m_combo_box_type_value==2)
m_lbl_array_type.Text(“Array type = float”);
if(m_combo_box_type_value==3)
m_lbl_array_type.Text(“Array type = double”);
if(m_combo_box_type_value==4)
m_lbl_array_type.Text(“Array type = long”);
}
}
//— CMemoryControlクラスオブジェクト
CMemoryControl ExtDialog;
//+——————————————————————+
//| エキスパート初期化に使用される関数                                   |
//+——————————————————————+
int OnInit()
{
//— ダイアログを作成する
if(!ExtDialog.Create(0,“MemoryControl”,0,X_START,Y_START,X_SIZE,Y_SIZE))
return(INIT_FAILED);
//— 実行
ExtDialog.Run();
//—
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| エキスパート初期化解除に使用される関数                                 |
//+——————————————————————+
void OnDeinit(const int reason)
{
//—
ExtDialog.Destroy(reason);
}
//+——————————————————————+
//| エキスパートチャートイベント関数                                     |
//+——————————————————————+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
ExtDialog.ChartEvent(id,lparam,dparam,sparam);
}

ArrayGetAsSeries

配列の索引付けの方向をチェックします。

bool  ArrayGetAsSeries(
const void&  array[]   // チェックされる配列
);

パラメータ

array

[in]  チェックされた配列

戻り値

指定された配列にAS_SERIESフラグが設定され、すなわち配列へのアクセスは、時系列のように前後反対に行われる場合 trueを返します。時系列と通常の配列の違いは、時系列のインデックスが後ろから前へ(最新のデータから古いデータへ)つけられていることです。

注意事項

配列が時系列であるかどうかをチェックするには ArrayIsSeries() 関数を使用します。OnCalculate() 関数に入力パラメータとして渡された価格データの配列は時系列と同じインデックス方向を持っていません。必要なインデックス方向は ArraySetAsSeries() 関数を使用して設定出来ます。

例:

#property description “Indicator calculates absolute values of the difference between”
#property description “Open and Close or High and Low prices displaying them in a separate subwindow”
#property description “as a histrogram.”
//— 指標の設定
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//—- プロット
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_style1 STYLE_SOLID
#property indicator_width1  3
//— 入力パラメータ
input bool InpAsSeries=true; // 指標バッファでの索引付けの方向
input bool InpPrices=true;   // 計算価格(true – 始/終、false – 高/低)
//— 指標バッファ
double ExtBuffer[];
//+——————————————————————+
//| 指標値の計算                                                       |
//+——————————————————————+
void CandleSizeOnBuffer(const int rates_total,const int prev_calculated,
const double &first[],const double &second[],double &buffer[])
{
//— バーを計算する start 変数
int start=prev_calculated;
//— 指標値が前のティックで計算されている場合には最後のバーを使用する
if(prev_calculated>0)
start–;
//— 配列の索引付けの方向を定義する
bool as_series_first=ArrayGetAsSeries(first);
bool as_series_second=ArrayGetAsSeries(second);
bool as_series_buffer=ArrayGetAsSeries(buffer);
//— 必要に応じて、索引付け方向を直接なものにする
if(as_series_first)
ArraySetAsSeries(first,false);
if(as_series_second)
ArraySetAsSeries(second,false);
if(as_series_buffer)
ArraySetAsSeries(buffer,false);
//— 指標値を計算する
for(int i=start;i<rates_total;i++)
buffer[i]=MathAbs(first[i]-second[i]);
}
//+——————————————————————+
//| カスタム指標を初期化する関数                                            |
//+——————————————————————+
int OnInit()
{
//— 指標バッファを結合する
SetIndexBuffer(0,ExtBuffer);
//— 指標バッファのインデックス要素を設定する
ArraySetAsSeries(ExtBuffer,InpAsSeries);
//— 指標が計算されている価格をチェックする
if(InpPrices)
{
//— 価格を開け閉めする
PlotIndexSetString(0,PLOT_LABEL,“BodySize”);
//— 指標の色を設定する
PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrOrange);
}
else
{
//— 高値と安値
PlotIndexSetString(0,PLOT_LABEL,“ShadowSize”);
//— 指標の色を設定する
PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrDodgerBlue);
}
//—
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(InpPrices)
CandleSizeOnBuffer(rates_total,prev_calculated,open,close,ExtBuffer);
else
CandleSizeOnBuffer(rates_total,prev_calculated,high,low,ExtBuffer);
//— 次の呼び出しのために prev_calculated の値を返す
return(rates_total);
}

参照

時系列へのアクセス、ArraySetAsSeries

ArrayInitialize

数値配列の全ての要素に同じ値を設定します。

char 型配列の初期化には

int  ArrayInitialize(
char    array[],    // 初期化された配列
char    value        // 初期化に使用される
);

short 型配列の初期化には

int  ArrayInitialize(
short  array[],    // 初期化された配列
short  value        // 初期化に使用される値
);

int 型配列の初期化には

int  ArrayInitialize(
int    array[],    // 初期化された配列
int    value        // 初期化に使用される値
);

long 型配列の初期化には

int  ArrayInitialize(
long    array[],    // 初期化された配列
long    value        // 初期化に使用される値
);

float 型配列の初期化には

int  ArrayInitialize(
float  array[],    // 初期化された配列
float  value        // 初期化に使用される値
);

double 型配列の初期化には

int  ArrayInitialize(
double  array[],    // 初期化された配列
double  value        // 初期化に使用される値
);

bool 型配列の初期化には

int  ArrayInitialize(
bool    array[],    // 初期化された配列
bool    value        // 初期化に使用される値
);

uint 型配列の初期化には

int  ArrayInitialize(
uint    array[],    // 初期化された配列
uint    value        // 初期化に使用される値
);

パラメータ

array[]

[out]  初期化を必要とする数値配列

value

[in]  全ての配列要素に設定する新しい値

戻り値

初期化された要素数

注意事項

ArrayResize() 関数は物理的なメモリの再配置を伴わずに配列のサイズと更なる拡大のための予備を設定することが出来ます。メモリ再配置の操作低速であるために、パフォーマンス向上のために実装されています。

ArrayInitialize(array, init_val) を使用して配列を初期化した場合、予備要素の値はこちらの配列で割り当てられたものとは違います。 ArrayResize() を使用して更に配列が拡大された場合、新しい要素は配列の末尾に追加されます。その値は定義されず通常 init_value とは異なります。

例:

void OnStart()
{
//— 動的配列
double array[];
//— 100 要素の配列のサイズを設定し、別の 10 要素のバッファを確保
ArrayResize(array,100,10);
//— EMPTY_VALUE=DBL_MAX で配列要素を初期化
ArrayInitialize(array,EMPTY_VALUE);
Print(“Values of 10 last elements after initialization”);
for(int i=90;i<100;i++) printf(“array[%d] = %G”,i,array[i]);
//— 5 要素で拡張
ArrayResize(array,105);
Print(“Values of 10 last elements after ArrayResize(array,105)”);
//— 最後の 5 要素の値は予備バッファから取得
for(int i=95;i<105;i++) printf(“array[%d] = %G”,i,array[i]);
}

ArrayFill

この関数は指定された値で配列を埋めます。

void  ArrayFill(
void&  array[],      // 配列
int    start,        // 開始インデックス
int   count,        // 埋める要素の数
void  value          // 値
);

パラメータ

array[]

[out] 基本データ型( char、uchar、short、ushort、int、uint、long、ulong、bool、color、datetime、float、double)の配列

start

[in]  開始インデックス。 この場合、指定された AS_SERIES フラグは無視されます。

count

[in]  埋められる要素の数

value

[in]  配列を埋める値

戻り値

なし

注意事項

ArrayFill() 関数が呼ばれる時は通常のインデックス方向(左から右)が常に暗黙的に指定されます。 ArraySetAsSeries() 関数を使用しての配列要素へのアクセスの順序の変更は無視されるということです。

ArrayFill() 関数によって処理される時には多次元配列は 1 次元として示されています。例えば array[2][4] は array[8] として処理されます。従って、この配列を操作する時初期要素のインデックスを 5 に等しくなるように指定することが出来ます。ArrayFill(array, 5, 2, 3.14) がarray[2][4] に呼ばれたらならば array[1][1] と array[1][2] が 3.14 で埋められます。

例:

void OnStart()
{
//— 動的配列を宣言する
int a[];
//— サイズを定める
ArrayResize(a,10);
//— 最初の 5 要素に 123 を書き込む
ArrayFill(a,0,5,123);
//— 次の 5 要素に 456 を書き込む
ArrayFill(a,5,5,456);
//— 値を表示する
for(int i=0;i<ArraySize(a);i++) printf(“a[%d] = %d”,i,a[i]);
}

ArrayIsDynamic

この関数は配列が動的であるかどうかをチェックします。

bool  ArrayIsDynamic(
const void&  array[]   // チェックされた配列
);

パラメータ

array[]

[in]  チェックされた配列

戻り値

選ばれた配列が動的の場合は true、それ以外の場合は false

例:

#property description “This indicator does not calculate values. It makes a single attempt to”
#property description “apply the call of ArrayFree() function to three arrays: dynamic one, static one and”
#property description “an indicator buffer. Results are shown in Experts journal.”
//— 指標の設定
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//— グローバル変数
double ExtDynamic[];   // 動的配列
double ExtStatic[100]; // 静的配列
bool   ExtFlag=true;   // フラグ
double ExtBuff[];     // 指標バッファ
//+——————————————————————+
//| カスタム指標を初期化する関数                                            |
//+——————————————————————+
int OnInit()
{
//— 配列へのメモリ追加
ArrayResize(ExtDynamic,100);
//— 指標バッファマッピング
SetIndexBuffer(0,ExtBuff);
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
//—
return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| カスタム指標の反復関数                                                |
//+——————————————————————+
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
{
//— 単一の分析を行う
if(ExtFlag)
{
//— メモリ解除を試みる
//— 1. 動的配列
Print(“+============================+”);
Print(“1. Check dynamic array:”);
Print(“Size before memory is freed = “,ArraySize(ExtDynamic));
Print(“Is this a dynamic array = “,ArrayIsDynamic(ExtDynamic) ? “Yes” : “No”);
//— 配列メモリ解除を試みる
ArrayFree(ExtDynamic);
Print(“Size after memory is freed = “,ArraySize(ExtDynamic));
//— 2. 静的配列
Print(“2. Check static array:”);
Print(“Size before memory is freed = “,ArraySize(ExtStatic));
Print(“Is this a dynamic array = “,ArrayIsDynamic(ExtStatic) ? “Yes” : “No”);
//— 配列メモリ解除を試みる
ArrayFree(ExtStatic);
Print(“Size after memory is freed = “,ArraySize(ExtStatic));
//— 3. 指標バッファ
Print(“3. Check indicator buffer:”);
Print(“Size before memory is freed = “,ArraySize(ExtBuff));
Print(“Is this a dynamic array = “,ArrayIsDynamic(ExtBuff) ? “Yes” : “No”);
//— 配列メモリ解除を試みる
ArrayFree(ExtBuff);
Print(“Size after memory is freed = “,ArraySize(ExtBuff));
//— フラグの値を変更する
ExtFlag=false;
}
//— 次の呼び出しのために prev_calculated の値を返す
return(rates_total);
}

参照

時系列と指標へのアクセス

ArrayIsSeries

この関数は配列が時系列であるかどうかをチェックします。

bool  ArrayIsSeries(
const void&  array[]   // チェックされた配列
);

パラメータ

array[]

[in]  チェックされた配列

戻り値

チェックされた配列が時系列の場合は true、それ以外の場合は false を返します。OnCalculate() 関数にパラメータとして渡された配列は ArrayGetAsSeries() によって要素アクセスの順序をチェックしれなければいけません。

例:

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//—- Label1 をプロットする
#property indicator_label1 “Label1”
#property indicator_type1   DRAW_LINE
#property indicator_color1 clrRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1  1
//— 指標バッファ
double         Label1Buffer[];
//+——————————————————————+
//| カスタム指標を初期化する関数                                            |
//+——————————————————————+
void OnInit()
{
//— 指標バッファマッピング
SetIndexBuffer(0,Label1Buffer,INDICATOR_DATA);
//—
}
//+——————————————————————+
//| カスタム指標の反復関数                                                 |
//+——————————————————————+
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(ArrayIsSeries(open))
Print(“open[] is timeseries”);
else
Print(“open[] is not timeseries!!!”);
//— 次の呼び出しのために prev_calculated の値を返す
return(rates_total);
}

参照

時系列と指標へのアクセス

ArrayMaximum

多次元数値配列の初次元で最大の要素を検索します。

int  ArrayMaximum(
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;
}

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;
}

ArrayPrint

単純型または単純な構造体の配列を操作ログに出力します。

void  ArrayPrint(
const void&  array[],            // 出力された配列
uint          digits=_Digits,      // 小数点以下の桁数
const string  separator=NULL,      // 構造体フィールド値のセパレーター
ulong        start=0,            // 最初に出力された要素のインデックス
ulong         count=WHOLE_ARRAY,   // 出力された要素の数
ulong         flags=ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN
);

パラメータ

array[]

[in]  単純型または単純な構造体の配列。

digits=_Digits

[in]  実数型の小数点以下の桁数。デフォルト値は_Digits.。

separator=NULL

[in]  構造体フィールド値のセパレーター。デフォルト値のNULLは空のラインを意味します。この場合スペースが区切り文字として使用されます。

start=0

[in]  最初に出力された配列要素のインデックス。デフォルトではゼロインデックスから出力されます。

count=WHOLE_ARRAY

[in]  出力される配列要素の数。デフォルトでは配列全体が表示されます(count=WHOLE_ARRAY)。

flags=ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN

[in]  出力モードを設定するフラグの組み合わせ。デフォルトではすべてのフラグが有効です。

    • ARRAYPRINT_HEADER – 構造体配列のヘッダを出力します。
    • ARRAYPRINT_INDEX – インデックスを左側に出力します。
    • ARRAYPRINT_LIMIT – 配列の最初の100および最後の100要素のみを出力します。大きな配列の一部だけを出力したい場合に使用します。
    • ARRAYPRINT_ALIGN – 出力された値の位置合わせを可能にします – 数は右、ラインは左整列されます。
    • ARRAYPRINT_DATE – datetimeを出力するときはdd.mm.yyyy形式を使います。
    • ARRAYPRINT_MINUTES – datetimeを出力するときはHH:MM形式を使います。
    • ARRAYPRINT_SECONDS – datetimeを出力するときはHH:MM:SS形式を使います。

戻り値

いいえ

注意事項

ArrayPrint() は構造体配列のフィールドを操作ログに出力するものではありません。配列とオブジェクトポインタフィールドは抜かされます。これらの列は、単により便利なプレゼンテーションのために出力されません。すべての構造体のフィールドを出力する必要がある場合は、希望の書式を使用して独自のマス出力関数を記述する必要があります。

例:

//— 最後の10バーの値を出力する
MqlRates rates[];
if(CopyRates(_Symbol,_Period,1,10,rates))
{
ArrayPrint(rates);
Print(“Checkn[time]t[open]t[high]t[low]t[close]t[tick_volume]t[spread]t[real_volume]”);
for(int i=0;i<10;i++)
{
PrintFormat(“[%d]t%st%Gt%Gt%Gt%Gt%Gt%Gt%I64dt”,i,
TimeToString(rates[i].time,TIME_DATE|TIME_MINUTES|TIME_SECONDS),
rates[i].open,rates[i].high,rates[i].low,rates[i].close,
rates[i].tick_volume,rates[i].spread,rates[i].real_volume);
}
}
else
PrintFormat(“CopyRates failed, error code=%d”,GetLastError());
//— 出力例
/*
[time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
[0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295         18110       10   17300175000
[1] 2016.11.09 05:00:00 1.12296 1.12825 1.11930 1.12747         17829        9   15632176000
[2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744         13458       10    9593492000
[3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194         15362        9   12352245000
[4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172         16833        9   12961333000
[5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052         15933        8   10720384000
[6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528         11888        9    8084811000
[7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915          7284       10    5087113000
[8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904          8710        9    6769629000
[9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263          8956        7    7192138000
確認
[time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume]
[0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295 18110 10 17300175000
[1] 2016.11.09 05:00:00 1.12296 1.12825 1.1193 1.12747 17829 9 15632176000
[2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744 13458 10 9593492000
[3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194 15362 9 12352245000
[4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172 16833 9 12961333000
[5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052 15933 8 10720384000
[6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528 11888 9 8084811000
[7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915 7284 10 5087113000
[8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904 8710 9 6769629000
[9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263 8956 7 7192138000
*/

参照

FileSave、FileLoad

ArrayRange

この関数は配列の指定された次元の要素数を返します。

int  ArrayRange(
const void&   array[],      // チェックされる配列
int          rank_index    // 次元のインデックス
);

パラメータ

array[]

[in]  チェックされた配列

rank_index

[in]  次元のインデックス

戻り値

配列の指定された次元の要素数

注意事項

インデックスは 0 から始まるので、配列の次元の数は最後の次元のインデックスより 1 大きいです。

例:

void OnStart()
{
//— 4 次元配列を作成する
double array[][5][2][4];
//— 0 次元のサイズを設定する
ArrayResize(array,10,10);
//—次元をプリントする
int temp;
for(int i=0;i<4;i++)
{
//— i 次元のサイズを受け取る
temp=ArrayRange(array,i);
//— プリント
PrintFormat(“dim = %d, range = %d”,i,temp);
}
//— 結果
// dim = 0, range = 10
// dim = 1, range = 5
// dim = 2, range = 2
// dim = 3, range = 4
}

ArrayResize

この関数は最初の次元のサイズを新しく設定します。

int  ArrayResize(
void&  array[],              // 参照によって渡された配列
int    new_size,            // 新しい配列サイズ
int    reserve_size=0        // 予備サイズの値(超過)
);

パラメータ

array[]

[out] サイズを変更する配列

new_size

[in]  最初の次元の新しいサイズ

reserve_size=0

[in]  予備を取得するための分散サイズ

戻り値

正常に実行された場合はサイズ変更後の配列に含まれる全ての要素の数を返します。それ以外の場合は、-1を返し、配列のサイズは変更されません。

ArrayResize()が静的配列、時系列または指標バッファに適応された場合、配列サイズは同じままです。これらの配列は再割り当てされません。この場合new_size<=ArraySize(array)であれば、この関数はnew_sizeのみを返します。その他の場合は -1が返されます。

注意事項

この関数は 動的配列のみに使用出来ます。SetIndexBuffer() 関数によって指標バッファとして割り当てられた動的配列のサイズは変更出来ないので注意が必要です。指標バッファについては、サイズ変更の全ての操作は端末のランタイムサブシステムによって実行されます。

配列の要素数の合計は 2,147,483,647を超えることは出来ません。

頻繁なメモリ割り当てをする場合には、物理メモリの割り当て量を減らすために予備を設定する 3 番目のパラメータを使用することをお勧めします。ArrayResize の後続の呼び出しはメモリの物理的な再配分にはつながらず、確保したメモリ内の最初の配列の次元のサイズを変更するだけです。3 番目のパラメータは物理メモリの割り当て時にのみ使用されることを忘れてはいけません。例:

ArrayResize(arr,1000,1000);
for(int i=1;i<3000;i++)
ArrayResize(arr,i,1000);

この場合、メモリは2 回再割り当てされます。1 回目は3000要素のループに入る前(配列のサイズを1000に設定されます)で2 回目は i が 2000の時です。3 番目のパラメータを省略した場合は、メモリの物理的な再配分が2000回起こりプログラムの実行がを遅くなります。

例:

//+——————————————————————+
//| スクリプトプログラムを開始する関数                                          |
//+——————————————————————+
void OnStart()
{
//—カウンタ
ulong start=GetTickCount();
ulong now;
int   count=0;
//— 迅速なバージョンのデモ配列
double arr[];
ArrayResize(arr,100000,100000);
//— 予備メモリを使用したバージョンがどんなに迅速かをチェックする
Print(“— Test Fast: ArrayResize(arr,100000,100000)”);
for(int i=1;i<=300000;i++)
{
//— 100,000 予備要素を指定して新しい配列サイズを設定する。
ArrayResize(arr,i,100000);
//— ラウンド数に達した時、配列のサイズとかかった時間を表示する
if(ArraySize(arr)%100000==0)
{
now=GetTickCount();
count++;
PrintFormat(“%d. ArraySize(arr)=%d Time=%d ms”,count,ArraySize(arr),(now-start));
start=now;
}
}
//— 予備メモリを使用したバージョンがどんなに低速かを見る
double slow[];
ArrayResize(slow,100000,100000);
//—
count=0;
start=GetTickCount();
Print(“—- Test Slow: ArrayResize(slow,100000)”);
//—
for(int i=1;i<=300000;i++)
{
//— 新しい配列サイズを設定するが予備を使用しない
ArrayResize(slow,i);
//— ラウンド数に達した時、配列のサイズとかかった時間を表示する
if(ArraySize(slow)%100000==0)
{
now=GetTickCount();
count++;
PrintFormat(“%d. ArraySize(slow)=%d Time=%d ms”,count,ArraySize(slow),(now-start));
start=now;
}
}
}
//— スクリプトのサンプル結果
/*
Test_ArrayResize (EURUSD,H1)   — Test Fast: ArrayResize(arr,100000,100000)
Test_ArrayResize (EURUSD,H1)   1. ArraySize(arr)=100000 Time=0 ms
Test_ArrayResize (EURUSD,H1)   2. ArraySize(arr)=200000 Time=0 ms
Test_ArrayResize (EURUSD,H1)   3. ArraySize(arr)=300000 Time=0 ms
Test_ArrayResize (EURUSD,H1)   —- Test Slow: ArrayResize(slow,100000)
Test_ArrayResize (EURUSD,H1)   1. ArraySize(slow)=100000 Time=0 ms
Test_ArrayResize (EURUSD,H1)   2. ArraySize(slow)=200000 Time=0 ms
Test_ArrayResize (EURUSD,H1)   3. ArraySize(slow)=300000 Time=228511 ms
*/

参照

ArrayInitialize

ArrayInsert

指定されたインデックスから開始して、指定された数の要素をソース配列からターゲット配列に挿入します。

bool  ArrayInsert(
void&        dst_array[],          // 挿入先の配列
const void&  src_array[],          // 挿入元の配列
uint        dst_start,            // 挿入先の配列に挿入されるインデックス
uint        src_start=0,         // 挿入元の配列でコピーするインデックス
uint        count=WHOLE_ARRAY     // 挿入する要素数
);

パラメータ

dst_array[]

[in][out]  追加先の配列

src_array[]

[in]  追加元の配列

dst_start

[in]  ソース配列から要素を挿入するためのターゲット側配列内のインデックス

src_start=0

[in] 開始位置からソース配列の要素が挿入のために取得される、ターゲット配列のインデックス。

count

[in]  ソース配列から追加される要素数。WHOLE_ARRAYは指定されたインデックスから配列の最後までのすべての要素を意味します。

戻り値

成功の場合はtrue、それ以外の場合はfalse. エラー情報を取得するには、GetLastError() 関数が呼ばれます。可能なエラーは下記です。

  • 5052 – ERR_SMALL_ARRAY(startおよび/またはcount パラメータは間違って設定されている、またはsrc_array[]ソース配列が空である)
  • 5056 – ERR_SERIES_ARRAY(配列が変更不可能、指標バッファ)
  • 4006 – ERR_INVALID_ARRAY(自分自身へのコピーは許可されていない、配列の型が異なる、または、クラスオブジェクトまたはデストラクタ構造体を含む固定サイズの配列がある)
  • 4005 – ERR_STRUCT_WITHOBJECTS_ORCLASS(配列にPOD構造体が含まれていないため、シンプルなコピーが不可能)。
  • 配列サイズArrayRemove()関数の説明にあるターゲット配列サイズであるdst_array[]を変更するときにエラーが発生しました。

 

注意事項

この関数が固定サイズの配列に使用されている場合、ターゲット側の dst_array[]配列自体のサイズは変わりません。Starting from the dst_start位置から初めて、ターゲット配列の要素は右にシフトされます。最後のcounts要素は失われ、ソース配列からコピーされた要素がとってかわります。

SetIndexBuffer()関数で指標バッファとして指定された動的配列に要素を挿入することはできません。指標バッファの場合、すべてのサイズ変更操作は端末の実行サブシステムによって実行されます。

ソース配列では、要素はsrc_start指数から始めてコピーされます。ソース配列サイズは変更されません。ターゲット配列に追加される要素は、ソース配列要素へのリンクではありません。つまり、要素が後に2つの配列のいずれかで変更されると、あと一つの配列には反映されません。

例:

//+——————————————————————+
//| スクリプトプログラムを開始する関数                                          |
//+——————————————————————+
void OnStart()
{
//— 固定サイズの配列を宣言し、値を埋める
int array_dest[10];
for(int i=0;i<10;i++)
{
array_dest[i]=i;
}
//— ソース配列
int array_source[10];
for(int i=0;i<10;i++)
{
array_source[i]=10+i;
}
//— 要素を挿入する前に配列を表示する
Print(“Before calling ArrayInsert()”);
ArrayPrint(array_dest);
ArrayPrint(array_source);
//— ソース配列の3つの要素をターゲット配列に挿入して新しいターゲット配列を表示する
ArrayInsert(array_dest,array_source,4,0,3);
Print(“After calling ArrayInsert()”);
ArrayPrint(array_dest);
/*
実行結果
ArrayInsert()呼び出し前
0 1 2 3 4 5 6 7 8 9
ArrayInsert()呼び出し後
0 1 2 3 10 11 12 7 8 9
*/

参照

ArrayRemove、 ArrayCopy、ArrayResize、 ArrayFree

 

ArrayRemove

指定されたインデックスから開始して、配列内の指定された数の要素を削除します。

bool  ArrayRemove(
void&        array[],            // 任意の型の配列
uint        start,              // 削除開始インデックス
uint        count=WHOLE_ARRAY  // 要素数
);

パラメータ

array[]

[in][out]  配列

start

[in] 配列要素の削除を始めるインデックス

count=WHOLE_ARRAY

[in] 削除される要素の数。WHOLE_ARRAYは指定されたインデックスから配列の最後までのすべての要素を意味します。

戻り値

成功の場合はtrue、それ以外の場合はfalse. エラー情報を取得するには、GetLastError() 関数が呼ばれます。可能なエラーは下記です。

  • 5052 – ERR_SMALL_ARRAY(start値が大き過ぎる)
  • 5056 – ERR_SERIES_ARRAY(配列が変更不可能、指標バッファ)
  • 4003 – ERR_INVALID_PARAMETER(count値が大き過ぎる)
  • 4005 – ERR_STRUCT_WITHOBJECTS_ORCLASS(デストラクタを持つ複雑なオブジェクトを含む固定サイズの配列)
  • 4006 – ERR_INVALID_ARRAY(デストラクタを持つオブジェクトまたはクラスオブジェクトを含む固定サイズの配列)

 

注意事項

この関数が固定サイズの配列に使用されている場合、配列サイズは変わりません。残りの「tail」が物理的にstartポジションにコピーされます。関数がどのように機能するかを正確に理解するには、以下の例を参照してください。「物理的」コピーとは、コピーされたオブジェクトがコンストラクタまたはコピー演算子の呼び出しによっては作成されないことを意味します。代わりに、オブジェクトのバイナリ表現がコピーされます。このため、デストラクタを使用してArrayRemove()関数をオブジェクトを含む固定サイズの配列に適用することはできません(ERR_INVALID_ARRAYまたはERR_STRUCT_WITHOBJECTS_ORCLASSエラーが発生しています)。このようなオブジェクトを削除するときは、元のオブジェクトとそのコピーに対して、デストラクタを2回呼び出す必要があります。

SetIndexBuffer()関数で指標バッファとして指定された動的配列から要素を削除することはできません。これにより、ERR_SERIES_ARRAYエラーが発生します。指標バッファの場合、すべてのサイズ変更操作は端末の実行サブシステムによって実行されます。

例:

//+——————————————————————+
//| スクリプトプログラムを開始する関数                                          |
//+——————————————————————+
void OnStart()
{
//— 固定サイズの配列を宣言し、値を埋める
int array[10];
for(int i=0;i<10;i++)
{
array[i]=i;
}
//— 要素を削除する前に配列を表示する
Print(“Before calling ArrayRemove()”);
ArrayPrint(array);
//— 配列から2つの要素を削除してあたらしい集合を表示する
ArrayRemove(array,4,2);
Print(“After calling ArrayRemove()”);
ArrayPrint(array);
/*
実行結果:
ArrayRemove()呼び出し前
0 1 2 3 4 5 6 7 8 9
ArrayRemove()呼び出し後
0 1 2 3 6 7 8 9 8 9
*/

参照

ArrayInsert、 ArrayCopy、ArrayResize、 ArrayFree

 

ArrayReverse

指定されたインデックスから開始して、配列内の指定された数の要素を反転します。

bool  ArrayReverse(
void&        array[],            // 任意の型の配列
uint        start=0,           // 配列反転開始インデックス
uint        count=WHOLE_ARRAY  // 要素数
);

パラメータ

array[]

[in][out]  配列

start=0

[in] 反転を開始する配列のインデックス

count=WHOLE_ARRAY

[in] 反転される要素の数。WHOLE_ARRAYの場合、指定されたstartインデックスから配列の最後の要素までの位置が反転されます。

戻り値

成功の場合はtrue、それ以外の場合はfalse

注意事項

ArraySetAsSeries()関数は物理的に配列要素を移動するものではありません。代わりに、要素へのアクセスを時系列同様に変更するために、インデックスの方向を逆方向に変更するだけです。ArrayReverse()関数は、配列が「反転」されるように物理的に配列要素を移動します。

例:

//+——————————————————————+
//| スクリプトプログラムを開始する関数                                          |
//+——————————————————————+
void OnStart()
{
//— 固定サイズの配列を宣言し、値を埋める
int array[10];
for(int i=0;i<10;i++)
{
array[i]=i;
}
//— 配列を反転する前に配列を表示する
Print(“Before calling ArrayReverse()”);
ArrayPrint(array);
//— 配列内の3つの要素を反転して新しい集合を表示する
ArrayReverse(array,4,3);
Print(“After calling ArrayReverse()”);
ArrayPrint(array);
/*
実行結果:
ArrayReverse()呼び出し前
0 1 2 3 4 5 6 7 8 9
ArrayReverse()呼び出し後
0 1 2 3 6 5 4 7 8 9
*/

参照

ArrayInsert、ArrayRemove、ArrayCopy、 ArrayResize、ArrayFree、 ArrayGetAsSeries、ArraySetAsSeries

 

ArraySetAsSeries

この関数は選択された 動的配列オブジェクトに AS_SERIES フラグを設定し 時系列のように索引付けをします。

bool  ArraySetAsSeries(
const void&  array[],   // 参照配列
bool        flag        // true はインデックスの順番が反対であることを示す
);

パラメータ

array[]

[in][out]  設定される数値配列

flag

[in]  索引付けの方向

戻り値

成功の場合は true、それ以外の場合は false

注意事項

AS_SERIES フラグは 多次元配列または静的配列(サイズがコンパイル段階ですでに角括弧で定義される配列)には設定することが出来ません。時系列と通常の配列の違いは、時系列のインデックスが後ろから前へ(最新のデータから古いデータへ)つけられていることです。

例:バー番号を表示する指標

バー番号を表示する指標

 

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//—- プロット記数
#property indicator_label1 “Numeration”
#property indicator_type1   DRAW_LINE
#property indicator_color1 CLR_NONE
//— 指標バッファ
double         NumerationBuffer[];
//+——————————————————————+
//| カスタム指標を初期化する関数                                            |
//+——————————————————————+
int OnInit()
{
//— 指標バッファマッピング
SetIndexBuffer(0,NumerationBuffer,INDICATOR_DATA);
//— バッファのインデックスを時系列式に付ける
ArraySetAsSeries(NumerationBuffer,true);
//— データウィンドウに表示する精度を設定する
  IndicatorSetInteger(INDICATOR_DIGITS,0);
//— 指標配列の名称の データウィンドウでの表示の仕方
  PlotIndexSetString(0,PLOT_LABEL,“Bar #”);
//—
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[])
{
//—  現在のゼロバー開口部の時間を保存する
static datetime currentBarTimeOpen=0;
//— time[] 配列へのアクセスを元に返す – 時系列のようにアクセスする
ArraySetAsSeries(time,true);
//— ゼロバーの時間が格納されているものと異なる場合
if(currentBarTimeOpen!=time[0])
{
//— 現在からチャートの深さまで全てのバーを列挙する
for(int i=rates_total-1;i>=0;i–) NumerationBuffer[i]=i;
currentBarTimeOpen=time[0];
}
//— 次の呼び出しのために prev_calculated の値を返す
return(rates_total);
}

参照

時系列へのアクセス、ArrayGetAsSeries

ArraySize

この関数は配列の要素数を返します。

int  ArraySize(
const void&  array[]   // チェックされた配列
);

パラメータ

array[]

[in]  任意型の配列

戻り値

int 型の値

注意事項

1次元配列の場合 ArraySize の返す値は ArrayRange(array,0) の返す値と等しいです。

例:

void OnStart()
{
//— 配列を作成する
double one_dim[];
double four_dim[][10][5][2];
//— サイズ
int one_dim_size=25;
int reserve=20;
int four_dim_size=5;
//— 補助変数
int size;
//— バックアップせずにメモリを割り当てる
ArrayResize(one_dim,one_dim_size);
ArrayResize(four_dim,four_dim_size);
//— 1. 1 次元配列
Print(“+==========================================================+”);
Print(“Array sizes:”);
Print(“1. One-dimensional array”);
size=ArraySize(one_dim);
PrintFormat(“Zero dimension size = %d, Array size = %d”,one_dim_size,size);
//— 2. 多次元配列
Print(“2. Multidimensional array”);
size=ArraySize(four_dim);
PrintFormat(“Zero dimension size = %d, Array size = %d”,four_dim_size,size);
//— 次元サイズ
int d_1=ArrayRange(four_dim,1);
int d_2=ArrayRange(four_dim,2);
int d_3=ArrayRange(four_dim,3);
Print(“Check:”);
Print(“Zero dimension = Array size / (First dimension * Second dimension * Third dimension)”);
PrintFormat(“%d = %d / (%d * %d * %d)”,size/(d_1*d_2*d_3),size,d_1,d_2,d_3);
//— 3. メモリバックアップと 1 次元配列
Print(“3. One-dimensional array with memory backup”);
//— 値を倍増する
one_dim_size*=2;
//— メモリを割り当ててバックアップする
ArrayResize(one_dim,one_dim_size,reserve);
//— サイズをプリントする
size=ArraySize(one_dim);
PrintFormat(“Size with backup = %d, Actual array size = %d”,one_dim_size+reserve,size);
}

ArraySort

多次元数値配列の初次元の値を昇順にソートします。

bool  ArraySort(
void&  array[]      // ソートする配列
);

パラメータ

array[]

[in][out]  ソートする数値配列

戻り値

成功の場合は true、それ以外の場合は false

注意事項

配列は AS_SERIES フラグ値に関係なく昇順にソートされます。

ArraySort と ArrayBSearch 関数はパラメータとして、任意の次元の配列を受け入れます。しかし、検索ソートは常に最初(ゼロ)の次元に適用されます。

例:

#property description “The indicator analyzes data for the last month and draws all candlesticks with small”
#property description “and large tick volumes. The tick volume array is sorted out”
#property description “to define such candlesticks. The candlesticks having the volumes comprising the first InpSmallVolume”
#property description “per cent of the array are considered small. The candlesticks having the tick volumes comprising “
#property description “the last InpBigVolume per cent of the array are considered large.”
//— 指標の設定
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots   1
//— プロット
#property indicator_label1 “VolumeFactor”
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1 clrDodgerBlue,clrOrange
#property indicator_style1 STYLE_SOLID
#property indicator_width1  2
//— 定義済み定数
#define INDICATOR_EMPTY_VALUE 0.0
//— 入力パラメータ
input int InpSmallVolume=15; // 小ボリューム( <50 )の百分率値
input int InpBigVolume=20;   // 大ボリューム( <50 )の百分率値
//— 分析開始時間 (移動される)
datetime ExtStartTime;
//— 指標バッファ
double   ExtOpenBuff[];
double   ExtHighBuff[];
double   ExtLowBuff[];
double   ExtCloseBuff[];
double   ExtColorBuff[];
//— ローソク足を表示するためのボリュームの境界値
long     ExtLeftBorder=0;
long     ExtRightBorder=0;
//+——————————————————————+
//| ティックボリュームの境界値を受け取る                                        |
//+——————————————————————+
bool GetVolumeBorders(void)
{
//— 変数
datetime stop_time; // 終了時刻を複製する
long     buff[];     // 複製に使用するバッファ
//— 終了時刻が現在の時刻
stop_time=TimeCurrent();
//— start time は現在時間より1か月前である
ExtStartTime=GetStartTime(stop_time);
//— ティックボリュームの値を受け取る
ResetLastError();
if(CopyTickVolume(Symbol(),Period(),ExtStartTime,stop_time,buff)==-1)
{
//— データの受信に失敗し、再計算コマンドを起動するために false を返す
PrintFormat(“Failed to receive tick volume values. Error code = %d”,GetLastError());
return(false);
}
//— 配列サイズを計算する
int size=ArraySize(buff);
//— 配列をソートする
ArraySort(buff);
//— ティックボリュームの左と右の境界線の値を定義する
ExtLeftBorder=buff[size*InpSmallVolume/100];
ExtRightBorder=buff[(size-1)*(100-InpBigVolume)/100];
//— 実行成功
return(true);
}
//+——————————————————————+
//| 渡されたものよりも1ヶ月前のデータを受け取る                                  |
//+——————————————————————+
datetime GetStartTime(const datetime stop_time)
{
//— 終了時間を MqlDateTime 型構造変数に変換する
MqlDateTime temp;
TimeToStruct(stop_time,temp);
//— 1ヶ月前のデータを受け取る
if(temp.mon>1)
temp.mon-=1; // 現在の月が 1 月ではないので、前月の数が 1 小さい
else
{
temp.mon=12; // 現在の月が 1 月なので、前月の数は 12
temp.year-=1; // 年番号が 1 少ないうち
}
//— 日数は 28 を超えない
if(temp.day>28)
temp.day=28;
//— 取得された日付を返す
return(StructToTime(temp));
}
//+——————————————————————+
//| カスタム指標を初期化する関数                                            |
//+——————————————————————+
int OnInit()
{
//— 入力パラメータが条件を満たしているかどうかを確認する
if(InpSmallVolume<0 || InpSmallVolume>=50 || InpBigVolume<0 || InpBigVolume>=50)
{
Print(“Incorrect input parameters”);
return(INIT_PARAMETERS_INCORRECT);
}
//— 指標バッファマッピング
SetIndexBuffer(0,ExtOpenBuff);
SetIndexBuffer(1,ExtHighBuff);
SetIndexBuffer(2,ExtLowBuff);
SetIndexBuffer(3,ExtCloseBuff);
SetIndexBuffer(4,ExtColorBuff,INDICATOR_COLOR_INDEX);
//— 表示されない値を設定する
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,INDICATOR_EMPTY_VALUE);
//— 指標バッファのラベルを設定する
PlotIndexSetString(0,PLOT_LABEL,“Open;High;Low;Close”);
//—
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<rates_total)
{
//— ボリュームの左右の境界線の新しい値を受け取る
if(!GetVolumeBorders())
return(0);
}
//— バーの計算に使用されるstart 変数
int start=prev_calculated;
//— 指標値が前のティックで計算されている場合には最後のバーを使用する
if(start>0)
start–;
//— 時系列に直接のインデックス作成を設定する
ArraySetAsSeries(time,false);
ArraySetAsSeries(open,false);
ArraySetAsSeries(high,false);
ArraySetAsSeries(low,false);
ArraySetAsSeries(close,false);
ArraySetAsSeries(tick_volume,false);
//— 指標値の計算ループ
for(int i=start;i<rates_total;i++)
{
//— 最初の日からローソク足に必要事項を記入する
if(ExtStartTime<=time[i])
{
//— 値が右の境界以上であれば、ローソク足に必要事項を記入する
if(tick_volume[i]>=ExtRightBorder)
{
//— ローソク足を描画するためのデータを受信する
ExtOpenBuff[i]=open[i];
ExtHighBuff[i]=high[i];
ExtLowBuff[i]=low[i];
ExtCloseBuff[i]=close[i];
//— DodgerBlue 色
ExtColorBuff[i]=0;
//— ループを続行する
continue;
}
//— 値が左の境界線を超えていない場合にはローソク足に必要事項を記入する
if(tick_volume[i]<=ExtLeftBorder)
{
//— ローソク足を描画するためのデータを受信する
ExtOpenBuff[i]=open[i];
ExtHighBuff[i]=high[i];
ExtLowBuff[i]=low[i];
ExtCloseBuff[i]=close[i];
//— 橙色
ExtColorBuff[i]=1;
//— ループを続行する
continue;
}
}
//— 計算に含まれていないバーの空の値を設定する
ExtOpenBuff[i]=INDICATOR_EMPTY_VALUE;
ExtHighBuff[i]=INDICATOR_EMPTY_VALUE;
ExtLowBuff[i]=INDICATOR_EMPTY_VALUE;
ExtCloseBuff[i]=INDICATOR_EMPTY_VALUE;
}
//— 次の呼び出しのために prev_calculated の値を返す
return(rates_total);
}

参照

ArrayBsearch

ArraySwap

同じ型の2つの動的配列の内容を交換します。多次元配列の場合、最初の次元を除くすべての次元の要素の数は一致する必要があります。

bool  ArraySwap(
void&  array1[],      // 1番目の配列
void&  array2[]       // 2番目の配列</
);

パラメータ

array1[]

[in][out]  数値型配列

array2[]

[in][out]  数値型配列

戻り値

成功の場合はtrue、それ以外の場合はfalse 。この場合、GetLastError()はエラーコードERR_INVALID_ARRAYを返します。

注意事項

この関数は、最初のものを除いて、同じ型および同じ次元の動的配列を受け入れます。整数型の場合、符号は無視されます(char==uchar)。

例:

//+——————————————————————+
//| スクリプトプログラムを開始する関数                                          |
//+——————————————————————+
void OnStart()
{
//— 相場を格納する配列
double source_array[][8];
double   dest_array[][8];
MqlRates rates[];
//— 現在の時間枠で最後の20本のローソク足のデータを取得する
int copied=CopyRates(NULL,0,0,20,rates);
if(copied<=0)
{
PrintFormat(“CopyRates(%s,0,0,20,rates) failed, error=%d”,
Symbol(),GetLastError());
return;
}
//— コピーされたデータ量の配列サイズを設定する
ArrayResize(source_array,copied);
//— rate_array_1[]配列にrates[]のデータを書き入れる
for(int i=0;i<copied;i++)
{
source_array[i][0]=(double)rates[i].time;
source_array[i][1]=rates[i].open;
source_array[i][2]=rates[i].high;
source_array[i][3]=rates[i].low;
source_array[i][4]=rates[i].close;
source_array[i][5]=(double)rates[i].tick_volume;
source_array[i][6]=(double)rates[i].spread;
source_array[i][7]=(double)rates[i].real_volume;
}
//— source_array[]とdest_array[]のデータを互いに取り替える
if(!ArraySwap(source_array,dest_array))
{
PrintFormat(“ArraySwap(source_array,rate_array_2) failed, error code=%d”,GetLastError());
return;
}
//— スワップ後にソース配列が0になっていることを確認する
PrintFormat(“ArraySwap() done: ArraySize(source_array)=%d”,ArraySize(source_array));
//— dest_array []出力先配列のデータを表示する
ArrayPrint(dest_array);
}

参照

ArrayCopy、ArrayFill、ArrayRange、ArrayIsDynamic

Originally posted 2019-07-29 23:01:28.

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">