各種利用制限を実装する

EAやインジケーターを作成すると、有料で販売を行う場合や購入希望者に試用版を配布したい場合があります。
そのまま配布すると二次配布などによる不正利用が想定されるため、様々な制限が必要となります。

デモ口座のみ利用可能に制限


利用中の口座がデモ口座であるかは、IsDemo関数あるいはAccountInfoInteger関数によって調べることが可能です。

bool IsDemo();

IsDemo関数は利用中の口座がデモ口座であればtrue, リアル口座であればfalseを返します。

OnInit関数内でIsDemoを実行し、結果がfalseの場合はOnInit関数の戻り値にINIT_FAILEDを指定することで、プログラムを強制終了させることができます。

int OnInit(){
// デモ口座でのみ有効化
if(IsDemo() == false){
Alert("デモ口座でのみ有効なプログラムです。");
return(INIT_FAILED);
}

return(INIT_SUCCEEDED);
}

逆にリアル口座でのみ稼働させたい場合には、IsDemoの結果がtrueの場合にINIT_FAILEDとします。

int OnInit(){
// リアル口座でのみ有効化
if(IsDemo() == true){
Alert("リアル口座でのみ有効なプログラムです。");
return(INIT_FAILED);
}

return(INIT_SUCCEEDED);
}

口座の種類はAccountInfoInteger関数の引数に、ACCOUNT_TRADE_MODEを指定することでも確認できます。
デモ口座の場合には、戻り値がACCOUNT_TRADE_MODE_DEMOとなります。

int OnInit(){
// デモ口座でのみ有効化
if(AccountInfoInteger(ACCOUNT_TRADE_MODE) == ACCOUNT_TRADE_MODE_DEMO){
Alert("デモ口座でのみ有効なプログラムです。");
return(INIT_FAILED);
}

return(INIT_SUCCEEDED);
}


口座番号で制限


利用者の口座番号が事前に分かる場合には、口座番号で制限かけることで確実に1ユーザーのみ利用可能とすることが可能です。
利用中のMT4の口座番号は、AccountNumber関数で調べることできます。

int AccountNumber();

ソースコード内に変数を作成し、利用を許可する口座番号を代入します。
AccountNumber関数の実行結果が作成した変数の値と異なる場合にはプログラムを終了させます。

int OnInit(){
int validAccountNumber = 1234567; // 口座番号1234567でのみ動作
if(AccountNumber() != validAccountNumber){
Alert("無効な口座です。");
return(INIT_FAILED);
}

return(INIT_SUCCEEDED);
}

口座番号はAccountInfoInteger関数の引数にACCOUNT_LOGINを指定することでも確認できます。

int OnInit(){
int validAccountNumber = 1234567; // 口座番号1234567でのみ動作
if(AccountInfoInteger(ACCOUNT_LOGIN) != validAccountNumber){
Alert("無効な口座です。");
return(INIT_FAILED);
}

return(INIT_SUCCEEDED);
}


ブローカーで制限


IB目的のEAなどでは、特定のブローカーでのみ利用して欲しい場合があります。
TerminalInfoString関数の引数にTERMINAL_COMPANYを指定することで利用中のブローカー名を取得することができます。

string TerminalInfoString(
int property_id
);

あらかじめ利用可能とするブローカー名をTerminalInfoString関数で調べてきおき、ブローカー名を変数に代入します。
実行中のプログラムのブローカー名が変数の値と違う場合にはプログラムを終了させます。
以下のプログラムはOANDA JapanのMT4でのみ利用を許可する例です。

int OnInit(){
string validCompany = "OANDA Corporation";
if(TerminalInfoString(TERMINAL_COMPANY) != validCompany){
Alert("無効なブローカーです。");
return(INIT_FAILED);
}

return(INIT_SUCCEEDED);
}

TerminalInfoString(TERMINAL_COMPANY)と似た動作をする関数にAccountCompay関数があります。
どちらも公式のドキュメントではブローカー名を返すとありますが、この2つの実行結果は違う場合があります。
またAccountCompay関数を使用した場合には、同じブローカーであっても口座タイプの違いによって実行結果が変わる場合があるので注意が必要です。

バックテスト時のみ利用可能に制限


配布したプログラムをバックテストでの検証のみ利用可能とすることも可能です。
プログラムがバックテストで実行されているかは、IsTesting関数で判別することが可能です。

bool IsTesting();

バックテストで利用されている場合はtrue, フォワードで利用されている場合にはfalseとなります。

IsTesting関数を実行し、結果がfalseの場合にはプログラムを終了させます。

int OnInit(){
if(IsTesting() == false){
Alert("バックテストのみ利用可能です。");
return(INIT_FAILED);
}

return(INIT_SUCCEEDED);
}


期間で制限


日付を使って使用期間に制限をかけることが可能です。
現在の日時に関する情報は以下の関数で取得できます。
年・・・Year関数
月・・・Month関数
日・・・Day関数
時・・・Hour関数
分・・・Minute関数
秒・・・Seconds関数

int Year();
int Month();
int Day();
int Hour();
int Minute();
int Seconds();


例えば2017年以降は利用できないよう制限をかけるには以下のように書くことができます。

int OnInit(){
if(Year() >= 2017){
Alert("利用期限を過ぎました。");
return(INIT_FAILED);
}

return(INIT_SUCCEEDED);
}


より細かく、2017年6月15日以降利用を制限する例は以下のようになります。

int OnInit(){
if(Year() >= 2018){
Alert("利用期限を過ぎました。");
return(INIT_FAILED);
}
else if(Year() == 2017){
if(Month() >= 7){
Alert("利用期限を過ぎました。");
return(INIT_FAILED);
}
else if(Month == 6){
if(Day() >= 15){
Alert("利用期限を過ぎました。");
return(INIT_FAILED);
}
}
}

return(INIT_SUCCEEDED);
}


注意点としまして、これらの関数が返す日時はMT4のサーバー時間となります。
そのためブローカー毎に時差が発生する場合や、マーケットがクローズしている間は正しい時刻が取得できません。

ローカル時間(ユーザーのPCの時間)を利用することも可能です。
MqlDateTime型の変数を作成し、TimeLocal関数のパラメータにすることで以下のように取得可能です。

MqlDateTime local;
TimeLocal(local);

local.year; // 年
local.mon; // 月
local.day; // 日
local.hour; // 時
local.min; // 分
local.sec; // 秒


ただしローカル時間を使用して利用制限を設定した場合、ユーザーがPCの時刻を意図的に変更することで、制限をすり抜けることができるため良い方法とは言えません。
TwitterでシェアFacebookでシェアGoogle+でシェアはてなブックマークに追加

TOPへ