【MQL5】SocketTimeouts関数の使い方と自動売買実装コード

1. SocketTimeouts関数の概要と実務での活用法

MQL5におけるSocketTimeouts関数は、ネットワーク通信(ソケット通信)を行う際、データの「送信」と「受信」にそれぞれ何ミリ秒待機するかを設定するための関数です。

実務レベルのEA(エキスパートアドバイザー)開発において、外部サーバーから経済指標を取得したり、独自のAPIを通じて売買シグナルを受け取ったりする場合、この設定は極めて重要です。

なぜこの関数が必要なのか?
デフォルトの設定では、相手サーバーのレスポンスが遅い場合にEAの処理が数秒〜数十秒間「フリーズ(ブロック)」してしまうことがあります。メタトレーダーのメインスレッドが停止すると、その間の価格更新や決済注文のチャンスを逃すという致命的なリスクが生じます。SocketTimeoutsを適切に設定することで、通信に時間がかかりすぎている場合に処理を強制的に切り上げ、EAの安定稼働を守ることができるのです。


2. 構文と戻り値

SocketTimeoutsの構文は以下の通りです。

bool  SocketTimeouts(
   int    socket,          // ソケットハンドル
   uint   timeout_send,    // 送信タイムアウト(ミリ秒)
   uint   timeout_receive  // 受信タイムアウト(ミリ秒)
   );

パラメーター

  • socket: SocketCreate関数で作成したソケットのハンドルを指定します。
  • timeout_send: データを送信する際の制限時間をミリ秒単位で指定します。
  • timeout_receive: データを受信する際の制限時間をミリ秒単位で指定します。

戻り値

  • 成功した場合は true、失敗した場合は false を返します。
  • 失敗した理由は GetLastError() 関数で確認できます。

3. 具体的な使い方・実践サンプルコード

以下は、外部サーバーに接続する際にタイムアウトを設定し、安全に通信を試みる実践的なサンプルコードです。

//+------------------------------------------------------------------+
//| 外部APIからデータを取得するサンプル                                     |
//+------------------------------------------------------------------+
void FetchExternalData()
{
   string host = "example.com";
   int port = 80;

   // 1. ソケットの作成
   int socket = SocketCreate();
   if(socket == INVALID_HANDLE)
   {
      Print("ソケット作成失敗: ", GetLastError());
      return;
   }

   // 2. サーバーへ接続
   if(SocketConnect(socket, host, port, 5000)) // 接続自体のタイムアウトは5秒
   {
      Print("サーバーに接続成功");

      // 3. 送受信のタイムアウトを個別に設定 (実務的な設定例)
      // 送信は1000ms(1秒)、受信は3000ms(3秒)に制限
      if(!SocketTimeouts(socket, 1000, 3000))
      {
         Print("タイムアウト設定失敗: ", GetLastError());
      }

      // 送信データ準備(HTTPリクエスト等)
      string request = "GET /api/signal HTTP/1.1\r\nHost: " + host + "\r\n\r\n";
      char data[];
      StringToCharArray(request, data);

      // 4. データ送信
      if(SocketSend(socket, data, ArraySize(data)) < 0)
      {
         Print("送信エラー: ", GetLastError());
      }
      else
      {
         // 5. データ受信
         char response[];
         uint timeout = 3000; // 受信待ち
         int len = SocketRead(socket, response, 10000, timeout);

         if(len > 0)
         {
            Print("受信成功: ", CharArrayToString(response));
         }
         else
         {
            Print("受信タイムアウトまたはエラー: ", GetLastError());
         }
      }
   }
   else
   {
      Print("接続失敗: ", GetLastError());
   }

   // 6. ソケットを閉じる(忘れるとメモリリークの原因)
   SocketClose(socket);
}

4. 使用上の注意点とよくあるエラー

タイムアウトを短くしすぎない

「反応を速くしたい」からといって、タイムアウトを10msなどの極端に短い値に設定すると、正常な通信であってもパケットの遅延(揺らぎ)によってエラーが発生しやすくなります。実務上は、送信は500ms〜2000ms、受信は2000ms〜5000ms程度が目安です。

接続関数(SocketConnect)との違い

SocketConnect関数の中にもタイムアウト引数がありますが、これはあくまで「接続が確立するまで」の待ち時間です。SocketTimeoutsは、接続が成功したのデータのやり取りに対する制限時間を決めるものだと理解してください。

エラーコード 5273 (ERR_NETSOCKET_TIMEOUT)

SocketReadSocketSendでこのエラーが出た場合は、設定したタイムアウト時間内に処理が終わらなかったことを意味します。この際、リトライ(再試行)のロジックを組むのが一般的ですが、無限ループに陥らないよう注意が必要です。


5. 【重要】自動売買における約定スピードと環境の罠

どれだけコード側でタイムアウトを最適化し、洗練されたアルゴリズムを構築したとしても、実行環境が「自宅のPC」であれば、プロの世界では通用しません。自宅のインターネット回線は、家庭用ルーターの処理遅延、プロバイダーによるパケット優先順位の低下、そして物理的な距離によるネットワーク遅延(レイテンシ)という、トレーダーにとっての「致命的な不純物」に満ちています。

0.1秒(100ミリ秒)の遅延は、ボラティリティが高い相場では数pipsの滑り(スリッページ)を招き、期待期待値を大幅に削り取ります。アルゴリズムトレードで安定した利益を追求するには、取引サーバーの目と鼻の先に位置するデータセンター内の「専用VPS」が必須です。24時間365日の安定稼働はもちろん、極限まで削ぎ落とされた低レイテンシ環境を手に入れることこそが、技術者が最初に投資すべき「勝つためのインフラ」なのです。

💡 この記事の内容を実運用で活かすには?

この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント

タイトルとURLをコピーしました