【超入門】MQL5 EA講座 第83回「ポジション情報管理クラスを作る-その2」【MT5用EAの作り方】

MQL5でEA作ろう講座

前回は、新たにOriginalCPositionsというクラスを宣言し、アクセスレベルprotected,publicそれぞれのメンバ変数・メンバ関数も併せて宣言しました。そしてアクセスレベルprotectedカテゴリーの関数である、GetPosInfo関数の処理実装記述について解説しました。

GetPosInfo関数は、必要なポジション情報を、これから作っていくpublicカテゴリーの関数に受け渡す処理を担う内部関数となります

GetPosInfo関数の処理記述内には、ChangeArraySize関数という、アクセスレベルprotected関数が使われていますが、ChangeArraySize関数は前回の時点ではまだ宣言しただけで、処理実装記述は完了していません。

今回はまずChangeArraySize関数の処理実装記述から行っていきたいと思います。

スポンサーリンク

ChangeArraySize関数について

ChangeArraySize関数は、ポジション情報が格納された配列の、配列サイズ変更を担う内部関数となります。

アクセスレベル=protectedとなっています。

ChangeArraySize関数の戻り値と引数構成

ChangeArraySize関数戻り値引数構成は、以下の通りです。

int OriginalCPositions::ChangeArraySize(ulong &parArray[])

引数のparArray[]にはポジション番号情報を格納する配列が記述される想定です。

戻り値int型なのは、配列「parArray」のインデックスを返す想定だからです。

ChangeArraySize関数の処理実装記述

//配列サイズを変更し、配列インデックスを返す関数
int OriginalCPositions::ChangeArraySize(ulong &parArray[])
{
  //配列の新しいサイズを計算
  int newSize = ArraySize(parArray) + 1;
  
//リサイズに失敗した場合に、ログ出力する
  if(ArrayResize(parArray, newSize) == -1)
    {
     //リサイズに失敗した場合のエラーハンドリング
     Print("配列のリサイズに失敗しました.");
     return -1; // 適切なエラーコードを返す
    }
  //配列の最後のインデックスを計算
  int arrayIndex = newSize - 1;

  //変数「arrayIndex」の値を戻り値として返す
  return arrayIndex;
}

ChangeArraySize関数の処理実装記述は以下の通りです。

一つ一つ順を追って見ていきましょう

新しい配列サイズを格納する変数「newSize」を宣言

//配列の新しいサイズを計算
  int newSize = ArraySize(parArray) + 1;

新しい配列サイズを格納する変数「newSize」を宣言します。「newSize」に代入する値ですが、ArraySize関数は指定した配列のサイズ数を戻り値として返す関数です(後程詳しく説明します)

従って、来るべき新しいポジション情報を格納するサイズ数にはそれに+1した値を代入させます。

配列のリサイズに失敗した場合に、ログ出力する記述を行う

続いて配列のリサイズに失敗した場合に、ログ出力する記述を行います。

//リサイズに失敗した場合に、ログ出力する
  if(ArrayResize(parArray, newSize) == -1)
    {
     //リサイズに失敗した場合のエラーハンドリング
     Print("配列のリサイズに失敗しました.");
     return -1; // 適切なエラーコードを返す
    }

ArrayResize関数戻り値は、配列の新しいサイズを返しますが、これは必ずしも配列の最後のイインデックスと一致するとは限りません。配列の最後のインデックスArraySize(parArray) - 1 です。しかし、ArrayResize関数の処理がが失敗した場合(例えば、メモリが不足している場合)は-1を返すため、この戻り値をそのままインデックスとして使用すると問題が生じる可能性があります。

従って、その場合、-1を返して、エラーが発生した旨をログ出力した上で関数処理を終了させる記述を入れます。

ArraySize関数について

ArraySize関数引数に指定した配列要素数、つまり「配列の長さ」を返す関数です。

配列とは言い換えれば、「変数という箱が連なったもの」です。ArraySize関数によって、その配列が「何個の箱を今持っているのか」を返してくれるという訳です。

ArraySize関数とArrayResize関数の違い

ArrayResize関数配列のサイズを設定したり変更したりするのに用いるのに対し、

ArraySize関数配列の現在のサイズを取得するために使用されます。

配列のサイズを規定・変更したいのであればArrayResize関数を使い、配列のサイズを確認したいのであればArraySize関数数を使う、という区別をして頂ければと思います。

ArrayResize関数については↓のリンク先セクションをご覧ください。

配列の最後のインデックスを計算し、戻り値として返す

話をChangeArraySize関数の処理実装記述に戻します↓

  //配列の最後のインデックスを計算
  int arrayIndex = newSize - 1;

  //変数「arrayIndex」の値を戻り値として返す
  return arrayIndex;

配列のリサイズに失敗しなければ「newSize」にはリサイズされた要素数が格納されているので、インデックスを「newSize – 1」で求め、「arrayIndex」に代入します。

最後に「arrayIndex」の値を戻り値として返して終了です。

GetBuyPosCount関数について

GetBuyPosCount関数は、買いポジションの数を取得して返す関数です。

GetBuyPosCount関数の引数構成と戻り値

GetBuyPosCount関数引数構成と戻り値は以下の通りです

//買いポジションの数を取得する関数
int OriginalCPositions::GetBuyPosCount(ulong parMagicNum)

買いポジションの数を戻り値として返すので必然的にデータ型int型になります。

GetBuyPosCount関数の処理実装記述

GetBuyPosCount関数の処理実装記述は以下の通りです。極めてシンプルです。

{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   
   //protected変数の「BuyPosCount」を呼び出し、戻り値として返す
   return BuyPosCount;
}

{}内の冒頭で、GetPosInfo関数を呼び出します。

GetPosInfo関数void型関数なので、戻り値を受け取る変数を用意する必要はありません。

関数を呼び出した時点で、ポジション数を格納するメンバ変数や、ポジション番号を格納するメンバ配列に値の振り分けを行ってくれているので、ここでは買いポジションの数を格納している変数の「BuyPosCount」を呼び出し、戻り値として返せばそれで処理実装記述は終了です。

GetSellPosCount関数について

GetSellPosCount関数は、売りポジションの数を取得して返す関数です。

GetSellPosCount関数の引数構成と戻り値

GetSellPosCount関数引数構成と戻り値は以下の通りです

//買いポジションの数を取得する関数
int OriginalCPositions::GetSellPosCount(ulong parMagicNum)

売りポジションの数を戻り値として返すので、データ型int型になります。

GetSellPosCount関数の処理実装記述

GetSellPosCount関数の処理実装記述は以下の通りです。

{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   
   //protected変数の「SellPosCount」を呼び出し、戻り値として返す
   return SellPosCount;
}

GetBuyPosCount関数と同様に{}内の冒頭で、GetPosInfo関数を呼び出します。

GetPosInfo関数がポジション数を格納するメンバ変数や、ポジション番号を格納するメンバ配列に値の振り分けを行ってくれているので、ここでは売りポジションの数を格納している変数の「SellPosCount」を呼び出し、戻り値として返します。

GetTotalPosCount関数について

GetTotalPosCount関数は、買いと売り、合計のポジション数を取得して返す関数です。

GetTotalPosCount関数の引数構成と戻り値

GetTotalPosCount関数引数構成と戻り値は以下の通りです

//買いポジションの数を取得する関数
int OriginalCPositions::GetTotalPosCount関数(ulong parMagicNum)

買いと売り、合計のポジション数を戻り値として返すので、データ型int型になります。

GetTotalPosCount関数の処理実装記述

GetTotalPosCount関数の処理実装記述は以下の通りです。

{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   
   //protected変数の「SellPosCount」を呼び出し、戻り値として返す
   return TotalPosCount;
}

やはり同じように{}内の冒頭で、GetPosInfo関数を呼び出します。

しつこいようですが、GetPosInfo関数がポジション数を格納するメンバ変数や、ポジション番号を格納するメンバ配列に値の振り分けを行ってくれています。

今回のGetTotalPosCount関数の場合は、売りと買い合計のポジション数を格納している変数「TotalPosCount」を戻り値として返すだけです。

GetBuyPosNum関数について

GetBuyPosNum関数は、買いポジションのポジション番号情報を取得する関数です。

GetBuyPosNum関数の引数構成と戻り値

GetBuyPosNum関数引数構成と戻り値は以下の通りです

void OriginalCPositions::GetBuyPosNum(ulong parMagicNum,ulong &parTickets[])

第1引数にはマジックナンバー、第2引数にはメインプログラムでポジション番号を格納する配列が記述される想定です。return配列情報を返すことができないので、戻り値void型です。

<復習用リンク>

マジックナンバー引数引数配列ポジション番号void型return演算子

GetBuyPosNum関数の処理実装記述

GetBuyPosNum関数の処理実装記述は以下の通りです

void OriginalCPositions::GetBuyPosNum(ulong parMagicNum,ulong &parTickets[])
{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   ArrayCopy(parTickets,BuyPosNum);
   return;
}

ポジション数を取得する関数と同様に、GetPosInfo関数を呼び出します。GetPosInfo関数の呼び出しにより、ポジション番号が格納されているBuyPosNum[]、SellPosNum[]、PosNum[]等のprotectedセクション配列にもアクセスできますから、買いポジションのポジション番号であればBuyPosNum[]配列の情報をメインプログラムに返す記述を行います。

繰り返しになりますが、return演算子配列情報を返すことは出来ません。

ここではArrayCopy関数を使って実現します。

ArrayCopy関数について

ArrayCopy関数は第2引数に指定した配列を第1引数配列に複製する関数です。

複製したい情報は買いポジションのポジション番号が格納されているBuyPosNum[]配列ですから、これを第2引数に記述します。第1引数のparTickets[]配列にBuyPosNum[]配列の情報が格納されます。

従って、第1引数のparTickets[]配列部分には、メインプログラムにてBuyPosNum[]配列に格納される情報を受け取る配列名が記述される想定です。

ArrayCopy関数によって、ポジション番号情報が第1引数配列にコピーされたので、GetBuyPosNum関数の処理はここで終了です。

GetSellPosNum関数について

GetSellPosNum関数は、売りポジションのポジション番号情報を取得する関数です。

GetSellPosNum関数の引数構成と戻り値

GetSellPosNum関数引数構成と戻り値は以下の通りです

void OriginalCPositions::GetSellPosNum(ulong parMagicNum,ulong &parTickets[])

第1引数にはマジックナンバー、第2引数にはメインプログラムでポジション番号を格納する配列が記述される想定です。return配列情報を返すことができないので、戻り値void型です。

引数構成と戻り値に関しては、GetBuyPosNum関数と全く同じです。

<復習用リンク>

マジックナンバー引数引数配列ポジション番号void型return演算子

GetSellPosNum関数の処理実装記述

GetSellPosNum関数の処理実装記述は以下の通りです


{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   ArrayCopy(parTickets,SellPosNum);
   return;
}

GetBuyPosNum関数と同様に、GetPosInfo関数を呼び出します。GetPosInfo関数の呼び出しにより、protectedセクション配列であるSellPosNum[]にもアクセスできるようになりますから、後はArrayCopy関数を使って、SellPosNum[]配列の情報を第1引数に記述した配列にコピーします。これでGetSellPosNum関数の処理記述は終了です。

GetTotalPosNum関数について

GetTotalPosNum関数は、買いと売り両方のポジションの、ポジション番号情報を取得する関数です。

GetTotalPosNum関数の引数構成と戻り値

GetTotalPosNum関数引数構成と戻り値は以下の通りです

void OriginalCPositions::GetTotalPosNum(ulong parMagicNum,ulong &parTickets[])

第1引数にはマジックナンバー、第2引数にはメインプログラムでポジション番号を格納する配列が記述される想定です。return配列情報を返すことができないので、戻り値void型です。

引数構成と戻り値に関しては、GetBuyPosNum関数GetSellPosNum関数と全く同じです。

GetTotalPosNum関数の処理実装記述

GetTotalPosNum関数の処理実装記述は以下の通りです


{
  GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   ArrayCopy(parTickets,PosNum);
   return;
}

GetTotalPosNum関数も、冒頭でGetPosInfo関数を呼び出します。

これで、売りと買いのポジションを合計したポジション番号を格納しているPosNum[]配列にアクセスできるようになっていますから、あとは後はArrayCopy関数を使って、PosNum[]配列の情報を第1引数に記述した配列にコピーします。GetTotalPosNum関数の処理記述は以上になります。

「OriginalCPositions」クラスの全体記述

今回の記事では、以下の関数の処理実装記述を解説しました

OriginalCPositionsクラスの全体記述は以下の通りです。

//ポジション情報を管理するクラス------------------------------
class OriginalCPositions
{
   protected:
      ulong BuyPosNum[];
      ulong SellPosNum[];
      ulong PosNum[];
      
      int BuyPosCount;
      int SellPosCount;
      int TotalPosCount;
      
      void GetPosInfo(ulong parMagicNum = 0);
      int ChangeArraySize(ulong &parArray[]); 
      
   public:
      int GetBuyPosCount(ulong parMagicNum);
      int GetSellPosCount(ulong parMagicNum);
      int GetTotalPosCount(ulong parMagicNum);
      
      
      void GetBuyPosNum(ulong parMagicNum,ulong &parTickets[]);
      void GetSellPosNum(ulong parMagicNum,ulong &parTickets[]);
      void GetTotalPosNum(ulong parMagicNum,ulong &parTickets[]);

};

// ポジション情報を取得・振り分けする関数
void OriginalCPositions::GetPosInfo(ulong parMagicNumber = 0)
{  
    //ポジション数を格納する変数の初期化
   BuyPosCount = 0;
   SellPosCount = 0;
   TotalPosCount = 0;
   
   //ポジション番号格納配列の初期化とリサイズ
   ArrayResize(BuyPosNum, 1);
   ArrayInitialize(BuyPosNum, 0);
   
   ArrayResize(SellPosNum, 1);
   ArrayInitialize(SellPosNum, 0);
   
   ArrayResize(PosNum, 1);
   ArrayInitialize(PosNum, 0);
  
   
   for(int i = 0; i < PositionsTotal(); i++)//未決済ポジション内を一番古いポジからチェック
	{
	   ulong posNumber = PositionGetTicket(i);//ポジションプール内からインデックス順にポジション番号を取得
	   PositionSelectByTicket(posNumber);//ポジション選択
	   
	   if(PositionGetInteger(POSITION_MAGIC) != parMagicNumber && parMagicNumber > 0) continue;
	   //当該EAからの注文でなければスキップ
	   
	   if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
	   {  //買いポジションの数を1増加させる
	      BuyPosCount++;
	      int arrayIndex = ChangeArraySize(BuyPosNum);//配列をリサイズし、インデックスを戻り値として返す
	      BuyPosNum[arrayIndex] = PositionGetInteger(POSITION_TICKET);//Buy ポジション番号情報を配列に格納
	     
	   }
	   else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
	   {  ////売りポジションの数を1増加させる
	      SellPosCount++;
	      int arrayIndex = ChangeArraySize(SellPosNum);//配列をリサイズし、インデックスを戻り値として返す
	      
	      SellPosNum[arrayIndex] = PositionGetInteger(POSITION_TICKET);//Sell ポジション番号情報を配列に格納
	      
	   }
	   //全体のポジション数を1増加させる
	   TotalPosCount++; 
      int arrayIndex = ChangeArraySize(PosNum);//配列をリサイズし、インデックスを戻り値として返す
      PosNum[arrayIndex] = PositionGetInteger(POSITION_TICKET);//全てのポジションの ポジション番号情報を配列に格納
      
	}// for(int i = 0; i < PositionsTotal(); i++)の終端
	
	//各種ポジカウント変数とポジション番号格納配列に必要な情報を振り分けて作業を終える
}

//配列サイズを変更し、配列インデックスを返す関数
int OriginalCPositions::ChangeArraySize(ulong &parArray[])
{
  //配列の新しいサイズを計算
  int newSize = ArraySize(parArray) + 1;
  
//リサイズに失敗した場合に、ログ出力する
  if(ArrayResize(parArray, newSize) == -1)
    {
     //リサイズに失敗した場合のエラーハンドリング
     Print("配列のリサイズに失敗しました.");
     return -1; // 適切なエラーコードを返す
    }
  //配列の最後のインデックスを計算
  int arrayIndex = newSize - 1;

  //変数「arrayIndex」の値を戻り値として返す
  return arrayIndex;
}
   
   //変数「arrayIndex」の値を戻り値として返す
   return arrayIndex;

}//int OriginalCPositions::ChangeArraySize(ulong &parArray[])

//買いポジションの数を取得する関数
int OriginalCPositions::GetBuyPosCount(ulong parMagicNum)
{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   
   //protected変数の「BuyPosCount」を呼び出し、戻り値として返す
   return BuyPosCount;
}


//売りポジションの数を取得する関数
int OriginalCPositions::GetSellPosCount(ulong parMagicNum)
{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   
   //protected変数の「BuyPosCount」を呼び出し、戻り値として返す
   return SellPosCount;
}


//買いと売りの合計ポジションの数を取得する関数
int OriginalCPositions::GetTotalPosCount(ulong parMagicNum)
{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   
   //protected変数の「BuyPosCount」を呼び出し、戻り値として返す
   return TotalPosCount;
}


void OriginalCPositions::GetBuyPosNum(ulong parMagicNum,ulong &parTickets[])
{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   ArrayCopy(parTickets,BuyPosNum);
   return;
}



void OriginalCPositions::GetSellPosNum(ulong parMagicNum,ulong &parTickets[])
{
   GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   ArrayCopy(parTickets,SellPosNum);
   return;
}

void OriginalCPositions::GetTotalPosNum(ulong parMagicNum,ulong &parTickets[])
{
  GetPosInfo(parMagicNum);//各種ポジカウント変数とポジション番号格納配列に、必要な情報を振り分けるprotected関数
   ArrayCopy(parTickets,PosNum);
   return;

※「OriginalCPositionsクラスもこれまでと同様に、OriginalTrade.mqhファイルに記述していきますが、記述が煩雑になるので、今回の記事では「OriginalCPositions」とそのメンバに関する記述のみにしてあります。

<復習用リンク>

これまでのOriginalTrade.mqhファイル全体の記述内容

OriginalCTradeクラスメンバや、これまでに追加してきた独立関数の記述が確認できます。

今回は以上とさせていただきます。

最後までお読みいただきありがとうございました<m(__)m>

【超入門】MQL5 EA講座 第82回「ポジション情報管理クラスを作る-その1」

【超入門】MQL5 EA講座 第84回「ポジション情報を取得する独立関数を作る」

コメント

タイトルとURLをコピーしました