MT4のお悩み

【完全ガイド】MQLで口座縛りを実装する方法

MT4のインジケーターに口座縛りを実装
yuki
yuki
この記事では開発者さん向けに、MT4のEAやインジケーターに口座縛りを実装する手順をご紹介していきます
カオチャイ
カオチャイ
口座縛りを実装すれば、コピー防止になって安心して配布することができるようになりますよ!

口座縛りとは?

MT4の口座番号MT4の左上には口座番号が表示されています

 

口座縛りとは、EA・インジケーターに指定した口座番号のMT4でしか動かないようにする方法です。

MT4の口座番号は、MT4のサーバーから直接取得される仕様ですので偽装ができません。その特性を利用し、事前に顧客から利用するMT4の口座番号を聞き取り、mq4ファイルに直接口座番号を書き込みます。

セキュリティは非常に高いので、有料のEA・インジケーターに多く実装されていますね。

ただしデメリットとして、事前に顧客から口座番号を聞き取って、それを毎回mq4に書き込んでコンパイルして納品するという手間は発生します。

また、配布済みツールのアップデートする時は、配布した分全てに書き換え作業&再配布の手間が発生しますので、ある程度の販売数が見込めるツールでしたら、書き換えの手間がいらないサーバー認証をおすすめします。

配布後の利便性 

実装の簡単さ 

セキュリティの高さ 

 

MQLで口座縛りを実装する手順

それでは口座縛りのコードを書いていきますが、ここでは下記2種類の縛りかたを紹介していきます。

・コード内に直接口座番号を書く方法
・口座番号から一意のパスワードを作成する方法

 

コードに直接口座番号を書く方法 (MQL4,MQL5共通)

yuki
yuki
さっそくコードの解説をしていきますが、EAとインジケーターでは書く場所が違いますのでご注意ください。理由は後述の注意点で説明します
//EAを動かす口座番号
int _allowedAccountNumber = 12345678;

int OnInit(){
   if(AccountInfoInteger(ACCOUNT_LOGIN) != _allowedAccountNumber){
      Alert("この口座では使用できません。");
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}
//インジケーターを動かす口座番号
int _allowedAccountNumber = 12345678;

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(AccountInfoInteger(ACCOUNT_LOGIN) != _allowedAccountNumber){
      Alert("この口座では使用できません。");
      return 0;
   }
   return(rates_total);
}

 

まずはグローバル変数(OnInit関数やOnCalculate関数の外側)_allowedAccountNumberで、口座縛りをしたい口座番号を指定します。ソースコードの一番上に書いておくと、口座番号を変更してコンパイルする際なんかに便利です。

AccountInfoInteger関数の引数にACCOUNT_LOGINを指定することで、MT4でログインしている口座番号を取得することができます。MQL4の場合はAccountNumber関数でも取得できますが、MQL5ではAccountNumber関数が廃止されているので注意してください。

あとはグローバル変数で指定した番号と、MT4から取得した口座番号をif文で照合すれば口座縛りの完成です。グローバル変数で指定した番号とMT4から取得した口座番号が同じだと認証が成功し、異なると「この口座では使用できません。」というアラートが出てEAやインジケータが動かなくなります。

たった数行で口座縛りを実装できるので、非常に簡単な方法です。デメリットはEA・インジケーターを動かす口座番号を変えたり増やしたりする場合は、毎回コンパイルし直す必要があります

 

複数の口座番号を一度に書き込むこともできる

コードが少しややこしくなりますが、EA・インジケーターを配布する人が既に複数決まっているときは最初から複数の口座番号を記載してもOKです。

//EA・インジケーターを動かす口座番号
int _allowedAccountNumber[] = {12345678, 23456789, 34567890};

//インジケーターの場合はOnCalculate関数内に書いてください
int OnInit(){
   bool allowed = false;
   for(int index = 0; index < ArraySize(_allowedAccountNumber); index++){
      if(_allowedAccountNumber[index] == AccountInfoInteger(ACCOUNT_LOGIN)){
         allowed = true;
         break;
      }
   }
   if(!allowed) {
      Alert("この口座では使用できません。");
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

インジケーターの場合は前例と同様にOnCalculate関数内に書いてください。

グローバル変数_allowedAccountNumberをint型の配列にし、複数の番号を保存しておきます。forループでMT4の口座番号が_allowedAccountNumber配列に存在すれば認証が成功します。

 

口座番号からパスワードを自動生成する方法

こちらは、口座番号から一意のパスワードを自動生成するタイプの口座縛りです。

相手の口座番号を聞き、口座番号から算出したパスワードを相手に伝えます。そのパスワードをパラメータで入力することで認証が成功する仕組みです。

ソースコードに口座番号を直接書き込む方法に比べて、口座番号に応じてコードを書き換えて再コンパイルする必要がないので、こちらの方が負担は少ないです。

input string _password = "";//パスワード

//インジケーターの場合はOnCalculate関数内に書いてください
int OnInit(){
   string pass = (string)(AccountInfoInteger(ACCOUNT_LOGIN) * 123);
   if(_password  != pass ){
      Alert("パスワードが間違っています。");
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

この例では、口座番号に123を掛けた値をパスワードにしています。

 

もう少し複雑にしてパスワードがバレにくいようにした例も見てみましょう。

input string _password = "";//パスワード

//インジケーターの場合はOnCalculate関数内に書いてください
int OnInit(){
   long result = 1;
   string accountNumberString = (string)AccountInfoInteger(ACCOUNT_LOGIN);
   for(int i = 0; i < StringLen(accountNumberString); i++) {
      if((long)StringSubstr(accountNumberString, i, 1) > 0)
         result *= (long)StringSubstr(accountNumberString, i, 1);
   }
   string pass = (string)(result * 456);
   if(_password  != pass ) {
      Alert("この口座では使用できません。");
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

この例では、口座番号のそれぞれの桁(0以外)を全部掛けた数に456を掛けた値をパスワードにしています。

例示なので簡単な計算式にしていますが、パスワードを算出する規則がバレてしまうと口座縛りの効果が無くなってしまうので、算出規則は特定できないような複雑なものにしてください。

例えば0→a、1→bのように0~9の数字をアルファベットのa~jに変換したりすると、より推測しにくい強固なパスワードになります。

パスワードを生成する規則はアイデア次第です。自分にしか解読できないオリジナルな規則を考えてみてください。

 

正しく稼働するかのチェックは重要

コードが書けたら実際に自分の口座番号やパスワードを入力して試してみましょう。

認証に失敗すると次のようなアラートが表示され、EA・インジケーターが動かなくなっていれば成功です。

認証に成功した場合は何も表示されずEA・インジケーターが動くと思いますが、認証に成功したのがわかりやすいようにPrint関数でメッセージを出したりするのも良いかもしれませんね。

Print("認証に成功しました。");

 

 

口座縛り実装後の注意点

記事前半で、EAとインジケーターでは認証コードを書く場所が変えた方が良いと説明しましたが、その理由を説明します。

MQLのAccountInfoInteger(ACCOUNT_LOGIN)で得られる口座番号(AccountNumber関数も同様)は、MT4サーバにログインしてからでないと0を返します。

インジケーターの場合、MT4を起動した直後は必ずAccountInfoInteger(ACCOUNT_LOGIN)が0を返します。

チャートにインジケーターを挿入している状態でMT4を起動したとき、MT4サーバにログインする前にインジケーターの初期化(OnInit関数)が終了してしまいます。

そのため、AccountInfoInteger(ACCOUNT_LOGIN)を利用する口座番号認証では、OnInit()内に認証用コードを書くと、MT4サーバにログインする前に認証が行われてしまうため、必ず認証に失敗します。

そこで、インジケーターの場合はOnCalculate関数内に口座認証コードを書くのがおすすめです。

EAの場合は口座にログインしてからEAの稼働が始まるので、OnInit関数内に書くと良いでしょう。

 

おすすめはサーバー認証

ここまで口座縛りの方法を解説してきましたが、もしある程度の販売見込みがあったり、EAのアップデートをこまめに行って着実に顧客を囲い込んでいく戦略をとるならば、口座縛りではなくサーバー認証方式をおすすめします。

サーバー認証とは?

サーバー認証のしくみ

サーバー認証は、顧客の口座番号を販売者のサーバー上に記憶させ、MT4をネットに繋げた時にサーバーに口座番号が登録されていれば稼働、登録されていなければ稼働できないという方式です。

コード上に書き込む口座認証方式と違い、アップデート時にわざわざコードの口座番号を書き直す必要はなく、そのままインジケーターの配布が可能です。

セキュリティは今回ご紹介した中で一番高いので、有料配布ツールには一番オススメできる方法です。

ただし、個人でサーバーを借りて導入する方法はコスト面からみると現実的ではないので、MQLAuth実装代行サービスなどのレンタルサーバー認証実装サービスを使うのがおすすめです。

個人でMQLAuthを実装する方法についてはこちらの記事で解説しています。

配布後の利便性 

実装の簡単さ 

セキュリティの高さ 

 

MQLで口座縛りを実装する方法 まとめ

yuki
yuki
最近は個人でEAやインジケーターを販売されている方が増えてきましたが、セキュリティに関心が薄い開発者さんが多く、優秀なロジックがそのまま転用されるなんて事例もありますので認証関連はしっかりやっておきたいですね
カオチャイ
カオチャイ
ご自身で作ったインジケーターが知らないところでパスワード付きで転売されたりすることもあるので気をつけたいですね
ex4ファイルは逆コンパイルは可能なのか?
ex4ファイルとmq4ファイルの違い
ex4ファイルとmq4ファイルの違い【デコンパイルは構造上できません】 まずはファイル拡張子を理解しよう 上記は同じ『tester』というファイルですが、拡張子が異なっています ex4とmq4...

 

ABOUT ME
YUKI
MT4をこよなく愛する開発者です。FX-EAラボの他に、サヤ取りを追求した株ラボ、MT4、MT5のツール制作に特化したシストレファクトリー、EAやインジケーターに認証やペイパル決済機能が付けられるMQLAuthシステムなどの開発にも関わっています。 YUKIプロフィール