EA口座認証の実装方法|不正コピー対策をMQL4コード付きで開発元が解説

※免責事項
本記事は情報提供を目的としており、特定の金融商品の購入・売却を推奨するものではありません。FX取引にはリスクが伴い、投資元本を失う可能性があります。投資判断はご自身の責任において行ってください。
EA開発者必読
EA口座認証の実装方法
不正コピーからあなたのEAを守る完全ガイド

苦労して開発したEAが無断複製・再配布されるリスクを徹底解説。
MQL4コード付きで口座認証の実装手順をわかりやすく説明します。

この記事でわかること:EA不正コピーの実態 → 口座番号認証の基本実装(MQL4コード付き)→ 複数口座対応 → オンライン認証サーバー連携 → 有効期限付きライセンス → ユーザーフレンドリーなエラー設計 → GogoJungle vs 自社販売の認証戦略の違い

目次

なぜ口座認証が必要か|EA不正コピー・再配布の実態

EAの不正コピー問題は、販売者が想像する以上に深刻です。国内外のフォーラム・SNS・ファイル共有サイトでは、有料EAが無断で共有される事例が後を絶ちません。

67%
有料EAの不正共有が確認された割合(海外フォーラム調査)
数十万円
人気EAの開発者が受ける年間機会損失の推定額
口座認証
最もシンプルかつ効果的なコピー防止の手段

EA(自動売買プログラム)はMQL4/MQL5ファイルをコンパイルした .ex4 / .ex5 形式で配布されます。バイナリ形式とはいえ、逆コンパイルツールを使えばロジックをある程度復元できますし、ファイルそのものを別のPCやアカウントにコピーするだけで動作してしまう場合があります。

口座認証を実装することで、購入者の口座番号(AccountNumber)と紐づけた専用ファイルを発行できます。たとえ第三者にファイルが流出しても、その人の口座番号と一致しなければEAが起動しない仕組みになります。

不正コピーが発生しやすい主な経路

  • 国内外のトレーダーフォーラム(2ch/5ch、Forex Factory等)でのファイル共有
  • 購入者から知人への「お裾分け」(悪意なき共有が多い)
  • 中古売買・ファイル転売サイトへの出品
  • Telegram・Discordグループでの無断配布
  • 海外の「EA crack」サイトによる改ざん配布

口座番号認証の基本実装|MQL4コード解説

最もシンプルな認証方式は、MT4の組み込み関数 AccountNumber() を使って、起動時に口座番号を検証する方法です。以下のコードを参考にしてください。

MQL4:基本的な口座番号認証
//--- 入力パラメータ:購入者の口座番号を設定
input long AllowedAccountNumber = 0;

//--- OnInit() 内で認証チェック
int OnInit()
{
   //--- 口座番号の一致を確認
   if(AllowedAccountNumber != 0 &&
      AccountNumber() != AllowedAccountNumber)
   {
      Alert("認証エラー:このEAはアカウント番号 " +
            IntegerToString(AllowedAccountNumber) +
            " 専用です。\n現在の口座: " +
            IntegerToString(AccountNumber()));
      return(INIT_FAILED);
   }

   Print("口座認証OK:", AccountNumber());
   return(INIT_SUCCEEDED);
}

実装のポイント:販売時に購入者から口座番号を申告してもらい、AllowedAccountNumber にその値をセットしたカスタムビルドを発行します。INIT_FAILED を返すことでEAがチャートに適用されず、OnTick()も実行されません。

認証は「完璧」より「割に合わなくする」発想で

口座認証を考えるとき、つい「決して破られない完璧な仕組み」を目指したくなりますが、現実にはどんな認証も時間と労力をかければ突破される可能性はあります。重要なのは完璧を目指すことではなく、「不正コピーする手間より、正規に買う方が楽だ」と思わせる水準に持っていくことです。

多くの購入者は悪意のない一般ユーザーであり、シンプルな口座番号認証だけでもカジュアルな使い回しは十分に防げます。販売規模が小さいうちは軽量な認証で始め、売上が伸びてから、オンライン認証や有効期限管理へ段階的に強化していくのが現実的です。最初から過剰に作り込んでコストをかけるより、規模に応じて投資する考え方が、開発リソースを無駄にしません。

複数口座対応の実装パターン

1ライセンスでデモ口座とリアル口座の両方を使いたい、またはVPS用に複数口座を許可したいというケースは非常に多くあります。複数口座対応には主に2つのパターンがあります。

パターンA:配列で複数口座を直接記述
コード内に許可口座番号の配列を埋め込む方法。シンプルで改ざんされにくいが、口座追加のたびに再コンパイルが必要。
パターンB:外部ライセンスファイル読み込み
MQL4/Filesフォルダに配置したテキストファイルから口座番号を読み込む方法。再コンパイル不要で柔軟に対応できる。
MQL4:パターンA:配列による複数口座認証
//--- 許可する口座番号をコンパイル時に埋め込む
long AllowedAccounts[] = {1234567, 7654321, 9988776};

bool IsAccountAuthorized()
{
   long currentAccount = AccountNumber();
   int total = ArraySize(AllowedAccounts);
   for(int i = 0; i < total; i++)
   {
      if(AllowedAccounts[i] == currentAccount)
         return true;
   }
   return false;
}

int OnInit()
{
   if(!IsAccountAuthorized())
   {
      Alert("認証失敗:この口座はライセンスされていません。\n" +
            "購入・お問い合わせ: https://ea-creators.com/ea-create/");
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}
MQL4:パターンB:外部ファイル読み込みによる認証
//--- MQL4/Files/license.txt から口座番号リストを読み込む
bool IsAccountAuthorizedFromFile()
{
   int handle = FileOpen("license.txt", FILE_READ|FILE_TXT|FILE_ANSI);
   if(handle == INVALID_HANDLE)
   {
      Alert("ライセンスファイルが見つかりません。");
      return false;
   }

   long currentAcc = AccountNumber();
   while(!FileIsEnding(handle))
   {
      string line = FileReadString(handle);
      if(StringToInteger(line) == currentAcc)
      {
         FileClose(handle);
         return true;
      }
   }
   FileClose(handle);
   return false;
}

オンライン認証サーバーとの連携|WebRequest活用

より堅牢な認証を実現したい場合、MT4の WebRequest() 関数を使ってオンラインの認証APIと連携する方法があります。EA起動時にサーバーへ口座番号とEA IDを送信し、サーバー側で認証結果を返す仕組みです。

オンライン認証の全体フロー

1
EA起動 → AccountNumber() と EA固有IDを取得
2
WebRequest() で認証APIにPOSTリクエストを送信
3
サーバー(PHP/Python/Node.js等)がDBで口座番号を照合
4
“OK” または “NG” をレスポンスとして受信し、EAが起動判断
MQL4:WebRequestによるオンライン認証
//--- ツール > オプション > エキスパートアドバイザー で
//    対象URLの許可設定が必要
input string AuthServerURL = "https://your-server.com/api/auth";
input string EA_ID         = "MY_EA_V1";

bool OnlineAuthenticate()
{
   string postData = "account=" + IntegerToString(AccountNumber()) +
                     "&ea_id=" + EA_ID +
                     "&broker=" + AccountCompany();

   char   postArr[];
   char   resultArr[];
   string headers = "Content-Type: application/x-www-form-urlencoded\r\n";
   string resHeaders;

   StringToCharArray(postData, postArr, 0, StringLen(postData));
   ArrayResize(postArr, StringLen(postData));

   int statusCode = WebRequest(
      "POST", AuthServerURL, headers, 5000,
      postArr, resultArr, resHeaders
   );

   if(statusCode == 200)
   {
      string response = CharArrayToString(resultArr);
      if(StringFind(response, "OK") >= 0) return true;
   }
   return false;
}

int OnInit()
{
   if(!OnlineAuthenticate())
   {
      Alert("オンライン認証に失敗しました。\n" +
            "ライセンスをご確認ください: https://ea-creators.com/ea-create/");
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

注意:WebRequestを使用するには、MT4の「ツール → オプション → エキスパートアドバイザー」タブで認証サーバーのURLを「許可するURLリスト」に追加する必要があります。購入者向けのセットアップガイドに忘れず記載してください。

有効期限付きライセンスの実装

月額課金型のEAや試用期間付きライセンスを提供する場合、有効期限を認証に組み込むことができます。

MQL4:有効期限チェックの実装
//--- ライセンス有効期限(UNIX タイムスタンプで指定)
input long LicenseExpiry = 1767225600;

bool IsLicenseValid()
{
   datetime now = TimeGMT();
   if((long)now > LicenseExpiry)
   {
      int daysExpired = (int)((now - (datetime)LicenseExpiry) / 86400);
      Alert("ライセンスの有効期限が " + IntegerToString(daysExpired) +
            " 日前に切れています。\n更新: https://ea-creators.com/ea-create/");
      return false;
   }

   long daysLeft = (LicenseExpiry - (long)now) / 86400;
   if(daysLeft <= 7)
   {
      Print("ライセンス残り " + IntegerToString((int)daysLeft) + " 日です。");
   }
   return true;
}

int OnInit()
{
   if(!IsLicenseValid()) return(INIT_FAILED);
   return(INIT_SUCCEEDED);
}

有効期限認証の活用ケース

月額サブスクモデル
毎月更新タイムスタンプを再発行。安定した収益を確保
無料トライアル
14日間の体験版を提供し、購入へのハードルを下げる
バージョン管理
古いバージョンを期限切れにし、最新版への移行を促進

認証エラー時のUX設計

認証エラーが発生したとき、ユーザーが「何が起きているか」「どうすれば解決できるか」をすぐに理解できるメッセージを表示することが重要です。不親切なエラーメッセージはサポートコストの増大と悪評につながります。

悪い例

Authentication failed.
Error code: -1
EA initialization failed.

何が問題か不明。どうすれば良いかわからない。

良い例

【認証エラー】
このEAはご購入いただいた
口座専用です。
現在の口座: 1234567
ライセンス口座: 7654321
お問い合わせ: ea-creators.com

状況が明確。次のアクションがわかる。

エラーメッセージ設計の5原則

  1. 原因を明示する:「口座番号不一致」「有効期限切れ」など具体的に
  2. 現在の状態を表示する:現在の口座番号・残り日数など
  3. 解決手順を示す:「○○ページからライセンスを更新してください」
  4. 問い合わせ先を明記する:URL・メールアドレスをメッセージに含める
  5. 日本語で丁寧に:英語エラーコードのみは避ける

エラー時こそ「正規ユーザーへの配慮」を忘れない

認証エラーのUX設計で見落とされがちなのが、「不正対策」と「正規ユーザーの利便性」のバランスです。認証を厳しくしすぎると、口座番号を打ち間違えただけの正規購入者まで締め出してしまい、サポート問い合わせが増えて結局自分の首を絞めます。エラーメッセージには「何が原因で、どうすれば直るか」を具体的に示すことが大切です。

たとえば「認証に失敗しました」だけでは不親切で、「登録口座番号と異なります。購入時の口座番号をご確認ください」のように案内すれば、正規ユーザーは自力で解決できます。不正利用者には厳しく、正規ユーザーには優しく。この使い分けを意識すると、認証が「売上を守る盾」であると同時に「顧客満足を保つ仕組み」にもなります。当社のEAも、認証手順を購入後メールで丁寧に案内し、つまずきを最小化しています。

GogoJungle販売 vs 自社サイト販売|認証戦略の違い

EAの販売チャネルによって、最適な認証方式は異なります。GogoJungleのようなプラットフォーム販売と自社サイト販売では、購入者への対応フローも変わります。

GogoJungle販売の認証
  • GogoJungle側でDRM保護機能あり
  • プラットフォームのライセンス管理に依存可能
  • 独自認証を追加することで二重保護が可能
  • 口座番号申請フォームはGJ販売ページ経由で設置
  • 推奨:シンプルな配列認証 or GJ DRM依存
自社サイト販売の認証
  • プラットフォームDRMなし=完全自己責任
  • 購入フロー内で口座番号申請を組み込める
  • オンライン認証で収益データも収集可能
  • 有効期限付きサブスク課金と相性が良い
  • 推奨:オンライン認証 + 有効期限の組み合わせ

両チャネル共通:独自の口座番号認証を実装しておくことで、万が一のトラブル時も自社でライセンス管理を継続できます。価格戦略との連動も重要です。

EA口座認証についてよくある質問

口座番号認証を実装してもex4ファイルをコピーされませんか?
ファイルのコピー自体は技術的に可能ですが、口座番号認証があれば別口座で起動した時点で INIT_FAILED が返り動作しません。オンライン認証を組み合わせれば、コピーからの認証試行をサーバーログで検知・ブロックでき、カジュアルなコピーの99%以上を防げます。
購入者が口座番号を変更したらどう対応すればいいですか?
あらかじめポリシーを明確にしておくのが重要です。「1ライセンスにつき口座変更は1回まで無料」などを設けるケースが多くあります。VPS環境でのEA運用では口座番号が固定になりやすく、トラブルが減ります。オンライン認証ならサーバー側DBの更新だけで対応できます。
認証サーバーが落ちたときにEAが使えなくなりませんか?
オンライン認証の最大のリスクです。対策としてグレースピリオド方式(認証成功時にローカルキャッシュを保存し、サーバーに繋がらない場合は72時間キャッシュを有効とする)がよく使われます。口座番号認証(ローカル完結)とのハイブリッド実装も有効です。
口座認証付きのEA制作を依頼できますか?
はい。当社 EA CreatorsLAB は現役のMQL開発工房として、口座番号認証・有効期限管理・オンライン認証サーバー連携の実装込みでEA制作を承っています(ココナラ)。既存EAへの認証機能の追加(改造)にも対応します。

EA口座認証の実装まとめ

EA口座認証は、開発者の収益を守るための必須機能です。シンプルな口座番号チェックから、オンライン認証サーバー連携、有効期限管理まで、販売規模と技術力に応じた段階的な実装ができます。GogoJungleでのEA販売を始める際は、最低限の口座番号認証は実装しておきましょう。価格設定戦略と組み合わせれば、サブスク型の安定収益モデルも実現できます。

▦ NEXT ACTION

当社 EA CreatorsLAB が3方向すべてご案内します

現役のMQL開発工房として、口座認証の実装からEA本体までお手伝いします

※当社が提供する製品・有料サービスのご案内です。過去実績は将来を保証しません

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次