【コピペでOK】バイナリーオプションサインツールに体験版機能を機能を実装してみました

MQL実装例
yuki
yuki
今回はMQLAuth応用編です!お手本としてバイナリーオプションのRSIを使ってサインを出すツールにMQLAuthの機能を盛り込んでみました!
カオチャイ
カオチャイ
リンク付きロゴなどに加え、ツールの無料配布に便利な体験版機能などの実装を行いますよ!
yuki
yuki
この機能は無料でご利用できますが、MQLAuth.mqhのバージョン1.01以上がインストールされている必要がございますので、まだ準備ができていない方は下記の記事を参考にしてくださいね!
MQLAuth準備編
MQLAuthシステムを利用するための事前準備 MQLAuthを使うための準備 MQLAuthシステムを使う前提条件として「インジケーターをMT4の口座番号やパスワードで縛って管...

体験版機能付きのBO用サインツール

MT4にメッセージ表示 無料体験期間が終わるとこのようにメッセージが表示されます(こちらのメッセージは見本です)

 

今回書いていくコードは、下記の5つの機能を実装しています

7日の体験版付き口座認証

一括メッセージ機能

個別メッセ機能

アップデートお知らせ

リンク付きロゴ(ここではシストレファクトリーTOPへ飛ばします)

・RSIのBOサインツール(20以下で上矢印、80以上で下矢印)

 

カオチャイ
カオチャイ
それではご説明していきますが、個別のコード解説の部分にはわかりやすくするために注釈や一部コードを削除しておりますので、コピペで実装を行う場合は、全体コードを利用して下さいね
yuki
yuki
ロゴをクリックしてPayPal決済のページに飛ばしたい場合は、PayPal連携の記事を参考にしてくださいね

 

コードの全体像(コピペ用)

//+------------------------------------------------------------------+
//|                                                        RSIEA.mq4 |
//|                                      ©2020  MT4ツール製作【シストレファクトリー】 |
//|                                 https://interactivebrokers.work/ |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|  設定必須項目[MQLAUTH_ID] [APPLICATION_NAME]                      |
//+------------------------------------------------------------------+
#define MQLAUTH_ID ""
#define APPLICATION_NAME ""


#define VERSION "1.00"
#define HTTP_QUERY_FLAG -2147483648
string _prefix = "RSISign_";
#include <MQLAuth.mqh>
#resource "\\Include\\Images\\SYSFAClogo50.bmp"
#property copyright "©2020  MT4ツール製作【シストレファクトリー】"
#property link      "https://interactivebrokers.work/"
#property version   VERSION
#property strict
#property indicator_chart_window
#property indicator_buffers 2

//+------------------------------------------------------------------+
//|  カスタマイズ                                                        |
//+------------------------------------------------------------------+
bool _useApplicationMessage = true; // 一斉メッセージを利用する
int _applicationMessageViewSecond = 8; // メッセージを消すまでの秒数
bool _useUserMessage = true; // 個別メッセージを利用する
int _userMessageViewSecond = 8; // メッセージを消すまでの秒数
bool _useUpdateMessage = true; // アップデートのお知らせを利用する
bool _useLogo = true; // ロゴを表示する
bool _testAuth = true; // バックテスト時も認証をする

//+------------------------------------------------------------------+
//|  グローバル変数                                                     |
//+------------------------------------------------------------------+
//--- 口座認証に利用する変数
bool _isAuthorized = false; // 口座認証の成否を表す変数
datetime _date; // 口座認証を行った時間を保存する変数
string _ObjectAuthMessage1 = _prefix + "objectAuthMessage1"; // 認証メッセージを表示するラベル名1
string _ObjectAuthMessage2 = _prefix + "objectAuthMessage2"; // 認証メッセージを表示するラベル名2
//--- 口座認証に利用する変数

//--- 一斉メッセージに利用する変数
datetime _receiveApplicationMessage; // 前回メッセージを受信した日時
string _applicationMessageurl; // メッセージをクリックしたときに開くURLを格納する変数
string _labelApplicationMessage = _prefix + "applicationMessage"; // メッセージを表示するラベル名
long _viewApplicationMessageTime = 0; // メッセージを表示した日時を格納する変数
//--- 一斉メッセージに利用する変数

//--- 個別メッセージに利用する変数
datetime _receiveUserMessage; // 前回メッセージを受信した日時
string _userMessageurl; // メッセージをクリックしたときに開くURLを格納する変数
string _labelUserMessage = _prefix + "userMessage"; // メッセージを表示するラベル名
long _viewUserMessageTime = 0; // メッセージを表示した日時を格納する変数
//--- 個別メッセージに利用する変数

//--- アップデートのお知らせに利用する変数
string _updateurl; // アップデートのお知らせをクリックしたときに開くURLを格納する変数
string _labelUpdateMessage = _prefix + "updateMessage"; // アップデートのお知らせを表示するラベル名
string _labelUpdateMessage2 = _prefix + "updateMessage2"; // アップデートのお知らせを表示するラベル名
//--- アップデートのお知らせに利用する変数

//--- ロゴに利用する変数
string _logourl = "https://interactivebrokers.work/"; // ロゴをクリックしたときに開くURLを格納する変数
string _objectLogo = _prefix + "LOGO"; // ロゴオブジェクトの名前
//--- ロゴに利用する変数


double Buf0[]; //LowSign
double Buf1[]; //HighSign

//+------------------------------------------------------------------+
//|  OnInit                                                          |
//+------------------------------------------------------------------+
int OnInit() {
//--- ストラテジーテスターを使う場合の認証 ---
   if(IsTesting() && _testAuth)
      Auth();
//--- ストラテジーテスターを使う場合の認証 ---

//--- ロゴ表示 ---
   if(_useLogo)
      Auth_ShowBMPIMG("\\Include\\Images\\SYSFAClogo50.bmp", _prefix + "SYSFAC_LOGO", CORNER_LEFT_LOWER);

//--- ロゴ表示 ---

//--- HIGHLOWサイン ---
   SetIndexBuffer(0, Buf0);
   SetIndexBuffer(1, Buf1);

   SetIndexLabel(0, "LOW Signal");
   SetIndexLabel(1, "HIGH Signal");

   SetIndexArrow(0, 234);
   SetIndexArrow(1, 233);

   SetIndexStyle(0, 3, 0, 3, C'229 ,79 ,55');
   SetIndexStyle(1, 3, 0, 3, C'121 ,176 ,32');
//--- HIGHLOWサイン ---

//--- タイマー ---
   EventSetTimer(1);
//--- タイマー ---

   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//|   OnDeinit                                                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
//--- タイマー削除 ---
   EventKillTimer();

//--- ラベル削除
   ObjectsDeleteAll(ChartID(), _prefix, EMPTY, EMPTY);
}
//+------------------------------------------------------------------+
//|   OnTimer                                                        |
//+------------------------------------------------------------------+
void OnTimer() {
//--- 口座番号認証 ---
   if(AccountInfoInteger(ACCOUNT_LOGIN) != 0) {
      if(TimeDay(TimeLocal()) != TimeDay(_date)) {
         _date = TimeLocal();
         Auth();
      }
   }
//--- 口座番号認証 ---

//--- メッセージの処理 ---
   Message();
//--- メッセージの処理 ---
}
//+------------------------------------------------------------------+
//|   OnChartEvent                                                   |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam) {
   if(id == CHARTEVENT_OBJECT_CLICK) {
      if(StringFind(sparam, _labelApplicationMessage) >= 0)
         if(_applicationMessageurl != "")
            bool result = Auth_OpenURL(_applicationMessageurl);

      if(StringFind(sparam, _labelUserMessage) >= 0)
         if(_userMessageurl != "")
            bool result = Auth_OpenURL(_userMessageurl);

      if(sparam == _labelUpdateMessage)
         if(_updateurl != "")
            bool result = Auth_OpenURL(_updateurl);

      if(StringFind(sparam,  _objectLogo) >= 0)
         if(_logourl != "")
            bool result = Auth_OpenURL(_logourl);
   }
}
//+------------------------------------------------------------------+
//|    OnCalculate                                                   |
//+------------------------------------------------------------------+
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(!_isAuthorized) return(0);

   int limit;
   if (prev_calculated == 0)
      limit = rates_total - 1;
   else
      limit = rates_total - prev_calculated;

   for(int i = limit; i >= 0; i--) {
      int signal = Signal(i);
      if(signal > 0) {
         Buf0[i] = EMPTY_VALUE;
         Buf1[i] = Low[i];
      } else if(signal < 0) {
         Buf0[i] = High[i];
         Buf1[i] = EMPTY_VALUE;
      } else {
         Buf0[i] = EMPTY_VALUE;
         Buf1[i] = EMPTY_VALUE;
      }
   }

   return(rates_total);
}
//+------------------------------------------------------------------+
//| RSIが20以下で1、80以上で-1、それ以外は0を返す関数                      |
//+------------------------------------------------------------------+
int Signal(int bar) {
   double rsi = iRSI(Symbol(), PERIOD_CURRENT, 14, PRICE_CLOSE, bar);
   if(rsi <= 20) return 1;
   else if(rsi >= 80) return -1;
   return 0;
}

//+------------------------------------------------------------------+
//|  口座認証のための関数                                               |
//+------------------------------------------------------------------+
void Auth() {
   datetime period = AuthByAccountNumberWithAddUser_ReturnDatetime(MQLAUTH_ID, APPLICATION_NAME, 7);
   if(period >= TimeLocal()) {
      _isAuthorized = true;
      //--- バージョン情報を確認し、更新がある場合はお知らせを表示する
      if(_useUpdateMessage) {
         string newestVersion = Auth_GetNewestVersion(MQLAUTH_ID, APPLICATION_NAME, _updateurl);
         if(newestVersion != "" && StringToDouble(VERSION) < StringToDouble(newestVersion)) {
            ObjectCreate(ChartID(), _labelUpdateMessage, OBJ_LABEL, 0, 0, 0);
            ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_SELECTABLE, false);
            ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_SELECTED, false);
            ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_HIDDEN, true);
            ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_CORNER, CORNER_LEFT_LOWER);
            ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_XDISTANCE, 80);
            ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_YDISTANCE, 60);
            ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_ZORDER, 8);
            ObjectSetText(_labelUpdateMessage, "新しいバージョン " + newestVersion + " があります。", 12, "Meiryo", (color)ChartGetInteger(ChartID(), CHART_COLOR_FOREGROUND));
            ObjectCreate(ChartID(), _labelUpdateMessage2, OBJ_LABEL, 0, 0, 0);
            ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_SELECTABLE, false);
            ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_SELECTED, false);
            ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_HIDDEN, true);
            ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_CORNER, CORNER_LEFT_LOWER);
            ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_XDISTANCE, 80);
            ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_YDISTANCE, 40);
            ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_ZORDER, 8);
            ObjectSetText(_labelUpdateMessage2, "ダウンロードするにはここをクリック", 12, "Meiryo", (color)ChartGetInteger(ChartID(), CHART_COLOR_FOREGROUND));
         }
      }
      //--- バージョン情報を確認し、更新がある場合はお知らせを表示する
   } else {
      _isAuthorized = false;
      //--- 認証メッセージを表示するラベルの作成 ---
      ObjectCreate(_ObjectAuthMessage1, OBJ_LABEL, 0, 0, 0);
      ObjectSet(_ObjectAuthMessage1, OBJPROP_BACK, false);
      ObjectSetInteger(ChartID(), _ObjectAuthMessage1, OBJPROP_BGCOLOR, clrRed);

      ObjectSet(_ObjectAuthMessage1, OBJPROP_SELECTABLE, false);
      ObjectSet(_ObjectAuthMessage1, OBJPROP_SELECTED, false);
      ObjectSet(_ObjectAuthMessage1, OBJPROP_HIDDEN, true);
      ObjectSet(_ObjectAuthMessage1, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSet(_ObjectAuthMessage1, OBJPROP_XDISTANCE, 80);
      ObjectSet(_ObjectAuthMessage1, OBJPROP_YDISTANCE, 48);
      ObjectSetText(_ObjectAuthMessage1, "無料期間が終了しました", 18, "MS ゴシック", (color)ChartGetInteger(ChartID(), CHART_COLOR_FOREGROUND));
      ObjectCreate(_ObjectAuthMessage2, OBJ_LABEL, 0, 0, 0);
      ObjectSet(_ObjectAuthMessage2, OBJPROP_BACK, false);
      ObjectSetInteger(ChartID(), _ObjectAuthMessage2, OBJPROP_BGCOLOR, clrRed);

      ObjectSet(_ObjectAuthMessage2, OBJPROP_SELECTABLE, false);
      ObjectSet(_ObjectAuthMessage2, OBJPROP_SELECTED, false);
      ObjectSet(_ObjectAuthMessage2, OBJPROP_HIDDEN, true);
      ObjectSet(_ObjectAuthMessage2, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSet(_ObjectAuthMessage2, OBJPROP_XDISTANCE, 80);
      ObjectSet(_ObjectAuthMessage2, OBJPROP_YDISTANCE, 18);
      ObjectSetText(_ObjectAuthMessage2, "期間を延長する場合は左側のロゴをクリックしてください", 18, "MS ゴシック", (color)ChartGetInteger(ChartID(), CHART_COLOR_FOREGROUND));
//--- 認証メッセージを表示するラベルの作成 ---
   }
}

//+------------------------------------------------------------------+
//|   メッセージを取得し表示する関数                                       |
//+------------------------------------------------------------------+
void Message() {
   if(_isAuthorized && _useApplicationMessage && TimeHour(TimeLocal()) != TimeHour(_receiveApplicationMessage)) {
      _receiveApplicationMessage = TimeLocal();

      string messages = Auth_GetApplicationMessage(MQLAUTH_ID, APPLICATION_NAME);
      if(messages != "") {
         ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_YDISTANCE, -100);
         ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_YDISTANCE, -100);

         if(StringFind(messages, "#", 0) >= 0) {
            string result[];
            StringSplit(messages, '#', result);
            string message[];
            StringSplit(result[0], '\r', message);

            for(int i = 0; i < ArraySize(message); i++) {
               ObjectCreate(ChartID(), _labelApplicationMessage + (string)i, OBJ_LABEL, 0, 0, 0);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_BACK, false);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_SELECTABLE, false);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_SELECTED, false);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_HIDDEN, true);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_CORNER, CORNER_LEFT_LOWER);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_XDISTANCE, 85);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_YDISTANCE, 20 + 20 * (ArraySize(message) - 1 - i));
               ObjectSetText(_labelApplicationMessage + (string)i, message[i], 12, "Meiryo", (color)ChartGetInteger(ChartID(), CHART_COLOR_FOREGROUND));
            }
            _applicationMessageurl = result[1];
         } else {
            string message[];
            StringSplit(messages, '\r', message);

            for(int i = 0; i < ArraySize(message); i++) {
               ObjectCreate(ChartID(), _labelApplicationMessage + (string)i, OBJ_LABEL, 0, 0, 0);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_BACK, false);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_SELECTABLE, false);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_SELECTED, false);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_HIDDEN, true);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_CORNER, CORNER_LEFT_LOWER);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_XDISTANCE, 85);
               ObjectSetInteger(ChartID(), _labelApplicationMessage + (string)i, OBJPROP_YDISTANCE, 30 + 20 * (ArraySize(message) - 1 - i));
               ObjectSetText(_labelApplicationMessage + (string)i, message[i], 12, "Meiryo", (color)ChartGetInteger(ChartID(), CHART_COLOR_FOREGROUND));
            }
            _applicationMessageurl = "";
         }
         _viewApplicationMessageTime = GetTickCount();
      }
   }
   if(_isAuthorized && _useUserMessage && GetTickCount() - _viewApplicationMessageTime > _applicationMessageViewSecond * 1000 && TimeHour(TimeLocal()) !=  TimeHour(_receiveUserMessage)) {
      _receiveUserMessage = TimeLocal();
      ObjectsDeleteAll(ChartID(), _labelApplicationMessage, EMPTY, EMPTY);

      string messages = Auth_GetUserMessageByAccountNumber(MQLAUTH_ID, APPLICATION_NAME);
      if(messages != "") {
         ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_YDISTANCE, -100);
         ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_YDISTANCE, -100);

         if(StringFind(messages, "#", 0) >= 0) {
            string result[];
            StringSplit(messages, '#', result);
            string message[];
            StringSplit(result[0], '\r', message);

            for(int i = 0; i < ArraySize(message); i++) {
               ObjectCreate(ChartID(), _labelUserMessage + (string)i, OBJ_LABEL, 0, 0, 0);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_BACK, false);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_SELECTABLE, false);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_SELECTED, false);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_HIDDEN, true);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_CORNER, CORNER_LEFT_LOWER);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_XDISTANCE, 85);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_YDISTANCE, 20 + 20 * (ArraySize(message) - 1 - i));
               ObjectSetText(_labelUserMessage + (string)i, message[i], 12, "Meiryo", (color)ChartGetInteger(ChartID(), CHART_COLOR_FOREGROUND));
            }
            _userMessageurl = result[1];
         } else {
            string message[];
            StringSplit(messages, '\r', message);

            for(int i = 0; i < ArraySize(message); i++) {
               ObjectCreate(ChartID(), _labelUserMessage + (string)i, OBJ_LABEL, 0, 0, 0);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_BACK, false);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_SELECTABLE, false);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_SELECTED, false);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_HIDDEN, true);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_CORNER, CORNER_LEFT_LOWER);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_XDISTANCE, 85);
               ObjectSetInteger(ChartID(), _labelUserMessage + (string)i, OBJPROP_YDISTANCE, 30 + 20 * (ArraySize(message) - 1 - i));
               ObjectSetText(_labelUserMessage + (string)i, message[i], 12, "Meiryo", (color)ChartGetInteger(ChartID(), CHART_COLOR_FOREGROUND));
            }
            _userMessageurl = "";
         }
         _viewUserMessageTime = GetTickCount();
      }
   }
   if(_useUserMessage && _viewUserMessageTime != 0 && GetTickCount() - _viewUserMessageTime > _userMessageViewSecond * 1000) {
      ObjectsDeleteAll(ChartID(), _labelUserMessage, EMPTY, EMPTY);
      ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_YDISTANCE, 60);
      ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_YDISTANCE, 40);
   } else if(!_useUserMessage && _viewApplicationMessageTime != 0 && GetTickCount() - _viewApplicationMessageTime > _applicationMessageViewSecond * 1000) {
      ObjectsDeleteAll(ChartID(), _labelApplicationMessage, EMPTY, EMPTY);
      ObjectSetInteger(ChartID(), _labelUpdateMessage, OBJPROP_YDISTANCE, 60);
      ObjectSetInteger(ChartID(), _labelUpdateMessage2, OBJPROP_YDISTANCE, 40);
   }
}

 

yuki
yuki
ソースコードはこちらからダウンロードできます。このコードを使う場合は下記の2箇所を修正してからご利用くださいね

#define MQLAUTH_ID “” //””内に自分のMQLAUTH_IDを記入する

#define APPLICATION_NAME “” // “”内に自分の登録したEA・インジケーター名に書き換える(※ユーザー名ではないので注意)

 

カオチャイ
カオチャイ
それではコードの解説に行きたいと思います!

 

コードの解説

一斉メッセージを利用する設定

//+------------------------------------------------------------------+
//|  カスタマイズ                                                        |
//+------------------------------------------------------------------+
bool _useApplicationMessage = true; // 一斉メッセージを利用する
int _applicationMessageViewSecond = 8; // メッセージを消すまでの秒数

_useApplicationMessageにtrueを設定すると、MQLAuthで設定した一斉メッセージが表示されるようになります。一斉メッセージを利用しない場合はfalseに設定してください。

一斉メッセージは設定した秒数の間表示されます。デフォルトでは8秒になっていますので、必要に応じて調整してください。

 

個別メッセージを利用する設定

//+------------------------------------------------------------------+
//|  カスタマイズ                                                        |
//+------------------------------------------------------------------+
bool _useUserMessage = true; // 個別メッセージを利用する
int _userMessageViewSecond = 8; // メッセージを消すまでの秒数

_useUserMessageにtrueを設定すると、MQLAuthで設定した個別メッセージが表示されるようになります。個別メッセージを利用しない場合はfalseに設定してください。

個別メッセージは設定した秒数の間表示されます。デフォルトでは8秒になっていますので、必要に応じて調整してください。

 

アップデートのお知らせを利用する設定

//+------------------------------------------------------------------+
//|  カスタマイズ                                                        |
//+------------------------------------------------------------------+
bool _useUpdateMessage = true; // アップデートのお知らせを利用する

_useUpdateMessageにtrueを設定すると、MQLAuthで設定したバージョン番号が現在のバージョン番号より大きい場合にアップデートのお知らせが表示されるようになります。アップデートのお知らせを利用しない場合はfalseに設定してください。

アップデートのお知らせは、アップデートされるまではずっと表示されたままになります。

 

ロゴを利用する設定

//+------------------------------------------------------------------+
//|  カスタマイズ                                                        |
//+------------------------------------------------------------------+
bool _useLogo = true; // ロゴを表示する

_useLogoにtrueを設定すると、チャート画面左下にロゴが表示されるようになります。ロゴを表示しない場合はfalseに設定してください。

//+------------------------------------------------------------------+
//|   ロゴデータ                                          |
//+------------------------------------------------------------------+
int _logo[] = { 省略 };

ロゴを表示するには、ロゴ画像のデータをあらかじめソースコードに書いておく必要があります。ロゴ画像をソースコードに書く方法については以下の記事を参考にしてください。

MT4に画像を表示
MT4のチャート上に画像を表示してみよう https://interactivebrokers.work/start_mqlauth/ MT4に画像を表示 こ...
//+------------------------------------------------------------------+
//|  グローバル変数                                                     |
//+------------------------------------------------------------------+
//--- ロゴに利用する変数
string _logourl = "https://interactivebrokers.work/"; // ロゴをクリックしたときに開くURLを格納する変数
//--- ロゴに利用する変数

ロゴをクリックしたときに開くサイトのURLを変更する場合は、変数_logourlに設定します。

バックテスト時も認証をする設定

//+------------------------------------------------------------------+
//|  カスタマイズ                                                        |
//+------------------------------------------------------------------+
bool _testAuth = true; // バックテスト時も認証をする

_testAuthにtrueを設定すると、バックテスト時にも口座番号認証が行われ、口座番号が違うMT4だとバックテストができなくなります。

リアルタイムチャートでは口座番号縛りをしたいけど、バックテストはどの口座番号でもできるようにする場合はfalseに設定してください。

 

RSIのBOサインツール(20以下で上矢印、80以上で下矢印)

こちらはシンプルなRSI20以下で上矢印、80以上で下矢印を表示するロジックです。サインを出すロジックは、以下の3つの場所に分かれています。

 

double Buf0[]; //LowSign
double Buf1[]; //HighSign

//+------------------------------------------------------------------+
//|  OnInit                                                          |
//+------------------------------------------------------------------+
int OnInit() {
//--- HIGHLOWサイン
   SetIndexBuffer(0, Buf0);
   SetIndexBuffer(1, Buf1);

   SetIndexLabel(0, "LOW Signal");
   SetIndexLabel(1, "HIGH Signal");

   SetIndexArrow(0, 234);
   SetIndexArrow(1, 233);

   SetIndexStyle(0, 3, 0, 3, C'229 ,79 ,55');
   SetIndexStyle(1, 3, 0, 3, C'121 ,176 ,32');
//--- HIGHLOWサイン
}

矢印を出すバッファの設定です。Buf0がLOWサインの矢印で、Buf1がHIGHサインの矢印に設定しています。

 

//+------------------------------------------------------------------+
//| RSIが20以下で1、80以上で-1、それ以外は0を返す関数                       |
//+------------------------------------------------------------------+
int Signal(int bar) {
   double rsi = iRSI(Symbol(), PERIOD_CURRENT, 14, PRICE_CLOSE, bar);
   if(rsi <= 20) return 1;
   else if(rsi >= 80) return -1;
   return 0;
}
//+------------------------------------------------------------------+

サインを出すかどうかの判定をしている関数です。RSIが20以下のときに1を返し、80以上のときに-1を返し、それ以外は0を返しています。

 

//+------------------------------------------------------------------+
//|    OnCalculate                                                   |
//+------------------------------------------------------------------+
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(!_isAuthorized) return(0);

   int limit;
   if (prev_calculated == 0)
      limit = rates_total - 1;
   else
      limit = rates_total - prev_calculated;

   for(int i = limit; i >= 0; i--) {
      int signal = Signal(i);
      if(signal > 0) {
         Buf0[i] = EMPTY_VALUE;
         Buf1[i] = Low[i];
      } else if(signal < 0) {
         Buf0[i] = High[i];
         Buf1[i] = EMPTY_VALUE;
      } else {
         Buf0[i] = EMPTY_VALUE;
         Buf1[i] = EMPTY_VALUE;
      }
   }

   return(rates_total);
}

OnCalculate関数内では、前述のSignal関数で返された結果をもとに、ローソク足毎にバッファ値を入力しています。

ロジックをオリジナルのものに書き換えるときは、この3か所を見て、書き換えればよいでしょう。

 

yuki
yuki
今回の記事は以上となります!他の応用編の記事は下記を参考にしてくださいね!
EAやインジケーターに認証をつける方法
MT4のEAやインジケーターにサーバー認証(口座番号縛り)を実装する方法MQLAuthを使って、EAやインジケーターに口座番号認証を実装する方法を紹介しています。 従来のコピー防止だけでなく、遠隔での停止や決済機能の自動化なども可能になる画期的な認証方法です。...
MQL実装例
【コピペでOK】RSIのEAに口座認証や一括メッセージ機能を実装してみました https://interactivebrokers.work/start_mqlauth/ 個人でEAを販売する際につけてお...
MQL実装例
【コピペでOK】MT4のチャートから飛ばすURLをソースコードを編集せずに、MQLAuthの管理画面から変えられるようにする https://interactivebrokers.work/start_mqlauth/ メッセージのURL変更を簡単に ...