MQL4プログラミング 第14回 バイナリーの自動エントリー(2)

AMT本来の使い方 自動エントリー

今回も前回(MQL4プログラミング 第13回 バイナリーの自動エントリー(1))と同じくAMT本来の使い方である自動エントリーについて解説していきます。

①前回:自作サインツールにAMTの自動エントリー機能を構築する方法
②今回:既成のバッファ型サインツールにAMTの自動エントリー機能を構築する方法
となり今回は既成のインジケーターのバッファ型サインを自作インジケーターから取得する方法を公開します。

バッファ型サインツールのサインを取得する

今回はバッファ型サインツールのサインを取得する事がメインテーマとなります。
サインツールは大きく分けて
バッファ型サインサインツール
オブジェクト型サインツール
の2種類があります。

バッファ型とオブジェクト型の見分け方

まず、オブジェクト型のサインツールはサイン(上下の矢印)がオブジェクトで表示されています。
チャート上の矢印をダブルクリックすると矢印の周りが四角く囲まれています。

「表示中のライン等リスト」を見ると
ライン等:Arrow
名前:UpArrow_21_22:05
となっているのが確認できます。(下図)

次にバッファ型のサインツールは矢印をダブルクリックしてもオブジェクト型のように選択状態になりません。
以前の「MQL4プログラミング 第6回 インジケーターを作成してみよう(過去足のサイン表示)」で公開したサインツールを例にとって見ましょう。(下図)

ちょうど下矢印と上矢印が出ている例があるので見てみると上矢印は黄色、下矢印は赤色で表示されています。
「表示中のインディケーター」でL-blog_0006.ex4の色の設定を見ると0番が黄色、1番が赤色となっているのが確認できます。
ここで示した矢印(バッファ)の番号が、後のソースコードで重要になりますので覚えておいてください。

既成のインジケーターのバッファ型サインを取得するソースコード

まず、今回扱う「既成のインジケーター」の意味について説明すると有料、無料を問わずご自身が所有している(ソースコードを改変できない)ex4インジケーターとなります。なので今回稼働確認をおこなうインジケーターの構成は下図①、②となります。

それでは、今回のソースコードを示します。
ソースコードのベースは前回の(MQL4プログラミング 第13回 バイナリーの自動エントリー(1))を少し改修したものです。

// prg-0014.mq4
#property copyright "Copyright 2024, smile-invest-blog.com"
#property link      "https://www.smile-invest-blog.com/prg-0014/"
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Yellow
#property indicator_color2 Red
#property indicator_width1 2
#property indicator_width2 2

#define PREFIX_VLINE "VLine_"

double Log1Up[];   // Highサイン用バッファ
double Log1Down[]; // Low サイン用バッファ
int    realBars = 0;

int shortMaPeriod = 10;  // 短期移動平均線の期間
int longMaPeriod  = 30;  // 長期移動平均線の期間

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexStyle(0, DRAW_ARROW, EMPTY);
   SetIndexArrow(0, 233);
   SetIndexBuffer(0, Log1Up);
   SetIndexStyle(1, DRAW_ARROW, EMPTY);
   SetIndexArrow(1, 234);
   SetIndexBuffer(1, Log1Down);
   
//---
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| start function
//+------------------------------------------------------------------+
int start() {
   bool ret_hantei;  // hantei関数の結果格納用
   int counted_bars=IndicatorCounted(); 
   int limit = Bars - counted_bars;

   for(int i = limit - 1; i >= 0; i--) {
      if(i == 0) {
         Log1Down[i] = EMPTY_VALUE;
         Log1Up[i]   = EMPTY_VALUE;

         ret_hantei = hantei(i);    // 上下サイン表示の判定を関数化した
         if (ret_hantei == true) {  // hantei関数の結果がtrueの時
            if (realBars < Bars) {  // 1本のローソク足で1回だけ実行するための条件
               realBars = Bars;     // realBarsをBarsにする事で同じローソク足では1回だけ実行する
               if (Log1Up[i] != EMPTY_VALUE) {           // hantei関数内で上サイン表示と判定された
                  Alert(Symbol(), " *** High ***");
               }
               else if (Log1Down[i] != EMPTY_VALUE) {    // hantei関数内で下サイン表示と判定された
                  Alert(Symbol(), " *** Low ***");
               }
            }
         }

         if (TaskPeriod()){
            if (Log1Up[i+1] != EMPTY_VALUE) {
               entry(1, true);
            }
            if (Log1Down[i+1] != EMPTY_VALUE) {
               entry(0, true);
            }
         }
      }
   }

   return(0);
}

//+------------------------------------------------------------------+
//| エントリーの条件判定関数
//| int i メイン関数からのiの値
//+------------------------------------------------------------------+
bool hantei(int i) {
   double UpSign, DnSign;

   UpSign = getSign(0, i);
   DnSign = getSign(1, i);

   if (UpSign != EMPTY_VALUE) {
      // Highサイン
      Log1Up[i] = Low[i] - 10 * Point;
      return true;
   }
   else if (DnSign != EMPTY_VALUE) {
      // Lowサイン
      Log1Down[i] = High[i] + 10 * Point;
      return true;
   }

   return false;

}

//+------------------------------------------------------------------+
//| getSign メイン
//| 引数1 バッファの番号、
//| 引数2 シフト数、
//+------------------------------------------------------------------+
double getSign(int cNo, int shift) {
   double ret;

   ret = iCustom(                  // カスタムインジケータ呼び出し
                   NULL,           // 通貨ペア
                   0,              // 時間軸
                   "L-blog_0006",  // カスタムインジケータ名
                   cNo,            // カスタムインジケータのインジケータバッファインデックス
                   shift           // バーシフト
                );
   return ret;
}

//+------------------------------------------------------------------+
//| entry function                         |
//| 引数1 1:Highエントリー、0:Lowエントリー、
//| 引数2 false:手動エントリー、true:自動エントリー、
//+------------------------------------------------------------------+
void entry(int high_low, bool isAuto) {
   string strEntryCmd = " AMT";

/*
   アラートコマンドリスト(AMT側で設定すること)
   AMT1MA
   AMT1MM
   AMT5MA
   AMT5MM
   AMT15MA
   AMT15MM
   AMT60MA
   AMT60MM
   (AMTの個別アラート設定でそれぞれにHigh, Low の文字列を設定する)
*/
   if (Period() == 1) {
      strEntryCmd += "1M";
   }
   if (Period() == 5) {
      strEntryCmd += "5M";
   }
   if (Period() == 15) {
      strEntryCmd += "15M";
   }
   if (Period() == 60) {
      strEntryCmd += "1H";
   }

   if (isAuto) {
      strEntryCmd += "A";
   }
   else {
      strEntryCmd += "M";
   }

   if (high_low == 1) {
      strEntryCmd += " ***HIGH***";
   }
   else {
      strEntryCmd += " ***LOW***";
   }
   
   Alert(Symbol(), strEntryCmd);

   if (high_low == 1) {
      drawVLine(Lime);
   }
   if (high_low == 0) {
      drawVLine(Red);
   }
}

//+------------------------------------------------------------------+
//| ローソク足確定時の処理
//+------------------------------------------------------------------+
bool TaskPeriod() {
    static    datetime s_lasttime;                      // 最後に記録した時間軸時間
                                                        // staticはこの関数が終了してもデータは保持される

    datetime temptime    = iTime( Symbol(), Period() ,0 );  // 現在の時間軸の時間取得

    if ( temptime == s_lasttime ) {                     // 時間に変化が無い場合
        return false;                                         // 処理終了
    }
    s_lasttime = temptime;                              // 最後に記録した時間軸時間を保存

    // ----- 処理はこれ以降に追加 -----------
    return true;                                        // 移動平均線のクロス判定
}

void drawVLine(color clr) {
    string obj_name = StringFormat("%s_%d", PREFIX_VLINE, Bars);
    int    chart_id = 0;

    ObjectCreate(chart_id,obj_name,                                 // オブジェクト作成
                 OBJ_VLINE,                                         // オブジェクトタイプ
                 0,                                                 // サブウインドウ番号
                 Time[0],                                           // 1番目の時間のアンカーポイント
                 0                                                  // 1番目の価格のアンカーポイント
                 );
    
    ObjectSetInteger(chart_id,obj_name,OBJPROP_COLOR,clr);          // ラインの色設定
    ObjectSetInteger(chart_id,obj_name,OBJPROP_STYLE,STYLE_SOLID);  // ラインのスタイル設定
    ObjectSetInteger(chart_id,obj_name,OBJPROP_WIDTH,1);            // ラインの幅設定
    ObjectSetInteger(chart_id,obj_name,OBJPROP_BACK,false);         // オブジェクトの背景表示設定
    ObjectSetInteger(chart_id,obj_name,OBJPROP_SELECTABLE,true);    // オブジェクトの選択可否設定
    ObjectSetInteger(chart_id,obj_name,OBJPROP_SELECTED,false);     // オブジェクトの選択状態
    ObjectSetInteger(chart_id,obj_name,OBJPROP_HIDDEN,true);        // オブジェクトリスト表示設定
    ObjectSetInteger(chart_id,obj_name,OBJPROP_ZORDER,0);           // オブジェクトのチャートクリックイベント優先順位
}

では、今回のソースコードの改修箇所の説明をします。

82行目:hantei関数では「既成のインジケーターのバッファ型サインを取得する」必要があるので、その対応をしました。

具体的には
85行目:getSign関数で上向き矢印
86行目:getSign関数で下向き矢印
それぞれの値を取得しています。
以下、この関数内の処理では
 ①上向き矢印の値が有効であれば(つまり上向き矢印が出ていれば)
 ②下向き矢印の値が有効であれば(つまり下向き矢印が出ていれば)
上記①、②のどちらかであればhantei関数は「true」の値を返します。

一方、メイン(start)関数では「true」の値が返ってくれば上下とちらの矢印かを判定してアラートメッセージを出します。
65~70行目:次足になって上下どちらかのサインが確定していればentry関数が呼ばれ自動エントリーをおこないます。

バッファ型サインを取得する関数

今回新しく登場するgetSign関数では、iCustomというテクニカルインディケーター関数を利用します。
iCustom関数はインジケーター名とバッファの番号を指定して、そのインジケーターの値を取得します。
112行目:通貨ペアを指定します。NULLの場合は現在の通貨ペアとなります。
113行目:通過ペアの時間軸を指定します。0の場合は現在の時間軸となります。
114行目:値を取得するカスタムインジケーター名を指定します。
115行目:値を取得するカスタムインジケーターのバッファ番号を指定します。
116行目:値を取得するカスタムインジケーターのシフト数を指定します。現在足は0、1つ前の足は1となります。

バッファ型サインの値の確認方法

チャートを選択し「Ctrl + D」(キーボードのCtrlキーを押しながらDキーを同時に押す)押下でデータウィンドウが表示されます。
値を確認したい矢印にマウスカーソルを合せます。
今回の例では「L-blog_0006.ex4」のインジケーターの値を取得するのでデータウィンドウの「L-blog_0006」の箇所を見ます。
下図左側の丸印で囲んだ部分にカーソルを合わせると「L-blog_0006」のすぐ右側にバッファ番号0の値が表示されています。
また下図右側の丸印で囲んだ部分にカーソルを合わせると「L-blog_0006」の1つ下の行にバッファ番号1の値が表示されています。

今回のまとめ

今回はどうでしたか?ソースコードと解説を見ながら理解が深まりましたでしょうか?
今回のプログラム内容を習得すれば既成のインジケーターの勝率も簡単に調べる事ができます。
MQL4プログラミング 第8回 インジケーターを作成してみよう(勝率の表示)」をベースに今回の修正内容を合体させれば実現できます。
是非挑戦してみてください。

今回の関連情報

・AMT(AutoMultiTrader)の無料ダウンロードは「AMT V2 ダウンロードサイト」から。
・ハイローのデモ口座は「ハイロー紹介ページ」から。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA